diff -r 000000000000 -r b16258d2340f applayerpluginsandutils/httpprotocolplugins/wspheadercodec/CWspHeaderWriter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerpluginsandutils/httpprotocolplugins/wspheadercodec/CWspHeaderWriter.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,2345 @@ +// 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 "cwspheaderwriter.h" + +const TInt KOffset = 1; // Offset as the WspLanguages string table does not have 0x80 in it +const TInt KShortIntLimit = 128; // A short integer can be within the range of 0-127 + +CWspHeaderWriter* CWspHeaderWriter::NewL(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + { + return new(ELeave)CWspHeaderWriter(aStrPool, aStrTable, aCodec); + } + +CWspHeaderWriter* CWspHeaderWriter::NewLC(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + { + CWspHeaderWriter* self = CWspHeaderWriter::NewL(aStrPool, aStrTable, aCodec); + CleanupStack::PushL(self); + return self; + } + +CWspHeaderWriter::CWspHeaderWriter(RStringPool aStrPool, const TStringTable& aStrTable, CWspHeaderCodec& aCodec) + : iStrPool(aStrPool), iStrTable(aStrTable), iCodec(aCodec) + { + } + +CWspHeaderWriter::~CWspHeaderWriter() + { + } + +void CWspHeaderWriter::EncodeHeaderL(RHeaderField& aHeader) + { + switch(aHeader.Name().Index(iStrTable)) + { + case WSP::EAccept: + { + EncodeAcceptL(aHeader); + } break; + case WSP::EAcceptCharsetDep: + case WSP::EAcceptCharset: + { + EncodeAcceptCharsetL(aHeader); + } break; + case WSP::EAcceptEncodingDep: + case WSP::EAcceptEncoding: + { + EncodeAcceptEncodingL(aHeader); + } break; + case WSP::EAcceptLanguage: + { + EncodeAcceptLanguageL(aHeader); + } break; + case WSP::EAllow: + { + EncodeAllowL(aHeader); + } break; + case WSP::EAuthorization: + { + EncodeAuthorizationL(aHeader); + } break; + case WSP::EContentEncoding: + { + EncodeContentEncodingL(aHeader); + } break; + case WSP::EContentLanguage: + { + EncodeContentLanguageL(aHeader); + } break; + case WSP::EContentLocation: + case WSP::EFrom: + case WSP::EProfile: + case WSP::EReferer: + case WSP::EUpgrade: + case WSP::EUserAgent: + case WSP::EVia: + { + GenericEncodeTextStringL(aHeader); + } break; + case WSP::EContentMD5: + { + EncodeContentMD5L(aHeader); + } break; + case WSP::EContentRangeDep: + case WSP::EContentRange: + { + EncodeContentRangeL(aHeader); + } break; + case WSP::EContentType: + { + EncodeContentTypeL(aHeader); + } break; + case WSP::ECookie: + { + EncodeCookieL(aHeader); + } break; + case WSP::EDate: + case WSP::ELastModified: + { + GenericEncodeDateL(aHeader); + } break; + case WSP::EEncodingVersion: + { + EncodeEncodingVersionL(aHeader); + } break; + case WSP::EExpect: + { + EncodeExpectL(aHeader); + } break; + case WSP::EPragma: + { + EncodePragmaL(aHeader); + } break; + case WSP::EProfileDiff: + { + EncodeProfileDiffL(aHeader); + } break; + case WSP::ERange: + { + EncodeRangeL(aHeader); + } break; + case WSP::ETE: + { + EncodeTEL(aHeader); + } break; + case WSP::ETrailer: + { + EncodeTrailerL(aHeader); + } break; + case WSP::EWarning: + { + EncodeWarningL(aHeader); + } break; + case WSP::EXWapApplicationId: + { + EncodeXWapApplicationIdL(aHeader); + } break; + default: + User::Leave(KErrNotSupported); + break; + } + } + + +void CWspHeaderWriter::EncodeAcceptL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + TInt partCount = 0; + TBool requireValueLength = EFalse; + aHeader.BeginRawDataL(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + requireValueLength = ETrue; + encoder->StartValueLengthL(); + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt typeValue = EncodeContentTypeValue(value); + if (typeValue < KShortIntLimit && typeValue > KErrNotFound) + encoder->AddShortIntL((TUint8)typeValue); + else if (typeValue == KErrNotFound) + { + TInt registeredValue = value.StrF().Index(WSPRegContentTypes::Table); + if (registeredValue > KErrNotFound) + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + const TInt KContentTypeOffset = 0x0201; // Offset for the Registered Content Type value string table + encoder->AddLongIntL(registeredValue + KContentTypeOffset); + } + else if (registeredValue == KErrNotFound) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + } + + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *encoder); + ++paramIter; + } + if (requireValueLength) + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + // If there is more than one header part it is necessary to append the name of the + // header to the buffer + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeAcceptCharsetL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + aHeader.BeginRawDataL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + TInt partCount = 0; + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + TBool requireValueLength = EFalse; + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + requireValueLength = ETrue; + encoder->StartValueLengthL(); + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + // Check for '*' (Any-charset) and that the WSP version is greater than 1.2 + if ((value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::EAny) + && (iCodec.GetWspVersion() > CWspHeaderCodec::EVersion1_2)) + { + encoder->AddTokenL(128); // '*' is encoded as + } + else + { + TInt charValue = GetCharacterSetValue(value.StrF()); + switch(charValue) + { + case KErrNotFound: + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } break; + default: + { + if (charValue < KShortIntLimit) + encoder->AddShortIntL((TUint8)charValue); + else + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + encoder->AddLongIntL(charValue); + } + } break; + } + } + + // Check if we have any parameters + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + THTTPHdrVal paramValue = param->Value(); + HBufC8* qValue = EncodeQValueL(paramValue.StrF()); + CleanupStack::PushL(qValue); + if (qValue != NULL) + encoder->AddDataL(*qValue); + ++paramIter; + CleanupStack::PopAndDestroy(qValue); + } + } + else + User::Leave(KErrCorrupt); + } + + // If we have a Q-value then we need to calculate the value-length + if (requireValueLength) + encoder->EndValueLengthL(); + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + // If there is more than one header part it is necessary to append the name of the + // header to the buffer + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeAcceptEncodingL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + TInt partCount = 0; + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + aHeader.BeginRawDataL(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + TBool requireValueLength = EFalse; + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + requireValueLength = ETrue; + encoder->StartValueLengthL(); + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt encValue = value.StrF().Index(WSPStdConstants::Table); + // Check for '*' (Any-encoding) and that the WSP version is greater than 1.2 + if ((encValue == WSPStdConstants::EAny) + && (iCodec.GetWspVersion() > CWspHeaderCodec::EVersion1_2)) + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + encoder->AddTokenL(131); // '*' is encoded as + } + else + { + switch(encValue) + { + case WSPStdConstants::EGzip: // Gzip is encoded as + { + encoder->AddTokenL(128); + } break; + case WSPStdConstants::ECompress: // Compress is encoded as + { + encoder->AddTokenL(129); + } break; + case WSPStdConstants::EDeflate: // Deflate is encoded as + { + encoder->AddTokenL(130); + } break; + default: + { + encoder->AddTokenTextL(value.StrF().DesC()); + } break; + } + } + + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + THTTPHdrVal paramValue = param->Value(); + HBufC8* qValue = EncodeQValueL(paramValue.StrF()); + CleanupStack::PushL(qValue); + if (qValue != NULL) + encoder->AddDataL(*qValue); + CleanupStack::PopAndDestroy(qValue); + ++paramIter; + } + } + else + User::Leave(KErrCorrupt); + } + + if (requireValueLength) + encoder->EndValueLengthL(); + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + // If there is more than one header part it is necessary to append the name of the + // header to the buffer + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeAcceptLanguageL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + TInt partCount = 0; + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + aHeader.BeginRawDataL(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + TBool requireValueLength = EFalse; + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + requireValueLength = ETrue; + encoder->StartValueLengthL(); + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt langValue = value.StrF().Index(WSPLanguages::Table); + switch(langValue) + { + case WSPLanguages::EAnyLanguage: + { + encoder->AddTokenL(128); // '*' (Any-language) is encoded as + } break; + case KErrNotFound: + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } break; + default: + { + if (langValue < KShortIntLimit) + encoder->AddShortIntL((TUint8)langValue); + else + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + encoder->AddLongIntL(langValue + KOffset); + } + } break; + } + + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + THTTPHdrVal paramValue = param->Value(); + HBufC8* qValue = EncodeQValueL(paramValue.StrF()); + CleanupStack::PushL(qValue); + if (qValue != NULL) + encoder->AddDataL(*qValue); + ++paramIter; + CleanupStack::PopAndDestroy(qValue); + } + } + else + User::Leave(KErrCorrupt); + } + + if (requireValueLength) + encoder->EndValueLengthL(); + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + // If there is more than one header part it is necessary to append the name of the + // header to the buffer + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeAllowL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + aHeader.BeginRawDataL(); + TInt partCount = 0; + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TUint8 allowNumber = 0; + TInt allowValue = value.StrF().Index(WSPTypeConstants::Table); + switch(allowValue) + { + case WSPTypeConstants::EGet: + { + allowNumber = 64; // Get is encoded as 0x40 + } break; + case WSPTypeConstants::EOptions: + { + allowNumber = 65; // Options is encoded as 0x41 + } break; + case WSPTypeConstants::EHead: + { + allowNumber = 66; // Head is encoded as 0x42 + } break; + case WSPTypeConstants::EDelete: + { + allowNumber = 67; // Delete is encoded as 0x43 + } break; + case WSPTypeConstants::ETrace: + { + allowNumber = 68; // Trace is encoded as 0x44 + } break; + case WSPTypeConstants::EPost: + { + allowNumber = 96; // Post is encoded as 0x60 + } break; + case WSPTypeConstants::EPut: + { + allowNumber = 97; // Put is encoded as 0x61 + } break; + default: + User::Leave(KErrNotFound); + break; + } + encoder->AddShortIntL(allowNumber); + } + else + User::Leave(KErrCorrupt); + } + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeAuthorizationL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + encoder->StartValueLengthL(); + // Check to see if the first part is 'Basic' + if (value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::EBasic) + { + // If it is, then encode Basic as and then iterate through the + // following parts which should contain the 'User-ID' and 'Password' + encoder->AddTokenL(128); + ++partIter; + while (!partIter.AtEnd()) + { + value = partIter()->Value(); + if(value.Type() == THTTPHdrVal::KStrFVal) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + ++partIter; + } + else + User::Leave(KErrCorrupt); + } + } + // Otherwise, the first part is an 'Authentication-scheme' with zero or more parameters + else + { + encoder->AddTokenTextL(value.StrF().DesC()); + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *encoder); + ++paramIter; + } + } + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + } + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeContentEncodingL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + aHeader.BeginRawDataL(); + TInt partCount = 0; + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt encValue = value.StrF().Index(WSPStdConstants::Table); + switch(encValue) + { + case WSPStdConstants::EGzip: + { + encoder->AddTokenL(128); // Gzip is encoded as + } break; + case WSPStdConstants::ECompress: + { + encoder->AddTokenL(129); // Compress is encoded as + } break; + case WSPStdConstants::EDeflate: + { + encoder->AddTokenL(130); // Deflate is encoded as + } break; + default: + { + encoder->AddTokenTextL(value.StrF().DesC()); + } break; + } + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeContentLanguageL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + TInt partCount = 0; + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + aHeader.BeginRawDataL(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt langValue = value.StrF().Index(WSPLanguages::Table); + switch(langValue) + { + case WSPLanguages::EAnyLanguage: + { + encoder->AddTokenL(128); // '*' (Any-language) is encoded as + } break; + case KErrNotFound: + { + encoder->AddTokenTextL(value.StrF().DesC()); + } break; + default: + { + if (langValue < KShortIntLimit) + encoder->AddShortIntL((TUint8)langValue); + else + encoder->AddLongIntL(langValue + KOffset); + } break; + } + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeContentMD5L(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TBool requireValueLength = EFalse; + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + encoder->StartValueLengthL(); + encoder->AddDataL(value.StrF().DesC()); + requireValueLength = ETrue; + } + else + User::Leave(KErrCorrupt); + + if (requireValueLength) + encoder->EndValueLengthL(); + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeContentRangeL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KTIntVal) + { + encoder->StartValueLengthL(); + encoder->AddUintVarL(value); + ++partIter; + if (!partIter.AtEnd()) + { + value = partIter()->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + // Check for '*' (Any-encoding) and that the WSP version is greater than 1.2 + if ((value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::EAny) + && (iCodec.GetWspVersion() > CWspHeaderCodec::EVersion1_2)) + { + encoder->AddTokenL(128); // '*' is encoded as + } + } + if (value.Type() == THTTPHdrVal::KTIntVal) + encoder->AddUintVarL(value); + } + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeContentTypeL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + TBool requireValueLength = EFalse; + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + requireValueLength = ETrue; + encoder->StartValueLengthL(); + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt typeValue = EncodeContentTypeValue(value); + if (typeValue < KShortIntLimit && typeValue > KErrNotFound) + encoder->AddShortIntL((TUint8)typeValue); + else if (typeValue == KErrNotFound) + { + TInt registeredValue = value.StrF().Index(WSPRegContentTypes::Table); + if (registeredValue > KErrNotFound) + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + const TInt KContentTypeOffset = 0x0201; // Offset for the Registered Content Type value string table + encoder->AddLongIntL(registeredValue + KContentTypeOffset); + } + else if (registeredValue == KErrNotFound) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + } + // check for params and append to temporary buffer + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *encoder); + ++paramIter; + } + + if (requireValueLength) + encoder->EndValueLengthL(); + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + else + User::Leave(KErrCorrupt); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeCookieL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + // Encode the first part which is the Cookie-version value + if (value.Type() == THTTPHdrVal::KStrFVal) + { + encoder->StartValueLengthL(); + TUint8 versionValue = EncodeVersionValueL(value.StrF()); + if (versionValue == 0) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else + encoder->AddShortIntL(versionValue); + + // Then move to the next part and iterate through all the parts that follow, appending + // the parameters if any exist + ++partIter; + while (!partIter.AtEnd()) + { + CWspHeaderEncoder* cookieEncoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(cookieEncoder); + value = partIter()->Value(); // The first part is the Cookie-Name + if (value.Type() == THTTPHdrVal::KStrFVal) + { + cookieEncoder->StartHeaderL((TUint8)token); + cookieEncoder->StartValueLengthL(); + User::LeaveIfError(CheckTextString(value.StrF())); + cookieEncoder->AddTextStringL(value.StrF().DesC()); + ++partIter; + part = partIter(); + value = partIter()->Value(); // The second part is the Cookie-Value + if (value.Type() == THTTPHdrVal::KStrFVal) + { + User::LeaveIfError(CheckTextString(value.StrF())); + cookieEncoder->AddTextStringL(value.StrF().DesC()); + THeaderFieldParamIter paramIter = part->Parameters(); // Now check for any parameters + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *cookieEncoder); + ++paramIter; + } + } + else + User::Leave(KErrCorrupt); + + cookieEncoder->EndValueLengthL(); + HBufC8* cookieBuffer = cookieEncoder->EndHeaderL(); + CleanupStack::PushL(cookieBuffer); + // Remove the header name from the buffer and then check if + // the first byte is equal to 31 i.e. a length quote, and if so remove it + TInt offset = 1; + if (cookieBuffer->Des()[1] == 31) + ++offset; + HBufC8* data = cookieBuffer->Mid(offset).AllocL(); + CleanupStack::PushL(data); + encoder->AddDataL(*data); + CleanupStack::PopAndDestroy(2, cookieBuffer); // data. cookieBuffer + } + ++partIter; + part = partIter(); + CleanupStack::PopAndDestroy(cookieEncoder); + } + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + } + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.BeginRawDataL(); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeEncodingVersionL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) // There is a version-value in the first part + { + TUint8 versionValue = EncodeVersionValueL(value.StrF()); + if (versionValue == 0) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else + encoder->AddShortIntL(versionValue); + } + else if (value.Type() == THTTPHdrVal::KTIntVal) // The first part is NOT a version-value but an int + { + encoder->StartValueLengthL(); + if (value.Int() < KShortIntLimit) + encoder->AddShortIntL((TUint8)value); + else + User::Leave(KErrCorrupt); + + ++partIter; + if (!partIter.AtEnd()) + { + value = partIter()->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TUint8 versionValue = EncodeVersionValueL(value.StrF()); + if (versionValue == 0) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else + encoder->AddShortIntL(versionValue); + } + } + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeExpectL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + if (value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::E100Continue) + encoder->AddTokenL(128); // 100-continue is encoded as + else + { + encoder->StartValueLengthL(); + while (!partIter.AtEnd()) + { + value = partIter()->Value(); + if(value.Type() == THTTPHdrVal::KStrFVal) + { + TPtrC8 valueDes(value.StrF().DesC()); + if (valueDes[0] == 0x22) // Check if we have a quoted-string + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else + encoder->AddTokenTextL(value.StrF().DesC()); + + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *encoder); + ++paramIter; + } + ++partIter; + part = partIter(); + } + else + User::Leave(KErrCorrupt); + } + encoder->EndValueLengthL(); + } + } + else + User::Leave(KErrCorrupt); + } + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodePragmaL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + partIter.First(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TBool requireValueLength = EFalse; + TInt token = EncodeFieldName(aHeader.Name()); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + if (value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::ENoCache) + encoder->AddTokenL(128); // 'No-cache' is encoded as + else + { + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + { + encoder->StartValueLengthL(); + EncodeParameterL(*param, *encoder); + requireValueLength = ETrue; + } + ++paramIter; + } + } + if (requireValueLength) + encoder->EndValueLengthL(); + + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + else + User::Leave(KErrCorrupt); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeProfileDiffL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt partCount = 0; + aHeader.BeginRawDataL(); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + encoder->StartValueLengthL(); + encoder->AddDataL(value.StrF().DesC()); + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeRangeL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + TInt partCount = 0; + aHeader.BeginRawDataL(); + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + encoder->StartValueLengthL(); + TInt rangeValue = value.StrF().Index(WSPStdConstants::Table); + switch (rangeValue) + { + case WSPStdConstants::EByteRange: + { + encoder->AddTokenL(128); // 'Byte-range' is encoded as + } break; + case WSPStdConstants::ESuffixByteRange: + { + encoder->AddTokenL(129); // 'Suffix-byte-range' is encoded as + } break; + default: + User::Leave(KErrCorrupt); + } + // Iterate through the parts that follow + ++partIter; + while (!partIter.AtEnd()) + { + value = partIter()->Value(); + if(value.Type() == THTTPHdrVal::KTIntVal) + { + encoder->AddUintVarL(value); + ++partIter; + } + else if(value.Type() == THTTPHdrVal::KStrFVal) + { + // Found the next header + break; + } + else + User::Leave(KErrCorrupt); + } + encoder->EndValueLengthL(); + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeTEL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + TBool requireValueLength = EFalse; + aHeader.BeginRawDataL(); + TInt partCount = 0; + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + TInt numParam = part->NumParameters(); + if (numParam > 0) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + if (value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::ETrailers) + encoder->AddTokenL(129); // 'Trailers' is encoded as + else + { + if (!requireValueLength) + { + encoder->StartValueLengthL(); + requireValueLength = ETrue; + } + TInt encValue = value.StrF().Index(WSPStdConstants::Table); + switch(encValue) + { + case WSPStdConstants::EChunked: + { + encoder->AddTokenL(130); // 'Chunked' is encoded as + } break; + case WSPStdConstants::EIdentity: + { + encoder->AddTokenL(131); // 'Identity' is encoded as + } break; + case WSPStdConstants::EGzip: + { + encoder->AddTokenL(132); // 'Gzip' is encoded as + } break; + case WSPStdConstants::ECompress: + { + encoder->AddTokenL(133); // 'Compress' is encoded as + } break; + case WSPStdConstants::EDeflate: + { + encoder->AddTokenL(134); // 'Deflate' is encoded as + } break; + default: + { + encoder->AddTokenTextL(value.StrF().DesC()); + } break; + } + + THeaderFieldParamIter paramIter = part->Parameters(); + paramIter.First(); + // Encode any parameters that exist. + // A parameter consists of a Q-token and a Q-value + while (!paramIter.AtEnd()) + { + const CHeaderFieldParam* param = paramIter(); + if (param != NULL) + EncodeParameterL(*param, *encoder); + ++paramIter; + } + if (requireValueLength) + encoder->EndValueLengthL(); + } + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeTrailerL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + TInt partCount = 0; + aHeader.BeginRawDataL(); + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + TInt headerNameVal = EncodeFieldName(value.StrF()); + if (headerNameVal < KShortIntLimit && headerNameVal > KErrNotFound) + encoder->AddShortIntL((TUint8)headerNameVal); + else if (headerNameVal > 127) + encoder->AddLongIntL(headerNameVal); + else + encoder->AddTokenTextL(value.StrF().DesC()); + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeWarningL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KTIntVal) + { + TUint8 warningNumber = 0; + switch(value) + { + case 110: + { + warningNumber = 10; // Warning code 110 is encoded as + } break; + case 111: + { + warningNumber = 11; // Warning code 111 is encoded as + } break; + case 112: + { + warningNumber = 12; // Warning code 112 is encoded as + } break; + case 113: + { + warningNumber = 13; // Warning code 113 is encoded as + } break; + case 199: + case 299: + { + warningNumber = 99; // Warning codes 199 and 299 are encoded as + } break; + case 214: + { + warningNumber = 14; // Warning code 214 is encoded as + } break; + default: + break; + } + + ++partIter; + if (partIter.AtEnd()) // Check to see if we have only one part + encoder->AddShortIntL(warningNumber); + else + { + encoder->StartValueLengthL(); // If there is more than one part then it is + encoder->AddShortIntL(warningNumber); // necessary to work out the value-length + while (!partIter.AtEnd()) + { + value = partIter()->Value(); + if(value.Type() == THTTPHdrVal::KStrFVal) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + ++partIter; + } + else + User::Leave(KErrCorrupt); + } + encoder->EndValueLengthL(); + } + } + else + User::Leave(KErrCorrupt); + } + aHeader.BeginRawDataL(); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeXWapApplicationIdL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else if (value.Type() == THTTPHdrVal::KTIntVal) + { + if (value.Int() < KShortIntLimit) + encoder->AddShortIntL((TUint8)(value.Int())); + else + encoder->AddLongIntL(value.Int()); + } + else + User::Leave(KErrCorrupt); + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.BeginRawDataL(); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + } + CleanupStack::PopAndDestroy(encoder); + } + + +// +// Generic methods +// + +void CWspHeaderWriter::GenericEncodeDateL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + partIter.First(); + if (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KDateVal) + { + encoder->AddDateL(value.DateTime()); + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TPtrC8 data(buffer->Mid(EncodeHeaderNameL(aHeader))); + aHeader.BeginRawDataL(); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + aHeader.CommitRawData(); + } + else + User::Leave(KErrCorrupt); + } + } + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::GenericEncodeTextStringL(RHeaderField& aHeader) const + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + aHeader.BeginRawDataL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt token = EncodeFieldName(aHeader.Name()); + TInt partCount = 0; + partIter.First(); + while (!partIter.AtEnd()) + { + if (token == KErrNotFound) + encoder->StartHeaderL(aHeader.Name().DesC()); + else + encoder->StartHeaderL((TUint8)token); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + { + User::LeaveIfError(CheckTextString(value.StrF())); + encoder->AddTextStringL(value.StrF().DesC()); + } + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + if (partCount == 1) + startPos = EncodeHeaderNameL(aHeader); + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + } + +void CWspHeaderWriter::EncodeParameterL(const CHeaderFieldParam& aHeaderFieldParam, CWspHeaderEncoder& aEncoder) const + { + THTTPHdrVal value = aHeaderFieldParam.Value(); + TInt paramIndex = EncodeParameterTokenValue(aHeaderFieldParam.Name()); + if (paramIndex == KErrNotFound) // This is an untyped parameter + { + // Append the name as a string + aEncoder.AddTokenTextL(aHeaderFieldParam.Name().DesC()); + + // Append the param value + switch(value.Type()) + { + case THTTPHdrVal::KTIntVal: + { + if (value.Int() < KShortIntLimit) + aEncoder.AddShortIntL((TUint8)(value.Int())); + else + aEncoder.AddLongIntL(value.Int()); + } break; + case THTTPHdrVal::KStrFVal: + { + User::LeaveIfError(CheckTextString(value.StrF())); + aEncoder.AddTextStringL(value.StrF().DesC()); + } break; + default: + { + User::Leave(KErrCorrupt); + } break; + } + } + else // This is a typed parameter + { + // Check encoding version and adjust token as neccessary + if (iCodec.GetWspVersion() > CWspHeaderCodec::EVersion1_3) + { + switch (paramIndex) + { + case 0x05: + paramIndex = 0x17; // Name-token is encoded as 0x17 in WSP version 1.4 + break; + case 0x06: + paramIndex = 0x18; // Filename-token is encoded as 0x18 in WSP version 1.4 + break; + case 0x0A: + paramIndex = 0x19; // Start-token is encoded as 0x19 in WSP version 1.4 + break; + case 0x0B: + paramIndex = 0x1A; // Start-info-token is encoded as 0x1A in WSP version 1.4 + break; + case 0x0C: + paramIndex = 0x1B; // Comment-token is encoded as 0x1B in WSP version 1.4 + break; + case 0x0D: + paramIndex = 0x1C; // Domain-token is encoded as 0x1C in WSP version 1.4 + break; + case 0x0F: + paramIndex = 0x1D; // Path-token is encoded as 0x1D in WSP version 1.4 + break; + default: + break; + } + } + // Append the name as an encoded value + aEncoder.AddShortIntL((TUint8)paramIndex); + + // Append the param value + switch(paramIndex) + { + case WSPParam::EQ: + { + HBufC8* qValue = EncodeQValueL(value.StrF()); + if (qValue != NULL) + { + CleanupStack::PushL(qValue); + aEncoder.AddDataL(*qValue); + CleanupStack::PopAndDestroy(qValue); + } + } break; + case WSPParam::ECharset: + { + if (value.StrF().Index(WSPStdConstants::Table) == WSPStdConstants::EAny) + aEncoder.AddTokenL(128); // '*' (Any-charset) is encoded as + else + { + TInt charValue = GetCharacterSetValue(value.StrF()); + User::LeaveIfError(charValue); + if (charValue < KShortIntLimit) + aEncoder.AddShortIntL((TUint8)charValue); + else + aEncoder.AddLongIntL(charValue); + } + } break; + case WSPParam::ELevel: + { + TUint8 versionValue = EncodeVersionValueL(value.StrF()); + if (versionValue == 0) + { + User::LeaveIfError(CheckTextString(value.StrF())); + aEncoder.AddTextStringL(value.StrF().DesC()); + } + else + aEncoder.AddShortIntL(versionValue); + } break; + case WSPParam::EType: + case WSPParam::EContentTypeType: + case WSPParam::ESize: + case WSPParam::EPadding: + case WSPParam::ESEC: + case WSPParam::EMaxAge: + { + if (value.Int() < KShortIntLimit) + aEncoder.AddShortIntL((TUint8)value.Int()); + else + aEncoder.AddLongIntL(value.Int()); + } break; + case WSPParam::ENameDep: + case WSPParam::EFilenameDep: + case WSPParam::EStartDep: + case WSPParam::EStartInfoDep: + case WSPParam::ECommentDep: + case WSPParam::EDomainDep: + case WSPParam::EPathDep: + case WSPParam::EName: + case WSPParam::EFilename: + case WSPParam::EStart: + case WSPParam::EStartInfo: + case WSPParam::EComment: + case WSPParam::EDomain: + case WSPParam::EPath: + case WSPParam::EMAC: + { + TPtrC8 valueDes(value.StrF().DesC()); + if ((iCodec.GetWspVersion() < CWspHeaderCodec::EVersion1_4) || + (valueDes.Length() == 0) || + (valueDes[0] == 0x22)) // Check if we have a quoted-string + { + User::LeaveIfError(CheckTextString(value.StrF())); + aEncoder.AddTextStringL(valueDes); + } + else + { + User::LeaveIfError(CheckTokenText(value.StrF())); + aEncoder.AddTokenTextL(valueDes); + } + } break; + case WSPParam::EDifferences: + { + TInt headerNameVal = EncodeFieldName(value.StrF()); + if (headerNameVal < KShortIntLimit && headerNameVal > KErrNotFound) + aEncoder.AddShortIntL((TUint8)headerNameVal); + else + aEncoder.AddTokenTextL(value.StrF().DesC()); + } break; + case WSPParam::ECreationDate: + case WSPParam::EModificationDate: + case WSPParam::EReadDate: + { + aEncoder.AddDateL(value.DateTime()); + } break; + case WSPParam::ESecure: + { + aEncoder.AddTokenL(0); + } break; + default: + { + aEncoder.AddTokenTextL(value.StrF().DesC()); + } break; + } + } + } + +TInt CWspHeaderWriter::GetCharacterSetValue(RStringF aCharSet) const + { + TInt value = KErrNotFound; + switch(aCharSet.Index(WSPCharacterSets::Table)) + { + case WSPCharacterSets::EBig5: + { + value = 0x07EA; // Character set big5 is encoded as 0x07EA + } break; + case WSPCharacterSets::EIso10646ucs2: + { + value = 0x03E8; // Character set iso-10646-ucs-2 is encoded as 0x03E8 + } break; + case WSPCharacterSets::EIso88591: + { + value = 0x04; // Character set iso-8859-1 is encoded as 0x04 + } break; + case WSPCharacterSets::EIso88592: + { + value = 0x05; // Character set iso-8859-2 is encoded as 0x05 + } break; + case WSPCharacterSets::EIso88593: + { + value = 0x06; // Character set iso-8859-3 is encoded as 0x06 + } break; + case WSPCharacterSets::EIso88594: + { + value = 0x07; // Character set iso-8859-4 is encoded as 0x07 + } break; + case WSPCharacterSets::EIso88595: + { + value = 0x08; // Character set iso-8859-5 is encoded as 0x08 + } break; + case WSPCharacterSets::EIso88596: + { + value = 0x09; // Character set iso-8859-6 is encoded as 0x09 + } break; + case WSPCharacterSets::EIso88597: + { + value = 0x0A; // Character set iso-8859-9 is encoded as 0x0A + } break; + case WSPCharacterSets::EIso88598: + { + value = 0x0B; // Character set iso-8859-8 is encoded as 0x0B + } break; + case WSPCharacterSets::EIso88599: + { + value = 0x0C; // Character set iso-8859-9 is encoded as 0x0C + } break; + case WSPCharacterSets::EShiftJIS: + { + value = 0x11; // Character set shift_JIS is encoded as 0x11 + } break; + case WSPCharacterSets::EUsAscii: + { + value = 0x03; // Character set us-ascii is encoded as 0x03 + } break; + case WSPCharacterSets::EUtf8: + case WSPCharacterSets::EGsmDefaultAlphabet: + { + value = 0x6A; // Character sets utf-8 and gsm-default-alphabet are + } break; // encoded as 0x6A + default: + // Use default value of KErrNotFound + break; + } + return value; + } + +HBufC8* CWspHeaderWriter::EncodeQValueL(RStringF aQValue) const + { + TInt decPointPos = aQValue.DesC().Locate('.'); + if (decPointPos != KErrNotFound) + { + if ((decPointPos + 1) >= aQValue.DesC().Length()) + User::Leave(KErrCorrupt); + TPtrC8 decValue(aQValue.DesC().Mid(decPointPos + 1)); + TLex8 intConvertDes(decValue); + TInt convertedInt = 0; + if (intConvertDes.Val(convertedInt) != KErrNone) + User::Leave(KErrCorrupt); + switch(decValue.Length()) + { + case 1: + convertedInt *= 10; + case 2: + ++convertedInt; + break; + case 3: + convertedInt += 100; + break; + default: + User::Leave(KErrCorrupt); + break; + } + return TWspPrimitiveEncoder::UintVarL(convertedInt); + } + return NULL; + } + +TUint8 CWspHeaderWriter::EncodeVersionValueL(RStringF aVersionValue) const + { + TPtrC8 version(aVersionValue.DesC()); + TInt versionLength = version.Length(); + if (versionLength == 0) + User::Leave(KErrCorrupt); + TInt decimalPos = version.Locate('.'); + TUint8 majorVersion = 0; + TUint8 minorVersion = 0x0F; + if (decimalPos != KErrNotFound) + { + if ((decimalPos + 1) == versionLength) + User::Leave(KErrCorrupt); + TPtrC8 minorDes(version.Mid(decimalPos + 1)); + TLex8 convertMinor(minorDes); + TInt convertedMinor = 0; + if (convertMinor.Val(convertedMinor) != KErrNone) + User::Leave(KErrCorrupt); + if (convertedMinor > 14) // The minor version number must be within the range 0-14 + return 0; + else + minorVersion = (TUint8)convertedMinor; + } + TPtrC8 majorDes; + if (decimalPos == KErrNotFound) + majorDes.Set(version); + else + majorDes.Set(version.Left(decimalPos)); + + TLex8 convertMajor(majorDes); + TInt convertedInt = 0; + if (convertMajor.Val(convertedInt) != KErrNone) + User::Leave(KErrCorrupt); + if (convertedInt > 7) // The major version has a maximum value of 7 + return 0; + else if (convertedInt > 0) // and a minimum value of 1 + majorVersion = (TUint8)convertedInt; + else + User::Leave(KErrCorrupt); + + majorVersion <<= 4; // Shift the bits across by four places so that + // they are the most significant bits + return (TUint8)(majorVersion | minorVersion); + } + +TInt CWspHeaderWriter::EncodeFieldName(RStringF aFieldName) const + { + TInt fieldName = aFieldName.Index(iStrTable); + const CWspHeaderCodec::TWspVersion wspVersion = iCodec.GetWspVersion(); + + // Check WSP version against encoded ranges + switch(wspVersion) + { + case CWspHeaderCodec::EVersion1_1: + { + if(fieldName > 0x2E) // Highest header encoding is 0x2E in v1.1 + fieldName = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_2: + { + if(fieldName > 0x37) // Highest header encoding is 0x2E in v1.2 + fieldName = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_3: + { + if(fieldName > 0x43) // Highest header encoding is 0x2E in v1.3 + fieldName = KErrNotFound; + } break; + default: // version is 1.4 that can encode everything + break; + } + + // Make any value changes based on WSP version + TInt name = fieldName; + switch(fieldName) + { + case WSP::EAcceptCharsetDep: + case WSP::EAcceptCharset: + { + if (wspVersion < CWspHeaderCodec::EVersion1_3) + name = 0x01; // Version 1.1 of Accept-Charset is encoded as 0x01 + else + name = 0x3B; // The current version (1.3) of Accept-Charset is encoded as 0x3B + } break; + case WSP::EAcceptEncodingDep: + case WSP::EAcceptEncoding: + { + if (wspVersion < CWspHeaderCodec::EVersion1_3) + name = 0x02; // Version 1.1 of Accept-Encoding is encoded as 0x02 + else + name = 0x3C; // The current version (1.3) of Accept-Encoding is encoded as 0x3C + } break; + case WSP::ECacheControlDep: + case WSP::ECacheControlDep2: + case WSP::ECacheControl: + { + if (wspVersion < CWspHeaderCodec::EVersion1_3) + name = 0x08; // Version 1.1 of Cache-Control is encoded as 0x08 + else if (wspVersion == CWspHeaderCodec::EVersion1_3) + name = 0x3D; // Version 1.3 of Cache-Control is encoded as 0x3D + else + name = 0x47; // The current version (1.4) of Cache-Control is encoded as 0x47 + } break; + case WSP::EContentRangeDep: + case WSP::EContentRange: + { + if (wspVersion < CWspHeaderCodec::EVersion1_3) + name = 0x10; // Version 1.1 of Content-Range is encoded as 0x10 + else + name = 0x3E; // The current version (1.3) of Content-Range is encoded as 0x3E + } break; + case WSP::EContentDispositionDep: + case WSP::EContentDisposition: + { + if (wspVersion < CWspHeaderCodec::EVersion1_4) + name = 0x2E; // Version 1.1 of Content-Disposition is encoded as 0x2E + else + name = 0x45; // The current version (1.4) of Content-Disposition is encoded as 0x45 + } break; + case WSP::EProfileWarningDep: + case WSP::EProfileWarning: + { + if (wspVersion < CWspHeaderCodec::EVersion1_4) + name = 0x37; // Version 1.2 of Profile-Warning is encoded as 0x37 + else + name = 0x44; // The current version (1.4) of Profile-Warning is encoded as 0x44 + } break; + default: + // Use default return name of fieldName. + break; + } + return name; + } + +TInt CWspHeaderWriter::EncodeHeaderNameL(RHeaderField& aHeader) const + { + TInt headerLength = 0; + TInt headerNameVal = EncodeFieldName(aHeader.Name()); + if (headerNameVal == KErrNotFound) + { + User::LeaveIfError(CheckTokenText(aHeader.Name())); + headerLength = aHeader.Name().DesC().Length(); + } + return ++headerLength; + } + +TInt CWspHeaderWriter::CheckTokenText(RStringF aTokenText) const + { + const TUint8 KMinValidCharValue = 32; // Minimum ASCII value for a valid character + const TUint8 KMaxValidCharValue = 126; // Maximum ASCII value for a valid character + _LIT8(KTxtSeparators, "()<>@,;:\\\"/[]?={} "); // Separator characters as defined in RFC2616 + + // Go through each character in the string ensuring that it is within the acceptable ASCII range + // and then check that the string does not contain any seperator characters. + const TInt tokenTextLength = aTokenText.DesC().Length(); + for (TInt ii = 0; ii < tokenTextLength; ++ii) + { + TUint8 currentChar = aTokenText.DesC()[ii]; + if ((currentChar < KMinValidCharValue) && (currentChar > KMaxValidCharValue)) + return KErrCorrupt; + if (KTxtSeparators().Locate(currentChar) != KErrNotFound) + return KErrCorrupt; + } + return KErrNone; + } + +TInt CWspHeaderWriter::CheckTextString(RStringF aTextString) const + { + const TUint KHorizTab = 9; + const TUint KLinefeed = 10; + const TUint KCarriageReturn = 13; + const TUint KSpace = 32; + const TInt textStringLength = aTextString.DesC().Length(); + for (TInt ii = 0; ii < textStringLength; ++ii) + { + TUint8 currentChar = aTextString.DesC()[ii]; + // Check for an ASCII control character (octets 0-31) or + // an ASCII space character (octet 32), but allow ASCII linear white spce (octets 9, + // 10, 13 and 32) + if (currentChar < 33 && !(currentChar == KHorizTab || currentChar == KLinefeed + || currentChar == KCarriageReturn || currentChar == KSpace)) + { + return KErrCorrupt; + } + // Check for an ASCII delete character (octet 127) + if (currentChar == 127) + return KErrCorrupt; + } + return KErrNone; + } + +TInt CWspHeaderWriter::EncodeContentTypeValue(THTTPHdrVal& aContentType) const + { + TInt encodedToken = aContentType.StrF().Index(WSPContentTypes::Table); + if( encodedToken > KErrNotFound ) + { + // Apply some WSP version control on encoded token + switch (iCodec.GetWspVersion()) + { + case CWspHeaderCodec::EVersion1_1: + { + if( encodedToken > 0x2D ) // Highest content-type encoding is 0x2D in v1.1 + encodedToken = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_2: + { + if( encodedToken > 0x34 ) // Highest content-type encoding is 0x34 in v1.2 + encodedToken = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_3: + { + if( encodedToken > 0x36 ) // Highest content-type encoding is 0x36 in v1.3 + encodedToken = KErrNotFound; + } break; + default: // version is 1.4 that can encode all content-types in string table + break; + } + } + return encodedToken; + } + +TInt CWspHeaderWriter::EncodeParameterTokenValue(RStringF aParameterName) const + { + TInt encodedToken = aParameterName.Index(WSPParam::Table); + if( encodedToken > KErrNotFound ) + { + // Apply some WSP version control on encoded token + switch (iCodec.GetWspVersion()) + { + // Check for maximum encoding token for current WSP version + case CWspHeaderCodec::EVersion1_1: + { + if( encodedToken > 0x08 ) // Highest parameter token encoding is 0x08 in v1.1 + encodedToken = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_2: + { + if( encodedToken > 0x0B ) // Highest parameter token encoding is 0x0b in v1.2 + encodedToken = KErrNotFound; + } break; + case CWspHeaderCodec::EVersion1_3: + { + if( encodedToken > 0x10 ) // Highest parameter token encoding is 0x10 in v1.3 + encodedToken = KErrNotFound; + } break; + default: // version is 1.4 that can encode all parameter tokens in string table + break; + } + } + return encodedToken; + } + +// Implementation of CWspDefaultHdrWriter +//------------------------------------------------------------------------------- + +CWspDefaultHdrWriter* CWspDefaultHdrWriter::NewL(RStringPool aStrPool) + { + return new(ELeave)CWspDefaultHdrWriter(aStrPool); + } + +CWspDefaultHdrWriter* CWspDefaultHdrWriter::NewLC(RStringPool aStrPool) + { + CWspDefaultHdrWriter* self = CWspDefaultHdrWriter::NewL(aStrPool); + CleanupStack::PushL(self); + return self; + } + +CWspDefaultHdrWriter::CWspDefaultHdrWriter(RStringPool aStrPool) + : iStrPool(aStrPool) + { + } + +CWspDefaultHdrWriter::~CWspDefaultHdrWriter() + { + } + +void CWspDefaultHdrWriter::EncodeHeaderL(RHeaderField& aHeader) + { + THeaderFieldPartIter partIter = aHeader.PartsL(); + CWspHeaderEncoder* encoder = CWspHeaderEncoder::NewL(); + CleanupStack::PushL(encoder); + TInt partCount = 0; + aHeader.BeginRawDataL(); + partIter.First(); + // Loop through all the parts and build up the raw data + while (!partIter.AtEnd()) + { + encoder->StartHeaderL(aHeader.Name().DesC()); + const CHeaderFieldPart* part = partIter(); + if (part != NULL) + { + ++partCount; + THTTPHdrVal value = part->Value(); + if (value.Type() == THTTPHdrVal::KStrFVal) + encoder->AddTextStringL(value.StrF().DesC()); + else + User::Leave(KErrCorrupt); + } + + HBufC8* buffer = encoder->EndHeaderL(); + CleanupStack::PushL(buffer); + TInt startPos = 0; + // If this is the first part then don't include the header name + if (partCount == 1) + startPos = (aHeader.Name().DesC().Length()) + 1; + TPtrC8 data(buffer->Mid(startPos)); + aHeader.WriteRawDataL(data); + CleanupStack::PopAndDestroy(buffer); + ++partIter; + } + aHeader.CommitRawData(); + CleanupStack::PopAndDestroy(encoder); + }