upnp/upnpstack/dlnawebserver/src/upnphttpbuffer.cpp
changeset 0 f5a58ecadc66
child 26 b6b8e90f9863
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies  this distribution, and is available 
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Declares HttpServer class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <libc/limits.h>
       
    21 #include "upnphttpbuffer.h"
       
    22 #include "upnphttpserver.h"
       
    23 #include "upnpcons.h"
       
    24 #include "upnphttpsession.h"
       
    25 #include "upnphttpfileaccess.h"
       
    26 #include "upnphttpfiletransferreader.h"
       
    27 #include "upnphttpchunkparser.h"
       
    28 #define KLogFile _L("DLNAWebServer.txt")
       
    29 #include "upnpcustomlog.h"
       
    30 #include "upnpcons.h"
       
    31 #include "httperr.h"
       
    32 // CONSTANTS
       
    33 
       
    34 const TInt KMaxBufferLength = 10240;
       
    35 
       
    36 // ============================ MEMBER FUNCTIONS ===============================
       
    37 
       
    38 // -----------------------------------------------------------------------------
       
    39 // CUpnpHttpBuffer::NewL
       
    40 // Two-phased constructor
       
    41 // -----------------------------------------------------------------------------
       
    42 //
       
    43 CUpnpHttpBuffer* CUpnpHttpBuffer::NewL( CUpnpHttpSession* aSession, TBool aToBeSavedInFile )
       
    44 	{
       
    45 LOGS("CUpnpHttpBuffer::NewL(CUpnpHttpSession*, TBool)");
       
    46 	CUpnpHttpBuffer* self = new (ELeave) CUpnpHttpBuffer( aSession, aToBeSavedInFile );
       
    47 	CleanupStack::PushL( self );
       
    48 	self->ConstructL();
       
    49 	CleanupStack::Pop( self );
       
    50 	
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 // -----------------------------------------------------------------------------
       
    55 // CUpnpHttpBuffer::~CUpnpHttpBuffer
       
    56 // C++ default destructor
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 CUpnpHttpBuffer::~CUpnpHttpBuffer()
       
    60 	{
       
    61 LOGS("CUpnpHttpBuffer::~CUpnpHttpBuffer()");
       
    62 
       
    63 	iBuffer.Close();
       
    64     delete iChunkParser;
       
    65 	}
       
    66 
       
    67 // -----------------------------------------------------------------------------
       
    68 // CUpnpHttpBuffer::CUpnpHttpBuffer
       
    69 // C++ default constructor
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 CUpnpHttpBuffer::CUpnpHttpBuffer( CUpnpHttpSession* aSession, TBool aToBeSavedInFile )
       
    73 	{
       
    74 	iContentLength = -1;
       
    75 	iSession = aSession;
       
    76 	iToFile = aToBeSavedInFile;
       
    77 	iContentLengthCounter = 0;
       
    78 	iErrorCodeCheckedForSaving = EFalse;
       
    79 	iOkToSaveToFile = EFalse;
       
    80 	iFileReadBufferSize = aSession->HttpServer()->FileReadBufferSize();
       
    81 	}
       
    82 
       
    83 // -----------------------------------------------------------------------------
       
    84 // CUpnpHttpBuffer::ConstructL
       
    85 // Two-phased constructor
       
    86 // -----------------------------------------------------------------------------
       
    87 //
       
    88 void CUpnpHttpBuffer::ConstructL()
       
    89 	{
       
    90 	iBuffer.Create( 0 );
       
    91 	iChunkParser = CUpnpHttpChunkParser::NewL();
       
    92 	}
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // CUpnpHttpBuffer::AppendHeadersL
       
    96 // 
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 TInt CUpnpHttpBuffer::AppendHeadersL( TDesC8& aBuffer, TBool aToBeSavedInFile )
       
   100 {
       
   101 	TInt PosOfDoubleLineFeed ( KErrNotFound );
       
   102 	
       
   103 	LOGS("CUpnpHttpBuffer::AppendL(TDesC8&)");
       
   104 	
       
   105 	if ( !IsHeaderReady() )
       
   106 		{
       
   107 		 iToFile = aToBeSavedInFile;
       
   108 		// header not yet ready. Checking if it gets ready with this received buffer
       
   109 		PosOfDoubleLineFeed = aBuffer.FindF( UpnpString::KDoubleLineFeed );
       
   110 		
       
   111 //trying to find double linefeed by spliiitng line
       
   112 		
       
   113 			if (iBuffer.Length() > 0)
       
   114 				{
       
   115 				if( !iBuffer.Right(UpnpString::KLineFeedLength).CompareF( UpnpString::KLineFeed) 
       
   116 					&& !aBuffer.FindF(UpnpString::KLineFeed) )
       
   117 					{
       
   118 					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KLineFeedLength;
       
   119 					}				
       
   120 				else if	(!iBuffer.Right(UpnpString::KCRLength).CompareF(UpnpString::KCR) 
       
   121 					&& !aBuffer.FindF(UpnpString::KLFCRLF))				
       
   122 					{
       
   123 					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KCRLength;
       
   124 					}
       
   125 				else if	(!iBuffer.Right(UpnpString::KCRLFCRLength).CompareF(UpnpString::KCRLFCR)  
       
   126 					&& !aBuffer.FindF(UpnpString::KLinefeed))				
       
   127 					{
       
   128 					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KCRLFCRLength;
       
   129 					}
       
   130 				//if double linefeed there are not found by splitting line
       
   131 				//may be it (all double linefeed) is in ne line	
       
   132 				else if ( PosOfDoubleLineFeed != KErrNotFound )
       
   133 					{
       
   134 					PosOfDoubleLineFeed += 	iBuffer.Length();			
       
   135 					}
       
   136 				}
       
   137 		
       
   138 		if ( PosOfDoubleLineFeed == KErrNotFound )
       
   139 			{
       
   140 			// double linefeed not found, so only adding unfinished headers to 
       
   141 			// iBuffer
       
   142 			
       
   143 			if (iBuffer.Length() <= KMaxBufferLength )    //10kb
       
   144 				{
       
   145 				    iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
       
   146 					iBuffer.Append( aBuffer );
       
   147 				}
       
   148 			
       
   149 			}
       
   150 		else
       
   151 			{
       
   152 			//  Double linefeed found. Appending headers and then checking if 
       
   153 			// response is OK.
       
   154 			TInt afterDoubleLineFeed = PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength - iBuffer.Length();
       
   155 			iBuffer.ReAllocL(PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength);
       
   156 			iBuffer.Append( aBuffer.Left(afterDoubleLineFeed));
       
   157 
       
   158             // is headers checked
       
   159     		if( !iErrorCodeCheckedForSaving )
       
   160     		    {
       
   161     		    TInt messageError = MessageErrorCode( iBuffer );
       
   162     		    TPtrC8 method = Method();
       
   163     		    TPtrC8 target = Target();
       
   164     		    
       
   165     		    if(method == KHttpPost ) 
       
   166     		        {
       
   167     		        messageError = EHttpOk;
       
   168     		        }
       
   169     		    
       
   170     		    _LIT8( KControl, "/control");
       
   171     		    
       
   172     		    if( method.FindC( KHttpPost() ) == 0 && 
       
   173     		        method.Length() == KHttpPost().Length() 
       
   174     		        )
       
   175     		        {
       
   176         		    TInt lastSlash = target.LocateReverse('/');
       
   177         		    if( lastSlash > KErrNotFound )
       
   178         		        {
       
   179             		    target.Set( target.Mid( lastSlash ) );
       
   180             		    }
       
   181                     }
       
   182     		    
       
   183     		    if ( messageError == EHttpOk || messageError == EHttpPartialContent )
       
   184     		        {
       
   185                     iOkToSaveToFile = ETrue;
       
   186     		        }
       
   187     		        
       
   188     		    // if EXPORTING, then saving to file
       
   189     		    else if( method.FindC( KHttpPost() ) == 0 &&
       
   190                             method.Length() == KHttpPost().Length() &&
       
   191                             target.FindC( KControl ) != 0 )
       
   192                     {
       
   193                     iOkToSaveToFile = ETrue;
       
   194     		        }
       
   195     		    else
       
   196     		        {
       
   197     		        iOkToSaveToFile = EFalse;
       
   198     		        CUpnpHttpFileAccess* temp = iSession->FileAccess();
       
   199     		        // Delete only downloaded file if it is not complete.
       
   200        		        if( temp && temp->Download() )
       
   201 	       		        {
       
   202                         temp->DeleteFile();
       
   203 	                    // no delete, not owned
       
   204 	        		    temp = NULL;
       
   205 	       		        }
       
   206     		        }
       
   207     		    // error code checked, no need to check it again.
       
   208     	        iErrorCodeCheckedForSaving = ETrue;
       
   209     		    }
       
   210 
       
   211     		return afterDoubleLineFeed;
       
   212 			}
       
   213 		}
       
   214 
       
   215 	return PosOfDoubleLineFeed;
       
   216 }
       
   217 
       
   218 // -----------------------------------------------------------------------------
       
   219 // CUpnpHttpBuffer::AppendL
       
   220 // This function appends the aBuffer data at the end of this HTTPBuffer.
       
   221 // -----------------------------------------------------------------------------
       
   222 //
       
   223 TInt CUpnpHttpBuffer::AppendL( TDesC8& aBuffer, TBool aToBeSavedInFile)
       
   224 	{
       
   225 	TInt retVal ( KErrNone );
       
   226 	
       
   227 	LOGS("CUpnpHttpBuffer::AppendL(TDesC8&)");
       
   228 	
       
   229 	if ( !IsHeaderReady() )
       
   230 		{
       
   231 		TInt PosOfDoubleLineFeed = AppendHeadersL( aBuffer, aToBeSavedInFile );
       
   232 
       
   233 		if ( PosOfDoubleLineFeed > KErrNotFound )
       
   234 		{
       
   235 			TInt afterDoubleLineFeed = PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength - iBuffer.Length();
       
   236     		TPtrC8 AppendPointer( aBuffer.Right( aBuffer.Length() - PosOfDoubleLineFeed ) );
       
   237 			//for file upload, data copied to the file transfer reader
       
   238 			if(iToFile && iOkToSaveToFile 
       
   239 				&& iSession->FileTransferReader() && iSession->FileTransferReader()->Activated())
       
   240 				{
       
   241 				if(AppendPointer.Length() > 0)
       
   242 					iSession->FileTransferReader()->AppendL(AppendPointer);
       
   243 				}
       
   244 			else if ( IsChunked() )
       
   245 				{
       
   246 				iPos =  iBuffer.Length();											
       
   247 				retVal = ParseL( AppendPointer );
       
   248 				}
       
   249 			else
       
   250 				{
       
   251 				iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
       
   252 				iBuffer.Append( AppendPointer );				
       
   253 				}
       
   254 			}
       
   255 		}
       
   256 	else
       
   257 		{
       
   258 		if( !iErrorCodeCheckedForSaving )
       
   259 		    {
       
   260 		    TInt messageError = MessageErrorCode( iBuffer );
       
   261 		    if ( messageError == EHttpOk || messageError == EHttpPartialContent )
       
   262 		        {
       
   263                 iOkToSaveToFile = ETrue;
       
   264 		        }
       
   265 		    else
       
   266 		        {
       
   267 		        iOkToSaveToFile = EFalse;
       
   268    		        CUpnpHttpFileAccess* temp = iSession->FileAccess();
       
   269    		        if( temp )
       
   270    		            {
       
   271     		        temp->DeleteFile();
       
   272                     // no delete, not owned
       
   273     		        temp = NULL;
       
   274     		        }
       
   275 		        }
       
   276 		    // error code checked, no need to check it again.
       
   277 	        iErrorCodeCheckedForSaving = ETrue;
       
   278 		    }
       
   279 		
       
   280 		//for file upload, data copied to the file transfer reader
       
   281 		if(iToFile && iOkToSaveToFile &&
       
   282 			iSession->FileTransferReader() && iSession->FileTransferReader()->Activated())
       
   283 			{
       
   284 			if(aBuffer.Length() > 0)
       
   285 				iSession->FileTransferReader()->AppendL(aBuffer);
       
   286 			return retVal;
       
   287 			}
       
   288 			    
       
   289 		if ( IsChunked() )
       
   290 			{
       
   291 			retVal = ParseL( aBuffer );
       
   292 			}
       
   293 		else
       
   294 			{
       
   295 			iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
       
   296 			iBuffer.Append( aBuffer );
       
   297 			}
       
   298 	    }
       
   299 	return retVal;
       
   300 	}
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // CUpnpHttpBuffer::ParseL
       
   304 // Decodes chunked messages.
       
   305 // -----------------------------------------------------------------------------
       
   306 //
       
   307 TInt CUpnpHttpBuffer::ParseL( TDesC8& aBuffer )
       
   308     {
       
   309     iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
       
   310     iBuffer.Append( aBuffer );
       
   311     return Parse( iBuffer, iPos ) < 0 ? KErrHttpUnknownParseState: KErrNone;                  
       
   312     }
       
   313 
       
   314 // -----------------------------------------------------------------------------
       
   315 // CUpnpHttpBuffer::Parse
       
   316 // Decodes chunked-encoded buffer
       
   317 // -----------------------------------------------------------------------------
       
   318 //	
       
   319 TInt CUpnpHttpBuffer::Parse(TDes8& aBuffer, TInt& aPos)
       
   320     {    
       
   321     if( aPos >= aBuffer.Length() )
       
   322         {
       
   323         iChunkParser->Reset();
       
   324         return KErrNone;
       
   325         }
       
   326     return iChunkParser->Parse( aBuffer, aPos );		
       
   327     }
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // CUpnpHttpBuffer::IsReady
       
   331 // Returns ETrue, if buffer is ready to be converted to HTTPMessage 
       
   332 // else returns EFalse.
       
   333 // -----------------------------------------------------------------------------
       
   334 //
       
   335 TBool CUpnpHttpBuffer::IsReadyL()
       
   336 	{
       
   337 LOGS("CUpnpHttpBuffer::IsReady()");
       
   338 	if ( IsHeaderReady() )
       
   339 		{
       
   340 		//Assuming here that HTTP GET -requests may not have a body.
       
   341 		//So if a HTTP GET request arrives and it has a CONTENT-TYPE or a 
       
   342 		//CONTENT-LENGHT header we may still serve the file
       
   343 		TPtrC8 method = Method();
       
   344 		if ( method.FindC( KHttpGet() ) == 0 )
       
   345 		    {
       
   346 		    return ETrue;
       
   347 		    }
       
   348 		if ( HasBody() )
       
   349 			{
       
   350 			return IsBodyReadyL();
       
   351 			}
       
   352 		else 
       
   353 			{
       
   354 			return ETrue;
       
   355 			}
       
   356 		}
       
   357 	return EFalse;
       
   358 	}
       
   359 
       
   360 // -----------------------------------------------------------------------------
       
   361 // CUpnpHttpBuffer::IsHeaderReady
       
   362 // Returns ETrue, if header part of HTTPMessage is ready, else returns EFalse.
       
   363 // -----------------------------------------------------------------------------
       
   364 //
       
   365 TBool CUpnpHttpBuffer::IsHeaderReady()
       
   366 	{
       
   367 LOGS("CUpnpHttpBuffer::IsHeaderReady()");
       
   368 	if ( iBuffer.Find( UpnpString::KDoubleLineFeed() ) > KErrNotFound )
       
   369 		{
       
   370 		return ETrue;
       
   371 		}
       
   372 	else
       
   373 		{
       
   374 		return EFalse;
       
   375 		}
       
   376 	}
       
   377 
       
   378 // -----------------------------------------------------------------------------
       
   379 // CUpnpHttpBuffer::IsBodyReadyL
       
   380 // Returns ETrue, if body part of HTTPMessage is ready, else returns EFalse.
       
   381 // -----------------------------------------------------------------------------
       
   382 //
       
   383 TBool CUpnpHttpBuffer::IsBodyReadyL()
       
   384 	{
       
   385 LOGS("CUpnpHttpBuffer::IsBodyReadyL()");
       
   386 	TInt bodyStart = iBuffer.FindF( UpnpString::KDoubleLineFeed );
       
   387 	TInt contLength = ContentLengthL();
       
   388 	if ( IsChunked() )
       
   389 		{
       
   390 		return ChunkTransferFinished();
       
   391 		}
       
   392 	else
       
   393 		{
       
   394 		if ( iHasContentType )
       
   395 			{	
       
   396 			TPtrC8 body = iBuffer.Mid( bodyStart + 
       
   397                 UpnpString::KDoubleLineFeed().Length() );
       
   398 			return body.Find( UpnpString::KDoubleLineFeed() ) != KErrNotFound;
       
   399 			}
       
   400 		}
       
   401 
       
   402 	TPtrC8 tempPtr;
       
   403 	if ( iToFile && iOkToSaveToFile )
       
   404 		{
       
   405 		if ( iContentLengthCounter >= contLength )
       
   406 			{
       
   407 			return !(IsChunked() && !ChunkTransferFinished());
       
   408 			}
       
   409 		else
       
   410 			{
       
   411 			return EFalse;		
       
   412 			}
       
   413 		}
       
   414 	else
       
   415 		{
       
   416 		tempPtr.Set( iBuffer.Mid( bodyStart + UpnpString::KDoubleLineFeedLength ) );		
       
   417 		if (  tempPtr.Length() >= contLength )
       
   418 			{
       
   419 			return !(IsChunked() && !ChunkTransferFinished());
       
   420 			}
       
   421 		else
       
   422 			{
       
   423 			return EFalse;
       
   424 			}
       
   425 		}
       
   426 	}
       
   427 
       
   428 // -----------------------------------------------------------------------------
       
   429 // CUpnpHttpBuffer::BytesInBuffer
       
   430 // Returns the length of entire buffer.
       
   431 // -----------------------------------------------------------------------------
       
   432 //
       
   433 TInt CUpnpHttpBuffer::BytesInBuffer()
       
   434 	{
       
   435 LOGS("CUpnpHttpBuffer::BytesInBuffer()");
       
   436 	return iBuffer.Length();
       
   437 	}
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CUpnpHttpBuffer::RemoveL
       
   441 // This function deletes aLength bytes from the beginning of HTTPBuffer.
       
   442 // -----------------------------------------------------------------------------
       
   443 //
       
   444 void CUpnpHttpBuffer::RemoveL( TInt aLength )
       
   445 	{
       
   446 LOGS1("CUpnpHttpBuffer::RemoveL(%i)", aLength);
       
   447 	if ( aLength <= iBuffer.Length() )
       
   448 		{
       
   449 		iBuffer.Delete( 0, aLength );
       
   450 		}
       
   451 	}
       
   452 
       
   453 // -----------------------------------------------------------------------------
       
   454 // CUpnpHttpBuffer::ChunkTransferFinished
       
   455 // Returns ETrue, if chunk encoded message is finished.
       
   456 // -----------------------------------------------------------------------------
       
   457 //
       
   458 TBool CUpnpHttpBuffer::ChunkTransferFinished()
       
   459 	{
       
   460 LOGS("CUpnpHttpBuffer::ChunkTransferFinished()");
       
   461 	return iChunkParser->IsFinished();
       
   462 	}
       
   463 
       
   464 // -----------------------------------------------------------------------------
       
   465 // CUpnpHttpBuffer::HasBody
       
   466 // Returns ETrue, if message has body, else returns EFalse.
       
   467 // -----------------------------------------------------------------------------
       
   468 //
       
   469 TBool CUpnpHttpBuffer::HasBody()
       
   470 	{
       
   471 LOGS("CUpnpHttpBuffer::HasBody()");
       
   472 	if( IsChunked() )
       
   473 		{
       
   474 		return ETrue;
       
   475 		}
       
   476 TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );
       
   477 if (endOfHeader>0)
       
   478 	{TPtrC8 tmp = iBuffer.Mid(0, endOfHeader);
       
   479 	if ( tmp.FindC( UpnpHTTP::KContentLength() ) > -1 )
       
   480 		{
       
   481 		iHasContentType = EFalse;
       
   482 		return ETrue;
       
   483 		}
       
   484 	else if ( tmp.FindC( UpnpHTTP::KContentType() ) > -1)
       
   485 		{
       
   486 		iHasContentType = ETrue;
       
   487 		return ETrue;
       
   488 		}
       
   489 	else 
       
   490 		{
       
   491 		iHasContentType = EFalse;
       
   492 		return EFalse;
       
   493 		}
       
   494 	}
       
   495 else
       
   496 	{
       
   497 	iHasContentType = EFalse;
       
   498 	return EFalse; //no end of the header, not possible to judge if there is a body	
       
   499 	}
       
   500 	}
       
   501 
       
   502 // -----------------------------------------------------------------------------
       
   503 // CUpnpHttpBuffer::IsChunked
       
   504 // Returns ETrue, if message's header contains "Transfer-encoding: 
       
   505 // Chunked" -header.
       
   506 // -----------------------------------------------------------------------------
       
   507 //
       
   508 TBool CUpnpHttpBuffer::IsChunked()
       
   509 	{
       
   510 	LOGS("CUpnpHttpBuffer::IsChunked()");	
       
   511 	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );	
       
   512 		
       
   513 	// to check only first 2k of data or whole portion with all headers 
       
   514 	// if they are bigger	
       
   515 	TPtrC8 TranferCodingPointer;
       
   516 	if (endOfHeader <= UpnpSSDP::KMaxMessageLength)
       
   517 		TranferCodingPointer.Set( iBuffer.Left( endOfHeader + UpnpString::KLineFeedLength ) ); 
       
   518 	else 
       
   519 		TranferCodingPointer.Set( iBuffer.Left( UpnpSSDP::KMaxMessageLength ) ); 
       
   520 
       
   521 	TInt TransferEncodingIndex = 
       
   522         TranferCodingPointer.FindC( UpnpHTTP::TransferEncoding );
       
   523 
       
   524 	if ( TransferEncodingIndex == KErrNotFound ) 
       
   525 		{
       
   526 		return EFalse;
       
   527 		}
       
   528 	else
       
   529 		{
       
   530 		TInt correct = 0;
       
   531 		TInt transferHeaderLength = 0;
       
   532 		correct = TransferEncodingIndex;
       
   533 		transferHeaderLength = UpnpHTTP::TransferEncoding().Length();
       
   534 
       
   535 		TPtrC8 tempPtr = iBuffer.Mid( correct + transferHeaderLength, 
       
   536             iBuffer.Length() - correct - transferHeaderLength );
       
   537 	
       
   538 		TInt LineFeedAfterTransferCoding = tempPtr.FindF( UpnpString::KLineFeed );
       
   539 
       
   540 		TPtrC8 codingPtr = tempPtr.Left( LineFeedAfterTransferCoding );
       
   541 		if ( codingPtr.FindC( UpnpHTTP::Chunked ) != KErrNotFound )
       
   542 			{
       
   543 			return ETrue;
       
   544 			}
       
   545 		else
       
   546 			{
       
   547 			return EFalse;
       
   548 			}
       
   549 		}
       
   550 	}
       
   551 
       
   552 // -----------------------------------------------------------------------------
       
   553 // CUpnpHttpBuffer::Headers
       
   554 // Returns Headers of the first message in the buffer.
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 TPtrC8 CUpnpHttpBuffer::Headers()
       
   558 	{
       
   559 LOGS("CUpnpHttpBuffer::Headers()");
       
   560 	TInt EndOfHeaders = iBuffer.FindC( UpnpString::KDoubleLineFeed );
       
   561 	TPtrC8 headers = iBuffer.Left( EndOfHeaders + UpnpString::KDoubleLineFeedLength  );	
       
   562 	return headers;
       
   563 	}
       
   564 
       
   565 
       
   566 // -----------------------------------------------------------------------------
       
   567 // CUpnpHttpBuffer::L
       
   568 // Returns the content of buffer.
       
   569 // -----------------------------------------------------------------------------
       
   570 //
       
   571 TPtrC8 CUpnpHttpBuffer::Content()
       
   572 	{
       
   573 LOGS("CUpnpHttpBuffer::Content()");
       
   574 	TInt PosOfContLength = iBuffer.FindC( UpnpHTTP::KHdrContentLength() );
       
   575 	TInt contLen = 0;
       
   576 	
       
   577 	if ( PosOfContLength > 0 )
       
   578 		{
       
   579 		TRAPD(error, contLen = ContentLengthL());
       
   580 		if (error)
       
   581 			{
       
   582 			contLen = 0;
       
   583 			}
       
   584 		}
       
   585 	else if ( iHasContentType )
       
   586 		{
       
   587 		return TPtrC8( iBuffer );
       
   588 		}
       
   589 	else if( IsChunked() )
       
   590 		{
       
   591 		TInt StartOfMessage = iBuffer.FindC( UpnpString::KDoubleLineFeed );
       
   592 		contLen = iBuffer.Length() - StartOfMessage;	
       
   593 		}
       
   594 	/*else
       
   595 		{
       
   596 		TInt StartOfMessage = iBuffer.FindC( UpnpString::KDoubleLineFeed );
       
   597 		contLen = iBuffer.Des().Length() - StartOfMessage;
       
   598 		}*/	
       
   599 
       
   600 	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );
       
   601 	TInt length = 0;
       
   602 	// Probably not all headers were sent
       
   603 	
       
   604 	if( endOfHeader == KErrNotFound  )
       
   605 		{
       
   606 		length = iBuffer.Length();
       
   607 		}
       
   608 	else
       
   609 		{
       
   610 		length = endOfHeader + contLen + UpnpString::KDoubleLineFeedLength;	
       
   611 		}
       
   612 
       
   613     if( length < 0 ) // in case of overflow of length value
       
   614         {
       
   615         length = INT_MAX;
       
   616         }
       
   617 
       
   618 	TPtrC8 message = iBuffer.Left( length );
       
   619 	return message;
       
   620 	}	
       
   621 
       
   622 // -----------------------------------------------------------------------------
       
   623 // CUpnpHttpBuffer::ContentLengthL
       
   624 // Returns the content length of first message in the buffer.
       
   625 // -----------------------------------------------------------------------------
       
   626 //
       
   627 TInt CUpnpHttpBuffer::ContentLengthL()
       
   628 	{
       
   629 	LOGS("CUpnpHttpBuffer::ContentLengthL()");
       
   630 	
       
   631 	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );	
       
   632     User::LeaveIfError(endOfHeader);
       
   633 	TPtrC8 findptr;
       
   634 	// to check only first 2k of data or whole portion with all headers 
       
   635 	// if they are bigger	
       
   636 	if (endOfHeader >= UpnpSSDP::KMaxMessageLength)
       
   637 		findptr.Set( iBuffer.Left( endOfHeader + UpnpString::KLineFeedLength ) ); 
       
   638 	else 
       
   639 		findptr.Set( iBuffer.Left( UpnpSSDP::KMaxMessageLength ) ); 						
       
   640 
       
   641 	TInt contentLengthIndex = findptr.FindC( UpnpHTTP::KHdrContentLength() );
       
   642 
       
   643 	TInt lengthOfContentLength = UpnpHTTP::KHdrContentLength().Length() +
       
   644         UpnpString::KColon().Length();
       
   645 	
       
   646 	if ( contentLengthIndex <= 0 ) 
       
   647 		{
       
   648 	return KErrNotFound;
       
   649 		}
       
   650 
       
   651 	TPtrC8 rest;
       
   652 	rest.Set( findptr );
       
   653 	rest.Set( rest.Mid( contentLengthIndex + lengthOfContentLength ) );
       
   654 
       
   655 	TInt lineEnd = rest.Find( UpnpString::KLineFeed );
       
   656 	if ( lineEnd < 0 )
       
   657 		{
       
   658 		return KErrNotFound;
       
   659 		}
       
   660 	
       
   661 	// LWS and spanning headers
       
   662 	TInt indexLWS = 0;
       
   663 	TPtrC8 clRest = rest;
       
   664 	TInt contentLengthValueEnd = lineEnd;
       
   665 	
       
   666 	while( ETrue )
       
   667 	    {
       
   668 	    indexLWS = CUpnpHttpMessage::FindLWS( clRest );
       
   669 	    if( indexLWS == lineEnd )
       
   670 	        {	     
       
   671 	        clRest.Set( clRest.Mid( lineEnd + UpnpString::KLineFeed().Length() ) );
       
   672 	        lineEnd = clRest.Find( UpnpString::KLineFeed );
       
   673 	        contentLengthValueEnd += lineEnd + UpnpString::KLineFeed().Length();
       
   674 	        }
       
   675 	    else
       
   676 	        {
       
   677 	        break;
       
   678 	        }
       
   679 	    }			
       
   680     
       
   681 	TPtrC8 length = rest.Left( contentLengthValueEnd );
       
   682     
       
   683     if( !length.Compare( KNullDesC8() ) )
       
   684         return -1;
       
   685     
       
   686     // Unfold header
       
   687     HBufC8* clValueBuf = length.AllocLC();
       
   688     TPtr8 ptrCLValue = clValueBuf->Des();
       
   689     
       
   690     // Remove CRLFs
       
   691     TInt pos;
       
   692 	while( ( pos = ptrCLValue.FindC( UpnpString::KLineFeed() ) ) != KErrNotFound)
       
   693 	    {
       
   694 		ptrCLValue.Delete(pos, UpnpString::KLineFeedLength);
       
   695 	    }
       
   696 	
       
   697     // Remove spaces
       
   698     while( ( pos = ptrCLValue.FindC( UpnpString::KSpace() ) ) != KErrNotFound)
       
   699 	    {
       
   700 		ptrCLValue.Delete(pos, 1);
       
   701 	    }
       
   702 	
       
   703 	// Remove tabs
       
   704     while( ( pos = ptrCLValue.FindC( UpnpString::KTab() ) ) != KErrNotFound)
       
   705 	    {
       
   706 		ptrCLValue.Delete(pos, 1);
       
   707 	    }
       
   708    
       
   709 	TLex8 lex( ptrCLValue );
       
   710 	TInt val = 0;
       
   711 	User::LeaveIfError(lex.Val( val ));
       
   712 	
       
   713 	CleanupStack::PopAndDestroy( clValueBuf );
       
   714 
       
   715 	iContentLength = val;
       
   716 
       
   717 	return val;
       
   718 	}
       
   719 
       
   720 // -----------------------------------------------------------------------------
       
   721 // CUpnpHttpBuffer::UsesConnectionClose
       
   722 // Returns ETrue, if message's header contains "Connection: close" -header.
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 TBool CUpnpHttpBuffer::UsesConnectionClose()
       
   726 	{
       
   727 LOGS("CUpnpHttpBuffer::UsesConnectionClose()");
       
   728 	if(IsHeaderReady())
       
   729 		{
       
   730 		TPtrC8 headers=Headers();
       
   731 		TInt posOfConn=headers.FindC(UpnpHTTP::KConnection());
       
   732 		TInt posOfHttp10 = headers.FindC(KHttp10); 	
       
   733 		
       
   734 		if( posOfConn != KErrNotFound )
       
   735 			{
       
   736 			TPtrC8 conn=headers.Mid(posOfConn+UpnpHTTP::KConnection().Length() +
       
   737                 UpnpString::KColon().Length());
       
   738 			
       
   739 			TInt posOfLineFeed=conn.FindC(UpnpString::KLineFeed());
       
   740 			if(posOfLineFeed != KErrNotFound)
       
   741 				{
       
   742 				conn.Set(conn.Left(posOfLineFeed));
       
   743 				
       
   744 				while((conn.Left(1)).CompareC(UpnpString::KSpace()) == 0)
       
   745 					{
       
   746 					conn.Set(conn.Mid(1)); // removing spaces in front of value
       
   747 					}
       
   748 					
       
   749 				if(conn.FindC(UpnpHTTP::KClose()) >= 0)
       
   750 					{
       
   751 					return ETrue;
       
   752 					}
       
   753 				else
       
   754 					{
       
   755 					return EFalse;
       
   756 					}
       
   757 				}
       
   758 			else
       
   759 				{
       
   760 				// If rsp = 'HTTP/1.0', we can assume that it contains 'connection:close' header, even if it doesn't!	
       
   761 		                   if( posOfHttp10 != KErrNotFound )
       
   762 		                        return ETrue;
       
   763 				return EFalse;
       
   764 				}
       
   765 			}
       
   766 		else
       
   767 			{
       
   768 		         // If rsp = 'HTTP/1.0', we can assume that it contains 'connection:close' header, even if it doesn't!	
       
   769 		         if( posOfHttp10 != KErrNotFound )
       
   770 		             return ETrue;
       
   771 			return EFalse;
       
   772 			}
       
   773 		}
       
   774 	return EFalse;
       
   775 	}
       
   776 
       
   777 // -----------------------------------------------------------------------------
       
   778 // CUpnpHttpBuffer::MessageErrorCode
       
   779 // Checks error code of received message.
       
   780 // -----------------------------------------------------------------------------
       
   781 //
       
   782 TInt CUpnpHttpBuffer::MessageErrorCode( TDesC8& aBuffer )
       
   783     {
       
   784     if( IsHeaderReady() )
       
   785         {
       
   786     	TInt posOfNextLine = aBuffer.Find(UpnpString::KLineFeed); 
       
   787     	if( posOfNextLine != KErrNotFound )
       
   788     		{
       
   789     		TPtrC8 spacePtr;
       
   790     		spacePtr.Set( aBuffer );
       
   791     		
       
   792     		// finding first space
       
   793     		TInt posOfFirstSpace = spacePtr.Find(UpnpString::KSpace);
       
   794             if ( posOfFirstSpace != KErrNotFound )
       
   795                 {
       
   796     		    spacePtr.Set( spacePtr.Left( posOfFirstSpace ) );
       
   797 
       
   798                 }
       
   799 
       
   800     		// back to basic handling
       
   801     		spacePtr.Set( aBuffer );
       
   802     		
       
   803     		if( posOfFirstSpace < posOfNextLine && posOfFirstSpace != KErrNotFound )
       
   804     			{
       
   805     			// if first space is found, it has to be before linefeed
       
   806     			// +1 comes from going over the first space, we are interested
       
   807     			// in what comes after it.
       
   808     			spacePtr.Set( spacePtr.Mid( posOfFirstSpace  + 1 ) );
       
   809     			TInt posOfSecondSpace = spacePtr.Find(UpnpString::KSpace);
       
   810     			if( posOfSecondSpace < posOfNextLine && posOfSecondSpace != KErrNotFound )
       
   811     				{
       
   812     				// check that length of path is longer than zero.
       
   813     				if( posOfSecondSpace > 0 )
       
   814     					{
       
   815                         // now setting spacePtr so that we have the error number in spacePrt
       
   816     					spacePtr.Set( spacePtr.Left( posOfSecondSpace ) );
       
   817 
       
   818                         // making conversion
       
   819           				TLex8 errorValue( spacePtr );
       
   820                         TInt messageErrorValue( 0 );                        
       
   821         				TInt convError = errorValue.Val( messageErrorValue );
       
   822         				
       
   823         				// checking that conversion was ok
       
   824         				if( convError == KErrNone )
       
   825         				    {
       
   826         				    return messageErrorValue;
       
   827         				    }
       
   828         				else
       
   829         				    {
       
   830         				    return KErrAbort;
       
   831         				    }
       
   832         				
       
   833     					}
       
   834     				else
       
   835     					{
       
   836     					// header too short. Invalid message
       
   837     					return KErrAbort;
       
   838     					}
       
   839     				}
       
   840     			else
       
   841     				{
       
   842     				// no second space found. Invalid message.
       
   843     				return KErrAbort;
       
   844     				}
       
   845     			}
       
   846     		else
       
   847     			{
       
   848     			// no space found before linefeed. Invalid message
       
   849     			return KErrAbort;
       
   850     			}
       
   851      		}
       
   852 		else
       
   853 			{
       
   854 			// no linefeed found in headers. Invalid message
       
   855 			return KErrAbort;
       
   856 			}        
       
   857         }
       
   858     else
       
   859         {
       
   860         return KErrAbort;
       
   861         }
       
   862     }
       
   863 
       
   864 // -----------------------------------------------------------------------------
       
   865 // CUpnpHttpBuffer::Method
       
   866 // returns the method of message
       
   867 // -----------------------------------------------------------------------------
       
   868 //
       
   869 TPtrC8 CUpnpHttpBuffer::Method()
       
   870     {
       
   871     if( IsHeaderReady() )
       
   872         {
       
   873         TPtrC8 ret;
       
   874         ret.Set( Headers() );
       
   875         TInt posOfSpace = ret.Locate(' ');
       
   876         if( posOfSpace != KErrNotFound )
       
   877             {
       
   878             ret.Set( ret.Left( posOfSpace ) );
       
   879             return ret;
       
   880             }
       
   881         else
       
   882             {
       
   883             return KNullDesC8();
       
   884             }
       
   885         
       
   886         }
       
   887     else
       
   888         {
       
   889         return KNullDesC8();
       
   890         }
       
   891     }
       
   892 
       
   893 // -----------------------------------------------------------------------------
       
   894 // CUpnpHttpBuffer::Target
       
   895 // 
       
   896 // -----------------------------------------------------------------------------
       
   897 //    
       
   898 TPtrC8 CUpnpHttpBuffer::Target()
       
   899     {
       
   900     if( IsHeaderReady() )
       
   901         {
       
   902         TPtrC8 ret;
       
   903         ret.Set( Headers() );
       
   904         TInt posOfSpace = ret.Locate(' ');
       
   905         if( posOfSpace != KErrNotFound )
       
   906             {
       
   907             ret.Set( ret.Mid( posOfSpace +1 ) );
       
   908             posOfSpace = ret.Locate(' ');
       
   909             if( posOfSpace != KErrNotFound )
       
   910                 {
       
   911                 ret.Set( ret.Left( posOfSpace ) );
       
   912                 return ret;
       
   913                 }
       
   914             else
       
   915                 {
       
   916                 return KNullDesC8();
       
   917                 }
       
   918             }
       
   919         else
       
   920             {
       
   921             return KNullDesC8();
       
   922             }
       
   923         
       
   924         }
       
   925     else
       
   926         {
       
   927         return KNullDesC8();
       
   928         }    
       
   929     }
       
   930 
       
   931 // -----------------------------------------------------------------------------
       
   932 // CUpnpHttpBuffer::IsToFile
       
   933 // Returns True if message content is going to be saved in file.
       
   934 // -----------------------------------------------------------------------------
       
   935 //    
       
   936 TBool CUpnpHttpBuffer::IsToFile()
       
   937 	{
       
   938 	return iToFile;		
       
   939 	}
       
   940 
       
   941 // -----------------------------------------------------------------------------
       
   942 // CUpnpHttpBuffer::SetToFile
       
   943 // Sets if body of message contained in buffer should be saved in file.
       
   944 // -----------------------------------------------------------------------------
       
   945 //        
       
   946 void CUpnpHttpBuffer::SetToFile( TBool aToFile )
       
   947 	{
       
   948 	iToFile = aToFile;			
       
   949 	}
       
   950 
       
   951 
       
   952 // End Of File