First public contribution.
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <wspencoder.h>
20 const TUint8 KWSPQuoteCharacter = 0x7F; // QUOTE character as specified in the WSP BNF.
21 const TUint8 KWSPQuote = 0x22; // The regular quote character ".
22 const TUint8 KCarryBitMask = 0x80; // Continue bit set
23 #define KTopBitMask KCarryBitMask // Mask for checking top bit
24 const TUint KUintVarIndicator = 31; // Byte value indicating a UIntVar follows.
25 const TUint KUIntVarOctetShift = 7; // Octet shift required processing a UnIntVar
26 const TUint KLongIntOctetShift = 8; // Octet shift required processing a LongInt
27 const TInt KDesArrayGranularity = 6; // Granularity of descriptor array
28 _LIT8(KWspStringTerminator, "\0");
29 _LIT8(KTxtSeparators, "()<>@,;:\\\"/[]?={} "); // Separator characters as defined in RFC2616
33 _LIT(KWspCodecPanicCategory,"WSPCODEC");
36 Static factory constructor.
39 @return returns a Pointer to fully constructed CWspHeaderEncoder object.
41 EXPORT_C CWspHeaderEncoder* CWspHeaderEncoder::NewL()
43 CWspHeaderEncoder* self = CWspHeaderEncoder::NewLC();
44 CleanupStack::Pop(self);
49 Static factory constructor.
52 @return returns a Pointer to fully constructed CWspHeaderEncoder object on the Heap.
54 EXPORT_C CWspHeaderEncoder* CWspHeaderEncoder::NewLC()
56 CWspHeaderEncoder* self = new (ELeave) CWspHeaderEncoder();
57 CleanupStack::PushL(self);
65 CWspHeaderEncoder::CWspHeaderEncoder()
72 EXPORT_C CWspHeaderEncoder::~CWspHeaderEncoder()
74 iArray.ResetAndDestroy();
78 Standard second phase construction.
80 void CWspHeaderEncoder::ConstructL()
83 CDesC8Array* buffer = new (ELeave) CDesC8ArrayFlat(KDesArrayGranularity);
84 CleanupStack::PushL(buffer);
85 User::LeaveIfError(iArray.Append(buffer));
86 CleanupStack::Pop(buffer);
90 Starts a new encoded header.
92 @param aToken field name being encoded as a Token value.
95 EXPORT_C void CWspHeaderEncoder::StartHeaderL(TUint8 aToken)
97 __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
102 Starts a new encoded header.
104 @param aString Fieldname parameter is encoded as a TextString.
107 EXPORT_C void CWspHeaderEncoder::StartHeaderL(const TDesC8& aString)
109 __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
110 AddTextStringL(aString);
114 Starts a new encoded header.
116 @param aString Fieldname parameter is encoded as a TextString.
117 @leave KErrNotSupported
119 EXPORT_C void CWspHeaderEncoder::StartHeaderL(const RStringF /* aString */ )
121 __ASSERT_DEBUG(iTotalLength==0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderCalledTwice));
122 User::Leave(KErrNotSupported);
127 Completes and returns encoded field 8 bit buffer. This method will panic if an
128 EndValueLengthL() is not called after a StartValueLength().
131 The final buffer containing the entire encoded header is constructed.
132 Returns buffer containing the encoded field constructed
133 from the first call to StartHeaderL.
135 @return Pointer to buffer containing the entire encoded field.
136 Responsibility for deallocating the memory is also passed.
137 @pre The function StartHeaderL should have been called.
138 @post Encoder is reset ready to be used again.
139 @leave HBufC8::NewL leaves, if the new 8 bit heap descriptor cannot be created.
142 EXPORT_C HBufC8* CWspHeaderEncoder::EndHeaderL()
144 __ASSERT_DEBUG(iArray.Count()==1,User::Panic(KWspCodecPanicCategory, EWspCodecPanicEndValueLengthNotCalled));
145 // concatenate array elements and return.
147 HBufC8* outputBuffer = HBufC8::NewL(iTotalLength);
149 CDesC8Array* desc = iArray[0];
150 TInt count = desc->Count();
151 for (TInt jj=0; jj<count; ++jj)
153 (outputBuffer->Des()).Append((*desc)[jj]);
162 Encodes input Integer value and adds it to the encoded field. Choice of encoded
163 form dependent on the size of the input.Either ShortInt or LongInt method chosen.
165 @param aInt Integer value to be encoded.
166 @pre StartHeaderL needs to have been called.
169 EXPORT_C void CWspHeaderEncoder::AddIntegerL(const TUint aInt)
171 // Determine if its a short or longInt we want
172 (aInt < KTopBitMask) ? AddShortIntL((TUint8) aInt) : AddLongIntL(aInt);
176 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
179 @param aValue value to be encoded.
180 @pre StartHeaderL needs to have been called.
183 EXPORT_C void CWspHeaderEncoder::AddShortIntL(const TUint8 aValue)
185 const TInt arrayCount=iArray.Count();
186 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
187 CDesC8Array* desc=iArray[arrayCount-1];
190 // ShortInt shoud be a character 127 or less. With highest bit set to 1.
191 TUint8 shortInt = TWspPrimitiveEncoder::ShortInt(aValue);
193 desc->AppendL(TPtrC8(&shortInt, 1));
199 Encodes input and adds it to the encoded field. For short length the value must
200 be between octet 0 - 31.
202 @param aValue value to be encoded.
203 @pre StartHeaderL needs to have been called.
204 @leave KErrNoMemory, KErrOverflow if the value is greater than 31
206 EXPORT_C void CWspHeaderEncoder::AddShortLengthL(const TUint8 aValue)
208 const TInt arrayCount=iArray.Count();
209 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
210 CDesC8Array* desc=iArray[arrayCount-1];
212 // Check if the value is in the correct range ie octet 0-31
213 if(aValue > KUintVarIndicator)
214 User::Leave(KErrOverflow);
216 desc->AppendL(TPtrC8(&aValue, 1));
221 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
224 @param aValue value to be encoded.
225 @pre StartHeaderL needs to have been called.
228 EXPORT_C void CWspHeaderEncoder::AddLongIntL(const TUint32 aValue)
230 const TInt arrayCount=iArray.Count();
231 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
232 CDesC8Array* desc=iArray[arrayCount-1];
234 HBufC8* buf = TWspPrimitiveEncoder::LongIntL(aValue);
235 CleanupStack::PushL(buf);
238 iTotalLength+=buf->Length();
240 CleanupStack::PopAndDestroy(buf);
244 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
247 @param aInt value to be encoded.
248 @pre StartHeaderL needs to have been called.
251 EXPORT_C void CWspHeaderEncoder::AddUintVarL(const TUint aInt)
253 const TInt arrayCount=iArray.Count();
254 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
255 CDesC8Array* desc=iArray[arrayCount-1];
257 HBufC8* buf = TWspPrimitiveEncoder::UintVarL(aInt);
258 CleanupStack::PushL(buf);
261 iTotalLength+=buf->Length();
263 CleanupStack::PopAndDestroy(buf);
267 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
270 @param aText value to be encoded.
271 @pre StartHeaderL needs to have been called.
274 EXPORT_C void CWspHeaderEncoder::AddTextStringL(const TDesC8& aText)
276 const TInt arrayCount=iArray.Count();
277 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
278 CDesC8Array* desc=iArray[arrayCount-1];
280 HBufC8* buf = TWspPrimitiveEncoder::TextStringL(aText);
281 CleanupStack::PushL(buf);
283 iTotalLength+=buf->Length();
284 CleanupStack::PopAndDestroy(buf);
288 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
291 @param aText value to be encoded.
292 @pre StartHeaderL needs to have been called.
295 EXPORT_C void CWspHeaderEncoder::AddTextStringL(const RString& /* aText */)
297 User::Leave(KErrNotSupported);
301 Encodes input and adds it to the encoded field.Encodes parameter value using WSP
304 @param aDate value to be encoded.
305 @pre StartHeaderL needs to have been called.
308 EXPORT_C void CWspHeaderEncoder::AddDateL(const TDateTime aDate)
310 const TInt arrayCount=iArray.Count();
311 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
312 CDesC8Array* desc=iArray[arrayCount-1];
314 HBufC8* buf = TWspPrimitiveEncoder::DateL(aDate);
315 CleanupStack::PushL(buf);
317 iTotalLength+=buf->Length();
318 CleanupStack::PopAndDestroy(buf);
322 Encodes input and adds it to the encoded field. Adds value as-is to the encoded field.
324 @param aToken parameter added without encodeing. Should be a valid WSP token,
325 a 8 bit number > 0x7F (i.e. top bit set).
326 @pre StartHeaderL and StartValueLengthL should have been called.
327 @post EndValueLengthL needs to be called subsequently.
329 EXPORT_C void CWspHeaderEncoder::AddTokenL(const TUint8 aToken)
331 const TInt arrayCount=iArray.Count();
332 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
333 CDesC8Array* desc=iArray[arrayCount-1];
335 TUint8 shortInt = (TUint8) (aToken);
336 desc->AppendL(TPtrC8(&shortInt, 1));
341 Encodes input and adds it to the encoded field. Encodes parameter value using WSP
344 @param aTokenText value to be encoded.
347 EXPORT_C void CWspHeaderEncoder::AddTokenTextL(const TDesC8& aTokenText)
349 const TInt arrayCount=iArray.Count();
350 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
352 // Step through token text passed in and ensure there are no invalid characters
353 const TInt tokenTextLength = aTokenText.Length();
354 for( TInt ii = 0; ii<tokenTextLength; ++ii)
356 TUint8 currentChar = aTokenText[ii];
357 if( KTxtSeparators().Locate(currentChar) != KErrNotFound )
358 User::Leave(KErrCorrupt);
360 // Token text does not contain any invalid characters
361 HBufC8* buf = TWspPrimitiveEncoder::TextStringL(aTokenText);
362 CleanupStack::PushL(buf);
363 CDesC8Array* desc=iArray[arrayCount-1];
365 iTotalLength += buf->Length();
366 CleanupStack::PopAndDestroy(buf);
370 Encodes input and adds it to the encoded field. Adds value as-is to the encoded field.
372 @param aData value to be encoded.
375 EXPORT_C void CWspHeaderEncoder::AddDataL(const TDesC8& aData)
377 const TInt arrayCount=iArray.Count();
378 __ASSERT_DEBUG(arrayCount>0,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartHeaderLNotCalled));
379 CDesC8Array* desc=iArray[arrayCount-1];
380 desc->AppendL(aData);
381 iTotalLength += aData.Length();
385 From calling this function, the length in bytes of all encodings added subsequently will
386 be calculated and stored as part of the encoded string, as specified in WSP spec.Can be nested. i.e.
388 encoder->StartHeaderL();
389 encoder->StartValueLengthL();
390 encoder->StartValueLengthL();
391 encoder->AddLongIntL();
392 encoder->EndValueLengthL();
393 encoder->AddTextStringL();
394 encoder->EndValueLengthL();
395 HBufC8* output = encoder->EndHeaderL();
398 @pre StartHeaderL should have been called.
399 @post EndValueLengthL needs to be called subsequently.
402 EXPORT_C void CWspHeaderEncoder::StartValueLengthL()
404 // Create new buffer;
405 CDesC8Array* buffer = new (ELeave) CDesC8ArrayFlat(KDesArrayGranularity);
406 CleanupStack::PushL(buffer);
407 User::LeaveIfError(iArray.Append(buffer));
408 CleanupStack::Pop(buffer);
412 Needs to be called at the point in the construction of a header when ValueLength
415 @pre StartHeaderL and StartValueLengthL should have been called.
416 @post ValueLength has been calculated and added, together with the
417 encoded header, to the internal representation of the header buffer.
420 EXPORT_C void CWspHeaderEncoder::EndValueLengthL()
422 const TInt arrayCount=iArray.Count();
423 __ASSERT_ALWAYS(arrayCount>1,User::Panic(KWspCodecPanicCategory, EWspCodecPanicStartValueLengthNotCalled));
425 // Calculate the length of the current buffer.
426 // and append it onto the previous buffer. [length value, then data]
427 TUint32 valueLength=0;
430 CDesC8Array* desc=iArray[arrayCount-1]; // current descriptor being dealt with
431 CDesC8Array* parentDesc=iArray[arrayCount-2]; // parent descriptor to which it must be added.
433 TInt buffersToAdd=desc->Count();
434 TInt ii=buffersToAdd;
436 // Check the length of all parameters (not the first element in tha array, the field name)
438 valueLength+=(*desc)[--ii].Length();
440 // Remove desc from array. Will have to delete also.
441 iArray.Remove(arrayCount-1);
442 CleanupStack::PushL(desc);
444 // Depending of size of the length save as number or UintVar
445 if (valueLength < KUintVarIndicator)
447 // Value length represented by an 8 bit number.
448 AddShortLengthL( (TUint8) valueLength);
452 // Value length represented by an 8bit value indicating a UIntVar follows,
453 // followed by a UIntVar
454 AddShortLengthL( (TUint8) KUintVarIndicator);
455 AddUintVarL(valueLength);
458 // Add field value, parameters etc.
460 while (ii<buffersToAdd)
461 parentDesc->AppendL((*desc)[ii++]);
463 CleanupStack::PopAndDestroy(desc);
469 //**********************************************************************************
472 Takes a TUint8 parameter, and sets the top bit. As specified for the WSP ShortInt
475 @param aValue number to be encoded.
476 @return Output, encoded as a TUint8, representation of the header buffer.
477 If input greater that 127 (invalid input), returns 0
479 EXPORT_C TUint8 TWspPrimitiveEncoder::ShortInt(const TUint8 aValue)
481 // ShortInt should be a character 127 or less. With highest bit set to 1.
482 return (aValue > KWSPQuoteCharacter) ? (TUint8) 0: (TUint8) (aValue | KTopBitMask);
486 Takes a TUint32 parameter and encodes it using the WSP specified LongInt method.
488 @param aValue number to be encoded.
489 @return Output, encoded HBufC8 buffer.
492 EXPORT_C HBufC8* TWspPrimitiveEncoder::LongIntL(const TUint32 aValue)
494 // Consists of size and up to number of 30 bytes.
495 // for a TInt32 the maximum is 4 bytes long.
496 // Check size of number, to determine number of bytes needed to store it.
498 TUint8 size = 0; // maximum value is 4 with a 32bit integer
499 TUint32 value=aValue;
502 value >>=KLongIntOctetShift; ; // shift by 8 bits.
505 HBufC8* output = HBufC8::NewL(size+1);
506 TPtr8 outPtr(output->Des());
512 outPtr.Append( (TUint8) (aValue>>ii*KLongIntOctetShift) );
519 Takes a TUint32 parameter and encodes it using the WSP specified UintVar method.
521 @param aInt number to be encoded.
522 @return Output, encoded HBufC8 buffer.
525 EXPORT_C HBufC8* TWspPrimitiveEncoder::UintVarL(const TUint32 aInt)
527 TUint8 size = 0; // maximum value is 5 with a 32bit integer
531 value >>=KUIntVarOctetShift; ; // shift by 7 bits.
534 HBufC8* output = HBufC8::NewL(size);
535 TPtr8 outPtr(output->Des());
540 outPtr.Append( (TUint8)(aInt>>(KUIntVarOctetShift*(ii)) & KWSPQuoteCharacter) | KCarryBitMask);
543 // Finally the first 7 bits, last octet, do not set first bit.
544 outPtr.Append( (TUint8)(aInt & KWSPQuoteCharacter) ); // Add even if 0 value.
550 Takes a RString parameter and encodes it using the WSP specified TextString method.
552 @param aText string to be encoded.
553 @return Output, encoded HBufC8 buffer.
556 EXPORT_C HBufC8* TWspPrimitiveEncoder::TextStringL(const RString /* aText*/ )
558 User::Leave(KErrNotSupported);
563 Takes a TDesC8 parameter and encodes it using the WSP specified TextString method.
565 @param aText string to be encoded.
566 @return Output, encoded HBufC8 buffer.
569 EXPORT_C HBufC8* TWspPrimitiveEncoder::TextStringL(const TDesC8& aText)
572 TInt stringLength = aText.Length();
573 TUint8 firstChar = 0;
577 firstChar = aText[0];
578 lastChar = aText[stringLength-1];
581 TPtr8 outPtr(NULL,0);
582 if (firstChar > KWSPQuoteCharacter)
584 // Apply WSP rule: first character of the string not 7bit add QuoteCharacter.
585 // Add the quote character and include space for the NULL character
587 output = HBufC8::NewL(stringLength);
588 outPtr.Set(output->Des());
590 outPtr.Append(KWSPQuoteCharacter);
591 outPtr.Append(aText);
593 else if (firstChar==KWSPQuote && lastChar==KWSPQuote)
595 // Apply WSP rule: if quoted string, remove the closing quote
596 output = HBufC8::NewL(stringLength);
597 outPtr.Set(output->Des());
598 outPtr.Append(aText);
599 outPtr.SetLength(stringLength-1);
603 stringLength+=1; // terminating NULL char
604 output = HBufC8::NewL(stringLength);
605 outPtr.Set(output->Des());
606 outPtr.Append(aText);
609 // Terminate string with 0x00
610 outPtr.Append(KWspStringTerminator);
615 Takes a TDateTime parameter and encodes it using the WSP specified Date encoding method.
617 @param aDate value to be encoded.
618 @return Output, encoded HBufC8 buffer.
621 EXPORT_C HBufC8* TWspPrimitiveEncoder::DateL(const TDateTime aDate)
623 TTime baseTime(TDateTime(1970,EJanuary,0,0,0,0,0));
624 TTime dateTime(aDate);
625 TTimeIntervalSeconds interval;
626 dateTime.SecondsFrom(baseTime, interval);
628 return LongIntL(interval.Int());