cryptoservices/certificateandkeymgmt/wtlscert/wtlsnames.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
--- /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;
+	}