--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/httputils/wspcodec/WSPDecoder.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,466 @@
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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 <e32base.h>
+#include <stringpool.h>
+#include <wspdecoder.h>
+
+// Constants
+const TUint8 KWapQuote = 0x7F;
+const TUint8 KCarryBitMask = 0x80;
+#define KTopBitMask KCarryBitMask
+const TUint8 KTop3BitSet = 0x70;
+const TUint8 KQuoteChar = '\"';
+
+// Panic category
+_LIT(KUriPanicCategory,"WSPDECODER");
+
+
+//***********************************************************************
+// TWspHeaderSegmenter
+//**********************************************************************/
+
+
+/**
+ NextL iterates through the buffer. Each call returns a TWspField in the paramater.
+
+ @param aHeader Out - a TWspField containing the header <name,value> pair.
+ @warning The TWspField::iHdrName will be opened internally.
+ It must be closed by the caller before this class is destroyed.
+ @return KErrNone if next field is returned
+ KErrNotFound at the end of the buffer - no TWspField param returned
+ KErrCorrupt if segmenting does not parse correctly
+ @leave RStringPool::OpenFStringL StringPool leave code if opening string fails.
+*/
+EXPORT_C TInt TWspHeaderSegmenter::NextL(TWspField& aHeader)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrNotFound;
+
+ // Set decoder to current buffer
+ TWspPrimitiveDecoder decoder(iBuffer.Mid(iOffset));
+ TInt bufLen = 0;
+
+
+ // Get the Field Name
+ switch(decoder.VarType())
+ {
+ case TWspPrimitiveDecoder::EString:
+ {
+ TPtrC8 name;
+ bufLen = decoder.String(name);
+ if (bufLen < KErrNone) return bufLen;
+ aHeader.iHdrName = iPool.OpenFStringL(name);
+ }
+ break;
+
+ case TWspPrimitiveDecoder::E7BitVal:
+ {
+ TUint8 name;
+ bufLen = decoder.Val7Bit(name);
+ if (bufLen < KErrNone) return bufLen;
+
+ aHeader.iHdrName = iPool.StringF(name, iStringTable);
+ }
+ break;
+
+ default: // header name can't be anything else
+ return KErrCorrupt;
+ }
+
+ // move our pointer past header name
+ iOffset += bufLen;
+
+
+ // Get the value buffer by figuring out the type, then set the pointer to span the entire
+ // value. Note - further parsing will happen later to pull out specific value data.
+ switch(decoder.VarType())
+ {
+ case TWspPrimitiveDecoder::ELengthVal:
+ {
+ TInt len;
+ bufLen = decoder.LengthVal(len);
+ bufLen += len;
+ }
+ break;
+ case TWspPrimitiveDecoder::EQuotedString:
+ case TWspPrimitiveDecoder::EString:
+ {
+ TPtrC8 strBuf;
+ bufLen = decoder.String(strBuf);
+ }
+ break;
+ case TWspPrimitiveDecoder::E7BitVal:
+ bufLen = 1;
+ break;
+ default:
+ return KErrCorrupt;
+ }
+
+ if (bufLen < 0)
+ return bufLen;
+
+ if (iOffset + bufLen > iBuffer.Length())
+ return KErrCorrupt;
+
+ aHeader.iValBuffer.Set(iBuffer.Mid(iOffset, bufLen));
+ iOffset += bufLen;
+ return KErrNone;
+ }
+
+
+ //
+ // WAP-WSP 8.4.1.2
+ //
+
+/**
+ Looks at the byte currently pointed at in this buffer and returns the type.
+
+ @return TWspHeaderType - the type of this data octet
+*/
+EXPORT_C TWspPrimitiveDecoder::TWspHeaderType TWspPrimitiveDecoder::VarType() const
+ {
+ TWspHeaderType type = ENotSet;
+
+ // Check that the offset has not overflowed the buffer
+ if( iOffset >= iBuffer.Length() )
+ return type;
+
+ TInt octet = iBuffer[iOffset];
+
+ if (octet >= 0 && octet <= 31)
+ type = ELengthVal;
+ else if (octet == 34)
+ type = EQuotedString;
+ else if (octet >= 32 && octet <= 127)
+ type = EString;
+ else if (octet >= 128 && octet <= 255)
+ type = E7BitVal;
+
+ return type;
+ }
+
+
+/**
+ Returns length of the data following this byte.
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
+ @post internal offset gets updated to move past this primitive
+ @param aVal Out - the length encoded in this byte that indicates the size of the
+ data that follows.
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::LengthVal(TInt& aVal)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrCorrupt;
+
+ TInt bufLen = 0;
+ aVal = iBuffer[iOffset++];
+
+ if (aVal == 31)
+ {
+ TUint32 uintVarLen = 0;
+ bufLen = UintVar(uintVarLen);
+ if (bufLen < KErrNone) return bufLen;
+ aVal = (TInt)uintVarLen;
+ }
+
+ // add the 1 byte read at to get first aVal
+ ++bufLen;
+ return bufLen;
+ }
+
+
+/**
+ Returns a TPtrC holding the string the buffer currently points at without the NULL
+ termination. If the String type is a quoted string then the quotes are not included
+ in the returned buffer.
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspType::EString
+ @post internal offset gets updated to move past this primitive
+ @param aString Out - the string
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::String(TPtrC8& aString)
+ {
+ TWspHeaderType type = VarType();
+ if( type != EString && type != EQuotedString)
+ return KErrCorrupt;
+
+ TInt nullIndex = iBuffer.Mid(iOffset).Locate('\0');
+ if( nullIndex == KErrNotFound )
+ return KErrCorrupt;
+
+ // Set buffer to data not including the NULL terminator
+ TPtrC8 buf = iBuffer.Mid(iOffset, nullIndex);
+
+ // is there a WAP Quote (0x7F) or a " at the start - step over it
+ TInt bufferOffset = 0;
+ const TUint8 firstByte = iBuffer[iOffset];
+ if( firstByte == KQuoteChar || firstByte == KWapQuote )
+ ++bufferOffset;
+
+ // Set the descriptor with the correct buffer segment
+ aString.Set(buf.Mid(bufferOffset));
+
+ // Step over the NULL
+ ++nullIndex;
+
+ // update the offset
+ iOffset += nullIndex;
+
+ return nullIndex;
+ }
+
+/**
+ Returns a token, a short int or an octet value with the top bit cleared
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::E7BitVal
+ @post internal offset gets updated to move past this primitive
+ @param aVal Out - the 7 bit value with top bit cleared
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::Val7Bit(TUint8& aVal)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrCorrupt;
+
+ aVal = (TUint8)(iBuffer[iOffset] & KWapQuote);
+ ++iOffset;
+
+ // 1 byte read
+ return 1;
+ }
+
+
+/**
+ Returns an Integer - could be short or long.
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
+ VarType() == TWspHeaderType::E7BitVal
+ @post internal offset gets updated to move past this primitive
+ @param aVal Out - the long int
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::Integer(TUint32& aVal)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrCorrupt;
+
+ TInt bufLen = 0;
+
+ // read the first byte
+ aVal = iBuffer[iOffset];
+
+ // short integers have the top bit set
+ if (aVal & KTopBitMask)
+ {
+ aVal &= KWapQuote;
+ ++iOffset;
+ ++bufLen;
+ }
+ else
+ {
+ bufLen = LongInt(aVal);
+ }
+
+ return bufLen;
+ }
+
+/**
+ Returns a long int the buffer is currently pointing at.
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
+ @post internal offset gets updated to move past this primitive
+ @param aVal Out - the long int
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::LongInt(TUint32& aVal)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrCorrupt;
+
+ __ASSERT_DEBUG(aVal <= KMaxTUint, User::Panic(KUriPanicCategory, EWspDecoderLongIntOverflow));
+ // initialize
+ aVal = 0;
+
+ // Get num bytes encoding [len] [byte1] ... [byten]
+ // we are positioned at that location in the source descriptor
+ TUint8 numBytes = 0;
+ TInt bufLen = Val7Bit(numBytes);
+ if (bufLen < KErrNone) return bufLen;
+
+ // len can be up to 30 and verify we have enough buffer
+ if (numBytes > 30 || numBytes > iBuffer.Mid(iOffset).Length())
+ return KErrCorrupt;
+
+ // Loop over the buffer, taking each byte and shifting it in count times.
+ for (TInt count = 0; count < numBytes ; ++count)
+ aVal = (aVal << 8) + iBuffer[iOffset++];
+
+ return (bufLen + numBytes);
+ }
+
+/**
+ Returns a TUint32
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
+ VarType() == TWspHeaderType::E7BitVal
+ @post internal offset gets updated to move past this primitive
+ @param aVal Out - the TUint32 decoded
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::UintVar(TUint32& aVal)
+ {
+ // have we run out of buffer?
+ if (iOffset >= iBuffer.Length())
+ return KErrCorrupt;
+
+ // initialize return val
+ aVal = 0;
+
+ // maximum length for a uintvar is 5
+ TInt lenLeft = Min(iBuffer.Mid(iOffset).Length(), 5);
+
+ // get the first octet
+ TUint8 byte = iBuffer[iOffset++];
+ TInt numBytes = 1;
+
+ --lenLeft;
+
+ // Check if any of the top 3 bits, ignoring the very top 'continue' bit, are set.
+ // Later if we see that this is a 5 byte number - we'll know it is corrupt.
+ // Encoding uses 7 bits/number 7x5=35 and we only support a maxiumum number
+ // of 32 bits.
+ TBool topThreeBitsSet = byte & KTop3BitSet;
+
+ // copy over data from the byte into our return value (the top bit is a carry bit)
+ aVal = byte & KWapQuote;
+
+ // while the 'continue' bit is set and we have more data
+ while ((byte & KCarryBitMask) && (lenLeft > 0))
+ {
+ // shift our last value up
+ aVal <<= 7;
+ // get the next byte
+ byte = iBuffer[iOffset++];
+ // copy it over to the lowest byte
+ aVal |= byte & KWapQuote;
+ --lenLeft;
+ ++numBytes;
+ }
+
+ // last octet has continue bit set ... NOT allowed Or
+ // this was encoded wrong - can't have a number bigger than 32 bits
+ if ((byte & KCarryBitMask) || (numBytes == 5 && topThreeBitsSet))
+ return KErrCorrupt;
+
+ // number of bytes read
+ return numBytes;
+ }
+
+
+/**
+ Returns a formatted version string
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
+ @post internal offset gets updated to move past this primitive
+ @param aPool In - an opened string pool
+ @param aVer Out - a formatted version string. Caller must close this string.
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::VersionL(RStringPool aPool, RStringF& aVer)
+ {
+ const TInt KMaxBufLength=5;
+ TInt bufLen = 0;
+ TInt byte = iBuffer[iOffset];
+ if (!(byte & KTopBitMask))
+ {
+ TPtrC8 str;
+ bufLen = String(str);
+ if (bufLen < KErrNone) return KErrCorrupt;
+ aVer = aPool.OpenFStringL(str);
+ }
+ else
+ {
+ // Major 0-7 , Minor 0-15 [xxx][yyyy]
+ TUint8 val;
+ bufLen = Val7Bit(val);
+ if (bufLen < KErrNone) return KErrCorrupt;
+
+
+ TInt minVer = val & 0x0F;
+ TInt majVer = val & 0xF0;
+ majVer >>= 4;
+
+ if (majVer < 0 || majVer > 7)
+ return KErrCorrupt;
+
+ TBuf8<KMaxBufLength> buf;
+ if (minVer == 0x0F)
+ {
+ _LIT8(KVersionFormat, "%D");
+ buf.Format(KVersionFormat, majVer);
+ }
+ else
+ {
+ _LIT8(KVersionFormat, "%D.%D");
+ buf.Format(KVersionFormat, majVer, minVer);
+ }
+ aVer = aPool.OpenFStringL(buf);
+ }
+
+ return bufLen;
+ }
+
+/**
+ Returns a TDateTime offset from January 1, 1970 - WAP WSP Section 8.4.2.3 Panics if
+ the time val is greater then the maximum allowable integer size (32 bits).
+
+ @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
+ @post internal offset gets updated to move past this primitive
+ @param aDateTime Out - a WAP Date
+ @return postive number indicating the number of bytes read from the buffer
+ KErrCorrupt if data is not formatted correctly.
+*/
+EXPORT_C TInt TWspPrimitiveDecoder::Date(TDateTime& aDateTime)
+ {
+ TUint32 secVal;
+ TInt bufLen = LongInt(secVal);
+ __ASSERT_ALWAYS(bufLen <= KMaxTInt, User::Panic(KUriPanicCategory, EWspDecoderDateOverflow));
+ if (bufLen < KErrNone) return bufLen;
+
+ TDateTime dt(1970,EJanuary,0,0,0,0,0);
+ TTime time(dt);
+
+ TInt sec = STATIC_CAST(TInt, secVal);
+ time += TTimeIntervalSeconds(sec);
+ aDateTime = time.DateTime();
+
+ return bufLen;
+ }