upnp/upnpstack/dlnawebserver/src/upnphttpbuffer.cpp
changeset 0 f5a58ecadc66
child 9 5c72fd91570d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/dlnawebserver/src/upnphttpbuffer.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,952 @@
+/** @file
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies  this distribution, and is available 
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Declares HttpServer class.
+*
+*/
+
+
+// INCLUDE FILES
+#include <libc/limits.h>
+#include "upnphttpbuffer.h"
+#include "upnphttpserver.h"
+#include "upnpcons.h"
+#include "upnphttpsession.h"
+#include "upnphttpfileaccess.h"
+#include "upnphttpfiletransferreader.h"
+#include "upnphttpchunkparser.h"
+#define KLogFile _L("DLNAWebServer.txt")
+#include "upnpcustomlog.h"
+#include "upnpcons.h"
+#include "httperr.h"
+// CONSTANTS
+
+const TInt KMaxBufferLength = 10240;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::NewL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpBuffer* CUpnpHttpBuffer::NewL( CUpnpHttpSession* aSession, TBool aToBeSavedInFile )
+	{
+LOGS("CUpnpHttpBuffer::NewL(CUpnpHttpSession*, TBool)");
+	CUpnpHttpBuffer* self = new (ELeave) CUpnpHttpBuffer( aSession, aToBeSavedInFile );
+	CleanupStack::PushL( self );
+	self->ConstructL();
+	CleanupStack::Pop( self );
+	
+	return self;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::~CUpnpHttpBuffer
+// C++ default destructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpBuffer::~CUpnpHttpBuffer()
+	{
+LOGS("CUpnpHttpBuffer::~CUpnpHttpBuffer()");
+
+	iBuffer.Close();
+    delete iChunkParser;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::CUpnpHttpBuffer
+// C++ default constructor
+// -----------------------------------------------------------------------------
+//
+CUpnpHttpBuffer::CUpnpHttpBuffer( CUpnpHttpSession* aSession, TBool aToBeSavedInFile )
+	{
+	iContentLength = -1;
+	iSession = aSession;
+	iToFile = aToBeSavedInFile;
+	iContentLengthCounter = 0;
+	iErrorCodeCheckedForSaving = EFalse;
+	iOkToSaveToFile = EFalse;
+	iFileReadBufferSize = aSession->HttpServer()->FileReadBufferSize();
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::ConstructL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpBuffer::ConstructL()
+	{
+	iBuffer.Create( 0 );
+	iChunkParser = CUpnpHttpChunkParser::NewL();
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::AppendHeadersL
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::AppendHeadersL( TDesC8& aBuffer, TBool aToBeSavedInFile )
+{
+	TInt PosOfDoubleLineFeed ( KErrNotFound );
+	
+	LOGS("CUpnpHttpBuffer::AppendL(TDesC8&)");
+	
+	if ( !IsHeaderReady() )
+		{
+		 iToFile = aToBeSavedInFile;
+		// header not yet ready. Checking if it gets ready with this received buffer
+		PosOfDoubleLineFeed = aBuffer.FindF( UpnpString::KDoubleLineFeed );
+		
+//trying to find double linefeed by spliiitng line
+		
+			if (iBuffer.Length() > 0)
+				{
+				if( !iBuffer.Right(UpnpString::KLineFeedLength).CompareF( UpnpString::KLineFeed) 
+					&& !aBuffer.FindF(UpnpString::KLineFeed) )
+					{
+					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KLineFeedLength;
+					}				
+				else if	(!iBuffer.Right(UpnpString::KCRLength).CompareF(UpnpString::KCR) 
+					&& !aBuffer.FindF(UpnpString::KLFCRLF))				
+					{
+					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KCRLength;
+					}
+				else if	(!iBuffer.Right(UpnpString::KCRLFCRLength).CompareF(UpnpString::KCRLFCR)  
+					&& !aBuffer.FindF(UpnpString::KLinefeed))				
+					{
+					PosOfDoubleLineFeed = iBuffer.Length() - UpnpString::KCRLFCRLength;
+					}
+				//if double linefeed there are not found by splitting line
+				//may be it (all double linefeed) is in ne line	
+				else if ( PosOfDoubleLineFeed != KErrNotFound )
+					{
+					PosOfDoubleLineFeed += 	iBuffer.Length();			
+					}
+				}
+		
+		if ( PosOfDoubleLineFeed == KErrNotFound )
+			{
+			// double linefeed not found, so only adding unfinished headers to 
+			// iBuffer
+			
+			if (iBuffer.Length() <= KMaxBufferLength )    //10kb
+				{
+				    iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
+					iBuffer.Append( aBuffer );
+				}
+			
+			}
+		else
+			{
+			//  Double linefeed found. Appending headers and then checking if 
+			// response is OK.
+			TInt afterDoubleLineFeed = PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength - iBuffer.Length();
+			iBuffer.ReAllocL(PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength);
+			iBuffer.Append( aBuffer.Left(afterDoubleLineFeed));
+
+            // is headers checked
+    		if( !iErrorCodeCheckedForSaving )
+    		    {
+    		    TInt messageError = MessageErrorCode( iBuffer );
+    		    TPtrC8 method = Method();
+    		    TPtrC8 target = Target();
+    		    
+    		    if(method == KHttpPost ) 
+    		        {
+    		        messageError = EHttpOk;
+    		        }
+    		    
+    		    _LIT8( KControl, "/control");
+    		    
+    		    if( method.FindC( KHttpPost() ) == 0 && 
+    		        method.Length() == KHttpPost().Length() 
+    		        )
+    		        {
+        		    TInt lastSlash = target.LocateReverse('/');
+        		    if( lastSlash > KErrNotFound )
+        		        {
+            		    target.Set( target.Mid( lastSlash ) );
+            		    }
+                    }
+    		    
+    		    if ( messageError == EHttpOk || messageError == EHttpPartialContent )
+    		        {
+                    iOkToSaveToFile = ETrue;
+    		        }
+    		        
+    		    // if EXPORTING, then saving to file
+    		    else if( method.FindC( KHttpPost() ) == 0 &&
+                            method.Length() == KHttpPost().Length() &&
+                            target.FindC( KControl ) != 0 )
+                    {
+                    iOkToSaveToFile = ETrue;
+    		        }
+    		    else
+    		        {
+    		        iOkToSaveToFile = EFalse;
+    		        CUpnpHttpFileAccess* temp = iSession->FileAccess();
+    		        // Delete only downloaded file if it is not complete.
+       		        if( temp && temp->Download() )
+	       		        {
+                        temp->DeleteFile();
+	                    // no delete, not owned
+	        		    temp = NULL;
+	       		        }
+    		        }
+    		    // error code checked, no need to check it again.
+    	        iErrorCodeCheckedForSaving = ETrue;
+    		    }
+
+    		return afterDoubleLineFeed;
+			}
+		}
+
+	return PosOfDoubleLineFeed;
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::AppendL
+// This function appends the aBuffer data at the end of this HTTPBuffer.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::AppendL( TDesC8& aBuffer, TBool aToBeSavedInFile)
+	{
+	TInt retVal ( KErrNone );
+	
+	LOGS("CUpnpHttpBuffer::AppendL(TDesC8&)");
+	
+	if ( !IsHeaderReady() )
+		{
+		TInt PosOfDoubleLineFeed = AppendHeadersL( aBuffer, aToBeSavedInFile );
+
+		if ( PosOfDoubleLineFeed > KErrNotFound )
+		{
+			TInt afterDoubleLineFeed = PosOfDoubleLineFeed + UpnpString::KDoubleLineFeedLength - iBuffer.Length();
+    		TPtrC8 AppendPointer( aBuffer.Right( aBuffer.Length() - PosOfDoubleLineFeed ) );
+			//for file upload, data copied to the file transfer reader
+			if(iToFile && iOkToSaveToFile 
+				&& iSession->FileTransferReader() && iSession->FileTransferReader()->Activated())
+				{
+				if(AppendPointer.Length() > 0)
+					iSession->FileTransferReader()->AppendL(AppendPointer);
+				}
+			else if ( IsChunked() )
+				{
+				iPos =  iBuffer.Length();											
+				retVal = ParseL( AppendPointer );
+				}
+			else
+				{
+				iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
+				iBuffer.Append( AppendPointer );				
+				}
+			}
+		}
+	else
+		{
+		if( !iErrorCodeCheckedForSaving )
+		    {
+		    TInt messageError = MessageErrorCode( iBuffer );
+		    if ( messageError == EHttpOk || messageError == EHttpPartialContent )
+		        {
+                iOkToSaveToFile = ETrue;
+		        }
+		    else
+		        {
+		        iOkToSaveToFile = EFalse;
+   		        CUpnpHttpFileAccess* temp = iSession->FileAccess();
+   		        if( temp )
+   		            {
+    		        temp->DeleteFile();
+                    // no delete, not owned
+    		        temp = NULL;
+    		        }
+		        }
+		    // error code checked, no need to check it again.
+	        iErrorCodeCheckedForSaving = ETrue;
+		    }
+		
+		//for file upload, data copied to the file transfer reader
+		if(iToFile && iOkToSaveToFile &&
+			iSession->FileTransferReader() && iSession->FileTransferReader()->Activated())
+			{
+			if(aBuffer.Length() > 0)
+				iSession->FileTransferReader()->AppendL(aBuffer);
+			return retVal;
+			}
+			    
+		if ( IsChunked() )
+			{
+			retVal = ParseL( aBuffer );
+			}
+		else
+			{
+			iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
+			iBuffer.Append( aBuffer );
+			}
+	    }
+	return retVal;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::ParseL
+// Decodes chunked messages.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::ParseL( TDesC8& aBuffer )
+    {
+    iBuffer.ReAllocL( iBuffer.Length() + aBuffer.Length() );
+    iBuffer.Append( aBuffer );
+    return Parse( iBuffer, iPos ) < 0 ? KErrHttpUnknownParseState: KErrNone;                  
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::Parse
+// Decodes chunked-encoded buffer
+// -----------------------------------------------------------------------------
+//	
+TInt CUpnpHttpBuffer::Parse(TDes8& aBuffer, TInt& aPos)
+    {    
+    if( aPos >= aBuffer.Length() )
+        {
+        iChunkParser->Reset();
+        return KErrNone;
+        }
+    return iChunkParser->Parse( aBuffer, aPos );		
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::IsReady
+// Returns ETrue, if buffer is ready to be converted to HTTPMessage 
+// else returns EFalse.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::IsReadyL()
+	{
+LOGS("CUpnpHttpBuffer::IsReady()");
+	if ( IsHeaderReady() )
+		{
+		//Assuming here that HTTP GET -requests may not have a body.
+		//So if a HTTP GET request arrives and it has a CONTENT-TYPE or a 
+		//CONTENT-LENGHT header we may still serve the file
+		TPtrC8 method = Method();
+		if ( method.FindC( KHttpGet() ) == 0 )
+		    {
+		    return ETrue;
+		    }
+		if ( HasBody() )
+			{
+			return IsBodyReadyL();
+			}
+		else 
+			{
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::IsHeaderReady
+// Returns ETrue, if header part of HTTPMessage is ready, else returns EFalse.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::IsHeaderReady()
+	{
+LOGS("CUpnpHttpBuffer::IsHeaderReady()");
+	if ( iBuffer.Find( UpnpString::KDoubleLineFeed() ) > KErrNotFound )
+		{
+		return ETrue;
+		}
+	else
+		{
+		return EFalse;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::IsBodyReadyL
+// Returns ETrue, if body part of HTTPMessage is ready, else returns EFalse.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::IsBodyReadyL()
+	{
+LOGS("CUpnpHttpBuffer::IsBodyReadyL()");
+	TInt bodyStart = iBuffer.FindF( UpnpString::KDoubleLineFeed );
+	TInt contLength = ContentLengthL();
+	if ( IsChunked() )
+		{
+		return ChunkTransferFinished();
+		}
+	else
+		{
+		if ( iHasContentType )
+			{	
+			TPtrC8 body = iBuffer.Mid( bodyStart + 
+                UpnpString::KDoubleLineFeed().Length() );
+			return body.Find( UpnpString::KDoubleLineFeed() ) != KErrNotFound;
+			}
+		}
+
+	TPtrC8 tempPtr;
+	if ( iToFile && iOkToSaveToFile )
+		{
+		if ( iContentLengthCounter >= contLength )
+			{
+			return !(IsChunked() && !ChunkTransferFinished());
+			}
+		else
+			{
+			return EFalse;		
+			}
+		}
+	else
+		{
+		tempPtr.Set( iBuffer.Mid( bodyStart + UpnpString::KDoubleLineFeedLength ) );		
+		if (  tempPtr.Length() >= contLength )
+			{
+			return !(IsChunked() && !ChunkTransferFinished());
+			}
+		else
+			{
+			return EFalse;
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::BytesInBuffer
+// Returns the length of entire buffer.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::BytesInBuffer()
+	{
+LOGS("CUpnpHttpBuffer::BytesInBuffer()");
+	return iBuffer.Length();
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::RemoveL
+// This function deletes aLength bytes from the beginning of HTTPBuffer.
+// -----------------------------------------------------------------------------
+//
+void CUpnpHttpBuffer::RemoveL( TInt aLength )
+	{
+LOGS1("CUpnpHttpBuffer::RemoveL(%i)", aLength);
+	if ( aLength <= iBuffer.Length() )
+		{
+		iBuffer.Delete( 0, aLength );
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::ChunkTransferFinished
+// Returns ETrue, if chunk encoded message is finished.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::ChunkTransferFinished()
+	{
+LOGS("CUpnpHttpBuffer::ChunkTransferFinished()");
+	return iChunkParser->IsFinished();
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::HasBody
+// Returns ETrue, if message has body, else returns EFalse.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::HasBody()
+	{
+LOGS("CUpnpHttpBuffer::HasBody()");
+	if( IsChunked() )
+		{
+		return ETrue;
+		}
+TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );
+if (endOfHeader>0)
+	{TPtrC8 tmp = iBuffer.Mid(0, endOfHeader);
+	if ( tmp.FindC( UpnpHTTP::KContentLength() ) > -1 )
+		{
+		iHasContentType = EFalse;
+		return ETrue;
+		}
+	else if ( tmp.FindC( UpnpHTTP::KContentType() ) > -1)
+		{
+		iHasContentType = ETrue;
+		return ETrue;
+		}
+	else 
+		{
+		iHasContentType = EFalse;
+		return EFalse;
+		}
+	}
+else
+	{
+	iHasContentType = EFalse;
+	return EFalse; //no end of the header, not possible to judge if there is a body	
+	}
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::IsChunked
+// Returns ETrue, if message's header contains "Transfer-encoding: 
+// Chunked" -header.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::IsChunked()
+	{
+	LOGS("CUpnpHttpBuffer::IsChunked()");	
+	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );	
+		
+	// to check only first 2k of data or whole portion with all headers 
+	// if they are bigger	
+	TPtrC8 TranferCodingPointer;
+	if (endOfHeader <= UpnpSSDP::KMaxMessageLength)
+		TranferCodingPointer.Set( iBuffer.Left( endOfHeader + UpnpString::KLineFeedLength ) ); 
+	else 
+		TranferCodingPointer.Set( iBuffer.Left( UpnpSSDP::KMaxMessageLength ) ); 
+
+	TInt TransferEncodingIndex = 
+        TranferCodingPointer.FindC( UpnpHTTP::TransferEncoding );
+
+	if ( TransferEncodingIndex == KErrNotFound ) 
+		{
+		return EFalse;
+		}
+	else
+		{
+		TInt correct = 0;
+		TInt transferHeaderLength = 0;
+		correct = TransferEncodingIndex;
+		transferHeaderLength = UpnpHTTP::TransferEncoding().Length();
+
+		TPtrC8 tempPtr = iBuffer.Mid( correct + transferHeaderLength, 
+            iBuffer.Length() - correct - transferHeaderLength );
+	
+		TInt LineFeedAfterTransferCoding = tempPtr.FindF( UpnpString::KLineFeed );
+
+		TPtrC8 codingPtr = tempPtr.Left( LineFeedAfterTransferCoding );
+		if ( codingPtr.FindC( UpnpHTTP::Chunked ) != KErrNotFound )
+			{
+			return ETrue;
+			}
+		else
+			{
+			return EFalse;
+			}
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::Headers
+// Returns Headers of the first message in the buffer.
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CUpnpHttpBuffer::Headers()
+	{
+LOGS("CUpnpHttpBuffer::Headers()");
+	TInt EndOfHeaders = iBuffer.FindC( UpnpString::KDoubleLineFeed );
+	TPtrC8 headers = iBuffer.Left( EndOfHeaders + UpnpString::KDoubleLineFeedLength  );	
+	return headers;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::L
+// Returns the content of buffer.
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CUpnpHttpBuffer::Content()
+	{
+LOGS("CUpnpHttpBuffer::Content()");
+	TInt PosOfContLength = iBuffer.FindC( UpnpHTTP::KHdrContentLength() );
+	TInt contLen = 0;
+	
+	if ( PosOfContLength > 0 )
+		{
+		TRAPD(error, contLen = ContentLengthL());
+		if (error)
+			{
+			contLen = 0;
+			}
+		}
+	else if ( iHasContentType )
+		{
+		return TPtrC8( iBuffer );
+		}
+	else if( IsChunked() )
+		{
+		TInt StartOfMessage = iBuffer.FindC( UpnpString::KDoubleLineFeed );
+		contLen = iBuffer.Length() - StartOfMessage;	
+		}
+	/*else
+		{
+		TInt StartOfMessage = iBuffer.FindC( UpnpString::KDoubleLineFeed );
+		contLen = iBuffer.Des().Length() - StartOfMessage;
+		}*/	
+
+	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );
+	TInt length = 0;
+	// Probably not all headers were sent
+	
+	if( endOfHeader == KErrNotFound  )
+		{
+		length = iBuffer.Length();
+		}
+	else
+		{
+		length = endOfHeader + contLen + UpnpString::KDoubleLineFeedLength;	
+		}
+
+    if( length < 0 ) // in case of overflow of length value
+        {
+        length = INT_MAX;
+        }
+
+	TPtrC8 message = iBuffer.Left( length );
+	return message;
+	}	
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::ContentLengthL
+// Returns the content length of first message in the buffer.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::ContentLengthL()
+	{
+	LOGS("CUpnpHttpBuffer::ContentLengthL()");
+	
+	TInt endOfHeader = iBuffer.Find( UpnpString::KDoubleLineFeed );	
+    User::LeaveIfError(endOfHeader);
+	TPtrC8 findptr;
+	// to check only first 2k of data or whole portion with all headers 
+	// if they are bigger	
+	if (endOfHeader >= UpnpSSDP::KMaxMessageLength)
+		findptr.Set( iBuffer.Left( endOfHeader + UpnpString::KLineFeedLength ) ); 
+	else 
+		findptr.Set( iBuffer.Left( UpnpSSDP::KMaxMessageLength ) ); 						
+
+	TInt contentLengthIndex = findptr.FindC( UpnpHTTP::KHdrContentLength() );
+
+	TInt lengthOfContentLength = UpnpHTTP::KHdrContentLength().Length() +
+        UpnpString::KColon().Length();
+	
+	if ( contentLengthIndex <= 0 ) 
+		{
+	return KErrNotFound;
+		}
+
+	TPtrC8 rest;
+	rest.Set( findptr );
+	rest.Set( rest.Mid( contentLengthIndex + lengthOfContentLength ) );
+
+	TInt lineEnd = rest.Find( UpnpString::KLineFeed );
+	if ( lineEnd < 0 )
+		{
+		return KErrNotFound;
+		}
+	
+	// LWS and spanning headers
+	TInt indexLWS = 0;
+	TPtrC8 clRest = rest;
+	TInt contentLengthValueEnd = lineEnd;
+	
+	while( ETrue )
+	    {
+	    indexLWS = CUpnpHttpMessage::FindLWS( clRest );
+	    if( indexLWS == lineEnd )
+	        {	     
+	        clRest.Set( clRest.Mid( lineEnd + UpnpString::KLineFeed().Length() ) );
+	        lineEnd = clRest.Find( UpnpString::KLineFeed );
+	        contentLengthValueEnd += lineEnd + UpnpString::KLineFeed().Length();
+	        }
+	    else
+	        {
+	        break;
+	        }
+	    }			
+    
+	TPtrC8 length = rest.Left( contentLengthValueEnd );
+    
+    if( !length.Compare( KNullDesC8() ) )
+        return -1;
+    
+    // Unfold header
+    HBufC8* clValueBuf = length.AllocLC();
+    TPtr8 ptrCLValue = clValueBuf->Des();
+    
+    // Remove CRLFs
+    TInt pos;
+	while( ( pos = ptrCLValue.FindC( UpnpString::KLineFeed() ) ) != KErrNotFound)
+	    {
+		ptrCLValue.Delete(pos, UpnpString::KLineFeedLength);
+	    }
+	
+    // Remove spaces
+    while( ( pos = ptrCLValue.FindC( UpnpString::KSpace() ) ) != KErrNotFound)
+	    {
+		ptrCLValue.Delete(pos, 1);
+	    }
+	
+	// Remove tabs
+    while( ( pos = ptrCLValue.FindC( UpnpString::KTab() ) ) != KErrNotFound)
+	    {
+		ptrCLValue.Delete(pos, 1);
+	    }
+   
+	TLex8 lex( ptrCLValue );
+	TInt val = 0;
+	User::LeaveIfError(lex.Val( val ));
+	
+	CleanupStack::PopAndDestroy( clValueBuf );
+
+	iContentLength = val;
+
+	return val;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::UsesConnectionClose
+// Returns ETrue, if message's header contains "Connection: close" -header.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpHttpBuffer::UsesConnectionClose()
+	{
+LOGS("CUpnpHttpBuffer::UsesConnectionClose()");
+	if(IsHeaderReady())
+		{
+		TPtrC8 headers=Headers();
+		TInt posOfConn=headers.FindC(UpnpHTTP::KConnection());
+		TInt posOfHttp10 = headers.FindC(KHttp10); 	
+		
+		if( posOfConn != KErrNotFound )
+			{
+			TPtrC8 conn=headers.Mid(posOfConn+UpnpHTTP::KConnection().Length() +
+                UpnpString::KColon().Length());
+			
+			TInt posOfLineFeed=conn.FindC(UpnpString::KLineFeed());
+			if(posOfLineFeed != KErrNotFound)
+				{
+				conn.Set(conn.Left(posOfLineFeed));
+				
+				while((conn.Left(1)).CompareC(UpnpString::KSpace()) == 0)
+					{
+					conn.Set(conn.Mid(1)); // removing spaces in front of value
+					}
+					
+				if(conn.FindC(UpnpHTTP::KClose()) >= 0)
+					{
+					return ETrue;
+					}
+				else
+					{
+					return EFalse;
+					}
+				}
+			else
+				{
+				// If rsp = 'HTTP/1.0', we can assume that it contains 'connection:close' header, even if it doesn't!	
+		                   if( posOfHttp10 != KErrNotFound )
+		                        return ETrue;
+				return EFalse;
+				}
+			}
+		else
+			{
+		         // If rsp = 'HTTP/1.0', we can assume that it contains 'connection:close' header, even if it doesn't!	
+		         if( posOfHttp10 != KErrNotFound )
+		             return ETrue;
+			return EFalse;
+			}
+		}
+	return EFalse;
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::MessageErrorCode
+// Checks error code of received message.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpHttpBuffer::MessageErrorCode( TDesC8& aBuffer )
+    {
+    if( IsHeaderReady() )
+        {
+    	TInt posOfNextLine = aBuffer.Find(UpnpString::KLineFeed); 
+    	if( posOfNextLine != KErrNotFound )
+    		{
+    		TPtrC8 spacePtr;
+    		spacePtr.Set( aBuffer );
+    		
+    		// finding first space
+    		TInt posOfFirstSpace = spacePtr.Find(UpnpString::KSpace);
+            if ( posOfFirstSpace != KErrNotFound )
+                {
+    		    spacePtr.Set( spacePtr.Left( posOfFirstSpace ) );
+
+                }
+
+    		// back to basic handling
+    		spacePtr.Set( aBuffer );
+    		
+    		if( posOfFirstSpace < posOfNextLine && posOfFirstSpace != KErrNotFound )
+    			{
+    			// if first space is found, it has to be before linefeed
+    			// +1 comes from going over the first space, we are interested
+    			// in what comes after it.
+    			spacePtr.Set( spacePtr.Mid( posOfFirstSpace  + 1 ) );
+    			TInt posOfSecondSpace = spacePtr.Find(UpnpString::KSpace);
+    			if( posOfSecondSpace < posOfNextLine && posOfSecondSpace != KErrNotFound )
+    				{
+    				// check that length of path is longer than zero.
+    				if( posOfSecondSpace > 0 )
+    					{
+                        // now setting spacePtr so that we have the error number in spacePrt
+    					spacePtr.Set( spacePtr.Left( posOfSecondSpace ) );
+
+                        // making conversion
+          				TLex8 errorValue( spacePtr );
+                        TInt messageErrorValue( 0 );                        
+        				TInt convError = errorValue.Val( messageErrorValue );
+        				
+        				// checking that conversion was ok
+        				if( convError == KErrNone )
+        				    {
+        				    return messageErrorValue;
+        				    }
+        				else
+        				    {
+        				    return KErrAbort;
+        				    }
+        				
+    					}
+    				else
+    					{
+    					// header too short. Invalid message
+    					return KErrAbort;
+    					}
+    				}
+    			else
+    				{
+    				// no second space found. Invalid message.
+    				return KErrAbort;
+    				}
+    			}
+    		else
+    			{
+    			// no space found before linefeed. Invalid message
+    			return KErrAbort;
+    			}
+     		}
+		else
+			{
+			// no linefeed found in headers. Invalid message
+			return KErrAbort;
+			}        
+        }
+    else
+        {
+        return KErrAbort;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::Method
+// returns the method of message
+// -----------------------------------------------------------------------------
+//
+TPtrC8 CUpnpHttpBuffer::Method()
+    {
+    if( IsHeaderReady() )
+        {
+        TPtrC8 ret;
+        ret.Set( Headers() );
+        TInt posOfSpace = ret.Locate(' ');
+        if( posOfSpace != KErrNotFound )
+            {
+            ret.Set( ret.Left( posOfSpace ) );
+            return ret;
+            }
+        else
+            {
+            return KNullDesC8();
+            }
+        
+        }
+    else
+        {
+        return KNullDesC8();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::Target
+// 
+// -----------------------------------------------------------------------------
+//    
+TPtrC8 CUpnpHttpBuffer::Target()
+    {
+    if( IsHeaderReady() )
+        {
+        TPtrC8 ret;
+        ret.Set( Headers() );
+        TInt posOfSpace = ret.Locate(' ');
+        if( posOfSpace != KErrNotFound )
+            {
+            ret.Set( ret.Mid( posOfSpace +1 ) );
+            posOfSpace = ret.Locate(' ');
+            if( posOfSpace != KErrNotFound )
+                {
+                ret.Set( ret.Left( posOfSpace ) );
+                return ret;
+                }
+            else
+                {
+                return KNullDesC8();
+                }
+            }
+        else
+            {
+            return KNullDesC8();
+            }
+        
+        }
+    else
+        {
+        return KNullDesC8();
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::IsToFile
+// Returns True if message content is going to be saved in file.
+// -----------------------------------------------------------------------------
+//    
+TBool CUpnpHttpBuffer::IsToFile()
+	{
+	return iToFile;		
+	}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpBuffer::SetToFile
+// Sets if body of message contained in buffer should be saved in file.
+// -----------------------------------------------------------------------------
+//        
+void CUpnpHttpBuffer::SetToFile( TBool aToFile )
+	{
+	iToFile = aToFile;			
+	}
+
+
+// End Of File