--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoservices/certificateandkeymgmt/wtlscert/wtlsnames.cpp Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,511 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <wtlsnames.h>
+#include "wtlsdec.h"
+#include <x500dn.h>
+#include <utf.h>
+
+_LIT(KWTLSStructuredTextFieldSeparator, ";");
+_LIT(KWTLSStructuredTextAssignmentCharacter, "=");
+const TInt KWTLSTextHeaderLength = 3;
+
+EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSName::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSName::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSName* self = CWTLSName::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSName* self = new(ELeave) CWTLSName;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CWTLSName* CWTLSName::NewL(const CWTLSName& aName)
+ {
+ CWTLSName* self = CWTLSName::NewLC(aName);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CWTLSName* CWTLSName::NewLC(const CWTLSName& aName)
+ {
+ CWTLSName* self = new(ELeave) CWTLSName;
+ CleanupStack::PushL(self);
+ self->ConstructL(aName);
+ return self;
+ }
+
+CWTLSName::CWTLSName()
+ {
+ }
+
+void CWTLSName::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ if ((aBinaryData.Length() - aPos) < 1)
+ {
+ User::Leave(KErrArgument);
+ }
+ iNameType = aBinaryData[aPos];
+ aPos++;
+ switch(iNameType)
+ {
+ case EWTLSText:
+ {
+ AllocTextDataL(aBinaryData, aPos);
+ break;
+ }
+ case EWTLSX500DN:
+ {
+ AllocNameDataL(aBinaryData, aPos);
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ }
+
+void CWTLSName::ConstructL(const CWTLSName& aName)
+ {
+ iNameType = aName.iNameType;
+ iNameData = aName.iNameData->AllocL();
+ }
+
+EXPORT_C CWTLSName::~CWTLSName()
+ {
+ delete iNameData;
+ }
+
+void CWTLSName::AllocTextDataL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ if ((aBinaryData.Length() - aPos) < KWTLSTextHeaderLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ TInt nameLength = (aBinaryData[aPos+2] + KWTLSTextHeaderLength);
+ if ((aBinaryData.Length() ) < (aPos+nameLength))
+ {
+ User::Leave(KErrArgument);
+ }
+ iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
+ aPos += nameLength;
+ }
+
+void CWTLSName::AllocNameDataL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ if ((aBinaryData.Length() - aPos) < 1)
+ {
+ User::Leave(KErrArgument);
+ }
+ TUint8 nameLength = aBinaryData[aPos];
+ aPos++;
+ if (aBinaryData.Length() - (aPos + nameLength) < 0)
+ {
+ User::Leave(KErrArgument);
+ }
+ iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
+ aPos += nameLength;
+ }
+
+EXPORT_C TBool CWTLSName::ExactMatchL(const CWTLSName& aName) const
+ {
+//hmmm, in the absence of any matching rules, just match the bytes...
+ return (*(iNameData) == *(aName.iNameData));
+ }
+
+EXPORT_C TWTLSNameType CWTLSName::NameType() const
+ {
+ return iNameType;
+ }
+
+EXPORT_C TPtrC8 CWTLSName::NameData() const
+ {
+ return *iNameData;
+ }
+
+EXPORT_C HBufC* CWTLSName::DisplayNameL() const
+ {
+ switch (iNameType)
+ {
+ case EWTLSText:
+ {
+ CWTLSStructuredText* sText = NULL;
+ TRAPD(err, sText = CWTLSStructuredText::NewL(*iNameData));
+ if (err != KErrNone)
+ {
+ if (err != KErrArgument)
+ {
+ User::Leave(err);
+ }
+ else
+ {
+ CWTLSText* text = CWTLSText::NewLC(*iNameData);
+ HBufC* res = text->Name().AllocL();
+ CleanupStack::PopAndDestroy();//text
+ return res;
+ }
+ }
+ else
+ {
+ CleanupStack::PushL(sText);
+ HBufC* res = sText->DisplayNameL();
+ CleanupStack::PopAndDestroy();//sText
+ return res;
+ }
+ }
+ case EWTLSX500DN:
+ {
+ CX500DistinguishedName* dN = CX500DistinguishedName::NewLC(*iNameData);
+ HBufC* res = dN->DisplayNameL();
+ CleanupStack::PopAndDestroy();//dN
+ return res;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;//never gets to here...
+ }
+ }
+ }
+
+//************************************************************************//
+//text name
+EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSText::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSText::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSText* self = CWTLSText::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSText* self = new(ELeave) CWTLSText;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CWTLSText::~CWTLSText()
+ {
+ delete iName;
+ }
+
+EXPORT_C TBool CWTLSText::ExactMatchL(const CWTLSText& aName) const
+ {
+//subtle difference between this byte-match and
+//CWTLSName::ExactMatchL(...) is that this should successfully match 2 names that
+//are the same which were encoded using different character sets...
+ return (*iName == *(aName.iName));
+ }
+
+EXPORT_C TPtrC CWTLSText::Name() const
+ {
+ return *iName;
+ }
+
+EXPORT_C TWTLSCharSet CWTLSText::CharacterSet() const
+ {
+ return iCharacterSet;
+ }
+
+CWTLSText::CWTLSText()
+ {
+ }
+
+void CWTLSText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ if ((aBinaryData.Length() - aPos) < 3)
+ {
+ User::Leave(KErrArgument);
+ }
+ TWTLSDecUnsignedInteger decInt;
+ iCharacterSet = decInt.DecodeShortL(aBinaryData, aPos, 2);
+ TUint8 nameLength = aBinaryData[aPos];
+ aPos++;
+ if (aBinaryData.Length() < (aPos + nameLength))
+ {
+ User::Leave(KErrArgument);
+ }
+ TPtrC8 ptr = aBinaryData.Mid(aPos, nameLength);
+ //only works for latin-1 here...
+ iName = HBufC::NewL(ptr.Length());
+ switch (iCharacterSet)
+ {
+ case KWTLSLatin1CharSet://=latin-1
+ {
+ TPtr pRes = iName->Des();
+ pRes.Copy(ptr);
+ aPos+=nameLength;
+ break;
+ }
+ case KWTLSUTF8CharSet:
+ {
+ TPtr pRes = iName->Des();
+ User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(pRes, ptr));
+ break;
+ }
+ default:
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ }
+
+TWTLSStructuredTextField::TWTLSStructuredTextField(const TDesC& aType, const TDesC& aValue)
+ :iType(aType), iValue(aValue)
+ {
+ }
+
+EXPORT_C TPtrC TWTLSStructuredTextField::Type() const
+ {
+ return iType;
+ }
+
+EXPORT_C TPtrC TWTLSStructuredTextField::Value() const
+ {
+ return iValue;
+ }
+
+//Structured text class
+EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSStructuredText::NewL(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData)
+ {
+ TInt pos = 0;
+ return CWTLSStructuredText::NewLC(aBinaryData, pos);
+ }
+
+EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSStructuredText* self = CWTLSStructuredText::NewLC(aBinaryData, aPos);
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSStructuredText* self = new(ELeave) CWTLSStructuredText;
+ CleanupStack::PushL(self);
+ self->ConstructL(aBinaryData, aPos);
+ return self;
+ }
+
+EXPORT_C CWTLSStructuredText::~CWTLSStructuredText()
+ {
+ delete iFields;
+ }
+
+EXPORT_C HBufC* CWTLSStructuredText::DisplayNameL() const
+ {
+ if (iFields->Count() > 3)
+ {
+ return iFields->At(3).Value().AllocL();
+ }
+ else
+ {
+ return iFields->At(1).Value().AllocL();
+ }
+ }
+
+ //accessors for defined fields
+EXPORT_C TPtrC CWTLSStructuredText::ServiceName() const
+ {
+ //construction ensures iFields must have at least 3 elements
+ return iFields->At(0).Value();
+ }
+
+EXPORT_C TPtrC CWTLSStructuredText::Organization() const
+ {
+ //construction ensures iFields must have at least 3 elements
+ return iFields->At(1).Value();
+ }
+
+EXPORT_C TPtrC CWTLSStructuredText::Country() const
+ {
+ //construction ensures iFields must have at least 3 elements
+ return iFields->At(2).Value();
+ }
+
+EXPORT_C TInt CWTLSStructuredText::Count() const
+ {
+ return iFields->Count();
+ }
+
+EXPORT_C const TWTLSStructuredTextField* CWTLSStructuredText::FieldByName(const TDesC& aType) const
+ {
+ TInt count = iFields->Count();
+ for (TInt i = 0; i < count; i++)
+ {
+ TWTLSStructuredTextField* field = &(iFields->At(i));
+ if (field->Type() == aType)
+ {
+ return field;
+ }
+ }
+ return NULL;
+ }
+
+EXPORT_C const TWTLSStructuredTextField& CWTLSStructuredText::FieldByIndex(TInt aIndex) const
+ {
+ return iFields->At(aIndex);
+ }
+
+CWTLSStructuredText::CWTLSStructuredText()
+ {
+ }
+
+void CWTLSStructuredText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
+ {
+ CWTLSText::ConstructL(aBinaryData, aPos);
+ iFields = new(ELeave) CArrayFixFlat<TWTLSStructuredTextField> (4);
+ TInt pos = 0;
+ TInt end = iName->Length();
+ AddFieldValueL(KWTLSServiceName, pos);
+ AddFieldValueL(KWTLSOrganizationName, pos);
+ AddFieldValueL(KWTLSCountryName, pos);
+ if (pos < end)
+ {
+ AddFieldValueL(KWTLSCommonName, pos);
+ }
+ while (pos < end)
+ {
+ AddFieldL(pos);
+ }
+ }
+
+void CWTLSStructuredText::AddFieldValueL(const TDesC& aFieldName, TInt& aPos)
+ {
+ TPtrC startOfData = iName->Right(iName->Length() - aPos);
+ TPtrC value = GetFieldL(startOfData, aPos);
+ TWTLSStructuredTextField field(aFieldName, value);
+ iFields->AppendL(field);
+ }
+
+void CWTLSStructuredText::AddFieldL(TInt& aPos)
+ {
+ TPtrC startOfData = iName->Right(iName->Length() - aPos);
+ TPtrC fieldData = GetFieldL(startOfData, aPos);
+ TInt fieldLength = fieldData.Length();
+ TInt endType = fieldData.FindF(KWTLSStructuredTextAssignmentCharacter);
+ if ((endType == KErrNotFound) || ((endType+1) == fieldLength))
+ {
+ User::Leave(KErrArgument);
+ }
+ TPtrC type = fieldData.Left(endType);
+ TPtrC value = fieldData.Right( fieldLength - (endType+1) );
+ TWTLSStructuredTextField field(type, value);
+ iFields->AppendL(field);
+ }
+
+TPtrC CWTLSStructuredText::GetFieldL(TDesC& aString, TInt& aPos)
+ {
+//aString = where we've got up to
+//aPos = start of this chunk of name data
+ TInt length = 0;
+ TBool done = GetSubFieldL(aString, length);
+ while (!done)
+ {
+ TPtrC remainder = aString.Right(aString.Length() - (length));
+ TInt increment = 0;
+ done = GetSubFieldL(remainder, increment);
+ length += increment;
+ }
+ if (length == 0)
+ {
+ //disallow zero-length field values
+ User::Leave(KErrArgument);
+ }
+ aPos += length;
+ if (length < aString.Length())
+ {
+ //if we're not on the last field, skip the ';' character
+ aPos++;
+ }
+ return aString.Left(length);
+ }
+
+TBool CWTLSStructuredText::GetSubFieldL(TDesC& aString, TInt& aPos)
+ {
+//fields in structured text are separated by ';'. If this character appears
+//in the field text it's represented by ';;'. so, the string 'symbian;systems' would
+//be encoded as 'symbian;;systems'.
+
+//starting at the start of aString, this function sets 'aPos' to the position after the
+//first occurrence of ';' in aString. If the character following ';' is also ';' it returns
+//EFalse (meaning, this sub-field isn't a whole field), otherwise it returns ETrue.
+
+ aPos = aString.FindF(KWTLSStructuredTextFieldSeparator);
+ if (aPos == KErrNotFound)
+ {
+ aPos = aString.Length();
+ }
+ else
+ {
+ //separator char mustn't be last char
+ if (aPos == (aString.Length() -1))
+ {
+ User::Leave(KErrArgument);
+ }
+ else
+ {
+ //if the next char is ';', skip it and return EFalse
+ TPtrC next = aString.Mid(aPos + 1, 1);
+ if (next == KWTLSStructuredTextFieldSeparator)
+ {
+ aPos++;
+ return EFalse;
+ }
+ //if it isn't, that's the end of the field
+ }
+ }
+ return ETrue;
+ }