applayerprotocols/wappushsupport/HTTPResponse/CHTTPResponse.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 1998-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 // Purpose:  This file provides the definition of the CHTTPResponse class.
       
    15 // The HTTP Response class encodes HTTP response headers only. It
       
    16 // contains the methods used to transcode from WSP->HTTP fields
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 // System includes
       
    22 //
       
    23 #include <wspdecoder.h>
       
    24 #include <chttpresponse.h>
       
    25 
       
    26 // Wap Logging
       
    27 //
       
    28 #include <waplog.h>
       
    29 #include <logdef.h>
       
    30 
       
    31 const TUint8 KWapQuote = 0x7F;
       
    32 const TUint8 KTop3BitSet = 0x70;
       
    33 const TUint8 KCarryBitMask = 0x80;
       
    34 
       
    35 // Default MIME type is text/plain if we can't identify any other
       
    36 //
       
    37 static const TText8* const defaultType = _S8("application/octet-stream");
       
    38 
       
    39 // Implementation of CHTTPResponse class
       
    40 //
       
    41 
       
    42 
       
    43 // Factory method to construct this class.
       
    44 //
       
    45 // Rtn: a new CHTTPResponse object, by ptr. Ownership is transferred to the
       
    46 //      caller.
       
    47 //
       
    48 
       
    49 EXPORT_C CHTTPResponse* CHTTPResponse::NewL()
       
    50 	{
       
    51 	CHTTPResponse* me = new(ELeave)CHTTPResponse();
       
    52 	CleanupStack::PushL(me);
       
    53 	me->ConstructL();
       
    54 	CleanupStack::Pop();
       
    55 	return me;
       
    56 	}
       
    57 
       
    58 
       
    59 // Destructor for this class. Removes this object and releases memory held
       
    60 // by it
       
    61 //
       
    62 
       
    63 EXPORT_C CHTTPResponse::~CHTTPResponse()
       
    64     {
       
    65     Reset();
       
    66 	__CLOSE_LOG;
       
    67     }
       
    68 
       
    69 
       
    70 // Clean out the fields buffer
       
    71 //
       
    72 
       
    73 EXPORT_C void CHTTPResponse::Reset()
       
    74     {
       
    75 	__LOG_ENTER(_L("CHTTPResponse::Reset"));
       
    76     delete iResponse;
       
    77     iResponse = NULL;
       
    78 	__LOG_RETURN;
       
    79     }
       
    80 
       
    81 
       
    82 // Set the fields buffer with the response received from the WAP Stack
       
    83 //
       
    84 // In:
       
    85 //  aResponse - an 8-bit descriptor field containing the origin server's
       
    86 //				WSP-encoded response header. Ownership is transferred to
       
    87 //				this class.
       
    88 //
       
    89 
       
    90 EXPORT_C void CHTTPResponse::AddResponse(HBufC8* aResponse)
       
    91     {
       
    92 	__LOG_ENTER(_L("CHTTPResponse::AddResponse"));
       
    93     delete iResponse;
       
    94     iResponse = aResponse;
       
    95 #ifdef _DEBUG
       
    96 	DumpToLog(*aResponse);
       
    97 #endif
       
    98 	__LOG_RETURN;
       
    99     }
       
   100 
       
   101 
       
   102 // Accessor to the HTTP response fields buffer
       
   103 //
       
   104 // Rtn: a reference to the response. Ownership is _NOT_ transferred
       
   105 //
       
   106 // NOTE THIS SHOULD RETURN CONST - BUT CAN'T BE CHANGED SINCE IT WOULD
       
   107 // BREAK BC.
       
   108 
       
   109 EXPORT_C HBufC8& CHTTPResponse::Response() const
       
   110     {
       
   111 	__LOG_ENTER(_L("CHTTPResponse::Response"));
       
   112 	__LOG_RETURN;
       
   113     return *iResponse;
       
   114     }
       
   115 
       
   116 
       
   117 // Accessor to the HTTP status code (e.g. 400, 300, 200, 500)
       
   118 //
       
   119 // Rtn: the status code - series number only.
       
   120 //
       
   121 
       
   122 EXPORT_C THttpStatusCode CHTTPResponse::StatusCode() const
       
   123     {
       
   124 	__LOG_ENTER(_L("CHTTPResponse::StatusCode"));
       
   125 	__LOG_RETURN;
       
   126     return iStatusCode;
       
   127     }
       
   128 
       
   129 
       
   130 // Accessor to the HTTP detailed status code (e.g. 404, 304, 200, 501)
       
   131 //
       
   132 // Rtn: the status code - series and specific code value
       
   133 //
       
   134 
       
   135 EXPORT_C THttpStatusCode CHTTPResponse::DetailedStatusCode() const
       
   136     {
       
   137 	__LOG_ENTER(_L("CHTTPResponse::DetailedStatusCode"));
       
   138 	__LOG_RETURN;
       
   139     return iDetailedStatusCode;
       
   140     }
       
   141 
       
   142 
       
   143 // Accessor to set the HTTP response status.
       
   144 //
       
   145 // In:
       
   146 //  aCode - the WSP-encoded status code
       
   147 //
       
   148 
       
   149 EXPORT_C void CHTTPResponse::SetStatusCode(TInt aCode)
       
   150     {
       
   151 //	__LOG_ENTER(_L("CHTTPResponse::SetStatusCode"));
       
   152 //	__LOG1(_L("CHTTPResponse::SetStatusCode : 'aCode' = %d"), aCode);
       
   153     
       
   154 	// Set iDetailedStatusCode to a default
       
   155     iDetailedStatusCode = EHttpUnknown;
       
   156 
       
   157     // Magic no.s come from the WAP WSP specification, Appendix A, Table 36
       
   158     switch (aCode)
       
   159         {
       
   160     case 0x10:
       
   161         iStatusCode = EHttpContinue;
       
   162         break;
       
   163     case 0x11:
       
   164         iDetailedStatusCode = EHttpSwitchingProtocols;
       
   165         iStatusCode = EHttpContinue;
       
   166         break;
       
   167 
       
   168     case 0x20:
       
   169         iStatusCode = EHttpOK;
       
   170         break;
       
   171     case 0x21:
       
   172         iDetailedStatusCode = EHttpCreated;
       
   173         iStatusCode = EHttpOK;
       
   174         break;
       
   175     case 0x22:
       
   176         iDetailedStatusCode = EHttpAccepted;
       
   177         iStatusCode = EHttpOK;
       
   178         break;
       
   179     case 0x23:
       
   180         iDetailedStatusCode = EHttpNonAuthorativeInformation;
       
   181         iStatusCode = EHttpOK;
       
   182         break;
       
   183     case 0x24:
       
   184         iDetailedStatusCode = EHttpNoContent;
       
   185         iStatusCode = EHttpOK;
       
   186         break;
       
   187     case 0x25:
       
   188         iDetailedStatusCode = EHttpResetContent;
       
   189         iStatusCode = EHttpOK;
       
   190         break;
       
   191     case 0x26:
       
   192         iDetailedStatusCode = EHttpPartialContent;
       
   193         iStatusCode = EHttpOK;
       
   194         break;
       
   195 
       
   196     case 0x30:
       
   197         iStatusCode = EHttpMultipleChoices;
       
   198         break;
       
   199     case 0x31:
       
   200         iDetailedStatusCode = EHttpMovedPermanently;
       
   201         iStatusCode = EHttpMultipleChoices;
       
   202         break;
       
   203     case 0x32:
       
   204         iDetailedStatusCode = EHttpMovedTemporarily;
       
   205         iStatusCode = EHttpMultipleChoices;
       
   206         break;
       
   207     case 0x33:
       
   208         iDetailedStatusCode = EHttpSeeOther;
       
   209         iStatusCode = EHttpMultipleChoices;
       
   210         break;
       
   211     case 0x34:
       
   212         iDetailedStatusCode = EHttpNotModified;
       
   213         iStatusCode = EHttpMultipleChoices;
       
   214         break;
       
   215     case 0x35:
       
   216         iDetailedStatusCode = EHttpUseProxy;
       
   217         iStatusCode = EHttpMultipleChoices;
       
   218         break;
       
   219 
       
   220     case 0x40:
       
   221         iStatusCode = EHttpBadRequest;
       
   222         break;
       
   223     case 0x41:
       
   224         iDetailedStatusCode = EHttpUnauthorized;
       
   225         iStatusCode = EHttpBadRequest;
       
   226         break;
       
   227     case 0x42:
       
   228         iDetailedStatusCode = EHttpPaymentRequired;
       
   229         iStatusCode = EHttpBadRequest;
       
   230         break;
       
   231     case 0x43:
       
   232         iDetailedStatusCode = EHttpForbidden;
       
   233         iStatusCode = EHttpBadRequest;
       
   234         break;
       
   235     case 0x44:
       
   236         iDetailedStatusCode = EHttpNotFound;
       
   237         iStatusCode = EHttpBadRequest;
       
   238         break;
       
   239     case 0x45:
       
   240         iDetailedStatusCode = EHttpMethodNotAllowed;
       
   241         iStatusCode = EHttpBadRequest;
       
   242         break;
       
   243     case 0x46:
       
   244         iDetailedStatusCode = EHttpNotAcceptable;
       
   245         iStatusCode = EHttpBadRequest;
       
   246         break;
       
   247     case 0x47:
       
   248         iDetailedStatusCode = EHttpProxyAuthenticationRequired;
       
   249         iStatusCode = EHttpBadRequest;
       
   250         break;
       
   251     case 0x48:
       
   252         iDetailedStatusCode = EHttpRequestTimeout;
       
   253         iStatusCode = EHttpBadRequest;
       
   254         break;
       
   255     case 0x49:
       
   256         iDetailedStatusCode = EHttpConflict;
       
   257         iStatusCode = EHttpBadRequest;
       
   258         break;
       
   259     case 0x4a:
       
   260         iDetailedStatusCode = EHttpGone;
       
   261         iStatusCode = EHttpBadRequest;
       
   262         break;
       
   263     case 0x4b:
       
   264         iDetailedStatusCode = EHttpLengthRequired;
       
   265         iStatusCode = EHttpBadRequest;
       
   266         break;
       
   267     case 0x4c:
       
   268         iDetailedStatusCode = EHttpPreconditionFailed;
       
   269         iStatusCode = EHttpBadRequest;
       
   270         break;
       
   271     case 0x4d:
       
   272         iDetailedStatusCode = EHttpRequestEntityTooLarge;
       
   273         iStatusCode = EHttpBadRequest;
       
   274         break;
       
   275     case 0x4e:
       
   276         iDetailedStatusCode = EHttpRequestURITooLong;
       
   277         iStatusCode = EHttpBadRequest;
       
   278         break;
       
   279     case 0x4f:
       
   280         iDetailedStatusCode = EHttpUnsupportedMediaType;
       
   281         iStatusCode = EHttpBadRequest;
       
   282         break;
       
   283 
       
   284     case 0x60:
       
   285         iStatusCode = EHttpInternalServerError;
       
   286         break;
       
   287     case 0x61:
       
   288         iDetailedStatusCode = EHttpNotImplemented;
       
   289         iStatusCode = EHttpInternalServerError;
       
   290         break;
       
   291     case 0x62:
       
   292         iDetailedStatusCode = EHttpBadGateway;
       
   293         iStatusCode = EHttpInternalServerError;
       
   294         break;
       
   295     case 0x63:
       
   296         iDetailedStatusCode = EHttpServiceUnavailable;
       
   297         iStatusCode = EHttpInternalServerError;
       
   298         break;
       
   299     case 0x64:
       
   300         iDetailedStatusCode = EHttpGatewayTimeout;
       
   301         iStatusCode = EHttpInternalServerError;
       
   302         break;
       
   303     case 0x65:
       
   304         iDetailedStatusCode = EHttpHTTPVersionNotSupported;
       
   305         iStatusCode = EHttpInternalServerError;
       
   306         break;
       
   307 
       
   308     default:
       
   309         iStatusCode = EHttpUnknown;
       
   310         break;
       
   311         }
       
   312     if (iDetailedStatusCode == EHttpUnknown)
       
   313         iDetailedStatusCode = iStatusCode;
       
   314 //	__LOG1(_L("CHTTPResponse::SetStatusCode : status code = %d"), iStatusCode);
       
   315 //	__LOG1(_L("CHTTPResponse::SetStatusCode : detailed status code = %d"), iDetailedStatusCode);
       
   316 //	__LOG_RETURN;
       
   317     }
       
   318 
       
   319 
       
   320 // Method to find a named field, that returns null terminated 
       
   321 // WSP text strings. Note that there is no checking that it is a text string
       
   322 // which follows.
       
   323 //
       
   324 // In:
       
   325 //  aField		- the field type
       
   326 //  aStartIndex	- the index to search from (defaults to the buffer start)
       
   327 //
       
   328 // Out:
       
   329 //  aDesc - a pointer-type descriptor into the response buffer at the
       
   330 //			position where the field was located. The caller must NOT
       
   331 //			modify the descriptor contents
       
   332 //
       
   333 // Rtn: TBool - set to ETrue if the field was found, EFalse otherwise
       
   334 //
       
   335 
       
   336 EXPORT_C TBool CHTTPResponse::FindField(THttpHeaderField aField,
       
   337 							   TPtrC8& aDesc,
       
   338 							   TInt aStartIndex) const
       
   339     {
       
   340 //	__LOG_ENTER(_L("CHTTPResponse::FindField (string)"));
       
   341 //	__LOG1(_L("CHTTPResponse::FindField : searching for field type = %d"), aField);
       
   342     TInt index = LocateField(aField, aStartIndex);
       
   343     if (index >0)
       
   344         {
       
   345         TInt count = 0;
       
   346         for (count = index; (count < iResponse->Length()) &&
       
   347 			(iResponse->Des()[count] != 0); count++) {};
       
   348         if (count <= iResponse->Length())
       
   349             {
       
   350             aDesc.Set(&(iResponse->Des()[index]), count-index);
       
   351 //			__LOG(_L("CHTTPResponse::FindField : found string:"));
       
   352 #ifdef _DEBUG
       
   353 			DumpToLog(aDesc);
       
   354 #endif
       
   355 //			__LOG_RETURN;
       
   356             return ETrue;
       
   357             }
       
   358         }
       
   359 //	__LOG(_L("CHTTPResponse::FindField : nothing found"));
       
   360 //	__LOG_RETURN;
       
   361     return EFalse;
       
   362     }
       
   363 
       
   364 
       
   365 // Method to find a named field, that returns 8-bit octet data (binary
       
   366 // or strings - not stipulated which).
       
   367 //
       
   368 // In:
       
   369 //  aField		- the field type
       
   370 //  aStartIndex	- the index to search from (defaults to the buffer start)
       
   371 //
       
   372 // Out:
       
   373 //  aDesc - a pointer-type descriptor into the response buffer at the
       
   374 //			position where the field was located. The caller must NOT
       
   375 //			modify the descriptor contents
       
   376 //
       
   377 // Rtn: TBool - set to ETrue if the field was found, EFalse otherwise
       
   378 //
       
   379 
       
   380 EXPORT_C TBool CHTTPResponse::FindBinaryDescField(THttpHeaderField aField,
       
   381 										 TPtrC8& aDesc,
       
   382 										 TInt aStartIndex) const
       
   383     {
       
   384     TInt index = LocateField(aField, aStartIndex);
       
   385     if (index >= 0)
       
   386         {
       
   387 		TInt offset = 0;
       
   388 		TInt fieldLength = iResponse->Des()[index];	// assume the length is in
       
   389 													// a short integer
       
   390 		if(fieldLength == 31)
       
   391 			{
       
   392 			// Nope : Code 31 indicates that the following bytes make a
       
   393 			// UIntVar,  which indicates the number of data octets after it. 
       
   394 			// The UIntVar itself could be composed of upto 5 bytes
       
   395 			// Copy a full 5 bytes from the header
       
   396 			// Note that actually fewer might have been used; 
       
   397 			// the UIntVar to Int converter function returns the exact number 
       
   398 			// that were used.
       
   399 			TInt consumed = ParseUIntVar(iResponse->Des().Mid(index + 1), fieldLength);
       
   400 
       
   401 			__ASSERT_DEBUG( consumed >= KErrNone, User::Invariant() );
       
   402 			
       
   403 			offset += consumed;			
       
   404 			}
       
   405         else if (fieldLength > 127)
       
   406 			{
       
   407  			// Oops be sneaky and reuse this single byte
       
   408  			// Because this is a special code
       
   409  			fieldLength = 1;		
       
   410  			offset = -1;
       
   411  			}
       
   412 
       
   413 		if(fieldLength)
       
   414             {
       
   415             aDesc.Set(&(iResponse->Des()[index + offset + 1]), fieldLength);
       
   416 #ifdef _DEBUG
       
   417 			DumpToLog(aDesc);
       
   418 #endif
       
   419             return ETrue;
       
   420             }
       
   421         }
       
   422     return EFalse;
       
   423     }
       
   424 
       
   425 
       
   426 // Method to find a named field, that returns an EPOC date/time structure.
       
   427 //
       
   428 // In:
       
   429 //  aField		- the field type
       
   430 //  aStartIndex	- the index to search from (defaults to the buffer start)
       
   431 //
       
   432 // Out:
       
   433 //  aTime - a structure containing the time (and date) found in the header
       
   434 //
       
   435 // Rtn: TBool - set to ETrue if the field was found, EFalse otherwise
       
   436 //
       
   437 
       
   438 EXPORT_C TBool CHTTPResponse::FindField(THttpHeaderField aField,
       
   439 							   TTime& aTime,
       
   440 							   TInt aStartIndex) const
       
   441     {
       
   442 	__LOG_ENTER(_L("CHTTPResponse::FindField (time)"));
       
   443 	TBool result = EFalse;
       
   444     TInt index = LocateField(aField, aStartIndex);
       
   445     if (index > 0)
       
   446         {
       
   447  		TPtr8 respChars  = iResponse->Des();
       
   448    		ExtractFieldDateValue(respChars,index,aTime);
       
   449 		result = ETrue;
       
   450         }
       
   451 	__LOG_RETURN;
       
   452     return result;
       
   453     }
       
   454 
       
   455 
       
   456 // Method to find a named field within the Cache Control header
       
   457 //
       
   458 // In:
       
   459 //  aField		- the field type
       
   460 //
       
   461 // Out:
       
   462 //
       
   463 // Rtn: TBool - set to ETrue if the field was found, EFalse otherwise
       
   464 //
       
   465 
       
   466 EXPORT_C TBool CHTTPResponse::FindCacheControlFieldValue(TCacheControlFieldValue aField) const
       
   467 	{
       
   468 	TPtrC8 cacheControl;
       
   469 	return FindCacheControlFieldValue(aField,cacheControl) != KErrNotFound;
       
   470 	}
       
   471 
       
   472 
       
   473 // Method to find a named field within the Cache Control header, 
       
   474 // that returns an EPOC date/time structure.
       
   475 //
       
   476 // In:
       
   477 //  aField		- the field type
       
   478 //
       
   479 // Out:
       
   480 //  aTime - a structure containing the time (and date) found in the header
       
   481 //			field
       
   482 //
       
   483 // Rtn: TBool - set to ETrue if the field was found, EFalse otherwise
       
   484 //
       
   485 
       
   486 EXPORT_C TBool CHTTPResponse::ExtractCacheControlTime(TCacheControlFieldValue aField,
       
   487 											 TTime& aTime) const
       
   488 	{
       
   489 	__LOG_ENTER(_L("CHTTPResponse::ExtractCacheControlTime"));
       
   490 	__ASSERT_DEBUG(aField == ECacheCtrlMaxAge || aField == ECacheCtrlMaxStale
       
   491 						|| aField == ECacheCtrlMinFresh, User::Invariant());
       
   492 	TBool result = EFalse;
       
   493 	TPtrC8 cacheControl;
       
   494 	aTime = 0;
       
   495 	TInt index = FindCacheControlFieldValue(aField, cacheControl);
       
   496 	if(index != KErrNotFound)
       
   497 		{
       
   498 		// Have the cache control and the field position
       
   499 		// Now we need to extract the field's delta-secs value
       
   500 		index++;
       
   501 		TInt time = 0;
       
   502 		TPtrC8 integerSource = cacheControl.Mid(index);
       
   503 
       
   504 		if(integerSource[0] >= 0x80)			// Short integer value
       
   505 			time = integerSource[0] & 0x7F;
       
   506 		else								// Otherwise its multi octet
       
   507 			ExtractMultiOctetInteger(time, integerSource);
       
   508 		
       
   509 		TTimeIntervalSeconds timeSeconds(time);
       
   510 		aTime += timeSeconds;			// Store the seconds in the time field
       
   511 		result = ETrue;
       
   512 		}
       
   513 	__LOG_RETURN;
       
   514 	return result;
       
   515 	}
       
   516 
       
   517 
       
   518 // Method to search for the content type encoded in the response header
       
   519 //
       
   520 // Out:
       
   521 //  aDesc - a pointer-type descriptor into the appropriate element of an
       
   522 //			array prefilled with all the content types that have WSP
       
   523 //			encodings. e.g. "text/vnd.wap.wml".  The contents of the
       
   524 //			descriptor must NOT be modified.
       
   525 //
       
   526 
       
   527 EXPORT_C void CHTTPResponse::ContentType(TPtrC8& aDesc) const
       
   528     {
       
   529 	// Decode the content-type data as per the WSP bnf...
       
   530 	// Note - There is no provision available here to handle content-type parameters
       
   531 	// so parameters are ignored here.
       
   532 	TInt error = LocateField(EHttpContentType);
       
   533 	TInt token = 0;
       
   534 	TBool isString = EFalse;
       
   535 	if (error != KErrNotFound)
       
   536 		{
       
   537 		TPtrC8 respChars(*iResponse);
       
   538 		TWspPrimitiveDecoder wspDecoder(respChars);
       
   539 		TWspPrimitiveDecoder::TWspHeaderType type = wspDecoder.VarType();
       
   540 		switch(type)
       
   541 			{
       
   542 			case TWspPrimitiveDecoder::E7BitVal:
       
   543 				{
       
   544 				// 128-255 - encoded 7 bit value, this header has no more data
       
   545 				TUint8 byteCode = 0;
       
   546 				error = wspDecoder.Val7Bit(byteCode); // error code
       
   547 				token = static_cast<TInt>(byteCode);
       
   548 				} break;
       
   549 			case TWspPrimitiveDecoder::EString:
       
   550 				{
       
   551 				// 32-127 - value is a text string, terminated by a '\0' 
       
   552 				// Content type is embedded as a text string
       
   553 				error = wspDecoder.String(aDesc); // error code
       
   554 				isString = ETrue;
       
   555 				} break;
       
   556 			case TWspPrimitiveDecoder::ELengthVal:
       
   557 				{
       
   558 				// 0-31 -  octet is a value length
       
   559 				TInt dataLength = 0;
       
   560 				error = wspDecoder.LengthVal(dataLength);
       
   561 				if( error >= KErrNone )
       
   562 					{
       
   563 					type = wspDecoder.VarType();
       
   564 					if( type == TWspPrimitiveDecoder::E7BitVal || type == TWspPrimitiveDecoder::ELengthVal )
       
   565 						{
       
   566 						TUint32 contentTypeToken = 0;
       
   567 						error = wspDecoder.Integer(contentTypeToken);
       
   568 						token = static_cast<TInt>(contentTypeToken);
       
   569 						}
       
   570 					else if( type == TWspPrimitiveDecoder::EString )
       
   571 						{
       
   572 						error = wspDecoder.String(aDesc);
       
   573 						isString = ETrue;
       
   574 						}
       
   575 					}
       
   576 
       
   577 				} break;
       
   578 			default:
       
   579 				{
       
   580 				error = KErrNotFound;
       
   581 				} break;
       
   582 			}
       
   583 		}
       
   584 
       
   585 	if(error < KErrNone)
       
   586 		token = KErrNotFound;
       
   587 
       
   588 	// Look up the appropriate content type, provided an error hasn't occurred or the string
       
   589 	// has not already been set
       
   590 	if (token == KErrNotFound || !isString)
       
   591 		{
       
   592 		// Convert the content type string to the supplied descriptor
       
   593 		const TText8* type = ContentType(token);
       
   594 		aDesc.Set(TPtrC8(type));
       
   595 //		__LOG1(_L("CHTTPResponse::ContentType : contentIndex = %d"), contentIndex);
       
   596 		}
       
   597 
       
   598 	}
       
   599 
       
   600 
       
   601 // Method to search for the realm encoded in the response header, when the
       
   602 // response challenges the client for HTTP authentication (code 401)
       
   603 //
       
   604 // Out:
       
   605 //  aDesc - a pointer-type descriptor into the response header buffer
       
   606 //			positioned at the realm string within the challenge. The
       
   607 //			contents of the descriptor must NOT be modified.
       
   608 //
       
   609 // Rtn: TBool - set to ETrue if a WWWAuthenticate header was found, EFalse
       
   610 //				otherwise
       
   611 //
       
   612 
       
   613 EXPORT_C TBool CHTTPResponse::FindRealm(TPtrC8& aRealm) const
       
   614     {
       
   615 	__LOG_ENTER(_L("CHTTPResponse::FindRealm"));
       
   616 	// Search for the WWWAuthenticate field
       
   617 	TPtrC8 realmPtr(aRealm);
       
   618     TBool retVal = FindField(EHttpWWWAuthenticate, realmPtr, 0);
       
   619     if (retVal)
       
   620         {
       
   621 		// realmPtr now points to the WWWAuthentication field value. This contains the Authentication scheme, realm
       
   622 		// value and optional parameters. Check authentication is Basic (encoded as 0x80). This is stored in the
       
   623 		// second byte of the header value (i.e. index [1]).
       
   624 		if (realmPtr[1] == 0x80)
       
   625 			{
       
   626 			// Set the realm descriptor passed in
       
   627             aRealm.Set(realmPtr.Mid(2));
       
   628 #ifdef _DEBUG
       
   629 			// In debug builds, convert the 8-bit realm to 16-bit UNICODE in order to log it.
       
   630 			HBufC16* aRealm16 = HBufC16::New(aRealm.Length());
       
   631 			if(aRealm16!=NULL)
       
   632 				{
       
   633 				TPtr16 aRealm16_Ptr = aRealm16->Des();
       
   634 				aRealm16_Ptr.Copy(aRealm);
       
   635 				__LOG1(_L("CHTTPResponse::FindRealm : found realm string: %S"), &aRealm16_Ptr);
       
   636 				delete aRealm16;
       
   637 				}
       
   638 #endif
       
   639 			}
       
   640 		else
       
   641 			{
       
   642 			__LOG(_L("CHTTPResponse::FindRealm : nothing found"));
       
   643 			retVal = EFalse;
       
   644 			}
       
   645 		}
       
   646 	__LOG_RETURN;
       
   647     return retVal;
       
   648     }
       
   649 
       
   650 
       
   651 // Method to search for the character set encoded in the Content-Type field of
       
   652 // the response header
       
   653 //
       
   654 // Out:
       
   655 //  aDesc - a pointer-type descriptor into the appropriate element of an
       
   656 //			array prefilled with all the character sets that have WSP
       
   657 //			encodings. e.g. "utf-8".  The contents of the descriptor must
       
   658 //			NOT be modified.
       
   659 //
       
   660 // Rtn: TBool - set to ETrue if a character set was found, EFalse if not
       
   661 //
       
   662 
       
   663 EXPORT_C TBool CHTTPResponse::CharSet(TPtrC8& aDesc) const
       
   664     {
       
   665 //	__LOG_ENTER(_L("CHTTPResponse::CharSet"));
       
   666 	// Find the byte index in the header for the content type value
       
   667     TInt index = LocateField(EHttpContentType);
       
   668 
       
   669     TUint8 byteCode = 0;
       
   670 	TInt paramByteCode = KErrNotFound;
       
   671 	TInt valueByteCode1 = KErrNotFound;
       
   672 	TInt charsetCode = 0;
       
   673 	// Read the byte code, unless KErrNotFound was returned
       
   674 	if (index != KErrNotFound)
       
   675 		{
       
   676 		TPtr8 respChars = iResponse->Des();
       
   677 		TInt respLength = iResponse->Length();
       
   678 
       
   679 		// If the byteCode is in the range 0-30 then a range of bytes is
       
   680 		// indicated: the following byte gives the content type and the
       
   681 		// remainder are arranged as a series of parameter attribute-value
       
   682 		// pairs. This method checks for the presence of a 'charset' parameter.
       
   683 		byteCode = respChars[index];
       
   684 //		__LOG1(_L("CHTTPResponse::CharSet : found bytecode = %d"), byteCode);
       
   685 
       
   686 		// Check valid range ... note that a range of zero could not contain a charset
       
   687 		// parameter anyway, so exclude it...
       
   688 		if ((byteCode > 0) && (byteCode <= 30))
       
   689 			{
       
   690 			// Check for overrun... if this occurs it should be an error.  Note that
       
   691 			// corruption _could_ occur in this response buffer - some gateways, which
       
   692 			// don't return error decks (e.g. AnyTime GW) send a response buffer 1 byte
       
   693 			// long, containing only the value 0x01 - which is invalid WSP.
       
   694 			// Be conservative and safe here - we can't overrun.  Use the value of byte-
       
   695 			// -Code (which should be the WSP encoding of how many bytes follow), or the
       
   696 			// total length of the response - whichever is smaller.
       
   697 			if (index + byteCode < respLength)
       
   698 				{
       
   699 				// e,g, header to illustrate use of offsets in this code:
       
   700 				// 03 94 81 84 : Content-Type: application/vnd.wap.wmlc; charset=iso-8859-1
       
   701 				// +0 +1 +2 +3 : 03 = no. bytes in Content-Type header
       
   702 				//			   : 94 = 14 | 80 = application/vnd.wap.wmlc
       
   703 				//			   : 81 = 01 | 80 = Charset parameter
       
   704 				//			   : 84 = 04 | 80 = iso-8859-1
       
   705 				paramByteCode = respChars[index + 2];
       
   706 
       
   707 				if ((paramByteCode & 0x7f) == EHttpCharset)
       
   708 					{
       
   709 					// We have a charset
       
   710 					paramByteCode &= 0x7f;
       
   711 					valueByteCode1 = respChars[index + 3];
       
   712 
       
   713 					if (valueByteCode1 & 0x80)
       
   714 						{
       
   715 						// A short one-byte value
       
   716 						charsetCode = valueByteCode1 & 0x7f;
       
   717 						}
       
   718 					else
       
   719 						{
       
   720 						// A multibyte value
       
   721 						ExtractMultiOctetInteger(charsetCode, 
       
   722 												 respChars.Mid(index + 3));
       
   723 						}
       
   724 					}
       
   725 				}
       
   726 			else
       
   727 				{
       
   728 				index = KErrNotFound;
       
   729 				}
       
   730 			}
       
   731 		}
       
   732 
       
   733 	// If a parameter-value pair was found, determine whether it encodes a
       
   734 	// charset
       
   735 	if ( (index != KErrNotFound) && (paramByteCode == EHttpCharset) )
       
   736 		{
       
   737 		// Look up the value from the charset table.
       
   738 		const TText8* chset;
       
   739 		chset = CharSet(charsetCode);
       
   740 
       
   741 		// Convert the charset string to the supplied descriptor
       
   742 		if (chset)
       
   743 			aDesc.Set(TPtrC8(chset));
       
   744 		else
       
   745 			index = KErrNotFound; // We've found a charset but we don't recognise it
       
   746 		}
       
   747 	else	// Either no content-type header (hence no charset) or a content-type
       
   748 			// header with a parameter other than charset
       
   749 		{
       
   750 		index = KErrNotFound;
       
   751 		}
       
   752 
       
   753 //	__LOG1(_L("CHTTPResponse::CharSet : CharSet = %S"), &aDesc);
       
   754 //	__LOG_RETURN;
       
   755 	return (index !=KErrNotFound);
       
   756     }
       
   757 
       
   758 
       
   759 // Normal constructor - do non-allocating creation of this class
       
   760 //
       
   761 
       
   762 EXPORT_C CHTTPResponse::CHTTPResponse()
       
   763 	: iStatusCode(EHttpUnknown), iDetailedStatusCode(EHttpUnknown)
       
   764     {
       
   765 	// Does nothing here
       
   766     }
       
   767 
       
   768 
       
   769 // Second phase construction - any allocation for this class must take place
       
   770 // here. Sets up the resources required by an HTTP Response.
       
   771 //
       
   772 
       
   773 EXPORT_C void CHTTPResponse::ConstructL()
       
   774     {
       
   775     // Does nothing
       
   776 	__OPEN_LOG(__LOG_WAP_FILE_NAME); 
       
   777     }
       
   778 
       
   779 
       
   780 // Method to locate a named field in the response header, starting at the
       
   781 // specified index position.
       
   782 //
       
   783 // In:
       
   784 //  aField		- the header field type
       
   785 //  aStartIndex - the (optional) position in the header to start searching
       
   786 //
       
   787 // Rtn: TInt - the index position of the required field _value_ (not the
       
   788 //             field name), or KErrNotFound otherwise.
       
   789 //
       
   790 
       
   791 EXPORT_C TInt CHTTPResponse::LocateField(THttpHeaderField aField,
       
   792 								TInt aStartIndex) const
       
   793     {
       
   794 	// Content-Type is a special case; it appears to always be at the first
       
   795 	// byte of the header, and doesn't have any encoding of the field name -
       
   796 	// just straight into the Field Value at byte 0.  This is an assumption
       
   797 	// however, since the WSP spec is not explicit - could it possibly be just
       
   798 	// the NWSS GW's implementation of WSP that does this?
       
   799 	if ( (aStartIndex == 0) && (aField == EHttpContentType) )
       
   800 		{
       
   801 		return aStartIndex; // the content-type field value position - ie. 0
       
   802 		}
       
   803 	
       
   804 	// Deal with other Field Names, (Possibly including Content-Type if the
       
   805 	// start index is offset into the header? Note that this is not likely to
       
   806 	// occur though, with the abbreviated encoding.)
       
   807 	TInt respLength = iResponse->Length();
       
   808 	TPtr8 respChars  = iResponse->Des();
       
   809     for (TInt index = aStartIndex; index < respLength; index++)
       
   810         {
       
   811 		// Examine the byte at this position in the header
       
   812         TUint8 byteCode = respChars[index];
       
   813 
       
   814 		// Expect byteCode to be a Field Name code (unless the search is at
       
   815 		// position zero, which has a missing content-type field name). Check
       
   816 		// for the search field, remembering to clear the top bit
       
   817         if ( ( (byteCode & 0x7f) == aField) && (index != 0) )
       
   818             {
       
   819 			// Got it - return the next position to locate the field value,
       
   820 			// checking for potential overrun
       
   821 			if (index < respLength - 1)
       
   822 				{
       
   823 				// Advance 1 to the header field value
       
   824 				++index;
       
   825 				return index;
       
   826 				}
       
   827 			else
       
   828 				{
       
   829 				return KErrNotFound;
       
   830 				}
       
   831             }
       
   832         else
       
   833             {
       
   834 			// Check that we aren't dealing with the Content-Type field
       
   835 			// (expected at position 0), since it doesn't use a field type
       
   836 			if (index != 0)
       
   837 				{
       
   838 				// WSP Spec Section 8.4.1.1 - Field Names
       
   839 				//
       
   840 				// If the byte is an alphanumeric, then it must be a field name that doesn't have
       
   841 				// a WSP encoding.  In this circumstance, we can't handle the field, and must
       
   842 				// therefore skip over it
       
   843 				if ((byteCode >= 32) && (byteCode <= 127))
       
   844 					{
       
   845 					// Hit the start of a Header Name string - this will be assumed
       
   846 					// continuous until the NUL is found or until the end
       
   847 					// of the header is hit (which would be an error)
       
   848 					while ( (respChars[index] != 0) && (index < respLength - 1) )
       
   849 						++index;
       
   850 					}
       
   851 
       
   852 				// WSP Spec Section 8.4.1.2 - Field Values
       
   853 				//
       
   854 				// Now examine the field value by advancing one place.  If that advance takes us off
       
   855 				// the end of the buffer, then (a) the WSP is invalid, and (b) the field is not found!
       
   856 				++index;
       
   857 				if (index == respLength)
       
   858 					return KErrNotFound;
       
   859 				}
       
   860 
       
   861 			// Read the next byte at this position in the header
       
   862             byteCode = respChars[index];
       
   863 
       
   864 			// Codes 0-30 represent that number of following data octets, so
       
   865 			// they should be skipped
       
   866 			if (byteCode == 0)			// 0 data octets follow !???? : (Strange but true)
       
   867 				{
       
   868 				// __DEBUGGER();
       
   869 				}
       
   870             else if (byteCode <= 30)
       
   871 				{
       
   872                 index += byteCode;
       
   873 				}
       
   874             else
       
   875                 {
       
   876 				// Code 31 indicates that the following bytes make a UIntVar,
       
   877 				// which indicates the number of data octets after it. The
       
   878 				// UIntVar itself could be composed of upto 5 bytes
       
   879                 if (byteCode == 31)
       
   880 					{
       
   881 					// Copy a full 5 bytes from the header - note that actually
       
   882 					// fewer might have been used; the UIntVar to Int
       
   883 					// converter function returns the exact number that were
       
   884 					// used.
       
   885 					TInt value = 0;
       
   886 					TInt consumed = ParseUIntVar(respChars.Mid(index + 1), value);
       
   887 					
       
   888 					if( consumed < KErrNone )
       
   889 						return KErrCorrupt;
       
   890 
       
   891 					// Advance to the last byte of data in this header
       
   892                     index += consumed + value;
       
   893 					}
       
   894                 else
       
   895 					// Codes 32-127 are alphanumerics representing a text
       
   896 					// string, up to a NUL termination
       
   897                     if (byteCode <= 127)
       
   898 						// Hit the start of a string - this will be assumed
       
   899 						// continuous until the NUL is found or until the end
       
   900 						// of the header is hit (which would be an error)
       
   901                         while ( (respChars[index] != 0) && (index < respLength - 1) )
       
   902 							++index;
       
   903                 }
       
   904             }
       
   905         }
       
   906 
       
   907 	// This return only occurs if the search ran off the end of the header
       
   908     return KErrNotFound;
       
   909     }
       
   910 
       
   911 
       
   912 // Perform a look-up of content type given a WSP encoding value, used as
       
   913 // an index.
       
   914 //
       
   915 // In:
       
   916 //  aIndex - the WSP encoding value
       
   917 //
       
   918 // Rtn: const TText* - the required content type text - NOT to be changed
       
   919 //
       
   920 
       
   921 EXPORT_C const TText8* CHTTPResponse::ContentType(TInt aContentTypeCode) const
       
   922     {
       
   923 
       
   924     if ((aContentTypeCode >= 0) && (aContentTypeCode < KHttpNumContentTypes))
       
   925         return KHttpContentTypes[aContentTypeCode];
       
   926     else
       
   927         return defaultType;
       
   928     }
       
   929 
       
   930 
       
   931 // Perform a look-up of character set given a WSP encoding value, used as
       
   932 // an index.
       
   933 //
       
   934 // In:
       
   935 //  aCharsetCode - the index into the content types table/
       
   936 //
       
   937 // Rtn: const TText8* - the required 8-bit character set text - NOT to be
       
   938 //						changed by the caller
       
   939 //
       
   940 
       
   941 EXPORT_C const TText8* CHTTPResponse::CharSet(TInt aCharSetCode) const
       
   942     {
       
   943 	// Search for an index for the supplied charset code
       
   944 	TInt charSetIdx = KErrNotFound;
       
   945 	for (TInt index = 0; ((index < KHttpNumCharacterSets) &&
       
   946 									(charSetIdx == KErrNotFound)); index++)
       
   947 		{
       
   948 		if (KHttpCharacterSetCodes[index] == aCharSetCode)
       
   949 			{
       
   950 			charSetIdx = index;
       
   951 			}
       
   952 		}
       
   953 
       
   954 	// If something was found, return the corresponding charset name
       
   955 	if (charSetIdx != KErrNotFound)
       
   956 		return KHttpCharacterSetNames[charSetIdx];
       
   957 	else
       
   958 		return NULL;
       
   959     }
       
   960 
       
   961 
       
   962 // Do a conversion from 32-bit UIntVar encoding into 32-bit integer
       
   963 //
       
   964 TInt CHTTPResponse::ParseUIntVar(const TDesC8& aBuffer, TInt& aVal) const
       
   965 	{
       
   966 	// Is there any buffer?
       
   967 	const TInt length = aBuffer.Length();
       
   968 	if( length == 0 )
       
   969 		return KErrCorrupt;
       
   970 
       
   971 	// initialize return val
       
   972 	aVal = 0;
       
   973 
       
   974 	// maximum length for a uintvar is 5
       
   975 	TInt lenLeft = Min(length, 5);
       
   976 
       
   977 	// get the first octet
       
   978 	TInt index = 0;
       
   979 	TUint8 byte = aBuffer[index++];
       
   980 	TInt numBytes = 1;
       
   981 
       
   982 	--lenLeft;	
       
   983 
       
   984 	// Check if any of the top 3 bits, ignoring the very top 'continue' bit, are set.  
       
   985 	// Later if we see that this is a 5 byte number - we'll know it is corrupt.  
       
   986 	// Encoding uses 7 bits/number 7x5=35 and we only support a maxiumum number 
       
   987 	// of 32 bits.
       
   988 	TBool topThreeBitsSet = byte & KTop3BitSet; 
       
   989 	
       
   990 	// copy over data from the byte into our return value (the top bit is a carry bit)
       
   991 	aVal = byte & KWapQuote;
       
   992 
       
   993 	// while the 'continue' bit is set and we have more data
       
   994 	while ((byte & KCarryBitMask) && (lenLeft > 0))
       
   995 		{
       
   996 		// shift our last value up
       
   997 		aVal <<= 7;
       
   998 		// get the next byte
       
   999 		byte = aBuffer[index++];
       
  1000 		// copy it over to the lowest byte
       
  1001 		aVal |= byte & KWapQuote;
       
  1002 		--lenLeft;
       
  1003 		++numBytes;
       
  1004 		} 
       
  1005 
       
  1006 	// last octet has continue bit set ... NOT allowed Or
       
  1007 	// this was encoded wrong - can't have a number bigger than 32 bits
       
  1008 	if ((byte & KCarryBitMask) || (numBytes == 5 && topThreeBitsSet))
       
  1009 		return KErrCorrupt;
       
  1010 
       
  1011 	// number of bytes read
       
  1012 	return numBytes;
       
  1013 	}
       
  1014 
       
  1015 
       
  1016 // Extract a WSP encoded MultiOctet Integer encoding into 32-bit integer
       
  1017 //
       
  1018 // In:
       
  1019 //  aSource	- the source Multi-Octet integer
       
  1020 //
       
  1021 // Out:
       
  1022 //  aInt		- the 32-bit resulting integer
       
  1023 //
       
  1024 void CHTTPResponse::ExtractMultiOctetInteger(TInt& aInt, const TPtrC8& aSource) const
       
  1025  	// Extract a WSP encoded integer from the source descriptor
       
  1026 	{
       
  1027 	__LOG_ENTER(_L("CHTTPResponse::ExtractMultiOctetInteger"));
       
  1028 	// Get num bytes encoding the integer - 
       
  1029 	// we are positioned at that location in the source descriptor
       
  1030 	TUint8 numBytes = aSource[0];
       
  1031 	aInt = 0;
       
  1032 	if (numBytes <= 30)
       
  1033  		{
       
  1034  		__ASSERT_DEBUG(numBytes <= aSource.Length(), User::Invariant());
       
  1035  		// Loop over the source, taking each byte and shifting it in to the count.
       
  1036  		for (TInt count = 1; (count <= numBytes); count++)
       
  1037  		        aInt = (aInt << 8) + aSource[count];
       
  1038  		}
       
  1039  	else if (numBytes & 0x80) //  check top bit is set
       
  1040  		aInt = numBytes & 0x7f;
       
  1041  	// anything between 30 and 127 is not handled...
       
  1042 	__LOG_RETURN;
       
  1043 	}
       
  1044 
       
  1045 
       
  1046 // Method to find a named field within the Cache Control header
       
  1047 //
       
  1048 // In:
       
  1049 //  aSource		- the descriptor containing the date value
       
  1050 //	aFrom		- The position in the descriptor to start from
       
  1051 //
       
  1052 // Out:
       
  1053 //  aTime - a structure containing the time (and date) found in the descriptor
       
  1054 //
       
  1055 // NOTE THIS METHOD WAS EXPORTED FOR TESTING OF THE CACHE. IT SHOULDN'T BE
       
  1056 // NOW, BUT CAN'T BE CHANGED SINCE IT WOULD AFFECT BC.
       
  1057 void CHTTPResponse::ExtractFieldDateValue(const TPtrC8& aSource,
       
  1058 										  TInt aFrom,
       
  1059 										  TTime& aTime) const
       
  1060 	{
       
  1061 	__LOG_ENTER(_L("CHTTPResponse::ExtractFieldDateValue"));
       
  1062 	// Get num bytes encoding the date - 
       
  1063 	// we are positioned at that location in the source descriptor
       
  1064     TInt time = 0;
       
  1065 	TPtrC8 integerSource = aSource.Mid(aFrom);
       
  1066 	ExtractMultiOctetInteger(time, integerSource);
       
  1067 	// The WSP Date encoding is the number of seconds since the start of the
       
  1068 	// UNIX epoch (00:00:00.000, 01-Jan-1970), as a long integer
       
  1069 	TDateTime unixEpocDT(1970, EJanuary, 0, 0, 0, 0, 0);
       
  1070 	TTime unixEpoch(unixEpocDT);
       
  1071     TTimeIntervalSeconds timeSeconds(time);
       
  1072     aTime = unixEpoch + timeSeconds;
       
  1073 	__LOG_RETURN;
       
  1074 	}
       
  1075 
       
  1076 
       
  1077 // Method to find a named field within the Cache Control header
       
  1078 //
       
  1079 // In:
       
  1080 //  aField		- the field type
       
  1081 //
       
  1082 // Out:
       
  1083 //	the found aCacheControl string
       
  1084 //
       
  1085 // Rtn: TInt - set to KErrNotFound if the field was not found,
       
  1086 //		otherwise the position in the cache control descriptor that the field
       
  1087 //		was found
       
  1088 //
       
  1089 TInt CHTTPResponse::FindCacheControlFieldValue(TCacheControlFieldValue aField,
       
  1090 											   TPtrC8& aCacheControl) const
       
  1091 // Find a named field within the Cache Control header
       
  1092 	{
       
  1093 	__LOG_ENTER(_L("CHTTPResponse::FindCacheControlFieldValue"));
       
  1094 	TInt pos = KErrNotFound;
       
  1095 	TInt index = LocateField(EHttpCacheControl, 0);
       
  1096     if (index >0)
       
  1097         {
       
  1098 		// Have the cache control descriptor
       
  1099 		// Now we need to search for the field
       
  1100 
       
  1101 		// The following rules are used to encode cache control values.
       
  1102 		// Cache-control-value	=	No-cache | No-store | Max-stale |
       
  1103 		//							Only-if-cached | Private | Public |
       
  1104 		//							No-transform | Must-revalidate | 
       
  1105 		//							Proxy-revalidate | Cache-extension | 
       
  1106 		//							Value-length Cache-directive
       
  1107 		// Cache-directive	=	No-cache 1*(Field-name) | 
       
  1108 		//						Max-age Delta-second-value |
       
  1109 		//						Max-stale Delta-second-value |
       
  1110 		//						Min-fresh Delta-second-value |
       
  1111 		//						Private 1*(Field-name) |
       
  1112 		//						Cache-extension Parameter
       
  1113 		TUint8 byteCode = iResponse->Des()[index];		// check the first byte for a recognised value
       
  1114 		if((byteCode >= 32) && (byteCode <= 127))
       
  1115 			{
       
  1116 			// Hit the start of a Header Name string - this will be assumed
       
  1117 			// continuous until the NUL is found or until the end
       
  1118 			// of the header is hit (which would be an error)
       
  1119 			// - not supported
       
  1120 			return pos;				
       
  1121 			}
       
  1122 		switch (byteCode)
       
  1123 			{
       
  1124 			case ECacheControlNoCache:		// "no-cache"
       
  1125 			case ECacheCtrlNoStore:			// "no-store"
       
  1126 			case ECacheCtrlMaxStale:		// "max-stale"
       
  1127 			case ECacheCtrlOnlyIfCached:	// "only-if-cached"
       
  1128 			case ECacheCtrlPublic:			// "public"
       
  1129 			case ECacheCtrlPrivate:			// "private"
       
  1130 			case ECacheCtrlNoTransform:		// "no-transform"
       
  1131 			case ECacheCtrlMustRevalidate:	// "must-revalidate"
       
  1132 			case ECacheCtrlProxyRevalidate:	// "proxy-revalidate"
       
  1133 				if( aField == byteCode )
       
  1134 					pos = index;			// Right here (right now).
       
  1135 				break;
       
  1136 			case ECacheCtrlCacheExtension:	// "cache-extension":
       
  1137 				break;						// Not handled
       
  1138 			default:
       
  1139 				{
       
  1140 			// Value-length Cache-directive
       
  1141 				if(FindBinaryDescField(EHttpCacheControl,aCacheControl))
       
  1142 					{
       
  1143 					TInt respLength = aCacheControl.Length();
       
  1144 					TUint8 byteCode = 0;
       
  1145 					for (TInt count = 0; count < respLength; count++)
       
  1146 						{
       
  1147 						byteCode = aCacheControl[count];
       
  1148 						if(aField == byteCode)
       
  1149 							{
       
  1150 							// Found the field we are looking for
       
  1151 							pos = count;
       
  1152 							break;
       
  1153 							}
       
  1154 						else if(count < (respLength - 1))	// Check for overrun... if this occurs it should be an error
       
  1155 							{
       
  1156 							if (byteCode <= 30)
       
  1157 								{
       
  1158 								// Codes 0-30 represent that number of following data
       
  1159 								// octets, check the cache directive field after the length
       
  1160 								if(aField == aCacheControl[count + 1])
       
  1161 									{
       
  1162 									// Found the one we want
       
  1163 									pos = count + 1;
       
  1164 									break;
       
  1165 									}
       
  1166 								else if(byteCode)
       
  1167 									{
       
  1168 									// so the following data octets should be skipped
       
  1169 									count += byteCode;
       
  1170 									}
       
  1171 								else
       
  1172 									{
       
  1173 									__DEBUGGER();
       
  1174 									count++;	// 0 data octets follow !???? : (Strange but true)
       
  1175 									}
       
  1176 								}
       
  1177 							else if (byteCode == 31)
       
  1178 								{
       
  1179 								// Code 31 indicates that the following bytes make a
       
  1180 								// UIntVar,  which indicates the number of data octets
       
  1181 								// after it. 
       
  1182 								// The UIntVar itself could be composed of upto 5 bytes
       
  1183 								// Copy a full 5 bytes from the header
       
  1184 								// Note that actually fewer might have been used; 
       
  1185 								// the UIntVar to Int converter function returns the exact
       
  1186 								// number that were used.
       
  1187 								TInt value = 0;
       
  1188 								TInt consumed = ParseUIntVar(aCacheControl.Mid(count + 1), value);
       
  1189 								
       
  1190 								if( consumed < KErrNone )
       
  1191 									return KErrCorrupt;
       
  1192 																
       
  1193 								if(aField == aCacheControl[count + 1 + consumed])
       
  1194 									{
       
  1195 									// Found the one we want
       
  1196 									pos = count + 1 + consumed;
       
  1197 									break;
       
  1198 									}
       
  1199 								else
       
  1200 									{
       
  1201 									// so the following data octets should be skipped
       
  1202 									count += 1 + consumed + value;
       
  1203 									}
       
  1204 								}
       
  1205 							}
       
  1206 						}
       
  1207 					}
       
  1208 				}
       
  1209 				break;
       
  1210 			}
       
  1211 		}
       
  1212 	__LOG_RETURN;
       
  1213 	return pos;
       
  1214 	}
       
  1215 
       
  1216 
       
  1217 // Panic method
       
  1218 //
       
  1219 // In:
       
  1220 //  aPanicCode - a standard HTTP panic code (see <HttpStd.h>)
       
  1221 //
       
  1222 void CHTTPResponse::Panic(THttpPanicCode aPanicCode) const
       
  1223 	{
       
  1224 	_LIT(KWapCHTTPResponse, "CHTTPResp");
       
  1225 	User::Panic(KWapCHTTPResponse, aPanicCode);
       
  1226 	}
       
  1227 
       
  1228 
       
  1229 #ifdef _DEBUG
       
  1230 // Debug method to dump to log the response header's binary content
       
  1231 //
       
  1232 void CHTTPResponse::DumpToLog(const TDesC8& aData) const
       
  1233     {
       
  1234 //	__LOG_ENTER(_L("CHTTPResponse::DumpToLog"));
       
  1235 
       
  1236 	// Iterate the supplied block of data in blocks of 16 bytes
       
  1237 	__LOG(_L("CHTTPResponse::DumpToLog : START"));
       
  1238 	TInt pos = 0;
       
  1239 	TBuf<KMaxLogEntrySize> logLine;
       
  1240 	TBuf<KMaxLogEntrySize> anEntry;
       
  1241 	while (pos < aData.Length())
       
  1242 		{
       
  1243 		anEntry.Format(TRefByValue<const TDesC>_L("%04x : "), pos);
       
  1244 		logLine.Append(anEntry);
       
  1245 
       
  1246 		// Hex output
       
  1247 		for (TInt offset = 0; offset < 16; offset++)
       
  1248 			{
       
  1249 			if (pos + offset < aData.Length())
       
  1250 				{
       
  1251 				TInt nextByte = aData[pos + offset];
       
  1252 				anEntry.Format(TRefByValue<const TDesC>_L("%02x "), nextByte);
       
  1253 				logLine.Append(anEntry);
       
  1254 				}
       
  1255 			else
       
  1256 				{
       
  1257 				anEntry.Format(TRefByValue<const TDesC>_L("   "));
       
  1258 				logLine.Append(anEntry);
       
  1259 				}
       
  1260 			}
       
  1261 			anEntry.Format(TRefByValue<const TDesC>_L(": "));
       
  1262 			logLine.Append(anEntry);
       
  1263 
       
  1264 		// Char output
       
  1265 		for (TInt offset = 0; offset < 16; offset++)
       
  1266 			{
       
  1267 			if (pos + offset < aData.Length())
       
  1268 				{
       
  1269 				TInt nextByte = aData[pos + offset];
       
  1270 				if ((nextByte >= 32) && (nextByte <= 127))
       
  1271 					{
       
  1272 					anEntry.Format(TRefByValue<const TDesC>_L("%c"), nextByte);
       
  1273 					logLine.Append(anEntry);
       
  1274 					}
       
  1275 				else
       
  1276 					{
       
  1277 					anEntry.Format(TRefByValue<const TDesC>_L("."));
       
  1278 					logLine.Append(anEntry);
       
  1279 					}
       
  1280 				}
       
  1281 			else
       
  1282 				{
       
  1283 				anEntry.Format(TRefByValue<const TDesC>_L(" "));
       
  1284 				logLine.Append(anEntry);
       
  1285 				}
       
  1286 			}
       
  1287 			__LOG1(_L("%S"), &logLine);
       
  1288 			logLine.Zero();
       
  1289 
       
  1290 		// Advance to next 16 byte segment
       
  1291 		pos += 16;
       
  1292 		}
       
  1293 	__LOG(_L("CHTTPResponse::DumpToLog : END"));
       
  1294 //	__LOG_RETURN;
       
  1295     }
       
  1296 #endif
       
  1297 
       
  1298 
       
  1299 // Spare methods for future BC. Const- and non-const versions to assist
       
  1300 // the caller in preserving const-ness. IMPORT_C ensures they reserve a
       
  1301 // slot in the vtbl, which is essential to preseve future BC.
       
  1302 //
       
  1303 EXPORT_C TAny* CHTTPResponse::Extend_CHTTPResponse(TAny* aArgs)
       
  1304 	{
       
  1305 	Panic(EHttpReservedForFutureExpansion);
       
  1306 	return (TAny*)aArgs;
       
  1307 	}
       
  1308 EXPORT_C TAny* CHTTPResponse::Extend_CHTTPResponse_const(TAny* aArgs) const
       
  1309 	{
       
  1310 	Panic(EHttpReservedForFutureExpansion);
       
  1311 	return (TAny*)aArgs;
       
  1312 	}