diff -r 000000000000 -r f5a58ecadc66 servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/src/CHeaders.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/src/CHeaders.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,419 @@ +// Copyright (c) 2008-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 + +// Local includes +#include "CHeaderField.h" +#include "CHeaders.h" +#include "rhttpheaders.h" +#include "tupnpmessagepanic.h" + + +CHeaders* CHeaders::NewL(CHeaderCodec& aCodec) + { + CHeaders* me = new(ELeave)CHeaders(aCodec); + return me; + } + +CHeaders::~CHeaders() + { + PurgeFields(); + iFields.Close(); + } + +RHTTPHeaders CHeaders::Handle() + { + RHTTPHeaders handle; + handle.iImplementation = this; + return handle; + } + + +// create or append a field part for the named field and assigned value +void CHeaders::SetFieldL(RStringF aFieldName, THTTPHdrVal aFieldValue) + { + CHeaderField& field = CreateOrLookupFieldL(aFieldName); + + // Create a part for the value supplied + CHeaderFieldPart* part = CHeaderFieldPart::NewL(aFieldValue); + CleanupStack::PushL(part); + field.AddPartL(part); + CleanupStack::Pop(part); + } + +// create or append a field part with parameter, for the specified field, parameter and associated values +void CHeaders::SetFieldL(RStringF aFieldName, THTTPHdrVal aFieldValue, + RStringF aParamName, THTTPHdrVal aParamValue) + { + CHeaderField& field = CreateOrLookupFieldL(aFieldName); + + // Check whether a part with the supplied value already exists, if so then the API semantics are that + // an additional parameter should be set on that part. Otherwise a new part will be created. + THeaderFieldPartIter iter = field.PartsL(); + iter.First(); + CHeaderFieldPart* part = NULL; + while (!iter.AtEnd()) + { + const CHeaderFieldPart* pt = iter(); + if (pt->Value() == aFieldValue) + part = CONST_CAST(CHeaderFieldPart*, pt); + ++iter; + } + + // Create a part only if the match didn't occur + if (!part) + { + part = CHeaderFieldPart::NewL(aFieldValue); + CleanupStack::PushL(part); + field.AddPartL(part); + CleanupStack::Pop(part); + } + + // Create a parameter for the value supplied + CHeaderFieldParam* param = CHeaderFieldParam::NewL(aParamName, aParamValue); + CleanupStack::PushL(param); + part->AddParamL(param); + CleanupStack::Pop(param); + } + +// Set a named field in the header to contain the supplied Raw data. Any existing header field of +// this name will be lost. +void CHeaders::SetRawFieldL(RStringF aFieldName, const TDesC8& aRawFieldData, const TDesC8& aFieldSeparator) + { + // See if field exists + TInt idx = LocateFieldName(aFieldName); + + if (idx == KErrNotFound) + { + // create a new one using the field name + CHeaderField* hdr = CHeaderField::NewL(aFieldName, *this, aRawFieldData); + CleanupStack::PushL(hdr); + DoInsertInNameOrderL(hdr, aFieldName); + CleanupStack::Pop(hdr); + } + else + { + CHeaderField* field = iFields[idx].iField; + TPtrC8 originalRawData; + field->RawDataL(originalRawData); + + // add the new raw data to the existing field using the aFieldSeparator param as a separator + HBufC8* newRawDataBuf = HBufC8::NewLC(originalRawData.Length() + aFieldSeparator.Length() + aRawFieldData.Length()); + TPtr8 newRawDataPtr = newRawDataBuf->Des(); + newRawDataPtr.Append(originalRawData); + newRawDataPtr.Append(aFieldSeparator); + newRawDataPtr.Append(aRawFieldData); + field->BeginRawDataL(); + field->WriteRawDataL(*newRawDataBuf); + field->CommitRawData(); + CleanupStack::PopAndDestroy(newRawDataBuf); + } + } + +// Remove, entirely, the named header field from the header collection. All its parts and +// associated parameters (where they exist) are also removed +TInt CHeaders::RemoveField(RStringF aFieldName) + { + // Locate the name first - give up straight away if the field isn't found + TInt idx = LocateFieldName(aFieldName); + if (idx < 0) + return idx; + + __ASSERT_DEBUG(idx < iFields.Count(), TUPnPMessagePanic::Panic(TUPnPMessagePanic::EHeaderFieldMissing)); + // destroy the header field + CHeaderField* field = iFields[idx].iField; + iFields.Remove(idx); + delete field; + + return KErrNone; + } + +TInt CHeaders::RemoveFieldPartL(RStringF aFieldName, TInt aIndex) + { + TInt idx = LocateFieldName(aFieldName); + if (idx == KErrNotFound) + return idx; + + CHeaderField* field = iFields[idx].iField; + field->RemovePartL(aIndex); + + if (field->NumPartsL() == 0) + { + iFields.Remove(idx); + delete field; + } + return KErrNone; + } + +void CHeaders::RemoveAllFields() + { + PurgeFields(); + iFields.Reset(); + } + +// Obtain the number of parts in the named header field's value, Simple headers are created with a single part +// following one call to SetFieldL. Subsequent calls to SetFieldL create additional parts with the field exists +// already +TInt CHeaders::FieldPartsL(RStringF aFieldName) const + { + TInt idx = LocateFieldName(aFieldName); + if (idx == KErrNotFound) + return 0; + + CHeaderField* field = iFields[idx].iField; + return field->NumPartsL(); + } + +// Obtain the named header field's value. Optionally, the index of a part within the field +// may be specified. Parts are indexed from zero +TInt CHeaders::GetField(RStringF aFieldName, TInt aPartIdx, THTTPHdrVal& aHeaderValue) const + { + TInt error = KErrNone; + CHeaderFieldPart* part = NULL; + TRAPD(err, part = GetFieldPartL(aFieldName, aPartIdx)); + if (err) + return err; + + if (part) + aHeaderValue = part->Value(); + else + error = KErrNotFound; + return error; + } + +// Obtain the raw representation of the named header field's value. +TInt CHeaders::GetRawField(RStringF aFieldName, TPtrC8& aRawFieldData) const + { + TInt idx = LocateFieldName(aFieldName); + if (idx < 0) + return idx; + CHeaderField* field = iFields[idx].iField; + TRAPD(err,field->RawDataL(aRawFieldData)); + + if (err == KErrNone) + { + TInt newLinePos = aRawFieldData.Locate('\n'); + if (newLinePos != KErrNotFound) + { + aRawFieldData.Set(aRawFieldData.Left(newLinePos)); + } + } + + return err; + } + + +// Obtain the value of a named parameter, associated with the named header field. An optional index to a part +// within the header field may be supplied, if not it is assumed that it is the first part +THTTPHdrVal CHeaders::GetParam(RStringF aFieldName, RStringF aParamName, + THTTPHdrVal& aValue, TInt aPartIdx) const + { + CHeaderFieldParam* param = GetFieldParameter(aFieldName, aParamName, aPartIdx); + if (param == NULL) + return KErrNotFound; + aValue = param->Value(); + return 0; + } + +// Set a param, overwriting one if it exists +void CHeaders::SetParamL(RStringF aFieldName, RStringF aParamName,THTTPHdrVal aParamValue, TInt aPartIdx) + { + // Locate the name first + TInt idx = LocateFieldName(aFieldName); + User::LeaveIfError(idx); + CHeaderField* field = iFields[idx].iField; + CHeaderFieldPart* part = field->PartL(aPartIdx); + CHeaderFieldParam* param = CHeaderFieldParam::NewL(aParamName, aParamValue); + CleanupStack::PushL(param); + part->AddParamL(param); + CleanupStack::Pop(param); + } + + +// create an iterator initialised for this header collection +THTTPHdrFieldIter CHeaders::Fields() const + { + return THTTPHdrFieldIter(this); + } + +// Obtain the index in the CHeaderField/RStringF arrays for the named header +TInt CHeaders::LocateFieldName(RStringF aHeaderName) const + { + // Locate the name first in the array of field names + const TInt count = iFields.Count(); + for (TInt ii = 0; ii < count; ++ii) + { + if (iFields[ii].iFieldName == aHeaderName) + return ii; + } + return KErrNotFound; + } + +// Check if a named header field exists. If so, return it. If not, create it. +CHeaderField& CHeaders::CreateOrLookupFieldL(RStringF aFieldName) + { + // Locate the name first + TInt idx = LocateFieldName(aFieldName); + + // If the header was found, return it. If no header matched, create + // one for that field name + CHeaderField* found = NULL; + if (idx != KErrNotFound) + { + found = iFields[idx].iField; + } + else + { + CHeaderField* hdr = CHeaderField::NewL(aFieldName, *this); + CleanupStack::PushL(hdr); + DoInsertInNameOrderL(hdr, aFieldName); + CleanupStack::Pop(hdr); + found = hdr; + } + return *found; + } + +// Get the indexed part of the named field, if it exists +CHeaderFieldPart* CHeaders::GetFieldPartL(RStringF aFieldName, TInt aPartIdx) const + { + // check the field really exists + TInt idx = LocateFieldName(aFieldName); + User::LeaveIfError(idx); + + CHeaderField* field = iFields[idx].iField; + CHeaderFieldPart* part = field->PartL(aPartIdx); + return part; + } + +// Get the named parameter from the named field, if it exists +CHeaderFieldParam* CHeaders::GetFieldParameter(RStringF aFieldName, RStringF aParamName, TInt aPartIdx) const + { + // get the part and look up the named parameter + CHeaderFieldPart* part = NULL; + TRAPD(err, part = GetFieldPartL(aFieldName, aPartIdx)); + if (part && !err) + return part->Parameter(aParamName); + + if (err == KErrNotFound) + return NULL; + else + { + // find out what circumstances this might occur in. non-existent field is fine; + // however if GetFieldPartL left then there might be a decoding error that should + // be reported somehow. + __DEBUGGER(); + return NULL; + } + } + + +void CHeaders::DoInsertInNameOrderL(CHeaderField* aHeader, RStringF aHeaderName) + { + THeaderFieldNamePair field; + field.iFieldName = aHeaderName; + field.iField = aHeader; + TLinearOrder sortKey(THeaderFieldNamePair::CompareFieldNames); + User::LeaveIfError(iFields.InsertInOrder(field,sortKey)); + } + + +TInt CHeaders::THeaderFieldNamePair::CompareFieldNames(const THeaderFieldNamePair& aField1, + const THeaderFieldNamePair& aField2) + { + TInt val1 = KErrNone; + TInt val2 = KErrNone; + + RStringF header1 = aField1.iFieldName; + RStringPool pool1 = aField1.iFieldName.Pool(); + + RStringF nts1 = pool1.StringF(UPnP::ENTS, TUPnPTable::Table()); + RStringF nt1 = pool1.StringF(UPnP::ENT, TUPnPTable::Table()); + RStringF usn1 = pool1.StringF(UPnP::EUSN, TUPnPTable::Table()); + RStringF mx1 = pool1.StringF(UPnP::EMX, TUPnPTable::Table()); + RStringF st1 = pool1.StringF(UPnP::EST, TUPnPTable::Table()); + RStringF timeout1 = pool1.StringF(UPnP::ETimeout, TUPnPTable::Table()); + RStringF seq1 = pool1.StringF(UPnP::ESEQ, TUPnPTable::Table()); + RStringF man1 = pool1.StringF(UPnP::EMAN, TUPnPTable::Table()); + RStringF soapaction1 = pool1.StringF(UPnP::ESoapAction, TUPnPTable::Table()); + RStringF ext1 = pool1.StringF(UPnP::EExt, TUPnPTable::Table()); + RStringF sid1 = pool1.StringF(UPnP::ESID, TUPnPTable::Table()); + RStringF callback1 = pool1.StringF(UPnP::ECallback, TUPnPTable::Table()); + + RStringF header2 = aField2.iFieldName; + RStringPool pool2 = aField2.iFieldName.Pool(); + + RStringF nts2 = pool2.StringF(UPnP::ENTS, TUPnPTable::Table()); + RStringF nt2 = pool2.StringF(UPnP::ENT, TUPnPTable::Table()); + RStringF usn2 = pool2.StringF(UPnP::EUSN, TUPnPTable::Table()); + RStringF mx2 = pool2.StringF(UPnP::EMX, TUPnPTable::Table()); + RStringF st2 = pool2.StringF(UPnP::EST, TUPnPTable::Table()); + RStringF timeout2 = pool2.StringF(UPnP::ETimeout, TUPnPTable::Table()); + RStringF seq2 = pool2.StringF(UPnP::ESEQ, TUPnPTable::Table()); + RStringF man2 = pool2.StringF(UPnP::EMAN, TUPnPTable::Table()); + RStringF soapaction2 = pool2.StringF(UPnP::ESoapAction, TUPnPTable::Table()); + RStringF ext2 = pool2.StringF(UPnP::EExt, TUPnPTable::Table()); + RStringF sid2 = pool2.StringF(UPnP::ESID, TUPnPTable::Table()); + RStringF callback2 = pool2.StringF(UPnP::ECallback, TUPnPTable::Table()); + + if( + ((header1.DesC().Compare(nts1.DesC()) == 0)||(header1.DesC().Compare(nt1.DesC()) == 0)|| + (header1.DesC().Compare(usn1.DesC()) == 0)||(header1.DesC().Compare(mx1.DesC()) == 0)|| + (header1.DesC().Compare(st1.DesC()) == 0)||(header1.DesC().Compare(timeout1.DesC()) == 0)|| + (header1.DesC().Compare(seq1.DesC()) == 0)||(header1.DesC().Compare(man1.DesC()) == 0)|| + (header1.DesC().Compare(soapaction1.DesC()) == 0)||(header1.DesC().Compare(ext1.DesC()) == 0)|| + (header1.DesC().Compare(sid1.DesC()) == 0)||(header1.DesC().Compare(callback1.DesC()) == 0))&& + ((header2.DesC().Compare(nts2.DesC()) == 0)||(header2.DesC().Compare(nt2.DesC()) == 0)|| + (header2.DesC().Compare(usn2.DesC()) == 0)||(header2.DesC().Compare(mx2.DesC()) == 0)|| + (header2.DesC().Compare(st2.DesC()) == 0)||(header2.DesC().Compare(timeout2.DesC()) == 0)|| + (header2.DesC().Compare(seq2.DesC()) == 0)||(header1.DesC().Compare(man2.DesC()) == 0)|| + (header2.DesC().Compare(soapaction2.DesC()) == 0)||(header2.DesC().Compare(ext2.DesC()) == 0)|| + (header2.DesC().Compare(sid2.DesC()) == 0)||(header2.DesC().Compare(callback2.DesC()) == 0)) + ) + + { + val1 = aField1.iFieldName.Index(TUPnPTable::Table()); + val2 = aField2.iFieldName.Index(TUPnPTable::Table()); + } + else + { + val1 = aField1.iFieldName.Index(THTTPTable::Table()); + val2 = aField2.iFieldName.Index(THTTPTable::Table()); + } + + if (val1 != KErrNotFound && val2 != KErrNotFound) + return val1 - val2; + else if (val1 != KErrNotFound) + return -1; + else if (val2 != KErrNotFound) + return 1; + else + return aField1.iFieldName.DesC().Ptr() - + aField2.iFieldName.DesC().Ptr(); + } + + +void CHeaders::PurgeFields() + { + const TInt count = iFields.Count(); + for (TInt ii = 0; ii< count; ++ii) + { + delete iFields[ii].iField; + } + } +