servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/inc/CHeaderField.h
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/servicediscoveryandcontrol/pnp/test/upnp/upnpmessage/inc/CHeaderField.h	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,608 @@
+// 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:
+// Declaration of CHeaderField, CHeaderFieldPart, THeaderFieldPartIter, CHeaderFieldParam,
+// and THeaderFieldParamIter classes.
+// 
+//
+
+#ifndef __CHEADERFIELD_H__
+#define __CHEADERFIELD_H__
+
+#include <e32base.h>
+#include <http/thttphdrval.h>
+#include "rhttpheaders.h"
+
+
+
+// The default chunk size for Raw data should be set to the average length of a header field when encoded in
+// plaintext
+const TInt KHttpDefaultRawChunkSize= 32;
+
+
+class CHeaders;
+class CHeaderFieldPart;
+class THeaderFieldPartIter;
+class CHeaderFieldParam;
+class THeaderFieldParamIter;
+class CHeaderCodec;
+
+
+/** Generalised internal representation of a single HTTP header field.  The field's
+	value may be contained as raw data as received by HTTP, or
+	in a object-oriented parsed form, which is accessible to the client via
+	the class API.
+
+	Each field has a type and a (potentially complex) value.  The type must
+	be chosen at construction time, and remains the same during the
+	header's lifetime.
+
+	Simple headers are represented using a single 'part'.  Several factory
+	methods are provided for each type the part can take; e.g.
+	
+	@verbatim
+	Max-Forwards: 3							-- a single integer value
+	Location: http://ayg.com/				-- a single string token value
+	Expires: Mon, 15 Jan 2001 10:30:25 GMT	-- a single date/time value
+	@endverbatim
+	
+	More complex headers are possible (see the RFC2116 for many more examples)
+	which are built up from several parts; e.g.
+	
+	@verbatim
+	Accept: text/wml, application/vnd.wap.wmlc	-- a header with two string token parts
+	Allow: GET, POST, HEAD						-- a header with three string token parts
+	@endverbatim
+	
+	Multiple parts are supported by the CHeaderFieldPart class.
+
+	Furthermore, some headers allow parameters to be supplied in the form of attribute-value
+	pairs.   These may be present on any part of the header, according to the syntax defined
+	in the RFC; e.g.
+	
+	@verbatim
+	Accept-Charset: utf-8; q=0.8, us-ascii; q=0.2
+	Cache-Control: maxage=6000
+	@endverbatim
+	
+	Parameters are supported by the CHeaderFieldParam class.	
+
+    The classes CHeaderField, CHeaderFieldPart and CHeaderFieldParam are internal header representations
+	and will only be manipulated by protocol handlers and filters.  Only the RHTTPHeaders and THTTPHdrVal
+	classes are intended for use by the Client.
+	@see RHTTPHeaders
+	@see THTTPHdrVal
+	@see CHeaderFieldPart
+	@see CHeaderFieldParam
+	*/
+
+class CHeaderField : public CBase
+	{
+friend class THeaderFieldPartIter;
+friend class RHeaderField;
+public:
+	//
+	// Getters
+	//
+
+	/** Obtain the name of the header field, e.g. Accept
+		@return The header field name as a string token
+	*/
+	RStringF Name() const;
+
+	/** Access the header value parts via an iterator
+		@return An iterator constructed to point at the first part
+		@leave KErrNoMemory - insufficient free memory for object creation when decoding parts
+		@leave KErrNotSupported - if decoding when counting parts fails
+	*/
+	THeaderFieldPartIter PartsL();
+
+	/** Get the Raw header representation.  This will flip the internal state of the header,
+		if it's not already in Raw form. Requires a Codec to be set.
+		@param The 8-bit data buffer representing the header in Raw form
+		@leave KErrNoMemory - insufficient free memory for object creation when decoding parts
+		@leave KErrNotSupported - if decoding when counting parts fails
+	*/
+	IMPORT_C
+	void RawDataL(TPtrC8& aRawData);
+
+	//
+	// Setters
+	//
+
+	/** Set a part in the header. It replaces any existing parts at the specified index.
+		Note this is for use only by the header codec, when converting Raw data into parsed header parts from parsed Raw data.
+		This function may leave with any of the system wide error codes, if the attempt to append this part to the internal list
+		fails.
+		@param aPart The part to be added.  The header takes ownership of the new part.
+		@param aIndex The index of the part you are replacing
+	*/
+	//void SetPartL(CHeaderFieldPart* aPart, TInt aIndex);
+
+	/** Start setting Raw data in the header.  Leaves if initial Raw buffer allocation fails. The
+		optional parameter specifies the size to be used for Raw data chunk allocation.
+		Note this is for use only by the header codec. 
+		@leave KErrNoMemory - insufficient free memory buffer allocation
+	*/
+	void BeginRawDataL(TInt aChunkSize = KHttpDefaultRawChunkSize);
+
+	/** Add more Raw data, supplied as a descriptor.  The buffer is extended as necessary.
+		Leaves if buffer allocation fails.
+		Note this is for use only by the header codec. 
+		@leave KErrNoMemory - insufficient free memory buffer allocation
+	*/
+	void WriteRawDataL(const TDesC8& aData);
+
+	/** Add more Raw data, supplied as a single character.  The buffer is extended as necessary.
+		Leaves if buffer allocation fails.
+		Note this is for use only by the header codec. 
+		@leave KErrNoMemory - insufficient free memory buffer allocation
+	*/
+	//void WriteRawDataL(TChar aData);
+
+	/** Commit the Raw data.  The parsed header parts and parameters are removed.
+		Note this is for use only by the header codec.
+	*/
+	void CommitRawData();
+
+
+
+	/** Obtain the number of parts in this header
+		@return The number, as an integer
+		@leave KErrNoMemory - insufficient free memory for object creation when decoding parts
+		@leave KErrNotSupported - if decoding when counting parts fails
+	*/
+	TInt NumPartsL();
+
+
+	/** Create a new header field that has no value yet.
+		@param aHeaderFieldName The header field type.
+		@param aOwner The header fields collection that this field belongs to
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class.
+	*/
+	static CHeaderField* NewL(RStringF aHeaderFieldName, CHeaders& aOwner);
+
+	/** Create a new header field with a single part, whose HTTP value is specified.
+		@param aHeaderFieldName The header field type.
+		@param aOwner The header fields collection that this field belongs to
+		@param aVal The header field value. A copy is taken when storing.
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	static CHeaderField* NewL(RStringF aHeaderFieldName, CHeaders& aOwner, THTTPHdrVal aVal);
+
+	/** Create a new header field from the supplied Raw data using the specified transaction codec.
+		@param aHeaderFieldName The header field type.
+		@param aOwner The header fields collection that this field belongs to
+		@param aRawData The raw data buffer, as a descriptor
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	static CHeaderField* NewL(RStringF aHeaderFieldName, CHeaders& aOwner, const TDesC8& aRawData);
+
+	// Class destructor
+	virtual ~CHeaderField();
+	/** Access the header value parts by index
+		@param aIndex The index of the desired part. 0 references the first one.
+		@return The indexed part, or NULL if the index was invalid.
+		@leave KErrNoMemory - insufficient free memory for object creation when decoding parts
+		@leave KErrNotSupported - if decoding when counting parts fails
+	*/
+	CHeaderFieldPart* PartL(TInt aIndex);
+
+
+	/** Add a part to the header. It is appended after any existing parts. Simple headers
+		have just one part;  they could be constructed using the 'single part' NewL() methods.
+		@param aPart The part to be added.  The header takes ownership of the new part.
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	void AddPartL(CHeaderFieldPart* aPart);
+
+	/** Insert a part into the header. It is inserted at the specified index - i.e. to insert
+		a new part at the start of the header, aIndex should be set to 0.
+		@param aPart The part to be inserted.  The header takes ownership of the new part.
+		@param aIndex The index at which the part is to be inserted.
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	//void InsertPartL(CHeaderFieldPart* aPart, TInt aIndex);
+
+	
+	/** Remove the specified part from the header.
+		@param aPart The part to be removed.  The header deletes the removed part.
+		@return An error code; KErrNone if the removal succeeds or KErrNotFound if it didn't.
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	//TInt RemovePartL(CHeaderFieldPart* aPart);
+
+
+	/** Remove the indexed part from the header
+		@param aIndex An index to the part to be removed.  The header deletes the removed part.
+		@return An error code; KErrNone if the removal succeeds or KErrNotFound if it didn't.
+		@leave KErrNoMemory - insufficient free memory to create an instance of the class, or any classes needed to create subclasses for parsing
+		@leave KErrNotSupported - if decoding for this header field can't be made
+	*/
+	TInt RemovePartL(TInt aIndex);
+private: // methods
+
+	//
+	// Internal format conversion
+	//
+
+	/** Create an Raw encoding of the header's field name and value. This is done
+		using the Codec, which must be supplied prior to this call.	The part data is removed
+		after conversion to the Raw format.
+		@leave KErrNotSupported if a codec that supports encoding this header cannot be found
+	*/
+	void ConvertToRawFormatL();
+
+	/** Create the part objects that represent the header field's value, by parsing the 
+		Raw data received by HTTP.  The Raw data is removed after conversion completes
+		successfully.
+		@leave KErrNotSupported if a codec that supports encoding this header cannot be found
+	*/
+	void ConvertToParsedFormatL();	
+
+	/** Standard constructor.  Used when client constructs headers.
+		@param aHeaderFieldName A string table reference to the header field's name.
+		@param aOwner The header fields collection that this field belongs to
+		@return The constructed instance of CHeaderField
+	*/
+	CHeaderField(RStringF aHeaderFieldName, CHeaders& aOwner);
+
+	/** Phase Two construction. This variant copies-to-keep the supplied Raw data buffer.
+		@param aRawData An 8-bit buffer containing raw header data received by HTTP.
+	*/
+	void ConstructL(const TDesC8& aRawData);
+
+	// Empty and destroy contents of the 'parts' array.
+	void ClearParsedData();
+
+	// Empty and destroy any Raw data held
+	void ClearRawData();
+
+private: // types and enums
+
+	/** Enumeration of the states in which this header's value data can exist.
+	*/
+	enum TDataState
+		{
+		ENoDataSupplied	= 0x00, /**< the header object is not populated with data after construction*/
+		EDataInRawForm	= 0x01, /**< the data is in it's raw form, i.e. not accessible by part*/
+		EDataParsedOK	= 0x02, /**< the data is in it's client representation, i.e. parsed into parts.	*/
+		EDataParseError	= 0x03  /**< the data could not be parsed so remains in Raw form*/
+		};
+
+private: // attributes
+
+	/**  Name of this header (a reference into the string table) 
+	*/
+	RStringF iName;
+
+	/** Has this header been parsed yet? did it parse correctly?
+	*/
+	TDataState iDataParseState;
+
+	/**  Headers collection that owns this field
+	*/
+	CHeaders* iOwner;
+
+	/** Header data - in Raw format.
+	*/
+	HBufC8* iRawData;
+
+	/** Header data - in parsed format.
+	*/
+	RPointerArray<CHeaderFieldPart> iParts;
+	
+	/** Codec used to convert this header
+	*/
+	const CHeaderCodec& iCodec;
+
+	/** Size of data chunk used when allocating and extending the Raw data buffer
+	*/
+	TInt iRawChunkSize;
+	};
+
+
+
+
+/** Generalised representation of a single HTTP header value part.  The part takes a
+	value of one of the following three types:
+
+	- integer, signed (i.e. can be -ve or +ve)
+	- string token, which can represent free text (i.e. text with no special meaning; ETags; MD5 hashes;
+	  MIME types, etc.), enumerations (words with special meanings such as 'private', 'close', ') or URLs
+	- Date/Time
+
+	In addition the part may have one or more parameters.  These take the form of
+	attribute-value pairs.  They are implemented by the CHeaderFieldParam class.
+*/
+class CHeaderFieldPart : public CBase
+	{
+friend class THeaderFieldParamIter;
+
+public:
+	/** Create a new part, for the supplied HTTP value 
+		@param aVal The HTTP value for this part of the header field. A copy is taken when storing.
+		@return The constructed instance of CHeaderFieldPart.
+	*/
+	IMPORT_C
+	static CHeaderFieldPart* NewL(THTTPHdrVal aVal);
+
+	// Class destructor
+	virtual ~CHeaderFieldPart();
+
+	//
+	// Getters
+	//
+
+	/** Obtain the value held in this field part.  The caller must call Copy() on the returned THTTPHdrVal
+		if it is going to be stored.  This is needed in order to correctly maintain string references.
+		@return The field part's HTTP value
+	*/
+	IMPORT_C
+	THTTPHdrVal Value() const;
+
+	/** Obtain the number of parameters in this header
+		@return The number, as an integer
+	*/ 
+	IMPORT_C
+	TInt NumParameters() const;
+
+	/** Access the parameters in this header part via an iterator
+		@return An iterator constructed to point at the first parameter
+	*/
+	IMPORT_C
+	THeaderFieldParamIter Parameters() const;
+
+	/** Access the header parameters by index
+		@param aIndex The index of the desired parameter. 0 references the first one.
+		@return The indexed parameter, or NULL if the index was invalid.
+	*/
+	//CHeaderFieldParam* Parameter(TInt aIndex) const;
+
+	/** Access the header parameters by parameter name
+		@param aParamName The name of the desired part.
+		@return The named parameter, or NULL if it doesn't exist.
+	*/
+	CHeaderFieldParam* Parameter(RStringF aParamName) const;
+
+	//
+	// Setters
+	//
+
+	/** Change the value held in this field part
+		@param  The HTTP value. It is copied in order to store it.
+	*/
+	//void SetValue(THTTPHdrVal aVal);
+
+	/** Add a parameter to the header part. It is appended after any existing
+		parameters.
+		@param aParam The parameter to be added.  The header takes ownership of the
+					  new parameter.
+	*/
+	IMPORT_C
+	void AddParamL(CHeaderFieldParam* aParam);
+
+	/** Remove the specified parameter from the header part.
+		@param aParam The parameter to be removed.  The header deletes the removed
+					  parameter.
+		@return An error code; KErrNone if the removal succeeds or KErrNotFound if
+				it didn't.
+	*/
+	//TInt RemoveParam(CHeaderFieldParam* aParam);
+
+private: // methods
+
+	// Default constructor. 
+	CHeaderFieldPart(THTTPHdrVal aVal);
+
+private: // attributes
+
+	// The value of this part of the header field
+	THTTPHdrVal iValue;
+
+	// Parameters for this part.
+	RPointerArray<CHeaderFieldParam> iParams;
+	};
+
+
+/** Generalised representation of a single HTTP header parameter.  The parameter has
+	a name and takes a value using one of the three types supported in CHeaderFieldPart.
+
+	Special case:
+	- an unnamed parameter with an assigned value
+
+	Examples of the use for this special case are:
+
+	@verbatim
+	Cache-Control: max-stale [=delta-seconds]
+	Expect: expectation1=value1; expectation2=value2
+	Content-Range: bytes 0-1023/4096
+	@endverbatim
+
+	Cache-Control's max-stale directive can take an optional value; hence the client
+	should create a one-part header where the part is an enumeration value 'max-stale',
+	and assign to that part an un-named parameter for the delta-seconds value if it is
+	desired.
+
+	Expect's sets of expectation expressions should each be added by the client as a
+	separate part, each of which is given an unnamed parameter that takes the
+	expectation	value.
+
+	Content-Range should have one part added containing the enumeration 'bytes'.  Three
+	parameters should be defined for that part: 'first', 'last' and 'total' which take
+	the values in the byte-range.  This is, of course, application-specific and similar
+	guidelines might be adopted by the parser to represent other headers.
+	*/
+
+class CHeaderFieldParam : public CBase
+	{
+public: // methods
+
+	/** Create a new header parameter that has a descriptor value. 
+		@param aParamName The name of the parameter, as a string table
+						  reference. Can be an empty string.
+		@param aVal The HTTP value of the parameter. A copy is taken when storing.
+		@return The constructed instance of CHeaderFieldParam
+	*/
+	IMPORT_C
+	static CHeaderFieldParam* NewL(RStringF aParamName, THTTPHdrVal aVal);
+
+	// Class destructor
+	virtual ~CHeaderFieldParam();
+
+	//
+	// Getters
+	//
+
+	/** Obtain the name of the parameter, e.g. q
+	    @return String table reference to the name
+	*/
+	IMPORT_C
+	RStringF Name() const;
+
+	/** Obtain the value of the parameter.  The caller must call Copy() on the returned THTTPHdrVal
+		if it is going to be stored.  This is needed in order to correctly maintain string references.
+		@return The parameter's HTTP value
+	*/
+	IMPORT_C
+	THTTPHdrVal Value() const;
+
+	//
+	// Setters
+	//
+
+	/** Change the value held in this field parameter
+		@param  The HTTP value
+	*/
+	//void SetValue(THTTPHdrVal aVal);
+
+private: // methods
+
+	/** Default constructor. 
+	*/
+	CHeaderFieldParam(RStringF aName, THTTPHdrVal aVal);
+
+private: // attributes
+
+	// A string table reference for the name of this parameter
+	RStringF iName;
+
+	// The value of this part of the header field
+	THTTPHdrVal iValue;
+	};
+
+/** Iterator class to iterate the parts contained within a header field. Requires friendship with
+	CHeaderField and as such is tightly bound to that class.
+*/
+class THeaderFieldPartIter
+	{
+public:
+	/** Construct an iterator for the parts of the supplied header.
+		@param aHeader The header whose parts we want to iterate
+	*/
+	THeaderFieldPartIter(const CHeaderField* aHeader);
+	/** Class destructor
+	*/
+
+	/** Reset iterator to point at the first part of the header
+	*/
+	IMPORT_C
+	void First();
+	/** Check if the iterator is at the end of the list. If so, further calls to
+	    operator() will return NULL.
+		@return True if the iterator has hit the end of the parts list
+	*/
+	IMPORT_C
+	TBool AtEnd();
+
+	/** Advance the iterator.
+	*/
+	IMPORT_C
+	void operator++();
+	/** Obtain the header part currently pointed at by the iterator.
+		@return The header part;  NULL if the iterator has gone off the end of the list
+	*/
+	IMPORT_C
+	const CHeaderFieldPart* operator()();
+
+private:
+
+	/** Check the iterator state for invalidity following deletions in the list
+	*/
+	void CheckInvalidation();
+
+	/** The header whose parts we are iterating.
+	*/
+	const CHeaderField* iHeader;
+
+	/** The index of the part in the header that is currently pointed at by the iterator
+	*/
+	TInt iPosIdx;
+	};
+
+/** Iterator class to iterate the parameters contained within a header part. Requires friendship with
+	CHeaderFieldPart and as such is tightly bound to that class.
+*/
+class THeaderFieldParamIter
+	{
+public:
+	/** Construct an iterator for the parameterss of the supplied header part.
+		@param aHeaderPart The header part whose parameters we want to iterate
+	*/
+	THeaderFieldParamIter(const CHeaderFieldPart* aHeaderPart);
+	/** Class destructor
+	*/
+	IMPORT_C
+	~THeaderFieldParamIter();
+
+	/** Reset iterator to point at the first part of the header
+	*/
+	IMPORT_C
+	void First();
+	/** Check if the iterator is at the end of the list. If so, further calls to
+	    operator() will return NULL.
+	*/
+	IMPORT_C
+	TBool AtEnd();
+
+	/** Advance the iterator.
+		@return True if the iterator still points at a valid parameter after advancing.
+	*/
+	IMPORT_C
+	void operator++();
+	/** Obtain the header parameter currently pointed at by the iterator.
+		@return The header parameter;  NULL if the iterator has gone off the end of the list
+	*/
+	IMPORT_C
+	const CHeaderFieldParam* operator()();
+
+private:
+
+	/** Check the iterator state for invalidity following deletions in the list
+	*/
+	void CheckInvalidation();
+
+	/** The header part whose parameters we are iterating.
+	*/
+	const CHeaderFieldPart* iHeaderPart;
+	/** The index of the parameter in the header part that is currently pointed at by the iterator
+	*/
+	TInt iPosIdx;
+	};
+
+#endif // __CHEADERFIELD_H__