applayerpluginsandutils/httpprotocolplugins/httpheadercodec/chttpgeneralheaderwriter.cpp
changeset 0 b16258d2340f
child 17 8f055b80aa5b
child 23 ea9c9681bbaf
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "chttpgeneralheaderwriter.h"
       
    17 
       
    18 #include <http/rhttpsession.h>
       
    19 #include <httpstringconstants.h>
       
    20 #include <httperr.h>
       
    21 
       
    22 #include "CHeaderField.h"
       
    23 
       
    24 _LIT8(KSemiSpaceSep,"; ");
       
    25 
       
    26 CHttpGeneralHeaderWriter* CHttpGeneralHeaderWriter::NewL(RStringPool aStringPool)
       
    27 /** 
       
    28 	Factory constructor.
       
    29 	@internalComponent
       
    30 	@param		aStringPool	The current string pool.
       
    31 	@return		A pointer to a fully initialised object.
       
    32 	@leave		KErrNoMemory	Not enough memory to create object.
       
    33 */
       
    34 	{
       
    35 	return new(ELeave)CHttpGeneralHeaderWriter(aStringPool);
       
    36 	}
       
    37 
       
    38 CHttpGeneralHeaderWriter::~CHttpGeneralHeaderWriter()
       
    39 /**
       
    40 	Destructor
       
    41 	@internalComponent
       
    42 */
       
    43 	{
       
    44 	}
       
    45 
       
    46 CHttpGeneralHeaderWriter::CHttpGeneralHeaderWriter(RStringPool aStringPool)
       
    47 : CHttpHeaderWriter(aStringPool)
       
    48 /**
       
    49 	Constructor
       
    50 	@internalComponent
       
    51 	@param		aStringPool	The current string pool.
       
    52 */
       
    53 	{
       
    54 	}
       
    55 
       
    56 void CHttpGeneralHeaderWriter::EncodeCacheControlL(RHeaderField& aHeader) const
       
    57 /**
       
    58 	Encodes a Cache-Control header. RFC 2616 section 14.9 - 
       
    59 
       
    60 		Cache-Control			=	"Cache-Control" ":" 1#cache-directive
       
    61 		cache-directive			=	cache-request-directive 
       
    62 								|	cache-response-directive
       
    63 		cache-request-directive	=	"no-cache" 
       
    64 								|	"no-store" 
       
    65 								|	"max-age" "=" delta-seconds
       
    66 								|	"max-stale" [ "=" delta-seconds ] 
       
    67 								|	"min-fresh" "=" delta-seconds 
       
    68 								|	"no-transform" 
       
    69 								|	"only-if-cached" 
       
    70 								|	cache-extension
       
    71 
       
    72 		cache-response-directive=	"public" 
       
    73 								|	"private" [ "=" <"> 1#field-name <"> ] 
       
    74 								|	"no-cache" [ "=" <"> 1#field-name <"> ]
       
    75 								|	"no-store" 
       
    76 								|	"no-transform"
       
    77 								|	"must-revalidate"
       
    78 								|	"proxy-revalidate"
       
    79 								|	"max-age" "=" delta-seconds
       
    80 								|	"s-maxage" "=" delta-seconds
       
    81 								|	cache-extension
       
    82 
       
    83 		cache-extension			=	token [ "=" ( token | quoted-string ) ]
       
    84 
       
    85 	The cache-control header value is a comma separated list of values with at
       
    86 	least one value.
       
    87 	@internalComponent
       
    88 	@param		aHeader	The cache-control header field to encode.
       
    89 	@leave		CHttpWriter::DoTokenCsvListHeaderL
       
    90 	@todo		Is there any point in this? Why not call DoTokenCsvListHeaderL()
       
    91 				directly
       
    92 */
       
    93 	{
       
    94 	DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeCacheControl);
       
    95 	}
       
    96 
       
    97 void CHttpGeneralHeaderWriter::EncodeConnectionL(RHeaderField& aHeader) const
       
    98 /**
       
    99 	Decodes the Connection header. RFC2616 section 14.10 - 
       
   100 
       
   101 		Connection = "Connection" ":" 1#(connection-token)
       
   102 		connection-token  = token
       
   103 	The connection header value is a comma separated list of values with at least
       
   104 	one value.
       
   105 	@internalComponent
       
   106 	@param		aHeader	The connection header field to encode.
       
   107 	@leave		CHttpWriter::DoTokenCsvListHeaderL
       
   108 	@todo		Is there any point in this? Why not call DoTokenCsvListHeaderL()
       
   109 				directly
       
   110 */
       
   111 	{
       
   112 	DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeConnection);
       
   113 	}
       
   114 
       
   115 void CHttpGeneralHeaderWriter::EncodeDateL(RHeaderField& aHeader) const
       
   116 /**
       
   117 	Encodes the date header. RFC2616 section 14.18 - 
       
   118 
       
   119 		Date		=	"Date" ":" HTTP-Date
       
   120 
       
   121 	The HTTP-Date format has a few formats. E.g. Date: Tue, 15 Nov 1994 08:12:31 GMT
       
   122 	@internalComponent
       
   123 	@param		aHeader	The date header field to encode.
       
   124 	@leave		CHttpWriter::EncodeGenericDateL
       
   125 	@todo		Is there any point in this? Why not call EncodeGenericDateL()
       
   126 				directly
       
   127 */
       
   128 	{
       
   129 	EncodeGenericDateL(aHeader, KErrHttpEncodeDate);
       
   130 	}
       
   131 
       
   132 void CHttpGeneralHeaderWriter::EncodeTransferEncodingL(RHeaderField& aHeader) const
       
   133 /**
       
   134 	Encodes the transfer-encoding header. RFC2616 section 14.41 -
       
   135 
       
   136 		Transfer-Encoding       =	"Transfer-Encoding" ":" 1#transfer-coding
       
   137 		transfer-coding         =	"chunked" | transfer-extension
       
   138 		transfer-extension      =	token *( ";" parameter )
       
   139 		parameter               =	attribute "=" value
       
   140 		attribute               =	token
       
   141 		value                   =	token | quoted-string
       
   142 
       
   143 	The transfer-encoding header is a comma separated list of values with at 
       
   144 	least one value.
       
   145 	@internalComponent
       
   146 	@param		aHeader	The transfer-encoding header field to encode.
       
   147 	@leave		CHttpWriter::DoTokenCsvListHeaderL
       
   148 	@todo		Is there any point in this? Why not call DoTokenCsvListHeaderL()
       
   149 				directly
       
   150 */
       
   151 	{
       
   152 	DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeTransferEncoding);
       
   153 	}
       
   154 
       
   155 void CHttpGeneralHeaderWriter::EncodeContentTypeL(RHeaderField& aHeader) const
       
   156 /**
       
   157 	Encodes the content-type header. RFC2616 section 14.17
       
   158 
       
   159 		Content-Type			=	"Content-Type" ":" media-type
       
   160 		media-type				=	type "/" subtype *( ";" parameter )
       
   161 		type					=	token
       
   162 		subtype					=	token
       
   163 		parameter				=	attribute '=' value
       
   164 		attribute               =	token
       
   165 		value                   =	token | quoted-string
       
   166 	
       
   167 	The content-type header has a single media-type value. The atttribute 
       
   168 	is normally the 'charset'. E.g. Content-Type: text/html; charset=ISO-8859-4
       
   169 	@internalComponent
       
   170 	@param		aHeader	The content-type header field to encode.
       
   171 	@leave		RHeaderField::BeginRawDataL
       
   172 	@leave		RHeaderField::WriteRawDataL
       
   173 	@leave		CHttpWriter::WriteRawStrFPartL
       
   174 	@leave		KErrHttpEncodeContentType	There are no value tokens, the
       
   175 											parameter was empty or the parameter
       
   176 											was not a string type value.
       
   177 */
       
   178 	{
       
   179   __START_PERFORMANCE_LOGGER();
       
   180 	// Check part 1
       
   181 	THeaderFieldPartIter iter = aHeader.PartsL();
       
   182 	iter.First();
       
   183 	if( iter.AtEnd() )
       
   184 		{
       
   185 		// The header value is empty!
       
   186 		User::Leave(KErrHttpEncodeContentType);
       
   187 		}
       
   188 	aHeader.BeginRawDataL();
       
   189 	const CHeaderFieldPart* part = WriteRawStrFPartL(aHeader, iter, KErrHttpEncodeContentType);
       
   190 
       
   191 	// Check for parameters...
       
   192 	THeaderFieldParamIter iter2 = part->Parameters();
       
   193 	iter2.First();
       
   194 	while( !iter2.AtEnd() )
       
   195 		{
       
   196 		// Got a parameter - write a semicolon separator
       
   197 		aHeader.WriteRawDataL(KSemiSpaceSep);
       
   198 		const CHeaderFieldParam* param = iter2();
       
   199 		if( !param )
       
   200 			{
       
   201 			// Empty parameter!
       
   202 			User::Leave(KErrHttpEncodeContentType);
       
   203 			}
       
   204 		// Anticipate only string parameter values
       
   205 		THTTPHdrVal paramVal = param->Value();
       
   206 		if( paramVal.Type() != THTTPHdrVal::KStrFVal )
       
   207 			{
       
   208 			// Was not a string value...
       
   209 			User::Leave(KErrHttpEncodeContentType);
       
   210 			}
       
   211 		RStringF paramName = iStringPool.StringF(param->Name());
       
   212 		aHeader.WriteRawDataL(paramName.DesC());
       
   213 		aHeader.WriteRawDataL('=');
       
   214 		aHeader.WriteRawDataL(paramVal.StrF().DesC());
       
   215 		
       
   216 		// Move onto the next parameter, writing a separator as necessary
       
   217 		++iter2;
       
   218 		}
       
   219 	// All done!
       
   220 	aHeader.CommitRawData();
       
   221 	__END_PERFORMANCE_LOGGER(_L(",CHttpGeneralHeaderWriter::EncodeContentTypeL()"));
       
   222 	}
       
   223 
       
   224 void CHttpGeneralHeaderWriter::EncodeContentLengthL(RHeaderField& aHeader) const
       
   225 /**
       
   226 	Encodes the content-length header. RFC2616 section 14.13 - 
       
   227 
       
   228 		Content-Length    = "Content-Length" ":" 1*DIGIT
       
   229 
       
   230 	The content-length value is a number with at least one digit.
       
   231 	@internalComponent
       
   232 	@param		aHeader	The content-length header field to encode.
       
   233 	@leave		CHttpWriter::EncodeGenericNumberHeaderL
       
   234 	@todo		Is there any point in this? Why not call EncodeGenericNumberHeaderL()
       
   235 				directly. 
       
   236 */
       
   237 	{
       
   238 	EncodeGenericNumberHeaderL(aHeader, KErrHttpEncodeContentLength);
       
   239 	}
       
   240 
       
   241 /*
       
   242  *	Methods from CHeaderWriter
       
   243  */
       
   244 
       
   245 void CHttpGeneralHeaderWriter::EncodeHeaderL(RHeaderField& aHeader)
       
   246 /**
       
   247 	Encodes the header field value. 
       
   248 	@internalComponent
       
   249 	@param		aHeader		The header field to be encoded.
       
   250 	@leave		CHttpGeneralHeaderWriter::EncodeCacheControlL
       
   251 	@leave		CHttpGeneralHeaderWriter::EncodeConnectionL
       
   252 	@leave		CHttpGeneralHeaderWriter::EncodeDateL
       
   253 	@leave		CHttpGeneralHeaderWriter::EncodeTransferEncodingL
       
   254 	@leave		CHttpGeneralHeaderWriter::EncodeContentLengthL
       
   255 	@leave		CHttpWriter::DoTokenCsvListHeaderL
       
   256 	@leave		KErrNotSupported	The writer was asked to encode a header that
       
   257 									is does not support.
       
   258 */
       
   259 	{
       
   260 	RStringF fieldStr = iStringPool.StringF(aHeader.Name());
       
   261 	switch( fieldStr.Index(iStringTable) )
       
   262 		{
       
   263 	case HTTP::ECacheControl:
       
   264 		{
       
   265 		EncodeCacheControlL(aHeader);
       
   266 		} break;
       
   267 	case HTTP::EConnection:
       
   268 		{
       
   269 		EncodeConnectionL(aHeader);
       
   270 		} break;
       
   271 	case HTTP::EDate:
       
   272 		{
       
   273 		EncodeDateL(aHeader);
       
   274 		} break;
       
   275 	case HTTP::EPragma:
       
   276 		{
       
   277 		// RFC2616 section 14.32 - 
       
   278 		//
       
   279 		//		Pragma				=	"Pragma" ":" 1#pragma-directive
       
   280 		//		pragma-directive	=	"no-cache"	|	extension-pragma
       
   281 		//		extension-pragma	=	token [ "=" ( token ! quoted-string ) ]
       
   282 		//
       
   283 		// The pragma header value is a comma separated list of values with at 
       
   284 		// least one value.
       
   285 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodePragma);
       
   286 		} break;
       
   287 	case HTTP::ETransferEncoding:
       
   288 		{
       
   289 		EncodeTransferEncodingL(aHeader);
       
   290 		} break;
       
   291 	case HTTP::EContentEncoding:
       
   292 		{
       
   293 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeContentEncoding);
       
   294 		} break;
       
   295 	case HTTP::EContentLanguage:
       
   296 		{
       
   297 		// RFC2616 section 14.12 - 
       
   298 		// 
       
   299 		//		Content-Language	=	"Content-Language" ":" 1#language-tag
       
   300 		// 
       
   301 		// The content-language header value is a comma separated list of values
       
   302 		// with at least one value.
       
   303 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeContentLanguage);
       
   304 		} break;
       
   305 	case HTTP::EUpgrade:
       
   306 		{
       
   307 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeUpgrade);
       
   308 		} break;
       
   309 	case HTTP::EContentLength:
       
   310 		{
       
   311 		EncodeContentLengthL(aHeader);
       
   312 		} break;
       
   313 	case HTTP::EContentLocation:
       
   314 		{
       
   315 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeContentLocation);
       
   316 		} break;
       
   317 	case HTTP::EContentMD5:
       
   318 		{
       
   319 		DoTokenCsvListHeaderL(aHeader, KErrHttpEncodeContentMD5);
       
   320 		} break;
       
   321 	case HTTP::EContentType:
       
   322 		{
       
   323 		EncodeContentTypeL(aHeader);
       
   324 		} break;
       
   325 	case HTTP::EExpires:
       
   326 	case HTTP::ELastModified:
       
   327 		{
       
   328 		EncodeDateL(aHeader);
       
   329 		}break;
       
   330 	default:
       
   331 		User::Leave(KErrNotSupported);
       
   332 		break;
       
   333 		}
       
   334 	}