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.
17 #include <stringpool.h>
18 #include <wspdecoder.h>
21 const TUint8 KWapQuote = 0x7F;
22 const TUint8 KCarryBitMask = 0x80;
23 #define KTopBitMask KCarryBitMask
24 const TUint8 KTop3BitSet = 0x70;
25 const TUint8 KQuoteChar = '\"';
28 _LIT(KUriPanicCategory,"WSPDECODER");
31 //***********************************************************************
32 // TWspHeaderSegmenter
33 //**********************************************************************/
37 NextL iterates through the buffer. Each call returns a TWspField in the paramater.
39 @param aHeader Out - a TWspField containing the header <name,value> pair.
40 @warning The TWspField::iHdrName will be opened internally.
41 It must be closed by the caller before this class is destroyed.
42 @return KErrNone if next field is returned
43 KErrNotFound at the end of the buffer - no TWspField param returned
44 KErrCorrupt if segmenting does not parse correctly
45 @leave RStringPool::OpenFStringL StringPool leave code if opening string fails.
47 EXPORT_C TInt TWspHeaderSegmenter::NextL(TWspField& aHeader)
49 // have we run out of buffer?
50 if (iOffset >= iBuffer.Length())
53 // Set decoder to current buffer
54 TWspPrimitiveDecoder decoder(iBuffer.Mid(iOffset));
59 switch(decoder.VarType())
61 case TWspPrimitiveDecoder::EString:
64 bufLen = decoder.String(name);
65 if (bufLen < KErrNone) return bufLen;
66 aHeader.iHdrName = iPool.OpenFStringL(name);
70 case TWspPrimitiveDecoder::E7BitVal:
73 bufLen = decoder.Val7Bit(name);
74 if (bufLen < KErrNone) return bufLen;
76 aHeader.iHdrName = iPool.StringF(name, iStringTable);
80 default: // header name can't be anything else
84 // move our pointer past header name
88 // Get the value buffer by figuring out the type, then set the pointer to span the entire
89 // value. Note - further parsing will happen later to pull out specific value data.
90 switch(decoder.VarType())
92 case TWspPrimitiveDecoder::ELengthVal:
95 bufLen = decoder.LengthVal(len);
99 case TWspPrimitiveDecoder::EQuotedString:
100 case TWspPrimitiveDecoder::EString:
103 bufLen = decoder.String(strBuf);
106 case TWspPrimitiveDecoder::E7BitVal:
116 if (iOffset + bufLen > iBuffer.Length())
119 aHeader.iValBuffer.Set(iBuffer.Mid(iOffset, bufLen));
130 Looks at the byte currently pointed at in this buffer and returns the type.
132 @return TWspHeaderType - the type of this data octet
134 EXPORT_C TWspPrimitiveDecoder::TWspHeaderType TWspPrimitiveDecoder::VarType() const
136 TWspHeaderType type = ENotSet;
138 // Check that the offset has not overflowed the buffer
139 if( iOffset >= iBuffer.Length() )
142 TInt octet = iBuffer[iOffset];
144 if (octet >= 0 && octet <= 31)
146 else if (octet == 34)
147 type = EQuotedString;
148 else if (octet >= 32 && octet <= 127)
150 else if (octet >= 128 && octet <= 255)
158 Returns length of the data following this byte.
160 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
161 @post internal offset gets updated to move past this primitive
162 @param aVal Out - the length encoded in this byte that indicates the size of the
164 @return postive number indicating the number of bytes read from the buffer
165 KErrCorrupt if data is not formatted correctly.
167 EXPORT_C TInt TWspPrimitiveDecoder::LengthVal(TInt& aVal)
169 // have we run out of buffer?
170 if (iOffset >= iBuffer.Length())
174 aVal = iBuffer[iOffset++];
178 TUint32 uintVarLen = 0;
179 bufLen = UintVar(uintVarLen);
180 if (bufLen < KErrNone) return bufLen;
181 aVal = (TInt)uintVarLen;
184 // add the 1 byte read at to get first aVal
191 Returns a TPtrC holding the string the buffer currently points at without the NULL
192 termination. If the String type is a quoted string then the quotes are not included
193 in the returned buffer.
195 @pre iBuffer[iOffset] must be valid, VarType() == TWspType::EString
196 @post internal offset gets updated to move past this primitive
197 @param aString Out - the string
198 @return postive number indicating the number of bytes read from the buffer
199 KErrCorrupt if data is not formatted correctly.
201 EXPORT_C TInt TWspPrimitiveDecoder::String(TPtrC8& aString)
203 TWspHeaderType type = VarType();
204 if( type != EString && type != EQuotedString)
207 TInt nullIndex = iBuffer.Mid(iOffset).Locate('\0');
208 if( nullIndex == KErrNotFound )
211 // Set buffer to data not including the NULL terminator
212 TPtrC8 buf = iBuffer.Mid(iOffset, nullIndex);
214 // is there a WAP Quote (0x7F) or a " at the start - step over it
215 TInt bufferOffset = 0;
216 const TUint8 firstByte = iBuffer[iOffset];
217 if( firstByte == KQuoteChar || firstByte == KWapQuote )
220 // Set the descriptor with the correct buffer segment
221 aString.Set(buf.Mid(bufferOffset));
223 // Step over the NULL
227 iOffset += nullIndex;
233 Returns a token, a short int or an octet value with the top bit cleared
235 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::E7BitVal
236 @post internal offset gets updated to move past this primitive
237 @param aVal Out - the 7 bit value with top bit cleared
238 @return postive number indicating the number of bytes read from the buffer
239 KErrCorrupt if data is not formatted correctly.
241 EXPORT_C TInt TWspPrimitiveDecoder::Val7Bit(TUint8& aVal)
243 // have we run out of buffer?
244 if (iOffset >= iBuffer.Length())
247 aVal = (TUint8)(iBuffer[iOffset] & KWapQuote);
256 Returns an Integer - could be short or long.
258 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
259 VarType() == TWspHeaderType::E7BitVal
260 @post internal offset gets updated to move past this primitive
261 @param aVal Out - the long int
262 @return postive number indicating the number of bytes read from the buffer
263 KErrCorrupt if data is not formatted correctly.
265 EXPORT_C TInt TWspPrimitiveDecoder::Integer(TUint32& aVal)
267 // have we run out of buffer?
268 if (iOffset >= iBuffer.Length())
273 // read the first byte
274 aVal = iBuffer[iOffset];
276 // short integers have the top bit set
277 if (aVal & KTopBitMask)
285 bufLen = LongInt(aVal);
292 Returns a long int the buffer is currently pointing at.
294 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
295 @post internal offset gets updated to move past this primitive
296 @param aVal Out - the long int
297 @return postive number indicating the number of bytes read from the buffer
298 KErrCorrupt if data is not formatted correctly.
300 EXPORT_C TInt TWspPrimitiveDecoder::LongInt(TUint32& aVal)
302 // have we run out of buffer?
303 if (iOffset >= iBuffer.Length())
306 __ASSERT_DEBUG(aVal <= KMaxTUint, User::Panic(KUriPanicCategory, EWspDecoderLongIntOverflow));
310 // Get num bytes encoding [len] [byte1] ... [byten]
311 // we are positioned at that location in the source descriptor
313 TInt bufLen = Val7Bit(numBytes);
314 if (bufLen < KErrNone) return bufLen;
316 // len can be up to 30 and verify we have enough buffer
317 if (numBytes > 30 || numBytes > iBuffer.Mid(iOffset).Length())
320 // Loop over the buffer, taking each byte and shifting it in count times.
321 for (TInt count = 0; count < numBytes ; ++count)
322 aVal = (aVal << 8) + iBuffer[iOffset++];
324 return (bufLen + numBytes);
330 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal or
331 VarType() == TWspHeaderType::E7BitVal
332 @post internal offset gets updated to move past this primitive
333 @param aVal Out - the TUint32 decoded
334 @return postive number indicating the number of bytes read from the buffer
335 KErrCorrupt if data is not formatted correctly.
337 EXPORT_C TInt TWspPrimitiveDecoder::UintVar(TUint32& aVal)
339 // have we run out of buffer?
340 if (iOffset >= iBuffer.Length())
343 // initialize return val
346 // maximum length for a uintvar is 5
347 TInt lenLeft = Min(iBuffer.Mid(iOffset).Length(), 5);
349 // get the first octet
350 TUint8 byte = iBuffer[iOffset++];
355 // Check if any of the top 3 bits, ignoring the very top 'continue' bit, are set.
356 // Later if we see that this is a 5 byte number - we'll know it is corrupt.
357 // Encoding uses 7 bits/number 7x5=35 and we only support a maxiumum number
359 TBool topThreeBitsSet = byte & KTop3BitSet;
361 // copy over data from the byte into our return value (the top bit is a carry bit)
362 aVal = byte & KWapQuote;
364 // while the 'continue' bit is set and we have more data
365 while ((byte & KCarryBitMask) && (lenLeft > 0))
367 // shift our last value up
370 byte = iBuffer[iOffset++];
371 // copy it over to the lowest byte
372 aVal |= byte & KWapQuote;
377 // last octet has continue bit set ... NOT allowed Or
378 // this was encoded wrong - can't have a number bigger than 32 bits
379 if ((byte & KCarryBitMask) || (numBytes == 5 && topThreeBitsSet))
382 // number of bytes read
388 Returns a formatted version string
390 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
391 @post internal offset gets updated to move past this primitive
392 @param aPool In - an opened string pool
393 @param aVer Out - a formatted version string. Caller must close this string.
394 @return postive number indicating the number of bytes read from the buffer
395 KErrCorrupt if data is not formatted correctly.
397 EXPORT_C TInt TWspPrimitiveDecoder::VersionL(RStringPool aPool, RStringF& aVer)
399 const TInt KMaxBufLength=5;
401 TInt byte = iBuffer[iOffset];
402 if (!(byte & KTopBitMask))
405 bufLen = String(str);
406 if (bufLen < KErrNone) return KErrCorrupt;
407 aVer = aPool.OpenFStringL(str);
411 // Major 0-7 , Minor 0-15 [xxx][yyyy]
413 bufLen = Val7Bit(val);
414 if (bufLen < KErrNone) return KErrCorrupt;
417 TInt minVer = val & 0x0F;
418 TInt majVer = val & 0xF0;
421 if (majVer < 0 || majVer > 7)
424 TBuf8<KMaxBufLength> buf;
427 _LIT8(KVersionFormat, "%D");
428 buf.Format(KVersionFormat, majVer);
432 _LIT8(KVersionFormat, "%D.%D");
433 buf.Format(KVersionFormat, majVer, minVer);
435 aVer = aPool.OpenFStringL(buf);
442 Returns a TDateTime offset from January 1, 1970 - WAP WSP Section 8.4.2.3 Panics if
443 the time val is greater then the maximum allowable integer size (32 bits).
445 @pre iBuffer[iOffset] must be valid, VarType() == TWspHeaderType::ELengthVal
446 @post internal offset gets updated to move past this primitive
447 @param aDateTime Out - a WAP Date
448 @return postive number indicating the number of bytes read from the buffer
449 KErrCorrupt if data is not formatted correctly.
451 EXPORT_C TInt TWspPrimitiveDecoder::Date(TDateTime& aDateTime)
454 TInt bufLen = LongInt(secVal);
455 __ASSERT_ALWAYS(bufLen <= KMaxTInt, User::Panic(KUriPanicCategory, EWspDecoderDateOverflow));
456 if (bufLen < KErrNone) return bufLen;
458 TDateTime dt(1970,EJanuary,0,0,0,0,0);
461 TInt sec = STATIC_CAST(TInt, secVal);
462 time += TTimeIntervalSeconds(sec);
463 aDateTime = time.DateTime();