diff -r 000000000000 -r b16258d2340f applayerpluginsandutils/httpprotocolplugins/wspheadercodec/CWspHeaderReader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerpluginsandutils/httpprotocolplugins/wspheadercodec/CWspHeaderReader.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,1477 @@ +// 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: +// + +// System Includes +#include +#include +#include +#include +#include +#include +#include +#include + +// User Includes +#include "cheaderfield.h" +#include "cwspheaderreader.h" + +// Constants +const TInt KMaxNumQDigits = 5; // Maximum number of digits for a 'Q' value +const TUint32 KRegisteredContentTypesOffset = 0x0201; // Registered content types offset +const TUint8 KTopBitMask = 0x80; // Bit-wise mask for setting top bit to 1 + +CWspHeaderReader::~CWspHeaderReader() + { + } + +CWspHeaderReader* CWspHeaderReader::NewL(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + { + return new(ELeave)CWspHeaderReader(aStrPool, aStrTable, aCodec); + } + +CWspHeaderReader* CWspHeaderReader::NewLC(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + { + CWspHeaderReader* self = CWspHeaderReader::NewL(aStrPool, aStrTable, aCodec); + CleanupStack::PushL(self); + return self; + } + +CWspHeaderReader::CWspHeaderReader(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + : iStrPool(aStrPool), iStrTable(aStrTable), iCodec(aCodec) + { + } + +void CWspHeaderReader::DecodeHeaderL(RHeaderField& aHeader) + { + switch( aHeader.Name().Index(iStrTable) ) + { + case WSP::EContentType: + DecodeContentTypeL(aHeader); + break; + case WSP::EDate: + case WSP::ELastModified: + DecodeGenericDateValueL(aHeader); + break; + case WSP::EContentLocation: + case WSP::ELocation: + case WSP::EServer: + case WSP::EVia: + case WSP::EXWapInitiatorURI: + case WSP::EUpgrade: + DecodeGenericNewStringValueL(aHeader); + break; + case WSP::EPragma: + DecodePragmaL(aHeader); + break; + case WSP::EVary: + case WSP::ETrailer: + DecodeGenericFieldNameL(aHeader); + break; + case WSP::EWWWAuthenticate: + case WSP::EProxyAuthenticate: + DecodeGenericChallengeL(aHeader); + break; + case WSP::ESetCookie: + DecodeSetCookieL(aHeader); + break; + case WSP::EEncodingVersion: + DecodeEncodingVersionL(aHeader); + break; + case WSP::EAcceptRanges: + DecodeAcceptRangesL(aHeader); + break; + case WSP::EContentEncoding: + DecodeContentEncodingL(aHeader); + break; + case WSP::EContentLanguage: + DecodeContentLanguageL(aHeader); + break; + case WSP::EContentMD5: + DecodeContentMD5L(aHeader); + break; + case WSP::ERetryAfter: + DecodeRetryAfterL(aHeader); + break; + case WSP::EContentRange: + case WSP::EContentRangeDep: + DecodeContentRangeL(aHeader); + break; + case WSP::EXWapApplicationId: + DecodeXWapApplicationIdL(aHeader); + break; + case WSP::EPushFlag: + DecodePushFlagL(aHeader); + break; + case WSP::EAllow: + DecodeAllowL(aHeader); + break; + case WSP::EWarning: + DecodeWarningL(aHeader); + break; + case WSP::EProfileWarning: + case WSP::EProfileWarningDep: + DecodeProfileWarningL(aHeader); + break; + default: + User::Leave(KErrNotSupported); + break; + } + } + + +void CWspHeaderReader::DecodeContentTypeL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + + if( !(CheckNullDesPartL(aHeader, rawData, 0)) ) + { + TWspPrimitiveDecoder wspDecoder(rawData); + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::E7BitVal: + { + TUint8 contentTypeToken = 0; + User::LeaveIfError(wspDecoder.Val7Bit(contentTypeToken)); + RStringF contentType = iStrPool.StringF(contentTypeToken, WSPContentTypes::Table); + SetFStringPartL(aHeader, 0, contentType); + } break; + case TWspPrimitiveDecoder::EString: + { + AddNewDecoderStringPartL(aHeader, wspDecoder); + } break; + case TWspPrimitiveDecoder::ELengthVal: + { + TInt dataLength = 0; + TInt err = wspDecoder.LengthVal(dataLength); + User::LeaveIfError(err); + TInt bytesProcessed = err; + TWspPrimitiveDecoder::TWspHeaderType type = wspDecoder.VarType(); + CHeaderFieldPart* fieldPart = NULL; + if( type == TWspPrimitiveDecoder::E7BitVal || type == TWspPrimitiveDecoder::ELengthVal ) + { + TUint32 contentTypeToken = 0; + err = wspDecoder.Integer(contentTypeToken); + User::LeaveIfError(err); + bytesProcessed += err; + RStringF contentTypeStr; + if( contentTypeToken < KRegisteredContentTypesOffset ) + contentTypeStr = iStrPool.StringF(contentTypeToken, WSPContentTypes::Table); + else + contentTypeStr = iStrPool.StringF((contentTypeToken-KRegisteredContentTypesOffset), WSPRegContentTypes::Table); + + fieldPart = &(SetFStringPartL(aHeader, 0, contentTypeStr)); + } + else if( type == TWspPrimitiveDecoder::EString ) + { + TPtrC8 contentType; + err = wspDecoder.String(contentType); + User::LeaveIfError(err); + bytesProcessed += err; + fieldPart = &(SetNewFStringPartL(aHeader, 0, contentType)); + } + else + User::Leave(KErrCorrupt); + + // Check if paramters exist + while( bytesProcessed < rawData.Length() ) + { + TPtrC8 parameterBlock(rawData.Mid(bytesProcessed)); + bytesProcessed += DecodeGenericSingleParameterL(parameterBlock, *fieldPart); + } + } break; + default: + User::Leave(KErrCorrupt); + } + } + } + +void CWspHeaderReader::DecodePragmaL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + + // Check for which indicates "No-Cache" string + if( rawData[0] == 128 ) + { + SetFStringPartL(aHeader, 0, iStrPool.StringF(WSPStdConstants::ENoCache, WSPStdConstants::Table)); + } + else + { + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal ) + { + TInt dataLength = 0; + TInt bytesProcessed = wspDecoder.LengthVal(dataLength); + User::LeaveIfError(bytesProcessed); + TPtrC8 rawParamBlock(rawData.Mid(bytesProcessed)); + // Check that there is only one parameter block + if( dataLength != rawParamBlock.Length() ) + User::Leave(KErrCorrupt); + CHeaderFieldPart& fieldPart = SetNewFStringPartL(aHeader, 0, KNullDesC8()); + bytesProcessed += DecodeGenericSingleParameterL(rawParamBlock, fieldPart); + if( bytesProcessed != rawData.Length() ) + User::Leave(KErrCorrupt); + } + } + } + +void CWspHeaderReader::DecodeSetCookieL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 2); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() != TWspPrimitiveDecoder::ELengthVal ) + User::Leave(KErrCorrupt); + TInt valueLength = 0; + TInt bytesProcessed = wspDecoder.LengthVal(valueLength); + User::LeaveIfError(bytesProcessed); + + // Get the first part which is the cookie-version + TInt err = 0; + if( CheckForNullStringL(rawData, bytesProcessed, wspDecoder) ) + { + SetNewFStringPartL(aHeader, 0, KNullDesC8()); + } + else + { + RStringF version; + err = wspDecoder.VersionL(iStrPool, version); + User::LeaveIfError(err); + bytesProcessed += err; + CleanupClosePushL(version); + SetFStringPartL(aHeader, 0, version); + CleanupStack::PopAndDestroy(&version); + } + + // Loop through the next two + // Get the second part which is the cookie-name + // Get the third part which is the cookie-value + CHeaderFieldPart* fieldPart = NULL; + for(TInt ii=1; ii<3; ++ii) + { + TPtrC8 cookiePart(KNullDesC8()); + if( !(CheckForNullStringL(rawData, bytesProcessed, wspDecoder)) ) + { + err = wspDecoder.String(cookiePart); + User::LeaveIfError(err); + bytesProcessed += err; + } + fieldPart = &(SetNewFStringPartL(aHeader, ii, cookiePart)); + } + + // Check if there are any parameters. if so add them to the 3rd part + if( fieldPart != NULL ) + { + while( bytesProcessed < rawData.Length() ) + { + TPtrC8 parameterBlock(rawData.Mid(bytesProcessed)); + bytesProcessed += DecodeGenericSingleParameterL(parameterBlock, *fieldPart); + } + } + } + +TBool CWspHeaderReader::CheckForNullStringL(TPtrC8& aRawData, TInt& aBytesRead, + TWspPrimitiveDecoder& aDecoder) const + { + // Check that the buffer is not out of range + if( aBytesRead >= aRawData.Length() ) + User::Leave(KErrCorrupt); + + // Check if the data at the indicated position is a NULL terminator + if( aRawData[aBytesRead] == 0 ) + { + TUint8 value = 0; + TInt err = aDecoder.Val7Bit(value); + User::LeaveIfError(err); + aBytesRead += err; + return ETrue; + } + return EFalse; + } + +void CWspHeaderReader::DecodeEncodingVersionL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + + if( !(CheckNullDesPartL(aHeader, rawData, 0)) ) + { + // Check type and decode accordingly + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::ELengthVal: + { + TInt valLength = 0; + TInt bytesRead = 0; + TInt err = wspDecoder.LengthVal(valLength); + User::LeaveIfError(err); + bytesRead += err; + if( wspDecoder.VarType() == TWspPrimitiveDecoder::E7BitVal ) + { + TUint8 codePage = 0; + err = wspDecoder.Val7Bit(codePage); + User::LeaveIfError(err); + bytesRead += err; + SetNewIntegerPartL(aHeader, 0, codePage); + if( bytesRead < rawData.Length() ) + { + // Check for Null string first + if( rawData[bytesRead] == 0 ) + SetNewFStringPartL(aHeader, 1, KNullDesC8()); + else + DecodeGenericVersionL(aHeader, wspDecoder, 1); + } + } + else + User::Leave(KErrCorrupt); + } break; + case TWspPrimitiveDecoder::EString: + case TWspPrimitiveDecoder::E7BitVal: + { + DecodeGenericVersionL(aHeader, wspDecoder, 0); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + } + +void CWspHeaderReader::DecodeGenericVersionL(RHeaderField& aHeader, TWspPrimitiveDecoder& aDecoder, TInt aIndex) const + { + RStringF versionValue; + CleanupClosePushL(versionValue); + User::LeaveIfError(aDecoder.VersionL(iStrPool, versionValue)); + SetFStringPartL(aHeader, aIndex, versionValue); + CleanupStack::PopAndDestroy(&versionValue); + } + +void CWspHeaderReader::DecodeAcceptRangesL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TInt acceptRangeIndex = KErrNotFound; + switch( rawData[0] ) + { + case 128: // This is the token for 'None' + { + acceptRangeIndex = WSPStdConstants::ENone; + } break; + case 129: // This is the token for 'Bytes' + { + acceptRangeIndex = WSPStdConstants::EBytes; + } break; + default: // Must be token text + { + TWspPrimitiveDecoder wspDecoder(rawData); + // Check that the data is of string type + if( wspDecoder.VarType() == TWspPrimitiveDecoder::EString ) + { + // Extract and add the string as a part + AddNewDecoderStringPartL(aHeader, wspDecoder); + } + else + User::Leave(KErrCorrupt); + } break; + } + + if(acceptRangeIndex!=KErrNotFound) + SetFStringPartL(aHeader, 0, iStrPool.StringF(acceptRangeIndex, WSPStdConstants::Table)); + } + +void CWspHeaderReader::DecodeContentEncodingL(RHeaderField& aHeader) const + { + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field token name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.Locate((TUint8)(WSP::EContentEncoding + KTopBitMask)); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + CheckLengthL(rawData, 1); + TInt contentEncodingIndex = KErrNotFound; + switch( rawData[0] ) + { + case 128: // This is the token for 'GZip' + { + contentEncodingIndex = WSPStdConstants::EGzip; + } break; + case 129: // This is the token for 'Compress' + { + contentEncodingIndex = WSPStdConstants::ECompress; + } break; + case 130: // This is the token for 'Deflate' + { + contentEncodingIndex = WSPStdConstants::EDeflate; + } break; + default: // Must be token text + { + TWspPrimitiveDecoder wspDecoder(rawData); + // Check that the data is of string type + if( wspDecoder.VarType() == TWspPrimitiveDecoder::EString ) + { + // Extract and add the string as a part + AddNewDecoderStringPartL(aHeader, wspDecoder, ii); + } + else + User::Leave(KErrCorrupt); + } break; + } + + if(contentEncodingIndex!=KErrNotFound) + SetFStringPartL(aHeader, ii, iStrPool.StringF(contentEncodingIndex, WSPStdConstants::Table)); + ++ii; + startPos += (separatorPos + 1); + } while( separatorPos != KErrNotFound ); + } + +void CWspHeaderReader::DecodeContentLanguageL(RHeaderField& aHeader) const + { + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.Locate((TUint8)(WSP::EContentLanguage + KTopBitMask)); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + CheckLengthL(rawData, 1); + // First check for any language ('*') encoded as octet 128 + if( rawData[0] == 128 ) + SetFStringPartL(aHeader, ii, iStrPool.StringF(WSPLanguages::EAnyLanguage, WSPLanguages::Table)); + else + { + // Otherwise the language is encoded as a short int, long int or token text + TWspPrimitiveDecoder wspDecoder(rawData); + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::E7BitVal: // short int + case TWspPrimitiveDecoder::ELengthVal: // long int + { + TUint32 languageToken = 0; + User::LeaveIfError(wspDecoder.Integer(languageToken)); + // Check if the language token is short or long int as long requires an offset + if( languageToken >= 128 ) + // Language token is long int so apply the offset + --languageToken; + SetFStringPartL(aHeader, ii, iStrPool.StringF(languageToken, WSPLanguages::Table)); + } break; + case TWspPrimitiveDecoder::EString: // token text + { + // Extract the token text and set the part + AddNewDecoderStringPartL(aHeader, wspDecoder, ii); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + + ++ii; + startPos += (separatorPos + 1); + } while( separatorPos != KErrNotFound ); + } + +void CWspHeaderReader::DecodeContentMD5L(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal ) + { + TInt length = 0; + TInt bytesRead = wspDecoder.LengthVal(length); + User::LeaveIfError(bytesRead); + TPtrC8 md5Data(rawData.Mid(bytesRead)); + if( md5Data.Length() != length ) + User::Leave(KErrCorrupt); + + SetNewStringPartL(aHeader, 0, md5Data); + } + else + User::Leave(KErrCorrupt); + } + +void CWspHeaderReader::DecodeRetryAfterL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal ) + { + TInt lengthVal = 0; + TInt bytesRead = wspDecoder.LengthVal(lengthVal); + User::LeaveIfError(bytesRead); + switch( rawData[bytesRead] ) + { + case 128: // This is an absolute time + { + TUint8 updateOffset = 0; + User::LeaveIfError(wspDecoder.Val7Bit(updateOffset)); + TDateTime dateTime(1970, EJanuary, 0, 0, 0, 0, 0); + User::LeaveIfError(wspDecoder.Date(dateTime)); + SetNewDatePartL(aHeader, 0, dateTime); + } break; + case 129: // This is a relative time + { + TUint8 updateOffset = 0; + User::LeaveIfError(wspDecoder.Val7Bit(updateOffset)); + TUint32 relativeTime = 0; + User::LeaveIfError(wspDecoder.Integer(relativeTime)); + SetNewIntegerPartL(aHeader, 0, relativeTime); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + else + User::Leave(KErrCorrupt); + } + +void CWspHeaderReader::DecodeContentRangeL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal ) + { + TInt lengthVal = 0; + TInt bytesRead = wspDecoder.LengthVal(lengthVal); + User::LeaveIfError(bytesRead); + + // Get the first part, first byte pos + TUint32 uintvarValue = 0; + TInt err = wspDecoder.UintVar(uintvarValue); + User::LeaveIfError(err); + bytesRead += err; + SetNewIntegerPartL(aHeader, 0, uintvarValue); + + // Get the second part, entity length + // Check for '*' token and the encoding version is greater than v1.2 + if( (rawData[bytesRead]) == 128 && (iCodec.GetWspVersion() > CWspHeaderCodec::EVersion1_2) ) + { + RStringF unknownLenStr = iStrPool.StringF(WSPStdConstants::EAny, WSPStdConstants::Table); + SetFStringPartL(aHeader, 1, unknownLenStr); + } + else + { + User::LeaveIfError(wspDecoder.UintVar(uintvarValue)); + SetNewIntegerPartL(aHeader, 1, uintvarValue); + } + } + else + User::Leave(KErrCorrupt); + } + +void CWspHeaderReader::DecodeXWapApplicationIdL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::E7BitVal: + case TWspPrimitiveDecoder::ELengthVal: + { + if( rawData[0] != 0 ) + { + TUint32 applicationID = 0; + User::LeaveIfError(wspDecoder.Integer(applicationID)); + SetNewIntegerPartL(aHeader, 0, applicationID); + } + } break; + default: + DecodeGenericNewStringValueL(aHeader); + break; + } + } + +void CWspHeaderReader::DecodePushFlagL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + // Check that the value is a short integer + if( wspDecoder.VarType() == TWspPrimitiveDecoder::E7BitVal ) + { + TUint8 pushFlagVal = 0; + User::LeaveIfError(wspDecoder.Val7Bit(pushFlagVal)); + SetNewIntegerPartL(aHeader, 0, pushFlagVal); + } + else + User::Leave(KErrCorrupt); + } + +void CWspHeaderReader::DecodeAllowL(RHeaderField& aHeader) const + { + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.Locate((TUint8)(WSP::EAllow + KTopBitMask)); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + // Check that the value is a short integer + if( wspDecoder.VarType() == TWspPrimitiveDecoder::E7BitVal ) + { + TUint8 pushFlagVal = 0; + User::LeaveIfError(wspDecoder.Val7Bit(pushFlagVal)); + // Get the correct string for the integer value from the WSP Type Constants table + TInt stringTableIndex = KErrNotFound; + switch(pushFlagVal) + { + case 0x40: // Get + stringTableIndex = WSPTypeConstants::EGet; + break; + case 0x41: // Options + stringTableIndex = WSPTypeConstants::EOptions; + break; + case 0x42: // Head + stringTableIndex = WSPTypeConstants::EHead; + break; + case 0x43: // Delete + stringTableIndex = WSPTypeConstants::EDelete; + break; + case 0x44: // Trace + stringTableIndex = WSPTypeConstants::ETrace; + break; + case 0x60: // Post + stringTableIndex = WSPTypeConstants::EPost; + break; + case 0x61: // Put + stringTableIndex = WSPTypeConstants::EPut; + break; + default: // Not found so leave + User::Leave(KErrNotSupported); + break; + } + RStringF allowValue = iStrPool.StringF(stringTableIndex, WSPTypeConstants::Table); + SetFStringPartL(aHeader, ii, allowValue); + } + else + User::Leave(KErrCorrupt); + + ++ii; + startPos += (separatorPos + 1); + } while( separatorPos != KErrNotFound ); + } + +void CWspHeaderReader::DecodeWarningL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::E7BitVal: // This is a short int warn code + { + DecodeGenericWarnCodeL(aHeader, wspDecoder); + } break; + case TWspPrimitiveDecoder::ELengthVal: // This is value-length warning value + { + // Get the first part - warn-code (short int) + TInt length = 0; + TInt bytesProcessed = wspDecoder.LengthVal(length); + User::LeaveIfError(bytesProcessed); + DecodeGenericWarnCodeL(aHeader, wspDecoder); + ++bytesProcessed; + + // Get the second part - warn-agent (text string) + if(CheckForNullStringL(rawData, bytesProcessed, wspDecoder)) + SetNewFStringPartL(aHeader, 1, KNullDesC8()); + else + bytesProcessed += AddNewDecoderStringPartL(aHeader, wspDecoder, 1); + + // Get the third part - warn-text (text string) + if(CheckForNullStringL(rawData, bytesProcessed, wspDecoder)) + SetNewFStringPartL(aHeader, 2, KNullDesC8()); + else + { + AddNewDecoderStringPartL(aHeader, wspDecoder, 2); + } + } break; + default: + User::LeaveIfError(KErrCorrupt); + break; + } + } + +void CWspHeaderReader::DecodeProfileWarningL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + switch (wspDecoder.VarType()) + { + case TWspPrimitiveDecoder::E7BitVal: // This is a short int profile warn-code + { + DecodeGenericWarnCodeL(aHeader, wspDecoder); + } break; + case TWspPrimitiveDecoder::ELengthVal: + { + TInt length = 0; + TInt bytesRead = wspDecoder.LengthVal(length); + User::LeaveIfError(bytesRead); + + // Get the first part - profile warn-code (short int) + DecodeGenericWarnCodeL(aHeader, wspDecoder); + ++bytesRead; + + // Get the second part - warn-target + if(CheckForNullStringL(rawData, bytesRead, wspDecoder)) + SetNewFStringPartL(aHeader, 1, KNullDesC8()); + else + bytesRead += AddNewDecoderStringPartL(aHeader, wspDecoder, 1); + + // Get the warn-date if it exists + if( bytesRead < rawData.Length() ) + { + TDateTime dateTime(1970, EJanuary, 0, 0, 0, 0, 0); + User::LeaveIfError(wspDecoder.Date(dateTime)); + SetNewDatePartL(aHeader, 2, dateTime); + } + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + + +// Generic encoding methods + +void CWspHeaderReader::DecodeGenericWarnCodeL(RHeaderField& aHeader, TWspPrimitiveDecoder& aDecoder) const + { + TUint8 warnCode = 0; + User::LeaveIfError(aDecoder.Val7Bit(warnCode)); + // Convert the code + TInt convertedCode = 0; + switch( warnCode ) + { + case 10: // 110 - Response stale + case 11: // 111 - Revalidation failed + case 12: // 112 - Disconnected operation + case 13: // 113 - Heuristic expiration + case 99: // 199 - Miscellaneous warning + convertedCode = warnCode + 100; + break; + case 14: // 214 - Tranformation applied + convertedCode = warnCode + 200; + break; + // The following warning codes are UAProf specific + case 16: // 100 - OK + case 17: // 101 - Used stale profile + case 18: // 102 - Not used profile + convertedCode = warnCode + 84; + break; + case 32: // 200 - Not applied + case 33: // 201 - Content selection applied + case 34: // 202 - Content generation applied + case 35: // 203 - Transformation applied + convertedCode = warnCode + 168; + break; + default: + convertedCode = warnCode; + break; + } + // Add the value as an integer part + SetNewIntegerPartL(aHeader, 0, convertedCode); + } + +void CWspHeaderReader::DecodeGenericNewStringValueL(RHeaderField& aHeader) const + { + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.Locate((TUint8)(aHeader.Name().Index(WSP::Table) + KTopBitMask)); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + if( !(CheckNullDesPartL(aHeader, rawData, ii)) ) + { + AddNewDecoderStringPartL(aHeader, wspDecoder, ii); + } + + ++ii; + startPos += (separatorPos + 1); + } while( separatorPos != KErrNotFound ); + } + +void CWspHeaderReader::DecodeGenericDateValueL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() == TWspPrimitiveDecoder::ELengthVal ) + { + TDateTime dateTime(1970, EJanuary, 0, 0, 0, 0, 0); + User::LeaveIfError(wspDecoder.Date(dateTime)); + SetNewDatePartL(aHeader, 0, dateTime); + } + else + User::Leave(KErrCorrupt); + } + +void CWspHeaderReader::DecodeGenericFieldNameL(RHeaderField& aHeader) const + { + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.Locate((TUint8)(aHeader.Name().Index(WSP::Table) + KTopBitMask)); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + CheckLengthL(rawData, 1); + TWspPrimitiveDecoder wspDecoder(rawData); + switch( wspDecoder.VarType() ) + { + case TWspPrimitiveDecoder::EString: + { + AddNewDecoderStringPartL(aHeader, wspDecoder, ii); + } break; + case TWspPrimitiveDecoder::E7BitVal: + { + TUint8 fieldNameToken = 0; + User::LeaveIfError(wspDecoder.Val7Bit(fieldNameToken)); + RStringF fieldNameStr = iStrPool.StringF(fieldNameToken, iStrTable); + SetFStringPartL(aHeader, ii, fieldNameStr); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + + ++ii; + startPos += (separatorPos + 1); + } while( separatorPos != KErrNotFound ); + } + +TInt CWspHeaderReader::DecodeGenericSingleParameterL(TPtrC8& aRawParamBlock, CHeaderFieldPart& aHeaderFieldPart) const + { + TWspPrimitiveDecoder wspDecoder(aRawParamBlock); + TInt bytesRead = 0; + switch( wspDecoder.VarType() ) + { + // This is a typed parameter + case TWspPrimitiveDecoder::ELengthVal: + case TWspPrimitiveDecoder::E7BitVal: + { + DecodeWellKnownParamTokenL(wspDecoder, bytesRead, aRawParamBlock, aHeaderFieldPart); + } break; + // This is an untyped parameter + case TWspPrimitiveDecoder::EString: + { + DecodeUntypedParamL(wspDecoder, bytesRead, aRawParamBlock, aHeaderFieldPart); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + return bytesRead; + } + +void CWspHeaderReader::DecodeWellKnownParamTokenL(TWspPrimitiveDecoder& aDecoder, TInt& aBytesRead, + TPtrC8& aRawParamBlock, CHeaderFieldPart& aHeaderFieldPart) const + { + TInt err = 0; + TUint32 parameterToken = 0; + aBytesRead = aDecoder.Integer(parameterToken); + THTTPHdrVal paramValue; + RStringF paramDesValue; + CleanupClosePushL(paramDesValue); + RStringF paramName = iStrPool.StringF(parameterToken, WSPParam::Table); + switch( parameterToken ) + { + case WSPParam::EQ: + { + // Decode Q value + TUint32 qIntValue = 0; + err = aDecoder.UintVar(qIntValue); + User::LeaveIfError(err); + aBytesRead += err; + TReal q; + TInt numDecimals = 0; + TBuf8 qDesC; + if( qIntValue > 100 ) + { + // Value is -100 and then divide by 1000 + qIntValue -= 100; + q = ((TReal)(qIntValue/1000.)); + numDecimals = 3; + } + else + { + // Value is -1 and then divide by 100 + --qIntValue; + if( qIntValue%10 ==0 ) + numDecimals = 1; + else + numDecimals = 2; + q = ((TReal)(qIntValue/100.)); + } + TRealFormat realFt(KMaxNumQDigits,numDecimals); // set max width and 3 decimal places + // always use a decimal separator rather than the one supplied + // by the current locale + realFt.iPoint = TChar('.'); + qDesC.Num(q, realFt); + paramDesValue = iStrPool.OpenFStringL(qDesC); + paramValue.SetStrF(paramDesValue); + } break; + case WSPParam::ECharset: + { + if( aRawParamBlock[aBytesRead] == 128 ) + { + paramDesValue = iStrPool.StringF(WSPStdConstants::EAny, WSPStdConstants::Table); + paramValue.SetStrF(paramDesValue); + // Need to call Integer to update offset in WSP Decoder + TUint8 updateDecoder = 0; + err = aDecoder.Val7Bit(updateDecoder); + User::LeaveIfError(err); + aBytesRead += err; + } + else + { + switch( aDecoder.VarType() ) + { + case TWspPrimitiveDecoder::E7BitVal: + case TWspPrimitiveDecoder::ELengthVal: + { + TUint32 value = 0; + err = aDecoder.Integer(value); + User::LeaveIfError(err); + aBytesRead += err; + GetCharacterSetFromValueL(value, paramDesValue); + paramValue.SetStrF(paramDesValue); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + } break; + case WSPParam::ELevel: + { + // This is a version value + err = aDecoder.VersionL(iStrPool,paramDesValue); + User::LeaveIfError(err); + aBytesRead += err; + paramValue.SetStrF(paramDesValue); + } break; + case WSPParam::EType: + case WSPParam::ESize: + case WSPParam::EPadding: + case WSPParam::ESEC: + case WSPParam::EMaxAge: + { + TUint32 integerValue = 0; + err = aDecoder.Integer(integerValue); + User::LeaveIfError(err); + aBytesRead += err; + paramValue.SetInt(integerValue); + } break; + case WSPParam::ECreationDate: + case WSPParam::EModificationDate: + case WSPParam::EReadDate: + { + TDateTime dateTime(1970, EJanuary, 0, 0, 0, 0, 0); + err = aDecoder.Date(dateTime); + User::LeaveIfError(err); + aBytesRead += err; + paramValue.SetDateTime(dateTime); + } + case WSPParam::ENameDep: + case WSPParam::EFilenameDep: + case WSPParam::EStartDep: + case WSPParam::EStartInfoDep: + case WSPParam::ECommentDep: + case WSPParam::EDomainDep: + case WSPParam::EPathDep: + { + TPtrC8 textString; + err = aDecoder.String(textString); + User::LeaveIfError(err); + aBytesRead += err; + paramDesValue = iStrPool.OpenFStringL(textString); + paramValue.SetStrF(paramDesValue); + } break; + case WSPParam::EMAC: + case WSPParam::EName: + case WSPParam::EFilename: + case WSPParam::EStart: + case WSPParam::EStartInfo: + case WSPParam::EComment: + case WSPParam::EDomain: + case WSPParam::EPath: + { + // Check if the string has ie + if( aRawParamBlock[aBytesRead] == 0 ) + { + paramDesValue = iStrPool.OpenFStringL(KNullDesC8()); + paramValue.SetStrF(paramDesValue); + // Need to call Integer to update offset in WSP Decoder + TUint32 updateDecoder = 0; + err = aDecoder.Integer(updateDecoder); + User::LeaveIfError(err); + } + else + { + TPtrC8 textString; + err = aDecoder.String(textString); + User::LeaveIfError(err); + paramDesValue = iStrPool.OpenFStringL(textString); + paramValue.SetStrF(paramDesValue); + } + aBytesRead += err; + } break; + case WSPParam::EDifferences: + { + aBytesRead += DecodeGenericParamTokenL(aDecoder, iStrTable, paramValue, paramDesValue); + } break; + case WSPParam::EContentTypeType: + { + aBytesRead += DecodeGenericParamTokenL(aDecoder, WSPContentTypes::Table, paramValue, paramDesValue); + } break; + case WSPParam::ESecure: + { + // no-value + paramDesValue = iStrPool.OpenFStringL(KNullDesC8()); + paramValue.SetStrF(paramDesValue); + // Need to call Integer to update offset in WSP Decoder + TUint32 updateDecoder = 0; + err = aDecoder.Integer(updateDecoder); + User::LeaveIfError(err); + aBytesRead += err; + } break; + default: + User::Leave(KErrCorrupt); + break; + } + + // Add the parameter name and value + TPtrC8 paramDes(paramName.DesC()); + SetNewParamL(aHeaderFieldPart, paramDes, paramValue); + CleanupStack::PopAndDestroy(¶mDesValue); + } + +void CWspHeaderReader::DecodeUntypedParamL(TWspPrimitiveDecoder& aDecoder, TInt& aBytesRead, + TPtrC8& aRawParamBlock, CHeaderFieldPart& aHeaderFieldPart) const + { + TPtrC8 paramName; + aBytesRead = aDecoder.String(paramName); + User::LeaveIfError(aBytesRead); + TWspPrimitiveDecoder paramValueDecoder(aRawParamBlock.Mid(aBytesRead)); + TWspPrimitiveDecoder::TWspHeaderType type = paramValueDecoder.VarType(); + // Check if the first octet is NULL, if it is then the value is a string + if( aRawParamBlock[aBytesRead] == 0 ) + type = TWspPrimitiveDecoder::EString; + + switch( type ) + { + case TWspPrimitiveDecoder::ELengthVal: + case TWspPrimitiveDecoder::E7BitVal: + { + TUint32 paramIntValue = 0; + aBytesRead += paramValueDecoder.Integer(paramIntValue); + SetNewParamL(aHeaderFieldPart, paramName, paramIntValue); + } break; + case TWspPrimitiveDecoder::EString: + case TWspPrimitiveDecoder::EQuotedString: + { + RStringF paramValueStr; + CleanupClosePushL(paramValueStr); + // Check if the parameter has a value + if( aRawParamBlock[aBytesRead] == 0 ) + { + paramValueStr = iStrPool.OpenFStringL(KNullDesC8()); + ++aBytesRead; + } + else + { + TPtrC8 paramStrValue; + TInt err = paramValueDecoder.String(paramStrValue); + paramValueStr = iStrPool.OpenFStringL(paramStrValue); + User::LeaveIfError(err); + aBytesRead += err; + } + SetNewParamL(aHeaderFieldPart, paramName, paramValueStr); + CleanupStack::PopAndDestroy(¶mValueStr); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + } + +TInt CWspHeaderReader::DecodeGenericParamTokenL(TWspPrimitiveDecoder& aDecoder, const TStringTable& aStrTable, + THTTPHdrVal& aParamValue, RStringF& aParamDesValue) const + { + TInt err = 0; + switch( aDecoder.VarType() ) + { + case TWspPrimitiveDecoder::EString: + { + TPtrC8 fieldNameString; + err = aDecoder.String(fieldNameString); + User::LeaveIfError(err); + aParamDesValue = iStrPool.OpenFStringL(fieldNameString); + aParamValue.SetStrF(aParamDesValue); + } break; + case TWspPrimitiveDecoder::E7BitVal: + { + TUint8 fieldNameToken = 0; + err = aDecoder.Val7Bit(fieldNameToken); + User::LeaveIfError(err); + aParamDesValue = iStrPool.StringF(fieldNameToken, aStrTable); + aParamValue.SetStrF(aParamDesValue); + } break; + default: + User::Leave(KErrCorrupt); + break; + } + return err; + } + +void CWspHeaderReader::DecodeGenericChallengeL(RHeaderField& aHeader) const + { + TPtrC8 rawData; + aHeader.RawDataL(rawData); + CheckLengthL(rawData, 3); + TWspPrimitiveDecoder wspDecoder(rawData); + if( wspDecoder.VarType() != TWspPrimitiveDecoder::ELengthVal ) + User::Leave(KErrCorrupt); + + TInt lengthValue = 0; + // Check if the first byte is a length-quote + TInt bytesProcessed = wspDecoder.LengthVal(lengthValue); + + // An error may have occured + User::LeaveIfError(bytesProcessed); + + // Get the challenge data + TInt err = 0; + TBool basic = EFalse; + TPtrC8 challangeData = rawData.Mid(bytesProcessed); + // The if the first byte is then it is the Basic scheme otherwise + // the scheme is in token text + if( challangeData[0] == 128 ) + { + basic = ETrue; + SetFStringPartL(aHeader, 0, iStrPool.StringF(WSPStdConstants::EBasic, WSPStdConstants::Table)); + // Need to call Integer to update offset in WSP Decoder + TUint32 updateDecoder = 0; + err = wspDecoder.Integer(updateDecoder); + User::LeaveIfError(err); + } + else + err = AddNewDecoderStringPartL(aHeader, wspDecoder); + + bytesProcessed += err; + + // Get the second part which should be a text string + // First octet can be '0' ie No-value + CHeaderFieldPart* fieldPart = NULL; + if( rawData[bytesProcessed] == 0 ) + { + fieldPart = &(SetNewFStringPartL(aHeader, 1, KNullDesC8())); + // Need to call Integer to update offset in WSP Decoder + TUint32 updateDecoder = 0; + err = wspDecoder.Integer(updateDecoder); + User::LeaveIfError(err); + } + else + { + TPtrC8 realmValue; + err = wspDecoder.String(realmValue); + User::LeaveIfError(err); + fieldPart = &(SetNewFStringPartL(aHeader, 1, realmValue)); + } + bytesProcessed += err; + + // Check for parameters and process them + if( fieldPart == NULL || !basic ) + { + while( bytesProcessed < rawData.Length() ) + { + TPtrC8 parameterBlock(rawData.Mid(bytesProcessed)); + bytesProcessed += DecodeGenericSingleParameterL(parameterBlock, *fieldPart); + } + } + } + +void CWspHeaderReader::GetCharacterSetFromValueL(TInt aValue, RStringF& aCharSetStr) const + { + TInt charSetToken = 0; + const TStringTable& strTable = WSPCharacterSets::Table; + switch( aValue ) + { + case 0x07EA: + charSetToken = WSPCharacterSets::EBig5; + break; + case 0x03E8: + charSetToken = WSPCharacterSets::EIso10646ucs2; + break; + case 0x04: + charSetToken = WSPCharacterSets::EIso88591; + break; + case 0x05: + charSetToken = WSPCharacterSets::EIso88592; + break; + case 0x06: + charSetToken = WSPCharacterSets::EIso88593; + break; + case 0x07: + charSetToken = WSPCharacterSets::EIso88594; + break; + case 0x08: + charSetToken = WSPCharacterSets::EIso88595; + break; + case 0x09: + charSetToken = WSPCharacterSets::EIso88596; + break; + case 0x0A: + charSetToken = WSPCharacterSets::EIso88597; + break; + case 0x0B: + charSetToken = WSPCharacterSets::EIso88598; + break; + case 0x0C: + charSetToken = WSPCharacterSets::EIso88599; + break; + case 0x11: + charSetToken = WSPCharacterSets::EShiftJIS; + break; + case 0x03: + charSetToken = WSPCharacterSets::EUsAscii; + break; + case 0x6A: + charSetToken = WSPCharacterSets::EUtf8; + break; + default: + User::Leave(KErrCorrupt); + break; + } + aCharSetStr = iStrPool.StringF(charSetToken, strTable); + } + +// Generic methods + +CHeaderFieldPart& CWspHeaderReader::SetNewPartL(RHeaderField& aHeader, TInt aPartIndex, THTTPHdrVal& aPartVal) const + { + CHeaderFieldPart* part = CHeaderFieldPart::NewL(aPartVal); + CleanupStack::PushL(part); + aHeader.SetPartL(part, aPartIndex); + CleanupStack::Pop(part); + return *part; + } + +CHeaderFieldPart& CWspHeaderReader::SetNewIntegerPartL(RHeaderField& aHeader, TInt aPartIndex, TInt aValue) const + { + THTTPHdrVal partVal(aValue); + CHeaderFieldPart& part = SetNewPartL(aHeader, aPartIndex, partVal); + return part; + } + +CHeaderFieldPart& CWspHeaderReader::SetNewFStringPartL(RHeaderField& aHeader, TInt aPartIndex, TPtrC8 aValue) const + { + RStringF partStr = iStrPool.OpenFStringL(aValue); + CleanupClosePushL(partStr); + THTTPHdrVal partVal(partStr); + CHeaderFieldPart& part = SetNewPartL(aHeader, aPartIndex, partVal); + CleanupStack::PopAndDestroy(&partStr); + return part; + } + +CHeaderFieldPart& CWspHeaderReader::SetNewStringPartL(RHeaderField& aHeader, TInt aPartIndex, TPtrC8 aValue) const + { + RString partStr = iStrPool.OpenStringL(aValue); + CleanupClosePushL(partStr); + THTTPHdrVal partVal(partStr); + CHeaderFieldPart& part = SetNewPartL(aHeader, aPartIndex, partVal); + CleanupStack::PopAndDestroy(&partStr); + return part; + } + +CHeaderFieldPart& CWspHeaderReader::SetFStringPartL(RHeaderField& aHeader, TInt aPartIndex, RStringF aStrVal) const + { + // Check if a string was found + if( aStrVal.DesC().Length() == 0 ) + User::Leave(KErrCorrupt); + + THTTPHdrVal partVal(aStrVal); + CHeaderFieldPart& part = SetNewPartL(aHeader, aPartIndex, partVal); + return part; + } + +CHeaderFieldPart& CWspHeaderReader::SetNewDatePartL(RHeaderField& aHeader, TInt aPartIndex, TDateTime& aDate) const + { + THTTPHdrVal partVal(aDate); + CHeaderFieldPart& part = SetNewPartL(aHeader, aPartIndex, partVal); + return part; + } + +CHeaderFieldParam& CWspHeaderReader::SetNewParamL(CHeaderFieldPart& aHeaderPart, TPtrC8 aParamName, THTTPHdrVal aParamValue) const + { + RStringF paramNameStr = iStrPool.OpenFStringL(aParamName); + CleanupClosePushL(paramNameStr); + CHeaderFieldParam* param = CHeaderFieldParam::NewL(paramNameStr, aParamValue); + CleanupStack::PushL(param); + aHeaderPart.AddParamL(param); + CleanupStack::Pop(param); + CleanupStack::PopAndDestroy(¶mNameStr); + return *param; + } + +TBool CWspHeaderReader::CheckNullDesPartL(RHeaderField& aHeader, TPtrC8& aRawData, TInt aPartIndex) const + { + TUint8 firstByte = aRawData[0]; + if( firstByte == 0 ) + { + SetNewFStringPartL(aHeader, aPartIndex, KNullDesC8()); + return ETrue; + } + return EFalse; + } + +TInt CWspHeaderReader::AddNewDecoderStringPartL(RHeaderField& aHeader, TWspPrimitiveDecoder& aDecoder, TInt aIndex) const + { + TPtrC8 buffer; + TInt err = aDecoder.String(buffer); + User::LeaveIfError(err); + SetNewFStringPartL(aHeader, aIndex, buffer); + return err; + } + +// Implementation of CWspDefaultHdrReader +//------------------------------------------------------------------------- + +CWspDefaultHdrReader::~CWspDefaultHdrReader() + { + } + +CWspDefaultHdrReader* CWspDefaultHdrReader::NewL(RStringPool aStrPool) + { + return new(ELeave)CWspDefaultHdrReader(aStrPool); + } + +CWspDefaultHdrReader* CWspDefaultHdrReader::NewLC(RStringPool aStrPool) + { + CWspDefaultHdrReader* self = CWspDefaultHdrReader::NewL(aStrPool); + CleanupStack::PushL(self); + return self; + } + +CWspDefaultHdrReader::CWspDefaultHdrReader(RStringPool aStrPool) + : iStrPool(aStrPool) + { + } + +void CWspDefaultHdrReader::DecodeHeaderL(RHeaderField& aHeader) + { + // Get and store the header field name + TPtrC8 headerField(aHeader.Name().DesC()); + + // Decode the header as a text-string + TPtrC8 rawHeaderData; + aHeader.RawDataL(rawHeaderData); + + TInt startPos = 0; + TInt separatorPos = 0; + TInt ii = 0; + // Loop through all the parts separated by the header field name + do + { + TPtrC8 rawData(rawHeaderData.Mid(startPos)); + separatorPos = rawData.FindF(headerField); + if(separatorPos!=KErrNotFound) + rawData.Set(rawHeaderData.Mid(startPos, separatorPos)); + + // Check that the length of the data is at least 1 + if( rawData.Length() < 1 ) + User::Leave(KErrCorrupt); + + // Check if the data is an empty string which should only have a NULL terminator + // otherwise extract the text-string from the primitive decoder + TUint8 firstByte = rawData[0]; + TWspPrimitiveDecoder wspDecoder(rawData); + TPtrC8 buffer; + if( firstByte == 0 ) + buffer.Set(KNullDesC8()); + else + User::LeaveIfError(wspDecoder.String(buffer)); + + // Create a header part from the decoded buffer and add the part to the header field + RStringF partStr = iStrPool.OpenFStringL(buffer); + CleanupClosePushL(partStr); + THTTPHdrVal partVal(partStr); + CHeaderFieldPart* part = CHeaderFieldPart::NewL(partVal); + CleanupStack::PushL(part); + aHeader.SetPartL(part, ii); + CleanupStack::Pop(part); + CleanupStack::PopAndDestroy(&partStr); + + ++ii; + startPos += (separatorPos + headerField.Length() + 1); + } while( separatorPos != KErrNotFound ); + }