--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/httputils/wspcodec/WSPEncoder.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,630 @@
+// 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 <wspencoder.h>
+
+//constants
+//
+const TUint8 KWSPQuoteCharacter = 0x7F; // QUOTE character as specified in the WSP BNF.
+const TUint8 KWSPQuote = 0x22; // The regular quote character ".
+const TUint8 KCarryBitMask = 0x80; // Continue bit set
+#define KTopBitMask KCarryBitMask // Mask for checking top bit
+const TUint KUintVarIndicator = 31; // Byte value indicating a UIntVar follows.
+const TUint KUIntVarOctetShift = 7; // Octet shift required processing a UnIntVar
+const TUint KLongIntOctetShift = 8; // Octet shift required processing a LongInt
+const TInt KDesArrayGranularity = 6; // Granularity of descriptor array
+_LIT8(KWspStringTerminator, "\0");
+_LIT8(KTxtSeparators, "()<>@,;:\\\"/[]?={} "); // Separator characters as defined in RFC2616
+
+// Panic category
+//
+_LIT(KWspCodecPanicCategory,"WSPCODEC");
+
+/**
+ Static factory constructor.
+
+ @leave KErrNoMemory
+ @return returns a Pointer to fully constructed CWspHeaderEncoder object.
+*/
+EXPORT_C CWspHeaderEncoder* CWspHeaderEncoder::NewL()
+ {
+ CWspHeaderEncoder* self = CWspHeaderEncoder::NewLC();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+/**
+ Static factory constructor.
+
+ @leave KErrNoMemory
+ @return returns a Pointer to fully constructed CWspHeaderEncoder object on the Heap.
+*/
+EXPORT_C CWspHeaderEncoder* CWspHeaderEncoder::NewLC()
+ {
+ CWspHeaderEncoder* self = new (ELeave) CWspHeaderEncoder();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+/**
+ Default constructor.
+*/
+CWspHeaderEncoder::CWspHeaderEncoder()
+ {
+ }
+
+/**
+ Default destructor
+*/
+EXPORT_C CWspHeaderEncoder::~CWspHeaderEncoder()
+ {
+ iArray.ResetAndDestroy();
+ }
+
+/**
+ Standard second phase construction.
+*/
+void CWspHeaderEncoder::ConstructL()
+ {
+ // Create new buffer;
+ CDesC8Array* buffer = new (ELeave) CDesC8ArrayFlat(KDesArrayGranularity);
+ CleanupStack::PushL(buffer);
+ User::LeaveIfError(iArray.Append(buffer));
+ CleanupStack::Pop(buffer);
+ }
+
+/**
+ Starts a new encoded header.
+
+ @param aToken field name being encoded as a Token value.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::StartHeaderL(TUint8 aToken)
+ {
+ __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
+ AddShortIntL(aToken);
+ }
+
+/**
+ Starts a new encoded header.
+
+ @param aString Fieldname parameter is encoded as a TextString.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::StartHeaderL(const TDesC8& aString)
+ {
+ __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
+ AddTextStringL(aString);
+ }
+
+/**
+ Starts a new encoded header.
+
+ @param aString Fieldname parameter is encoded as a TextString.
+ @leave KErrNotSupported
+*/
+EXPORT_C void CWspHeaderEncoder::StartHeaderL(const RStringF /* aString */ )
+ {
+ __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
+ User::Leave(KErrNotSupported);
+ }
+
+
+/**
+ Completes and returns encoded field 8 bit buffer. This method will panic if an
+ EndValueLengthL() is not called after a StartValueLength().
+
+ Note:
+ The final buffer containing the entire encoded header is constructed.
+ Returns buffer containing the encoded field constructed
+ from the first call to StartHeaderL.
+
+ @return Pointer to buffer containing the entire encoded field.
+ Responsibility for deallocating the memory is also passed.
+ @pre The function StartHeaderL should have been called.
+ @post Encoder is reset ready to be used again.
+ @leave HBufC8::NewL leaves, if the new 8 bit heap descriptor cannot be created.
+
+*/
+EXPORT_C HBufC8* CWspHeaderEncoder::EndHeaderL()
+ {
+ __ASSERT_DEBUG(iArray.Count()==1,User::Panic(KWspCodecPanicCategory, EWspCodecPanicEndValueLengthNotCalled));
+ // concatenate array elements and return.
+
+ HBufC8* outputBuffer = HBufC8::NewL(iTotalLength);
+
+ CDesC8Array* desc = iArray[0];
+ TInt count = desc->Count();
+ for (TInt jj=0; jj<count; ++jj)
+ {
+ (outputBuffer->Des()).Append((*desc)[jj]);
+ }
+
+ desc->Reset();
+ iTotalLength=0;
+ return outputBuffer;
+ }
+
+/**
+ Encodes input Integer value and adds it to the encoded field. Choice of encoded
+ form dependent on the size of the input.Either ShortInt or LongInt method chosen.
+
+ @param aInt Integer value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddIntegerL(const TUint aInt)
+ {
+ // Determine if its a short or longInt we want
+ (aInt < KTopBitMask) ? AddShortIntL((TUint8) aInt) : AddLongIntL(aInt);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ ShortInt method.
+
+ @param aValue value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddShortIntL(const TUint8 aValue)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+
+ // ShortInt shoud be a character 127 or less. With highest bit set to 1.
+ TUint8 shortInt = TWspPrimitiveEncoder::ShortInt(aValue);
+
+ desc->AppendL(TPtrC8(&shortInt, 1));
+ ++iTotalLength;
+ }
+
+
+/**
+ Encodes input and adds it to the encoded field. For short length the value must
+ be between octet 0 - 31.
+
+ @param aValue value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory, KErrOverflow if the value is greater than 31
+*/
+EXPORT_C void CWspHeaderEncoder::AddShortLengthL(const TUint8 aValue)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ // Check if the value is in the correct range ie octet 0-31
+ if(aValue > KUintVarIndicator)
+ User::Leave(KErrOverflow);
+
+ desc->AppendL(TPtrC8(&aValue, 1));
+ ++iTotalLength;
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ LongInt method.
+
+ @param aValue value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddLongIntL(const TUint32 aValue)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ HBufC8* buf = TWspPrimitiveEncoder::LongIntL(aValue);
+ CleanupStack::PushL(buf);
+
+ desc->AppendL(*buf);
+ iTotalLength+=buf->Length();
+
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ UIntVar method.
+
+ @param aInt value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddUintVarL(const TUint aInt)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ HBufC8* buf = TWspPrimitiveEncoder::UintVarL(aInt);
+ CleanupStack::PushL(buf);
+
+ desc->AppendL(*buf);
+ iTotalLength+=buf->Length();
+
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ TextString method.
+
+ @param aText value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddTextStringL(const TDesC8& aText)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ HBufC8* buf = TWspPrimitiveEncoder::TextStringL(aText);
+ CleanupStack::PushL(buf);
+ desc->AppendL(*buf);
+ iTotalLength+=buf->Length();
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ TextString method.
+
+ @param aText value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddTextStringL(const RString& /* aText */)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+/**
+ Encodes input and adds it to the encoded field.Encodes parameter value using WSP
+ Date method.
+
+ @param aDate value to be encoded.
+ @pre StartHeaderL needs to have been called.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddDateL(const TDateTime aDate)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ HBufC8* buf = TWspPrimitiveEncoder::DateL(aDate);
+ CleanupStack::PushL(buf);
+ desc->AppendL(*buf);
+ iTotalLength+=buf->Length();
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Adds value as-is to the encoded field.
+
+ @param aToken parameter added without encodeing. Should be a valid WSP token,
+ a 8 bit number > 0x7F (i.e. top bit set).
+ @pre StartHeaderL and StartValueLengthL should have been called.
+ @post EndValueLengthL needs to be called subsequently.
+*/
+EXPORT_C void CWspHeaderEncoder::AddTokenL(const TUint8 aToken)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+
+ TUint8 shortInt = (TUint8) (aToken);
+ desc->AppendL(TPtrC8(&shortInt, 1));
+ ++iTotalLength;
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Encodes parameter value using WSP
+ TokenText method.
+
+ @param aTokenText value to be encoded.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddTokenTextL(const TDesC8& aTokenText)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+
+ // Step through token text passed in and ensure there are no invalid characters
+ const TInt tokenTextLength = aTokenText.Length();
+ for( TInt ii = 0; ii<tokenTextLength; ++ii)
+ {
+ TUint8 currentChar = aTokenText[ii];
+ if( KTxtSeparators().Locate(currentChar) != KErrNotFound )
+ User::Leave(KErrCorrupt);
+ }
+ // Token text does not contain any invalid characters
+ HBufC8* buf = TWspPrimitiveEncoder::TextStringL(aTokenText);
+ CleanupStack::PushL(buf);
+ CDesC8Array* desc=iArray[arrayCount-1];
+ desc->AppendL(*buf);
+ iTotalLength += buf->Length();
+ CleanupStack::PopAndDestroy(buf);
+ }
+
+/**
+ Encodes input and adds it to the encoded field. Adds value as-is to the encoded field.
+
+ @param aData value to be encoded.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::AddDataL(const TDesC8& aData)
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
+ CDesC8Array* desc=iArray[arrayCount-1];
+ desc->AppendL(aData);
+ iTotalLength += aData.Length();
+ }
+
+/**
+ From calling this function, the length in bytes of all encodings added subsequently will
+ be calculated and stored as part of the encoded string, as specified in WSP spec.Can be nested. i.e.
+ @code
+ encoder->StartHeaderL();
+ encoder->StartValueLengthL();
+ encoder->StartValueLengthL();
+ encoder->AddLongIntL();
+ encoder->EndValueLengthL();
+ encoder->AddTextStringL();
+ encoder->EndValueLengthL();
+ HBufC8* output = encoder->EndHeaderL();
+ @endcode
+
+ @pre StartHeaderL should have been called.
+ @post EndValueLengthL needs to be called subsequently.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::StartValueLengthL()
+ {
+ // Create new buffer;
+ CDesC8Array* buffer = new (ELeave) CDesC8ArrayFlat(KDesArrayGranularity);
+ CleanupStack::PushL(buffer);
+ User::LeaveIfError(iArray.Append(buffer));
+ CleanupStack::Pop(buffer);
+ }
+
+/**
+ Needs to be called at the point in the construction of a header when ValueLength
+ can be calculated.
+
+ @pre StartHeaderL and StartValueLengthL should have been called.
+ @post ValueLength has been calculated and added, together with the
+ encoded header, to the internal representation of the header buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C void CWspHeaderEncoder::EndValueLengthL()
+ {
+ const TInt arrayCount=iArray.Count();
+ __ASSERT_ALWAYS(arrayCount>1,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartValueLengthNotCalled));
+
+ // Calculate the length of the current buffer.
+ // and append it onto the previous buffer. [length value, then data]
+ TUint32 valueLength=0;
+
+
+ CDesC8Array* desc=iArray[arrayCount-1]; // current descriptor being dealt with
+ CDesC8Array* parentDesc=iArray[arrayCount-2]; // parent descriptor to which it must be added.
+
+ TInt buffersToAdd=desc->Count();
+ TInt ii=buffersToAdd;
+
+ // Check the length of all parameters (not the first element in tha array, the field name)
+ while (ii)
+ valueLength+=(*desc)[--ii].Length();
+
+ // Remove desc from array. Will have to delete also.
+ iArray.Remove(arrayCount-1);
+ CleanupStack::PushL(desc);
+
+ // Depending of size of the length save as number or UintVar
+ if (valueLength < KUintVarIndicator)
+ {
+ // Value length represented by an 8 bit number.
+ AddShortLengthL( (TUint8) valueLength);
+ }
+ else
+ {
+ // Value length represented by an 8bit value indicating a UIntVar follows,
+ // followed by a UIntVar
+ AddShortLengthL( (TUint8) KUintVarIndicator);
+ AddUintVarL(valueLength);
+ }
+
+ // Add field value, parameters etc.
+ ii=0;
+ while (ii<buffersToAdd)
+ parentDesc->AppendL((*desc)[ii++]);
+
+ CleanupStack::PopAndDestroy(desc);
+ }
+
+
+
+
+//**********************************************************************************
+
+/**
+ Takes a TUint8 parameter, and sets the top bit. As specified for the WSP ShortInt
+ encoding method.
+
+ @param aValue number to be encoded.
+ @return Output, encoded as a TUint8, representation of the header buffer.
+ If input greater that 127 (invalid input), returns 0
+*/
+EXPORT_C TUint8 TWspPrimitiveEncoder::ShortInt(const TUint8 aValue)
+ {
+ // ShortInt should be a character 127 or less. With highest bit set to 1.
+ return (aValue > KWSPQuoteCharacter) ? (TUint8) 0: (TUint8) (aValue | KTopBitMask);
+ }
+
+/**
+ Takes a TUint32 parameter and encodes it using the WSP specified LongInt method.
+
+ @param aValue number to be encoded.
+ @return Output, encoded HBufC8 buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C HBufC8* TWspPrimitiveEncoder::LongIntL(const TUint32 aValue)
+ {
+ // Consists of size and up to number of 30 bytes.
+ // for a TInt32 the maximum is 4 bytes long.
+ // Check size of number, to determine number of bytes needed to store it.
+
+ TUint8 size = 0; // maximum value is 4 with a 32bit integer
+ TUint32 value=aValue;
+ do {
+ ++size;
+ value >>=KLongIntOctetShift; ; // shift by 8 bits.
+ } while (value>0);
+
+ HBufC8* output = HBufC8::NewL(size+1);
+ TPtr8 outPtr(output->Des());
+
+ outPtr.Append(size);
+ TInt ii = size;
+ while (ii-- >0)
+ {
+ outPtr.Append( (TUint8) (aValue>>ii*KLongIntOctetShift) );
+ }
+
+ return output;
+ }
+
+/**
+ Takes a TUint32 parameter and encodes it using the WSP specified UintVar method.
+
+ @param aInt number to be encoded.
+ @return Output, encoded HBufC8 buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C HBufC8* TWspPrimitiveEncoder::UintVarL(const TUint32 aInt)
+ {
+ TUint8 size = 0; // maximum value is 5 with a 32bit integer
+ TUint32 value=aInt;
+ do {
+ ++size;
+ value >>=KUIntVarOctetShift; ; // shift by 7 bits.
+ } while (value>0);
+
+ HBufC8* output = HBufC8::NewL(size);
+ TPtr8 outPtr(output->Des());
+
+ TInt ii = size;
+ while (--ii > 0)
+ {
+ outPtr.Append( (TUint8)(aInt>>(KUIntVarOctetShift*(ii)) & KWSPQuoteCharacter) | KCarryBitMask);
+ }
+
+ // Finally the first 7 bits, last octet, do not set first bit.
+ outPtr.Append( (TUint8)(aInt & KWSPQuoteCharacter) ); // Add even if 0 value.
+
+ return output;
+ }
+
+/**
+ Takes a RString parameter and encodes it using the WSP specified TextString method.
+
+ @param aText string to be encoded.
+ @return Output, encoded HBufC8 buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C HBufC8* TWspPrimitiveEncoder::TextStringL(const RString /* aText*/ )
+ {
+ User::Leave(KErrNotSupported);
+ return NULL;
+ }
+
+/**
+ Takes a TDesC8 parameter and encodes it using the WSP specified TextString method.
+
+ @param aText string to be encoded.
+ @return Output, encoded HBufC8 buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C HBufC8* TWspPrimitiveEncoder::TextStringL(const TDesC8& aText)
+ {
+ HBufC8* output=NULL;
+ TInt stringLength = aText.Length();
+ TUint8 firstChar = 0;
+ TUint8 lastChar = 0;
+ if(stringLength>0)
+ {
+ firstChar = aText[0];
+ lastChar = aText[stringLength-1];
+ }
+
+ TPtr8 outPtr(NULL,0);
+ if (firstChar > KWSPQuoteCharacter)
+ {
+ // Apply WSP rule: first character of the string not 7bit add QuoteCharacter.
+ // Add the quote character and include space for the NULL character
+ stringLength+=2;
+ output = HBufC8::NewL(stringLength);
+ outPtr.Set(output->Des());
+
+ outPtr.Append(KWSPQuoteCharacter);
+ outPtr.Append(aText);
+ }
+ else if (firstChar==KWSPQuote && lastChar==KWSPQuote)
+ {
+ // Apply WSP rule: if quoted string, remove the closing quote
+ output = HBufC8::NewL(stringLength);
+ outPtr.Set(output->Des());
+ outPtr.Append(aText);
+ outPtr.SetLength(stringLength-1);
+ }
+ else
+ {
+ stringLength+=1; // terminating NULL char
+ output = HBufC8::NewL(stringLength);
+ outPtr.Set(output->Des());
+ outPtr.Append(aText);
+ }
+
+ // Terminate string with 0x00
+ outPtr.Append(KWspStringTerminator);
+ return output;
+ }
+
+/**
+ Takes a TDateTime parameter and encodes it using the WSP specified Date encoding method.
+
+ @param aDate value to be encoded.
+ @return Output, encoded HBufC8 buffer.
+ @leave KErrNoMemory
+*/
+EXPORT_C HBufC8* TWspPrimitiveEncoder::DateL(const TDateTime aDate)
+ {
+ TTime baseTime(TDateTime(1970,EJanuary,0,0,0,0,0));
+ TTime dateTime(aDate);
+ TTimeIntervalSeconds interval;
+ dateTime.SecondsFrom(baseTime, interval);
+
+ return LongIntL(interval.Int());
+ }
+