os/security/cryptoservices/certificateandkeymgmt/wtlscert/wtlsnames.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
#include <wtlsnames.h>
sl@0
    20
#include "wtlsdec.h"
sl@0
    21
#include <x500dn.h>
sl@0
    22
#include <utf.h>
sl@0
    23
sl@0
    24
_LIT(KWTLSStructuredTextFieldSeparator, ";");
sl@0
    25
_LIT(KWTLSStructuredTextAssignmentCharacter, "=");
sl@0
    26
const TInt KWTLSTextHeaderLength = 3;
sl@0
    27
sl@0
    28
EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData)
sl@0
    29
	{
sl@0
    30
	TInt pos = 0;
sl@0
    31
	return CWTLSName::NewL(aBinaryData, pos);
sl@0
    32
	}
sl@0
    33
sl@0
    34
EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData)
sl@0
    35
	{
sl@0
    36
	TInt pos = 0;
sl@0
    37
	return CWTLSName::NewLC(aBinaryData, pos);
sl@0
    38
	}
sl@0
    39
sl@0
    40
EXPORT_C CWTLSName* CWTLSName::NewL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    41
	{
sl@0
    42
	CWTLSName* self = CWTLSName::NewLC(aBinaryData, aPos);
sl@0
    43
	CleanupStack::Pop();
sl@0
    44
	return self;
sl@0
    45
	}
sl@0
    46
sl@0
    47
EXPORT_C CWTLSName* CWTLSName::NewLC(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    48
	{
sl@0
    49
	CWTLSName* self = new(ELeave) CWTLSName;
sl@0
    50
	CleanupStack::PushL(self);
sl@0
    51
	self->ConstructL(aBinaryData, aPos);
sl@0
    52
	return self;
sl@0
    53
	}
sl@0
    54
sl@0
    55
EXPORT_C CWTLSName* CWTLSName::NewL(const CWTLSName& aName)
sl@0
    56
	{
sl@0
    57
	CWTLSName* self = CWTLSName::NewLC(aName);
sl@0
    58
	CleanupStack::Pop();
sl@0
    59
	return self;
sl@0
    60
	}
sl@0
    61
sl@0
    62
EXPORT_C CWTLSName* CWTLSName::NewLC(const CWTLSName& aName)	
sl@0
    63
	{
sl@0
    64
	CWTLSName* self = new(ELeave) CWTLSName;
sl@0
    65
	CleanupStack::PushL(self);
sl@0
    66
	self->ConstructL(aName);
sl@0
    67
	return self;
sl@0
    68
	}
sl@0
    69
sl@0
    70
CWTLSName::CWTLSName() 	
sl@0
    71
	{
sl@0
    72
	}
sl@0
    73
sl@0
    74
void CWTLSName::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
    75
	{
sl@0
    76
	if ((aBinaryData.Length() - aPos) < 1)
sl@0
    77
		{
sl@0
    78
		User::Leave(KErrArgument);
sl@0
    79
		}
sl@0
    80
	iNameType = aBinaryData[aPos];
sl@0
    81
	aPos++;
sl@0
    82
	switch(iNameType)
sl@0
    83
		{
sl@0
    84
		case EWTLSText:
sl@0
    85
			{
sl@0
    86
			AllocTextDataL(aBinaryData, aPos);
sl@0
    87
			break;
sl@0
    88
			}
sl@0
    89
		case EWTLSX500DN:
sl@0
    90
			{
sl@0
    91
			AllocNameDataL(aBinaryData, aPos);
sl@0
    92
			break;
sl@0
    93
			}
sl@0
    94
		default:
sl@0
    95
			{
sl@0
    96
			User::Leave(KErrNotSupported);
sl@0
    97
			}
sl@0
    98
		}
sl@0
    99
	}
sl@0
   100
sl@0
   101
void CWTLSName::ConstructL(const CWTLSName& aName)
sl@0
   102
	{
sl@0
   103
	iNameType = aName.iNameType;
sl@0
   104
	iNameData = aName.iNameData->AllocL();
sl@0
   105
	}
sl@0
   106
sl@0
   107
EXPORT_C CWTLSName::~CWTLSName() 	
sl@0
   108
	{
sl@0
   109
	delete iNameData;
sl@0
   110
	}
sl@0
   111
sl@0
   112
void CWTLSName::AllocTextDataL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   113
	{
sl@0
   114
	if ((aBinaryData.Length() - aPos) < KWTLSTextHeaderLength)
sl@0
   115
		{
sl@0
   116
		User::Leave(KErrArgument);
sl@0
   117
		}
sl@0
   118
	TInt nameLength = (aBinaryData[aPos+2] + KWTLSTextHeaderLength);
sl@0
   119
	if ((aBinaryData.Length() ) < (aPos+nameLength))
sl@0
   120
		{
sl@0
   121
		User::Leave(KErrArgument);
sl@0
   122
		}
sl@0
   123
	iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
sl@0
   124
	aPos += nameLength;
sl@0
   125
	}
sl@0
   126
sl@0
   127
void CWTLSName::AllocNameDataL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   128
	{
sl@0
   129
	if ((aBinaryData.Length() - aPos) < 1)
sl@0
   130
		{
sl@0
   131
		User::Leave(KErrArgument);
sl@0
   132
		}
sl@0
   133
	TUint8 nameLength = aBinaryData[aPos];
sl@0
   134
	aPos++;
sl@0
   135
	if (aBinaryData.Length() - (aPos + nameLength) < 0)
sl@0
   136
		{
sl@0
   137
		User::Leave(KErrArgument);
sl@0
   138
		}
sl@0
   139
	iNameData = aBinaryData.Mid(aPos, nameLength).AllocL();
sl@0
   140
	aPos += nameLength;
sl@0
   141
	}
sl@0
   142
sl@0
   143
EXPORT_C TBool CWTLSName::ExactMatchL(const CWTLSName& aName) const	
sl@0
   144
	{		
sl@0
   145
//hmmm, in the absence of any matching rules, just match the bytes...
sl@0
   146
 	return (*(iNameData) == *(aName.iNameData));
sl@0
   147
	}
sl@0
   148
sl@0
   149
EXPORT_C TWTLSNameType CWTLSName::NameType() const
sl@0
   150
	{
sl@0
   151
	return iNameType;
sl@0
   152
	}
sl@0
   153
sl@0
   154
EXPORT_C TPtrC8 CWTLSName::NameData() const
sl@0
   155
	{
sl@0
   156
	return *iNameData;
sl@0
   157
	}
sl@0
   158
sl@0
   159
EXPORT_C HBufC* CWTLSName::DisplayNameL() const
sl@0
   160
	{
sl@0
   161
	switch (iNameType)
sl@0
   162
		{
sl@0
   163
		case EWTLSText:
sl@0
   164
			{
sl@0
   165
			CWTLSStructuredText* sText = NULL;
sl@0
   166
			TRAPD(err, sText = CWTLSStructuredText::NewL(*iNameData));
sl@0
   167
			if (err != KErrNone)
sl@0
   168
				{
sl@0
   169
				if (err != KErrArgument)
sl@0
   170
					{
sl@0
   171
					User::Leave(err);
sl@0
   172
					}
sl@0
   173
				else
sl@0
   174
					{
sl@0
   175
					CWTLSText* text = CWTLSText::NewLC(*iNameData);
sl@0
   176
					HBufC* res = text->Name().AllocL();
sl@0
   177
					CleanupStack::PopAndDestroy();//text
sl@0
   178
					return res;
sl@0
   179
					}
sl@0
   180
				}
sl@0
   181
			else
sl@0
   182
				{
sl@0
   183
				CleanupStack::PushL(sText);
sl@0
   184
				HBufC* res = sText->DisplayNameL();
sl@0
   185
				CleanupStack::PopAndDestroy();//sText
sl@0
   186
				return res;
sl@0
   187
				}
sl@0
   188
			}
sl@0
   189
		case EWTLSX500DN:
sl@0
   190
			{
sl@0
   191
			CX500DistinguishedName* dN = CX500DistinguishedName::NewLC(*iNameData);
sl@0
   192
			HBufC* res = dN->DisplayNameL();
sl@0
   193
			CleanupStack::PopAndDestroy();//dN
sl@0
   194
			return res;
sl@0
   195
			}
sl@0
   196
		default:
sl@0
   197
			{
sl@0
   198
			User::Leave(KErrNotSupported);
sl@0
   199
			return NULL;//never gets to here...
sl@0
   200
			}
sl@0
   201
		}
sl@0
   202
	}
sl@0
   203
sl@0
   204
//************************************************************************//
sl@0
   205
//text name
sl@0
   206
EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData)
sl@0
   207
	{
sl@0
   208
	TInt pos = 0;
sl@0
   209
	return CWTLSText::NewL(aBinaryData, pos);
sl@0
   210
	}
sl@0
   211
sl@0
   212
EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData)
sl@0
   213
	{
sl@0
   214
	TInt pos = 0;
sl@0
   215
	return CWTLSText::NewLC(aBinaryData, pos);
sl@0
   216
	}
sl@0
   217
sl@0
   218
EXPORT_C CWTLSText* CWTLSText::NewL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   219
	{
sl@0
   220
	CWTLSText* self = CWTLSText::NewLC(aBinaryData, aPos);
sl@0
   221
	CleanupStack::Pop();
sl@0
   222
	return self;
sl@0
   223
	}
sl@0
   224
sl@0
   225
EXPORT_C CWTLSText* CWTLSText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   226
	{
sl@0
   227
	CWTLSText* self = new(ELeave) CWTLSText;
sl@0
   228
	CleanupStack::PushL(self);
sl@0
   229
	self->ConstructL(aBinaryData, aPos);
sl@0
   230
	return self;
sl@0
   231
	}
sl@0
   232
sl@0
   233
EXPORT_C CWTLSText::~CWTLSText() 	
sl@0
   234
	{
sl@0
   235
	delete iName;
sl@0
   236
	}
sl@0
   237
sl@0
   238
EXPORT_C TBool CWTLSText::ExactMatchL(const CWTLSText& aName) const
sl@0
   239
	{
sl@0
   240
//subtle difference between this byte-match and 
sl@0
   241
//CWTLSName::ExactMatchL(...) is that this should successfully match 2 names that 
sl@0
   242
//are the same which were encoded using different character sets...
sl@0
   243
	return (*iName == *(aName.iName));
sl@0
   244
	}
sl@0
   245
sl@0
   246
EXPORT_C TPtrC CWTLSText::Name() const
sl@0
   247
	{
sl@0
   248
	return *iName;
sl@0
   249
	}
sl@0
   250
sl@0
   251
EXPORT_C TWTLSCharSet CWTLSText::CharacterSet() const
sl@0
   252
	{
sl@0
   253
	return iCharacterSet;
sl@0
   254
	}
sl@0
   255
sl@0
   256
CWTLSText::CWTLSText()
sl@0
   257
	{
sl@0
   258
	}
sl@0
   259
sl@0
   260
void CWTLSText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   261
	{
sl@0
   262
	if ((aBinaryData.Length() - aPos) < 3)
sl@0
   263
		{
sl@0
   264
		User::Leave(KErrArgument);
sl@0
   265
		}
sl@0
   266
	TWTLSDecUnsignedInteger decInt;
sl@0
   267
	iCharacterSet = decInt.DecodeShortL(aBinaryData, aPos, 2);
sl@0
   268
	TUint8 nameLength = aBinaryData[aPos];
sl@0
   269
	aPos++;
sl@0
   270
	if (aBinaryData.Length() < (aPos + nameLength))
sl@0
   271
		{
sl@0
   272
		User::Leave(KErrArgument);
sl@0
   273
		}
sl@0
   274
	TPtrC8 ptr = aBinaryData.Mid(aPos, nameLength);
sl@0
   275
	//only works for latin-1 here...
sl@0
   276
	iName = HBufC::NewL(ptr.Length());
sl@0
   277
	switch (iCharacterSet)
sl@0
   278
		{
sl@0
   279
		case KWTLSLatin1CharSet://=latin-1
sl@0
   280
			{
sl@0
   281
			TPtr pRes = iName->Des();
sl@0
   282
			pRes.Copy(ptr);
sl@0
   283
			aPos+=nameLength;
sl@0
   284
			break;
sl@0
   285
			}
sl@0
   286
		case KWTLSUTF8CharSet:
sl@0
   287
			{
sl@0
   288
			TPtr pRes = iName->Des();
sl@0
   289
			User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(pRes, ptr));	
sl@0
   290
			break;
sl@0
   291
			}
sl@0
   292
		default:
sl@0
   293
			{
sl@0
   294
			User::Leave(KErrNotSupported);
sl@0
   295
			}
sl@0
   296
		}
sl@0
   297
	}
sl@0
   298
sl@0
   299
TWTLSStructuredTextField::TWTLSStructuredTextField(const TDesC& aType, const TDesC& aValue)
sl@0
   300
	:iType(aType), iValue(aValue)
sl@0
   301
	{
sl@0
   302
	}
sl@0
   303
sl@0
   304
EXPORT_C TPtrC TWTLSStructuredTextField::Type() const
sl@0
   305
	{
sl@0
   306
	return iType;
sl@0
   307
	}
sl@0
   308
sl@0
   309
EXPORT_C TPtrC TWTLSStructuredTextField::Value() const
sl@0
   310
	{
sl@0
   311
	return iValue;
sl@0
   312
	}
sl@0
   313
sl@0
   314
//Structured text class
sl@0
   315
EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData)
sl@0
   316
	{
sl@0
   317
	TInt pos = 0;
sl@0
   318
	return CWTLSStructuredText::NewL(aBinaryData, pos);
sl@0
   319
	}
sl@0
   320
sl@0
   321
EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData)
sl@0
   322
	{
sl@0
   323
	TInt pos = 0;
sl@0
   324
	return CWTLSStructuredText::NewLC(aBinaryData, pos);
sl@0
   325
	}
sl@0
   326
sl@0
   327
EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   328
	{
sl@0
   329
	CWTLSStructuredText* self = CWTLSStructuredText::NewLC(aBinaryData, aPos);
sl@0
   330
	CleanupStack::Pop();
sl@0
   331
	return self;
sl@0
   332
	}
sl@0
   333
sl@0
   334
EXPORT_C CWTLSStructuredText* CWTLSStructuredText::NewLC(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   335
	{
sl@0
   336
	CWTLSStructuredText* self = new(ELeave) CWTLSStructuredText;
sl@0
   337
	CleanupStack::PushL(self);
sl@0
   338
	self->ConstructL(aBinaryData, aPos);
sl@0
   339
	return self;
sl@0
   340
	}
sl@0
   341
sl@0
   342
EXPORT_C CWTLSStructuredText::~CWTLSStructuredText()
sl@0
   343
	{
sl@0
   344
	delete iFields;
sl@0
   345
	}
sl@0
   346
sl@0
   347
EXPORT_C HBufC* CWTLSStructuredText::DisplayNameL() const
sl@0
   348
	{
sl@0
   349
	if (iFields->Count() > 3)
sl@0
   350
		{
sl@0
   351
		return iFields->At(3).Value().AllocL();
sl@0
   352
		}
sl@0
   353
	else
sl@0
   354
		{
sl@0
   355
		return iFields->At(1).Value().AllocL();
sl@0
   356
		}
sl@0
   357
	}
sl@0
   358
sl@0
   359
	//accessors for defined fields
sl@0
   360
EXPORT_C TPtrC CWTLSStructuredText::ServiceName() const
sl@0
   361
	{
sl@0
   362
	//construction ensures iFields must have at least 3 elements
sl@0
   363
	return iFields->At(0).Value();
sl@0
   364
	}
sl@0
   365
sl@0
   366
EXPORT_C TPtrC CWTLSStructuredText::Organization() const
sl@0
   367
	{
sl@0
   368
	//construction ensures iFields must have at least 3 elements
sl@0
   369
	return iFields->At(1).Value();
sl@0
   370
	}
sl@0
   371
sl@0
   372
EXPORT_C TPtrC CWTLSStructuredText::Country() const
sl@0
   373
	{
sl@0
   374
	//construction ensures iFields must have at least 3 elements
sl@0
   375
	return iFields->At(2).Value();
sl@0
   376
	}
sl@0
   377
sl@0
   378
EXPORT_C TInt CWTLSStructuredText::Count() const
sl@0
   379
	{
sl@0
   380
	return iFields->Count();
sl@0
   381
	}
sl@0
   382
sl@0
   383
EXPORT_C const TWTLSStructuredTextField* CWTLSStructuredText::FieldByName(const TDesC& aType) const
sl@0
   384
	{
sl@0
   385
	TInt count = iFields->Count();
sl@0
   386
	for (TInt i = 0; i < count; i++)
sl@0
   387
		{
sl@0
   388
		TWTLSStructuredTextField* field = &(iFields->At(i));
sl@0
   389
		if (field->Type() == aType)
sl@0
   390
			{
sl@0
   391
			return field;
sl@0
   392
			}
sl@0
   393
		}
sl@0
   394
	return NULL;
sl@0
   395
	}
sl@0
   396
sl@0
   397
EXPORT_C const TWTLSStructuredTextField& CWTLSStructuredText::FieldByIndex(TInt aIndex) const
sl@0
   398
	{
sl@0
   399
	return iFields->At(aIndex);
sl@0
   400
	}
sl@0
   401
sl@0
   402
CWTLSStructuredText::CWTLSStructuredText()
sl@0
   403
	{
sl@0
   404
	}
sl@0
   405
sl@0
   406
void CWTLSStructuredText::ConstructL(const TDesC8& aBinaryData, TInt& aPos)
sl@0
   407
	{
sl@0
   408
	CWTLSText::ConstructL(aBinaryData, aPos);
sl@0
   409
	iFields = new(ELeave) CArrayFixFlat<TWTLSStructuredTextField> (4);
sl@0
   410
	TInt pos = 0;
sl@0
   411
	TInt end = iName->Length();
sl@0
   412
	AddFieldValueL(KWTLSServiceName, pos);
sl@0
   413
	AddFieldValueL(KWTLSOrganizationName, pos);
sl@0
   414
	AddFieldValueL(KWTLSCountryName, pos);
sl@0
   415
	if (pos < end)
sl@0
   416
		{
sl@0
   417
		AddFieldValueL(KWTLSCommonName, pos);
sl@0
   418
		}
sl@0
   419
	while (pos < end)
sl@0
   420
		{
sl@0
   421
		AddFieldL(pos);
sl@0
   422
		}
sl@0
   423
	}
sl@0
   424
sl@0
   425
void CWTLSStructuredText::AddFieldValueL(const TDesC& aFieldName, TInt& aPos)
sl@0
   426
	{
sl@0
   427
	TPtrC startOfData = iName->Right(iName->Length() - aPos);
sl@0
   428
	TPtrC value = GetFieldL(startOfData, aPos);
sl@0
   429
	TWTLSStructuredTextField field(aFieldName, value);
sl@0
   430
	iFields->AppendL(field);
sl@0
   431
	}
sl@0
   432
sl@0
   433
void CWTLSStructuredText::AddFieldL(TInt& aPos)
sl@0
   434
	{
sl@0
   435
	TPtrC startOfData = iName->Right(iName->Length() - aPos);
sl@0
   436
	TPtrC fieldData = GetFieldL(startOfData, aPos);
sl@0
   437
	TInt fieldLength = fieldData.Length();
sl@0
   438
	TInt endType = fieldData.FindF(KWTLSStructuredTextAssignmentCharacter);
sl@0
   439
	if ((endType == KErrNotFound) || ((endType+1) == fieldLength))
sl@0
   440
		{
sl@0
   441
		User::Leave(KErrArgument);
sl@0
   442
		}
sl@0
   443
	TPtrC type = fieldData.Left(endType);
sl@0
   444
	TPtrC value = fieldData.Right(	fieldLength - (endType+1)	);
sl@0
   445
	TWTLSStructuredTextField field(type, value);
sl@0
   446
	iFields->AppendL(field);
sl@0
   447
	}
sl@0
   448
sl@0
   449
TPtrC CWTLSStructuredText::GetFieldL(TDesC& aString, TInt& aPos)
sl@0
   450
	{
sl@0
   451
//aString = where we've got up to
sl@0
   452
//aPos = start of this chunk of name data
sl@0
   453
	TInt length = 0;
sl@0
   454
	TBool done = GetSubFieldL(aString, length);
sl@0
   455
	while (!done)
sl@0
   456
		{
sl@0
   457
		TPtrC remainder = aString.Right(aString.Length() - (length));
sl@0
   458
		TInt increment = 0;
sl@0
   459
		done = GetSubFieldL(remainder, increment);
sl@0
   460
		length += increment;
sl@0
   461
		}
sl@0
   462
	if (length == 0)
sl@0
   463
		{
sl@0
   464
		//disallow zero-length field values
sl@0
   465
		User::Leave(KErrArgument);
sl@0
   466
		}
sl@0
   467
	aPos += length;
sl@0
   468
	if (length < aString.Length())
sl@0
   469
		{
sl@0
   470
		//if we're not on the last field, skip the ';' character
sl@0
   471
		aPos++;
sl@0
   472
		}
sl@0
   473
	return aString.Left(length);
sl@0
   474
	}
sl@0
   475
sl@0
   476
TBool CWTLSStructuredText::GetSubFieldL(TDesC& aString, TInt& aPos)
sl@0
   477
	{
sl@0
   478
//fields in structured text are separated by ';'. If this character appears 
sl@0
   479
//in the field text it's represented by ';;'.  so, the string 'symbian;systems' would
sl@0
   480
//be encoded as 'symbian;;systems'. 
sl@0
   481
sl@0
   482
//starting at the start of aString, this function sets 'aPos' to the position after the 
sl@0
   483
//first occurrence of ';' in aString. If the character following ';' is also ';' it returns 
sl@0
   484
//EFalse (meaning, this sub-field isn't a whole field), otherwise it returns ETrue.
sl@0
   485
sl@0
   486
	aPos = aString.FindF(KWTLSStructuredTextFieldSeparator);	
sl@0
   487
	if (aPos == KErrNotFound)
sl@0
   488
		{
sl@0
   489
		aPos = aString.Length();
sl@0
   490
		}
sl@0
   491
	else
sl@0
   492
		{		
sl@0
   493
		//separator char mustn't be last char
sl@0
   494
		if (aPos == (aString.Length() -1))
sl@0
   495
			{
sl@0
   496
			User::Leave(KErrArgument);
sl@0
   497
			}
sl@0
   498
		else
sl@0
   499
			{
sl@0
   500
			//if the next char is ';', skip it and return EFalse
sl@0
   501
			TPtrC next = aString.Mid(aPos + 1, 1);
sl@0
   502
			if (next == KWTLSStructuredTextFieldSeparator)
sl@0
   503
				{
sl@0
   504
				aPos++;
sl@0
   505
				return EFalse;
sl@0
   506
				}
sl@0
   507
			//if it isn't, that's the end of the field
sl@0
   508
			}
sl@0
   509
		}
sl@0
   510
	return ETrue;
sl@0
   511
	}