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