os/ossrv/genericservices/httputils/wspcodec/WSPDecoder.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include <e32base.h>
sl@0
    17
#include <stringpool.h>
sl@0
    18
#include <wspdecoder.h>
sl@0
    19
sl@0
    20
// Constants
sl@0
    21
const TUint8 KWapQuote = 0x7F;
sl@0
    22
const TUint8 KCarryBitMask = 0x80;
sl@0
    23
#define KTopBitMask KCarryBitMask
sl@0
    24
const TUint8 KTop3BitSet = 0x70;
sl@0
    25
const TUint8 KQuoteChar = '\"';
sl@0
    26
sl@0
    27
// Panic category
sl@0
    28
_LIT(KUriPanicCategory,"WSPDECODER");
sl@0
    29
sl@0
    30
sl@0
    31
//***********************************************************************
sl@0
    32
//	TWspHeaderSegmenter
sl@0
    33
//**********************************************************************/
sl@0
    34
sl@0
    35
sl@0
    36
/**
sl@0
    37
  NextL iterates through the buffer.  Each call returns a TWspField in the paramater.
sl@0
    38
sl@0
    39
  @param aHeader Out - a TWspField containing the header <name,value> pair.  
sl@0
    40
  @warning The TWspField::iHdrName will be opened internally.
sl@0
    41
			It must be closed by the caller before this class is destroyed.
sl@0
    42
  @return	KErrNone if next field is returned
sl@0
    43
			KErrNotFound at the end of the buffer - no TWspField param returned
sl@0
    44
			KErrCorrupt if segmenting does not parse correctly
sl@0
    45
  @leave	RStringPool::OpenFStringL StringPool leave code if opening string fails.
sl@0
    46
*/
sl@0
    47
EXPORT_C TInt TWspHeaderSegmenter::NextL(TWspField& aHeader)
sl@0
    48
	{
sl@0
    49
	// have we run out of buffer?
sl@0
    50
	if (iOffset >= iBuffer.Length())
sl@0
    51
		return KErrNotFound;
sl@0
    52
sl@0
    53
	// Set decoder to current buffer
sl@0
    54
	TWspPrimitiveDecoder decoder(iBuffer.Mid(iOffset));
sl@0
    55
	TInt bufLen = 0;
sl@0
    56
	
sl@0
    57
sl@0
    58
	// Get the Field Name 
sl@0
    59
	switch(decoder.VarType())
sl@0
    60
		{
sl@0
    61
		case TWspPrimitiveDecoder::EString:
sl@0
    62
			{
sl@0
    63
			TPtrC8 name;
sl@0
    64
			bufLen = decoder.String(name);
sl@0
    65
			if (bufLen < KErrNone) return bufLen;
sl@0
    66
			aHeader.iHdrName = iPool.OpenFStringL(name);
sl@0
    67
			}
sl@0
    68
			break;
sl@0
    69
sl@0
    70
		case TWspPrimitiveDecoder::E7BitVal:
sl@0
    71
			{
sl@0
    72
			TUint8 name;
sl@0
    73
			bufLen = decoder.Val7Bit(name);
sl@0
    74
			if (bufLen < KErrNone) return bufLen;
sl@0
    75
			
sl@0
    76
			aHeader.iHdrName = iPool.StringF(name, iStringTable);
sl@0
    77
			}
sl@0
    78
			break;
sl@0
    79
sl@0
    80
		default:	// header name can't be anything else
sl@0
    81
			return KErrCorrupt;
sl@0
    82
		}
sl@0
    83
	
sl@0
    84
	// move our pointer past header name
sl@0
    85
	iOffset += bufLen;
sl@0
    86
sl@0
    87
	
sl@0
    88
	// Get the value buffer by figuring out the type, then set the pointer to span the entire
sl@0
    89
	// value.  Note - further parsing will happen later to pull out specific value data.
sl@0
    90
	switch(decoder.VarType())
sl@0
    91
		{
sl@0
    92
		case TWspPrimitiveDecoder::ELengthVal:
sl@0
    93
			{
sl@0
    94
			TInt len;
sl@0
    95
			bufLen = decoder.LengthVal(len);
sl@0
    96
			bufLen += len;		
sl@0
    97
			}
sl@0
    98
			break;
sl@0
    99
		case TWspPrimitiveDecoder::EQuotedString:
sl@0
   100
		case TWspPrimitiveDecoder::EString:
sl@0
   101
			{
sl@0
   102
			TPtrC8 strBuf;
sl@0
   103
			bufLen = decoder.String(strBuf);
sl@0
   104
			}
sl@0
   105
			break;
sl@0
   106
		case TWspPrimitiveDecoder::E7BitVal:
sl@0
   107
			bufLen = 1;
sl@0
   108
			break;
sl@0
   109
		default:
sl@0
   110
			return KErrCorrupt;
sl@0
   111
		}
sl@0
   112
	
sl@0
   113
	if (bufLen < 0) 
sl@0
   114
		return bufLen;
sl@0
   115
sl@0
   116
	if (iOffset + bufLen > iBuffer.Length())
sl@0
   117
          return KErrCorrupt;
sl@0
   118
sl@0
   119
	aHeader.iValBuffer.Set(iBuffer.Mid(iOffset, bufLen));
sl@0
   120
	iOffset += bufLen;
sl@0
   121
	return KErrNone;
sl@0
   122
	}
sl@0
   123
sl@0
   124
sl@0
   125
 //
sl@0
   126
 // WAP-WSP 8.4.1.2
sl@0
   127
 //
sl@0
   128
sl@0
   129
/**
sl@0
   130
	Looks at the byte currently pointed at in this buffer and returns the type.
sl@0
   131
	
sl@0
   132
	@return TWspHeaderType - the type of this data octet
sl@0
   133
*/
sl@0
   134
EXPORT_C TWspPrimitiveDecoder::TWspHeaderType TWspPrimitiveDecoder::VarType() const
sl@0
   135
	{
sl@0
   136
	TWspHeaderType type = ENotSet;
sl@0
   137
	
sl@0
   138
	// Check that the offset has not overflowed the buffer
sl@0
   139
	if( iOffset >= iBuffer.Length() )
sl@0
   140
		return type;
sl@0
   141
sl@0
   142
	TInt octet = iBuffer[iOffset];
sl@0
   143
sl@0
   144
	if (octet >= 0 && octet <= 31)
sl@0
   145
		type = ELengthVal;
sl@0
   146
	else if (octet == 34)
sl@0
   147
		type = EQuotedString;
sl@0
   148
	else if (octet >= 32 && octet <= 127)
sl@0
   149
		type = EString;
sl@0
   150
	else if (octet >= 128 && octet <= 255)
sl@0
   151
		type = E7BitVal;
sl@0
   152
sl@0
   153
	return type;
sl@0
   154
	}
sl@0
   155
sl@0
   156
sl@0
   157
/**
sl@0
   158
	Returns length of the data following this byte.  
sl@0
   159
	
sl@0
   160
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
sl@0
   161
	@post internal offset gets updated to move past this primitive 
sl@0
   162
	@param aVal Out - the length encoded in this byte that indicates the size of the
sl@0
   163
		  	     data that follows.
sl@0
   164
	@return postive number indicating the number of bytes read from the buffer
sl@0
   165
			KErrCorrupt if data is not formatted correctly.
sl@0
   166
*/
sl@0
   167
EXPORT_C TInt TWspPrimitiveDecoder::LengthVal(TInt& aVal)
sl@0
   168
	{
sl@0
   169
	// have we run out of buffer?
sl@0
   170
	if (iOffset >= iBuffer.Length())
sl@0
   171
		return KErrCorrupt;
sl@0
   172
sl@0
   173
	TInt bufLen = 0;
sl@0
   174
	aVal = iBuffer[iOffset++];
sl@0
   175
sl@0
   176
	if (aVal == 31)
sl@0
   177
		{
sl@0
   178
		TUint32 uintVarLen = 0;
sl@0
   179
		bufLen = UintVar(uintVarLen);
sl@0
   180
		if (bufLen < KErrNone) return bufLen;
sl@0
   181
		aVal = (TInt)uintVarLen;
sl@0
   182
		}
sl@0
   183
sl@0
   184
	// add the 1 byte read at to get first aVal
sl@0
   185
	++bufLen;
sl@0
   186
	return bufLen;
sl@0
   187
	}
sl@0
   188
sl@0
   189
sl@0
   190
/**
sl@0
   191
   Returns a TPtrC holding the string the buffer currently points at without the NULL 
sl@0
   192
   termination. If the String type is a quoted string then the quotes are not included 
sl@0
   193
   in the returned buffer.
sl@0
   194
   
sl@0
   195
   @pre iBuffer[iOffset] must be valid, VarType() == TWspType::EString
sl@0
   196
   @post internal offset gets updated to move past this primitive 
sl@0
   197
   @param aString Out - the string
sl@0
   198
   @return postive number indicating the number of bytes read from the buffer
sl@0
   199
   		  KErrCorrupt if data is not formatted correctly.
sl@0
   200
*/
sl@0
   201
EXPORT_C TInt TWspPrimitiveDecoder::String(TPtrC8& aString)
sl@0
   202
	{
sl@0
   203
	TWspHeaderType type = VarType();
sl@0
   204
	if( type != EString && type != EQuotedString)
sl@0
   205
		return KErrCorrupt;
sl@0
   206
sl@0
   207
	TInt nullIndex = iBuffer.Mid(iOffset).Locate('\0');
sl@0
   208
	if( nullIndex == KErrNotFound )
sl@0
   209
		return KErrCorrupt;
sl@0
   210
sl@0
   211
	// Set buffer to data not including the NULL terminator
sl@0
   212
	TPtrC8 buf = iBuffer.Mid(iOffset, nullIndex);
sl@0
   213
sl@0
   214
	// is there a WAP Quote (0x7F) or a " at the start - step over it
sl@0
   215
	TInt bufferOffset = 0;
sl@0
   216
	const TUint8 firstByte = iBuffer[iOffset];
sl@0
   217
	if( firstByte == KQuoteChar || firstByte == KWapQuote )
sl@0
   218
		++bufferOffset;
sl@0
   219
sl@0
   220
	// Set the descriptor with the correct buffer segment
sl@0
   221
	aString.Set(buf.Mid(bufferOffset));
sl@0
   222
sl@0
   223
	// Step over the NULL
sl@0
   224
	++nullIndex;
sl@0
   225
sl@0
   226
	// update the offset
sl@0
   227
	iOffset += nullIndex;
sl@0
   228
sl@0
   229
	return nullIndex;
sl@0
   230
	} 
sl@0
   231
sl@0
   232
/**
sl@0
   233
	Returns a token, a short int or an octet value with the top bit cleared
sl@0
   234
	
sl@0
   235
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::E7BitVal
sl@0
   236
	@post internal offset gets updated to move past this primitive 
sl@0
   237
	@param aVal Out - the 7 bit value with top bit cleared
sl@0
   238
	@return postive number indicating the number of bytes read from the buffer
sl@0
   239
		    KErrCorrupt if data is not formatted correctly.
sl@0
   240
*/
sl@0
   241
EXPORT_C TInt TWspPrimitiveDecoder::Val7Bit(TUint8& aVal)
sl@0
   242
	{
sl@0
   243
	// have we run out of buffer?
sl@0
   244
	if (iOffset >= iBuffer.Length())
sl@0
   245
		return KErrCorrupt;
sl@0
   246
sl@0
   247
	aVal = (TUint8)(iBuffer[iOffset] & KWapQuote);
sl@0
   248
	++iOffset;
sl@0
   249
sl@0
   250
	// 1 byte read
sl@0
   251
	return 1;
sl@0
   252
	}
sl@0
   253
sl@0
   254
sl@0
   255
/**
sl@0
   256
	Returns an Integer - could be short or long.
sl@0
   257
	
sl@0
   258
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
sl@0
   259
		   VarType() == TWspHeaderType::E7BitVal
sl@0
   260
	@post internal offset gets updated to move past this primitive 
sl@0
   261
	@param aVal Out - the long int
sl@0
   262
	@return postive number indicating the number of bytes read from the buffer
sl@0
   263
			  KErrCorrupt if data is not formatted correctly.
sl@0
   264
*/
sl@0
   265
EXPORT_C TInt TWspPrimitiveDecoder::Integer(TUint32& aVal)
sl@0
   266
	{
sl@0
   267
	// have we run out of buffer?
sl@0
   268
	if (iOffset >= iBuffer.Length())
sl@0
   269
		return KErrCorrupt;
sl@0
   270
sl@0
   271
	TInt bufLen = 0;
sl@0
   272
sl@0
   273
	// read the first byte
sl@0
   274
	aVal = iBuffer[iOffset];
sl@0
   275
	
sl@0
   276
	// short integers have the top bit set
sl@0
   277
	if (aVal & KTopBitMask)
sl@0
   278
		{
sl@0
   279
		aVal &= KWapQuote;
sl@0
   280
		++iOffset;
sl@0
   281
		++bufLen;
sl@0
   282
		}
sl@0
   283
	else
sl@0
   284
		{
sl@0
   285
		bufLen = LongInt(aVal);
sl@0
   286
		}
sl@0
   287
sl@0
   288
	return bufLen;
sl@0
   289
	}
sl@0
   290
sl@0
   291
/**
sl@0
   292
	Returns a long int the buffer is currently pointing at. 
sl@0
   293
	
sl@0
   294
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal  
sl@0
   295
	@post internal offset gets updated to move past this primitive 
sl@0
   296
	@param aVal Out - the long int
sl@0
   297
	@return postive number indicating the number of bytes read from the buffer
sl@0
   298
		  KErrCorrupt if data is not formatted correctly.
sl@0
   299
*/
sl@0
   300
EXPORT_C TInt TWspPrimitiveDecoder::LongInt(TUint32& aVal)
sl@0
   301
	{
sl@0
   302
	// have we run out of buffer?
sl@0
   303
	if (iOffset >= iBuffer.Length())
sl@0
   304
		return KErrCorrupt;
sl@0
   305
sl@0
   306
	__ASSERT_DEBUG(aVal <= KMaxTUint, User::Panic(KUriPanicCategory, EWspDecoderLongIntOverflow));
sl@0
   307
	// initialize
sl@0
   308
	aVal = 0;
sl@0
   309
sl@0
   310
	// Get num bytes encoding [len] [byte1] ... [byten]
sl@0
   311
	// we are positioned at that location in the source descriptor
sl@0
   312
	TUint8 numBytes = 0;
sl@0
   313
	TInt bufLen = Val7Bit(numBytes);
sl@0
   314
	if (bufLen < KErrNone) return bufLen;
sl@0
   315
sl@0
   316
	// len can be up to 30 and verify we have enough buffer
sl@0
   317
	if (numBytes > 30 || numBytes > iBuffer.Mid(iOffset).Length())
sl@0
   318
		return KErrCorrupt;
sl@0
   319
	
sl@0
   320
	// Loop over the buffer, taking each byte and shifting it in count times.  
sl@0
   321
	for (TInt count = 0; count < numBytes ; ++count)
sl@0
   322
		aVal = (aVal << 8) + iBuffer[iOffset++];
sl@0
   323
	
sl@0
   324
	return (bufLen + numBytes);
sl@0
   325
	}
sl@0
   326
sl@0
   327
/**
sl@0
   328
	Returns a TUint32 
sl@0
   329
	
sl@0
   330
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
sl@0
   331
		   VarType() == TWspHeaderType::E7BitVal 
sl@0
   332
	@post internal offset gets updated to move past this primitive 
sl@0
   333
	@param aVal Out - the TUint32 decoded 
sl@0
   334
	@return postive number indicating the number of bytes read from the buffer
sl@0
   335
		    KErrCorrupt if data is not formatted correctly.
sl@0
   336
*/
sl@0
   337
EXPORT_C TInt TWspPrimitiveDecoder::UintVar(TUint32& aVal)
sl@0
   338
	{
sl@0
   339
	// have we run out of buffer?
sl@0
   340
	if (iOffset >= iBuffer.Length())
sl@0
   341
		return KErrCorrupt;
sl@0
   342
sl@0
   343
	// initialize return val
sl@0
   344
	aVal = 0;
sl@0
   345
sl@0
   346
	// maximum length for a uintvar is 5
sl@0
   347
	TInt lenLeft = Min(iBuffer.Mid(iOffset).Length(), 5);
sl@0
   348
sl@0
   349
	// get the first octet
sl@0
   350
	TUint8 byte = iBuffer[iOffset++];
sl@0
   351
	TInt numBytes = 1;
sl@0
   352
sl@0
   353
	--lenLeft;	
sl@0
   354
sl@0
   355
	// Check if any of the top 3 bits, ignoring the very top 'continue' bit, are set.  
sl@0
   356
	// Later if we see that this is a 5 byte number - we'll know it is corrupt.  
sl@0
   357
	// Encoding uses 7 bits/number 7x5=35 and we only support a maxiumum number 
sl@0
   358
	// of 32 bits.
sl@0
   359
	TBool topThreeBitsSet = byte & KTop3BitSet; 
sl@0
   360
	
sl@0
   361
	// copy over data from the byte into our return value (the top bit is a carry bit)
sl@0
   362
	aVal = byte & KWapQuote;
sl@0
   363
sl@0
   364
	// while the 'continue' bit is set and we have more data
sl@0
   365
	while ((byte & KCarryBitMask) && (lenLeft > 0))
sl@0
   366
		{
sl@0
   367
		// shift our last value up
sl@0
   368
		aVal <<= 7;
sl@0
   369
		// get the next byte
sl@0
   370
		byte = iBuffer[iOffset++];
sl@0
   371
		// copy it over to the lowest byte
sl@0
   372
		aVal |= byte & KWapQuote;
sl@0
   373
		--lenLeft;
sl@0
   374
		++numBytes;
sl@0
   375
		} 
sl@0
   376
sl@0
   377
	// last octet has continue bit set ... NOT allowed Or
sl@0
   378
	// this was encoded wrong - can't have a number bigger than 32 bits
sl@0
   379
	if ((byte & KCarryBitMask) || (numBytes == 5 && topThreeBitsSet))
sl@0
   380
		return KErrCorrupt;
sl@0
   381
sl@0
   382
	// number of bytes read
sl@0
   383
	return numBytes;
sl@0
   384
	}
sl@0
   385
sl@0
   386
sl@0
   387
/**
sl@0
   388
	Returns a formatted version string 
sl@0
   389
	
sl@0
   390
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal  
sl@0
   391
	@post internal offset gets updated to move past this primitive 
sl@0
   392
	@param aPool In - an opened string pool
sl@0
   393
	@param aVer Out - a formatted version string.  Caller must close this string.
sl@0
   394
	@return postive number indicating the number of bytes read from the buffer
sl@0
   395
		    KErrCorrupt if data is not formatted correctly.
sl@0
   396
*/
sl@0
   397
EXPORT_C TInt TWspPrimitiveDecoder::VersionL(RStringPool aPool, RStringF& aVer)
sl@0
   398
	{
sl@0
   399
	const TInt KMaxBufLength=5;
sl@0
   400
	TInt bufLen = 0;
sl@0
   401
	TInt byte = iBuffer[iOffset];
sl@0
   402
	if (!(byte & KTopBitMask))
sl@0
   403
		{
sl@0
   404
		TPtrC8 str;
sl@0
   405
		bufLen = String(str);
sl@0
   406
		if (bufLen < KErrNone) return KErrCorrupt;
sl@0
   407
		aVer = aPool.OpenFStringL(str);
sl@0
   408
		}
sl@0
   409
	else
sl@0
   410
		{
sl@0
   411
		// Major 0-7 , Minor 0-15 [xxx][yyyy]
sl@0
   412
		TUint8 val;
sl@0
   413
		bufLen = Val7Bit(val);
sl@0
   414
		if (bufLen < KErrNone) return KErrCorrupt;
sl@0
   415
sl@0
   416
sl@0
   417
		TInt minVer =  val & 0x0F;
sl@0
   418
		TInt majVer =  val & 0xF0;
sl@0
   419
		majVer >>= 4;
sl@0
   420
sl@0
   421
		if (majVer < 0 || majVer > 7)
sl@0
   422
			return KErrCorrupt;
sl@0
   423
sl@0
   424
		TBuf8<KMaxBufLength> buf;
sl@0
   425
		if (minVer == 0x0F)
sl@0
   426
			{
sl@0
   427
			_LIT8(KVersionFormat, "%D");
sl@0
   428
			buf.Format(KVersionFormat, majVer);
sl@0
   429
			}
sl@0
   430
		else
sl@0
   431
			{
sl@0
   432
			_LIT8(KVersionFormat, "%D.%D");
sl@0
   433
			buf.Format(KVersionFormat, majVer, minVer);
sl@0
   434
			}
sl@0
   435
			aVer = aPool.OpenFStringL(buf);
sl@0
   436
		}
sl@0
   437
sl@0
   438
	return bufLen;
sl@0
   439
	}
sl@0
   440
sl@0
   441
/**
sl@0
   442
	Returns a TDateTime offset from January 1, 1970 - WAP WSP Section 8.4.2.3 Panics if 
sl@0
   443
	the time val is greater then the maximum allowable integer size (32 bits).
sl@0
   444
	
sl@0
   445
	@pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal  
sl@0
   446
	@post internal offset gets updated to move past this primitive 
sl@0
   447
	@param aDateTime Out - a WAP Date
sl@0
   448
	@return postive number indicating the number of bytes read from the buffer
sl@0
   449
			  KErrCorrupt if data is not formatted correctly.
sl@0
   450
*/
sl@0
   451
EXPORT_C TInt TWspPrimitiveDecoder::Date(TDateTime& aDateTime)
sl@0
   452
	{
sl@0
   453
	TUint32 secVal;
sl@0
   454
	TInt bufLen = LongInt(secVal);
sl@0
   455
	__ASSERT_ALWAYS(bufLen <= KMaxTInt, User::Panic(KUriPanicCategory, EWspDecoderDateOverflow));
sl@0
   456
	if (bufLen < KErrNone) return bufLen;
sl@0
   457
sl@0
   458
	TDateTime dt(1970,EJanuary,0,0,0,0,0);
sl@0
   459
	TTime time(dt);
sl@0
   460
sl@0
   461
	TInt sec = STATIC_CAST(TInt, secVal);
sl@0
   462
	time += TTimeIntervalSeconds(sec);
sl@0
   463
	aDateTime = time.DateTime();
sl@0
   464
sl@0
   465
	return bufLen;
sl@0
   466
	}