upnp/upnpstack/upnputils/src/upnphttpmessage.cpp
changeset 0 f5a58ecadc66
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/upnputils/src/upnphttpmessage.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,2279 @@
+/** @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:  HTTP header
+*
+*/
+
+
+// INCLUDES
+#include <e32math.h>
+#include <f32file.h>
+#include <e32std.h>
+
+#include <e32property.h>
+
+#include "upnplist.h"
+
+#include "upnphttpmessage.h"
+#include "upnpcommonupnplits.h"
+#include "upnpcons.h"
+#include "upnpstring.h"
+#include "upnpcustomlog.h"
+#include "upnpmessageobserver.h"
+
+const TInt KHeadersMaxSixe = 8192;
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage* CUpnpHttpMessage::NewL()
+    {
+    CUpnpHttpMessage* self = new (ELeave) CUpnpHttpMessage();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCHttpMessage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage* CUpnpHttpMessage::NewL(const TInetAddr& aAddr)
+    {
+    return NewL(aAddr, NewSessionIdL());
+    }
+
+// -----------------------------------------------------------------------------
+// CCHttpMessage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage* CUpnpHttpMessage::NewL(TInetAddr aAddr, TInt aSessionId)
+    {
+    CUpnpHttpMessage* self = new (ELeave) CUpnpHttpMessage();
+    CleanupStack::PushL(self);
+    
+    
+    self->ConstructL(aAddr, aSessionId);
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CCHttpMessage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage* CUpnpHttpMessage::NewL(TDesC8& aMessageBuffer, TInetAddr aSender)
+    {
+    
+    return NewL(aMessageBuffer, aSender, NewSessionIdL());
+    }
+
+// -----------------------------------------------------------------------------
+// CCHttpMessage::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage* CUpnpHttpMessage::NewL(TDesC8& aMessageBuffer, const TInetAddr& aSender, TInt aSessionId)
+    {
+    CUpnpHttpMessage* self = NewL(aSender, aSessionId);
+    CleanupStack::PushL(self);
+    self->ParseL(aMessageBuffer);
+    CleanupStack::Pop();
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::~CUpnpHttpMessage
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage::~CUpnpHttpMessage()
+    {
+    if (iHeaderList)
+        {
+        iHeaderList->DeleteObjects();
+        delete iHeaderList;
+        }
+
+    if( iTimer )
+        {
+        iTimer->Cancel();
+        delete iTimer;
+        }
+
+    if ( iOutUri )
+        {
+        delete iOutUri;
+        }
+
+    delete iDestinationPath;
+
+
+    delete iSenderPath;
+
+
+    delete iTextBody;
+
+
+    delete iOutFilename;
+
+
+    delete iInFilename;
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::CUpnpHttpMessage
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpMessage::CUpnpHttpMessage()
+    {
+    iSessionPriority = EPriorityNormal;
+    
+    iOverwriteExisting = EFalse;
+    
+    // Parameters connected with downloading range of requested content.
+    // This mechanism if disabled by default an the whole file is requested.
+    iOffset = 0;
+    iLength = 0; 
+    iSaveAtOffset = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::ConstructL()
+    {
+    iHeaderList = new (ELeave) CUpnpHttpHeaderList;
+
+    
+    iTextBody = HBufC8::NewL(0);
+
+    iDestinationPath = HBufC8::NewL(0);
+    iSenderPath = HBufC8::NewL(0);
+
+    iInFilename = HBufC8::NewL(0);
+    iOutFilename = HBufC8::NewL(0);
+    //by default EFalse, meaning ignored
+    iClientRequest = EFalse;
+    //TCP-session's 0 means the value will be ignored unless changed later on!
+    iTcpTimeout = 0;
+    iInternalError = KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::ConstructL( TInetAddr& aSender, TInt aSessionId)
+    {
+    iDestinationPath = HBufC8::NewL(0);
+
+    iSenderPath = HBufC8::NewL(0);
+
+    iInFilename = HBufC8::NewL(0);
+    
+    iOutFilename = HBufC8::NewL(0);
+    
+    iHeaderList = new (ELeave) CUpnpHttpHeaderList;
+
+    iTextBody = HBufC8::NewL(0);
+    
+    iRemoteHost = aSender;
+    iSessionId = aSessionId;
+    //by default EFalse, meaning ignored
+    iClientRequest = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ParseL
+// Parses one row of headers.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::ParseL(TDesC8& aBuffer)
+    {
+
+    // position where the header ends
+    TInt endOfHeader=0;
+    
+    // position of first \r\n
+    TInt posOfNextLine = 0;
+    
+    // position of first space
+    TInt posOfFirstSpace = 0;
+
+    // position of second space
+    TInt posOfSecondSpace = 0;
+
+    // Boolean value that is used to check if message is
+    // request or response. If message is response, protocol
+    // version information is at the beginning of first row
+    // (HTTP/1.1 200 OK)
+    // In request, protocol version is at the end.
+    // (GET / HTTP/1.1)
+    TBool isResponse = EFalse;
+
+// Handling of header part
+    
+    // trying to find Head/body separator
+    endOfHeader = aBuffer.Find(UpnpString::KDoubleLineFeed);
+    if( endOfHeader == KErrNotFound)
+        {
+        User::Leave(KErrAbort);
+        }
+
+    posOfNextLine = aBuffer.Find(UpnpString::KLineFeed); 
+    if( posOfNextLine != KErrNotFound )
+        {
+        TPtrC8 spacePtr;
+        spacePtr.Set( aBuffer );
+        
+        // finding first space
+        posOfFirstSpace = spacePtr.Find(UpnpString::KSpace);
+        if ( posOfFirstSpace != KErrNotFound )
+            {
+            spacePtr.Set( spacePtr.Left( posOfFirstSpace ) );
+
+            // if first word of message is HTTP/1.1 or HTTP/1.0
+            // message is response
+            if( ( spacePtr.Find( KHttp11WithoutSpace() ) == 0 && 
+                  posOfFirstSpace == KHttp11WithoutSpace().Length() ) 
+                ||
+                ( spacePtr.Find( KHttp10() ) == 0 && 
+                  posOfFirstSpace == KHttp10().Length() ) )
+                {
+                isResponse = ETrue;
+                }
+            else
+                {
+                isResponse = EFalse;            
+                }
+            }
+        else
+            {
+            isResponse = EFalse;            
+            }
+
+        // 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 ) );
+            posOfSecondSpace = spacePtr.Find(UpnpString::KSpace);
+            if( posOfSecondSpace < posOfNextLine && posOfSecondSpace != KErrNotFound )
+                {
+                // check that length of path is longer than zero.
+                if( posOfSecondSpace > 0 )
+                    {
+                    // Now check that Protocol version is HTTP/1.0 
+                    // or HTTP/1.1. 
+                    
+                    // If message is response, version is defined in first 
+                    // parameter of the message. This has been checked before,
+                    // so if response, no check needed.
+                    spacePtr.Set( spacePtr.Mid( posOfSecondSpace+1 ) );
+                    posOfNextLine = spacePtr.FindC( UpnpString::KLineFeed() );
+                    spacePtr.Set( spacePtr.Left( posOfNextLine ) );
+                    
+                    if( !isResponse )
+                        {
+                        //Check protocol's version                        
+                        if (spacePtr.Match( KHttpVersionPattern() ) == 0 )
+                            {    
+                            //get only version numbers    
+                            TPtrC8 version = spacePtr.Mid(5);
+                            TLex8 lex(version);
+                            TUint major;                            
+                            if(lex.Val(major)!= KErrNone || lex.Peek()!='.')
+                                {
+                                {
+                                // (protocol NOT HTTP/1.0 or HTTP/1.1. Invalid message)
+                                User::Leave(KErrAbort);        
+                                }
+                                }
+                            lex.Inc();                                                        
+                            TUint minor;
+                            if (lex.Val(minor) !=KErrNone)
+                                {
+                                // (protocol NOT HTTP/1.x. Invalid message)
+                                User::Leave(KErrAbort);    
+                                }                                
+                            lex.SkipSpace();
+                            if (!lex.Eos())
+                                {
+                                // (protocol NOT HTTP/1.x. Invalid message)
+                                User::Leave(KErrAbort);    
+                                }
+                            //only 1.1 and 1.0 supported
+                            if(major != 1 || (minor>1))
+                                {
+                                // (HTTP Version not supported)
+                                User::Leave(-EHttpVersionNotSupported);    
+                                }
+                            
+                            }
+                        else
+                            {
+                            // (protocol NOT HTTP/1.0 or HTTP/1.1. Invalid message)
+                            User::Leave(KErrAbort);                                
+                            }
+                        }
+        
+                    }
+                else
+                    {
+                    // header too short. Invalid message
+                    User::Leave(KErrAbort);
+                    }
+                }
+            else
+                {
+                // no second space found. Invalid message.
+                User::Leave(KErrAbort);
+                }
+            }
+        else
+            {
+            // no space found before linefeed. Invalid message
+            User::Leave(KErrAbort);
+            }
+        }
+    else
+        {
+        // no linefeed found. Invalid message
+        User::Leave(KErrAbort);
+        }
+
+    if ( endOfHeader != KErrNotFound )
+        {
+        TPtrC8 tempHeaderPointer;
+        TPtrC8 finderIndexPointer;
+        tempHeaderPointer.Set(aBuffer.Left(endOfHeader));
+        
+        
+        // if header lenght is longer that 8k,cut headers after one that cross the line
+        if (endOfHeader > KHeadersMaxSixe)
+            {
+            TInt afterLimit = tempHeaderPointer.Mid(KHeadersMaxSixe).Find(UpnpString::KLineFeed);
+            if (afterLimit != KErrNotFound)
+                {
+                tempHeaderPointer.Set(tempHeaderPointer.Left(KHeadersMaxSixe + afterLimit));
+                }
+            }    
+        TInt index=0, indexLWS=0, indexCRLF=0;
+        TBool FirstLine=ETrue;
+        
+        while (index != KErrNotFound)
+            {
+            // locate end-of-line, parse each line separately
+        
+            //RFC822 3.2 field-name  =  1*<any CHAR, excluding CTLs, SPACE, and ":">
+            index = tempHeaderPointer.Find(UpnpString::KLineFeed);
+            indexLWS = FindLWS(tempHeaderPointer);
+            finderIndexPointer.Set(tempHeaderPointer);
+            indexCRLF = index;
+            //the length of the string for the end-line marker CRLF
+            TInt headerCRLF = 2;
+            while (indexCRLF == indexLWS && indexCRLF != KErrNotFound)
+            {
+                //3 below =the length of the LWS string
+                finderIndexPointer.Set(finderIndexPointer.Right(finderIndexPointer.Length()-(indexCRLF+3)));
+                indexCRLF = finderIndexPointer.Find(UpnpString::KLineFeed);
+                if (indexCRLF == KErrNotFound)
+                {
+                    //3 below =the length of the LWS string
+                    index += finderIndexPointer.Length() + 3; 
+                    indexLWS = finderIndexPointer.Length();
+                    headerCRLF = 0;
+                }
+                else
+                {
+                    index += indexCRLF+3;    
+                    indexLWS = FindLWS(finderIndexPointer);
+                }
+                
+                
+            }
+            if(index != KErrNotFound)
+                {
+                TPtrC8 oneHeaderRow;
+                oneHeaderRow.Set(tempHeaderPointer.Left(index));
+
+                // To check if is the first line of message (e.g. GET / HTTP 1.1 etc.)
+                if (FirstLine)
+                    {
+                    ParseHeaderRowL( (TDesC8&) oneHeaderRow, ETrue);
+                    FirstLine=EFalse;
+                    }
+                else 
+                    {
+                    ParseHeaderRowL(oneHeaderRow, EFalse);
+                    }
+
+                // To delete one header row + "\r\n" = length+2 to prepare for next row.
+                if (headerCRLF)
+                    {
+                    tempHeaderPointer.Set(tempHeaderPointer.Right(tempHeaderPointer.Length()-(index+headerCRLF)));    
+                    
+                    }
+                    else
+                    {
+                        index = KErrNotFound;
+                    }
+                }
+            }
+            
+        if (FirstLine)
+            {
+            ParseHeaderRowL(tempHeaderPointer, ETrue);
+            }
+        else
+            {
+            ParseHeaderRowL(tempHeaderPointer, EFalse);
+            }
+        }
+    // check if all HTTP/1 requests have HOST header
+    if(!isResponse && RequestHTTPVersion() == KHttp11WithoutSpace() )
+        {
+        TBool exists;
+        IsHeader(UpnpSSDP::KHdrHost(), exists);
+        if (!exists) 
+            User::Leave(KErrAbort);    
+        }
+    
+    // Handle body:
+    
+    if(iTextBody)
+        {
+        delete iTextBody;
+        iTextBody=NULL;
+        }
+    
+    iTextBody=HBufC8::NewL(aBuffer.Length() - endOfHeader);
+    iTextBody->Des().Zero();
+    
+    // Append rest of message to iTextBody. Leave out string "\r\n\r\n".
+    iTextBody->Des().Append(aBuffer.Right(aBuffer.Length() - (endOfHeader + 4)));
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ParseHeaderRowL
+// Parses one row of headers.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::FindLWS(const TDesC8& aText)
+{
+    TInt indexSP = aText.Find(UpnpString::KCRLFSP);
+    TInt indexHT = aText.Find(UpnpString::KCRLFHT);
+    
+    
+    if (indexSP == KErrNotFound) 
+        return indexHT;
+    else if    (indexHT == KErrNotFound) 
+        return indexSP;
+    else if(indexSP < indexHT) 
+        return indexSP;
+    else
+        return indexHT;
+    
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ParseHeaderRowL
+// Parses one row of headers.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::ParseHeaderRowL(const TDesC8& aBuffer, TBool aFirstLine)
+    {
+    TInt FirstColonPosition=0;
+
+    // locate first colon. This separates header's name and value.
+
+    FirstColonPosition = aBuffer.Find(UpnpString::KColon());
+    if(aFirstLine)
+        {
+        AddPairL(aBuffer, KSpace8());
+        }
+    else
+        {
+        if (FirstColonPosition == KErrNotFound )
+            {
+                User::Leave(KErrAbort);
+            }
+        else 
+            {    
+            HBufC8* TrimBuffer;
+            TrimBuffer=HBufC8::NewLC(aBuffer.Length() - (FirstColonPosition + 1));
+            TrimBuffer->Des().Zero();
+            
+            TrimBuffer->Des().Append(aBuffer.Right(aBuffer.Length() - (FirstColonPosition + 1)));
+            TrimBuffer->Des().Trim();
+            UnFoldHeader(TrimBuffer);
+
+            TPtrC8 ptr = aBuffer.Left(FirstColonPosition);
+            
+            // if there are spaces, ignore them.
+            TBool spaceFound = ETrue;
+
+            while( spaceFound )
+                {
+                if(ptr.Find(KSpace()) == 0)
+                    {
+                    ptr.Set(ptr.Mid(1));
+                    }
+                else
+                    {
+                    spaceFound = EFalse;
+                    }
+                }
+
+            AddPairL(ptr, *TrimBuffer);
+            
+            CleanupStack::PopAndDestroy();    
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::TimerEventL
+// Timer expired. For SSDP messages
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::TimerEventL( CUpnpNotifyTimer* /*aTimer*/ )
+    {
+    // Cancel timer if exists.
+    if( iTimer )
+        {
+        if( iTimer->IsActive() )
+            {
+            iTimer->Cancel();
+            }
+        }
+    iMessageObserver->MessageExpiredL( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetMessageTimeoutL
+// Set message timer timeout for SSDP messages.
+// -----------------------------------------------------------------------------
+//   
+EXPORT_C TInt CUpnpHttpMessage::SetMessageTimeoutL( MUpnpMessageObserver* aObserver, const TInt aTimeoutValue )
+    {
+    // check that request is valid.
+    if( !aObserver )
+        {
+        return KErrNotFound;
+        }
+        
+    iMessageObserver = aObserver;
+
+    if( iTimer )
+        {
+        if( iTimer->IsActive() )
+            {
+            iTimer->Cancel();
+            }
+        }
+    else
+        {
+        // setup timer;
+        iTimer = CUpnpNotifyTimer::NewL( this );
+        }
+    iTimer->After( aTimeoutValue );
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::CancelMessageTimeout
+// Set message timer timeout.
+// -----------------------------------------------------------------------------
+//   
+EXPORT_C void CUpnpHttpMessage::CancelMessageTimeout()
+    {
+    if ( iTimer )
+        {
+        iTimer->Cancel();
+        // Deleting timer will also null the observer in the timer.
+        delete iTimer;
+        iTimer = NULL;
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::AddPairL
+// Adds a Headerrow in this message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::AddPairL(const TDesC8& aName, const TDesC8& aValue)
+    {
+    // first checking if given header already exists in the message
+
+    CUpnpHttpHeader* chk = iHeaderList->First();
+    while( chk != NULL )
+        {
+        if( chk->Name().CompareC( aName ) == 0 )
+            {
+            chk->SetValueL( aValue );
+            // no delete to chk, it is owned by iHeaderList.
+            return;
+            }
+        chk = iHeaderList->Next( chk );
+        }
+    
+    // header name not found, adding it.
+        
+    CUpnpHttpHeader* hdr = CUpnpHttpHeader::NewL(aName, aValue);
+    CleanupStack::PushL(hdr);
+    iHeaderList->AddL(hdr);
+    CleanupStack::Pop(hdr);
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::AddPairL
+// Adds a Headerrow in this message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::RemovePairL(const TDesC8& aName)
+    {
+    // first checking if given header already exists in the message
+
+    CUpnpHttpHeader* chk = iHeaderList->First();
+    while( chk != NULL )
+        {
+        if( chk->Name().CompareC( aName ) == 0 )
+            {
+            // no delete to chk, it is owned by iHeaderList.
+            iHeaderList->Remove(chk);
+            delete chk;
+            return;
+            }
+        chk = iHeaderList->Next( chk );
+        }
+    
+    }
+
+    
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetBodyL
+// Sets the body of message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetBodyL(const TDesC8& aBody)
+    {
+    delete iTextBody;
+    iTextBody = NULL;
+    iTextBody = aBody.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Body
+// Getter for the body of message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TDesC8& CUpnpHttpMessage::Body()
+    {
+    return *iTextBody;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::HeadersToStringL
+// Returns message as HBufC8.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CUpnpHttpMessage::HeadersToStringL()
+    {
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+
+    HBufC8* headerBuf = NULL;
+    headerBuf = HBufC8::NewL(0);
+    headerBuf->Des().SetLength(0);
+    TBool firstLine = ETrue;
+    
+    while (hdr != NULL)
+        {
+        CleanupStack::PushL( headerBuf );
+        
+        HBufC8* tempHeader = NULL;
+    
+        tempHeader=HBufC8::NewLC( hdr->Name().Length() +
+                                    hdr->Value().Length() +
+                                    4 ); // 4 for colon, space and linefeed
+        tempHeader->Des().Zero();        
+        tempHeader->Des().Append(hdr->Name());
+
+
+        //first line is Request line (Request-Line   = Method SP Request-URI SP HTTP-Version CRLF)
+        //block is needed for URI manipualtion, first line is ALSO added
+        //-- can not be folded, DLNA says directly "Each HTTP header line"
+
+
+        TInt posOfSpace = tempHeader->Des().Find(UpnpString::KSpace());
+            TPtrC8 ptr;
+            if (posOfSpace != KErrNotFound)
+                {
+                ptr.Set( 
+                tempHeader->Des().Right( tempHeader->Des().Length() - 
+                                            (posOfSpace + 1)  )
+                    );
+                }
+            
+            TInt posOfSecondSpace = ptr.Find( UpnpString::KSpace() );
+            TPtrC8 ptr2;
+            
+            if (posOfSecondSpace != KErrNotFound)            
+                ptr2.Set( ptr.Left( posOfSecondSpace ) );
+
+            HBufC8* url = ptr2.AllocLC();
+
+            
+        tempHeader->Des().Replace( posOfSpace+1,
+                                          url->Des().Length(),
+                                          *url );
+
+            CleanupStack::PopAndDestroy( url );
+            url = NULL;
+            
+/*------if Content-Length is not at the beginning (can be some same string in value) so copy it, otherwise will be added and calcualted at the end----*/
+
+        if(hdr->Name().FindC(UpnpHTTP::KHdrContentLength()) != 0)
+
+            {
+            if (hdr->Value().Length() > 0 && !firstLine)
+                {
+                tempHeader->Des().Append(UpnpString::KColon());
+                tempHeader->Des().Append(UpnpString::KSpace());
+                tempHeader->Des().Append(hdr->Value());
+                }
+            else 
+                {
+                if (firstLine)
+                    {
+                    firstLine = EFalse;
+                    }
+                else
+                    {
+                    tempHeader->Des().Append(UpnpString::KColon());
+                    }
+                }
+            //folding, we pass with lineFeed
+            FoldHeaderL(tempHeader);                
+            tempHeader->Des().Append(UpnpString::KLineFeed());
+            }
+
+        HBufC8* tempBuf;
+        tempBuf = HBufC8::NewLC( headerBuf->Des().Length() +
+                                 tempHeader->Des().Length() );
+        tempBuf->Des().Zero();
+        tempBuf->Des().Append( *headerBuf );
+        
+
+        if(hdr->Name().FindC(UpnpHTTP::KHdrContentLength()) != 0)
+            {
+            tempBuf->Des().Append(*tempHeader);
+            }
+        
+        CleanupStack::Pop( tempBuf );
+        CleanupStack::PopAndDestroy( tempHeader ); 
+        CleanupStack::PopAndDestroy( headerBuf ); 
+        
+        tempHeader = NULL;
+        headerBuf = NULL;
+
+        headerBuf = tempBuf;
+        tempBuf = NULL;
+        
+        hdr = iHeaderList->Next(hdr);    
+        }
+    
+    AppendContentLengthToHeadersL(headerBuf);
+    return headerBuf;
+}
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::AppendContentLengthToHeadersL
+// Appends ContentLength when headers are dumped to string (using public method HeadersToStringL).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::AppendContentLengthToHeadersL(HBufC8*& aHeaders){
+
+/*------open file which keep message--------*/
+    TInt bodyLength( 0 );
+    CleanupStack::PushL( aHeaders );    
+
+
+    if(iOutFilename->Length() > 0)
+        {
+        RFs fs;
+        CleanupClosePushL(fs);
+        RFile file;
+        CleanupClosePushL(file);
+
+        User::LeaveIfError( fs.Connect() );
+        
+        HBufC16* outFilename16 = UpnpString::ToUnicodeL( *iOutFilename);
+        CleanupStack::PushL(outFilename16);
+        
+        User::LeaveIfError( file.Open(fs,*outFilename16,  EFileRead|EFileShareAny ) );
+
+        TInt Filesize( 0 );
+        User::LeaveIfError( file.Size( Filesize ) );
+        
+        CleanupStack::PopAndDestroy( outFilename16 );
+        
+        CleanupStack::PopAndDestroy();  //file.Close();
+        outFilename16 = NULL;
+        
+        CleanupStack::PopAndDestroy(); //fs.Close();
+                
+        bodyLength = Filesize;
+        }
+    else
+        {
+        iTextBody->Des().Trim();
+        bodyLength=iTextBody->Des().Length();
+        }
+
+    TBuf8<20> tempBuf;
+    tempBuf.Num( bodyLength );
+
+    HBufC8* tempBuf2;
+    tempBuf2=HBufC8::NewL( aHeaders->Des().Length() +
+                            tempBuf.Length() +
+                            UpnpHTTP::KHdrContentLength().Length() +
+                            2 ); // +2 from colon and space
+    tempBuf2->Des().Append( *aHeaders);
+    
+    CleanupStack::Pop(aHeaders);
+    delete aHeaders;
+    aHeaders=NULL;
+
+    tempBuf2->Des().Append(UpnpHTTP::KHdrContentLength());
+    tempBuf2->Des().Append(UpnpString::KColon());
+    tempBuf2->Des().Append(UpnpString::KSpace());
+    tempBuf2->Des().Append(tempBuf);
+
+    aHeaders=tempBuf2;
+    tempBuf2=NULL;
+
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::FoldHeaderL
+// Folds long header fields (without last CRLF)  - "MUST limit 998".
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::FoldHeaderL(HBufC8*& aHeader){
+HBufC8* result = NULL;
+TInt length = aHeader->Length();
+
+    if(length > KLineLengthLimit)
+        {
+        //Body can be only folded, so 1st we check if name is not too long
+        if (aHeader->FindC(UpnpString::KColon()) > KLineLengthLimit-1)
+            {
+            User::Leave(KErrOverflow);
+            #ifdef _DEBUG
+            LOGS("[CUpnpHttpMessage::FoldHeaderL] name of header > KLineLengthLimit");
+            #endif //_DEBUG
+            }
+        else
+            {
+            //RFC 2822 3.2.3 (check if any FWS already exist and remove them) comment in DLNA doesnt exist so there are not processing)
+            UnFoldHeader(aHeader);
+            aHeader->Des().TrimAll();
+
+            //now proper folding
+            //new length is estimated,
+            //its faster way to estiamte max number (worst possible case) than calculate strict number
+            //how estimation is calculate: HighLevel break (but not SP) in worst case will be in every half -1 in every maxLength string
+            
+            
+            result = HBufC8::NewL(length + length/KLineLengthLimit*2*3 + 2);//CRLFSP + LineFeed
+            CleanupStack::PushL(result);
+            TInt x1 = 0, x2 = 0;
+            TBool last = EFalse;
+            while(ETrue)
+                {
+                length = aHeader->Length();
+                x2 = x1 + KLineLengthLimit;
+                if (x2 >= length) 
+                    {
+                    x2 = length-1;
+                    last = ETrue;
+                    }
+                else
+                    {
+                    TBool foundBreak = EFalse;
+                    for (TInt j=0; j<KHigherLevelSintaticBreaks().Length(); j++)
+                        {
+                        x2 = x1 + KLineLengthLimit;
+                        while (x2 > 0 && !foundBreak)
+                            {
+                            if (aHeader->Des()[x2] == KHigherLevelSintaticBreaks()[j])
+                                {
+                                foundBreak = ETrue;
+                                }
+                            else
+                                {
+                                x2--;
+                                }
+                                
+                            }
+                        if (foundBreak) break;
+                        }
+                    if (!foundBreak)
+                        {
+                        User::Leave(KErrOverflow);
+                        #ifdef _DEBUG
+                        LOGS("[CUpnpHttpMessage::FoldHeaderL] value of header > KLineLengthLimit");
+                        #endif //_DEBUG
+                        }
+                    }
+                //we will append in different way whether SP or other breaks
+                if (aHeader->Des()[x2] == UpnpString::KSpace()[0] || 
+                    aHeader->Des()[x2] == UpnpString::KTab()[0])
+                    {
+                    result->Des().Append(aHeader->Des().Mid(x1, x2));
+                    if (!last)
+                        {
+                        result->Des().Append(UpnpString::KLineFeed());
+                        }
+                    }
+                else
+                    {
+                    result->Des().Append(aHeader->Des().Mid(x1, x2+1));
+                    if (!last)
+                        {
+                        result->Des().Append(UpnpString::KLineFeed());
+                        result->Des().Append(UpnpString::KSpace());//additional space, HTTP req, also break reversibility (folding and unfolding will give new string)
+                        }
+                    }
+                aHeader->Des().Delete(x1, x2-x1);// from, length
+                if (last)
+                    {
+                    break;
+                    }
+                
+                }
+            CleanupStack::Pop(result);
+            CleanupStack::PopAndDestroy(aHeader);
+            aHeader = result;
+            CleanupStack::PushL(aHeader);
+            }
+        }
+    
+ 
+}
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ToStringL
+// Unfolds header by simply removing any CRLF that is immediately followed by WSP.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::UnFoldHeader(HBufC8*& aHeader){
+    TPtr8 ptr = aHeader->Des();
+    TInt pos = ptr.FindC(UpnpString::KLineFeed());
+    while(pos != KErrNotFound)
+    {
+        ptr.Delete(pos, 2);
+        pos = ptr.FindC(UpnpString::KLineFeed());
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ToStringL
+// Returns message as HBufC8.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CUpnpHttpMessage::ToStringL()
+    {
+    HBufC8* buffer;
+    buffer=HeadersToStringL();
+    CleanupStack::PushL(buffer);
+
+    HBufC8* returnBuf;
+    //4 added to the length of the buffer becasue of the additional 2 line feeds
+    returnBuf=HBufC8::NewL(buffer->Des().Length()+iTextBody->Des().Length()+4);
+    
+    returnBuf->Des().Append(*buffer);
+    CleanupStack::PopAndDestroy(buffer);
+    buffer=NULL;
+    //2 line feeds appended
+    returnBuf->Des().Append(UpnpString::KLineFeed);
+    returnBuf->Des().Append(UpnpString::KLineFeed);
+    
+    returnBuf->Des().Append(*iTextBody);
+    
+    return returnBuf;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetMessageDateL
+// Sets the date of message.
+// -----------------------------------------------------------------------------
+//
+
+EXPORT_C void CUpnpHttpMessage::SetMessageDateL(const TTime& aTime)
+{   
+    HBufC8* timebuf = NULL;
+    timebuf = UpnpString::GetDateLC(aTime);
+    
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+    TBool HeaderFound=EFalse;
+    
+    while (hdr != NULL)
+        {
+        if (hdr->Name() == UpnpHTTP::KHdrDate() )
+            {
+            HeaderFound = ETrue;
+            hdr->SetValueL(*timebuf);
+            }
+        hdr = iHeaderList->Next(hdr);    
+        }
+    
+    if(!HeaderFound)
+        {
+        AddPairL(UpnpHTTP::KHdrDate(),*timebuf);
+        }
+    CleanupStack::PopAndDestroy(timebuf);
+}
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Sender
+// Returns the IP address of the sender of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInetAddr& CUpnpHttpMessage::Sender()
+    {
+    return iRemoteHost;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Receiver
+// Returns the IP address of the receiver of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInetAddr& CUpnpHttpMessage::Receiver()
+    {
+    return iRemoteHost;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetDestinationPathL
+// Sets the DestinationPath of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetDestinationPathL(const TDesC8& aDestinationPath)
+    {
+    if(iDestinationPath)
+        {
+        delete iDestinationPath;
+        iDestinationPath = NULL;
+        }
+        
+    iDestinationPath = aDestinationPath.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::DestinationPath
+// Returns the DestinationPath of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CUpnpHttpMessage::DestinationPath()
+    {
+    if(iDestinationPath->Length()>0)
+        {
+        return iDestinationPath->Des();
+        }
+    else
+        {
+        return (TDesC8&) KNullDesC8();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetSenderPathL
+// Sets the SourcePath of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetSenderPathL(const TDesC8& aSenderPath)
+    {
+    if(iSenderPath)
+        {
+        delete iSenderPath;
+        iSenderPath = NULL;
+        }
+        
+    iSenderPath = aSenderPath.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SenderPath
+// Returns the SenderPath of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CUpnpHttpMessage::SenderPath()
+    {
+    if(iSenderPath->Length()>0)
+        {
+        return iSenderPath->Des();
+        }
+    else
+        {
+        return (TDesC8&) KNullDesC8();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SenderPathFromHeader
+// Returns the SenderPath from Headers.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TPtrC8 CUpnpHttpMessage::SenderPathFromHeader()
+    {
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+
+    if (hdr != NULL)
+        {
+        TInt FirstSpacePosition=hdr->Name().Find(KSpace);
+            
+        if (FirstSpacePosition != KErrNotFound)
+            {
+            TPtrC8 tempPtr;
+            tempPtr.Set(hdr->Name().Right(hdr->Name().Length() - (FirstSpacePosition + 1)));
+            TInt SecondSpacePosition=tempPtr.Find(UpnpString::KSpace());
+            if (SecondSpacePosition != KErrNotFound)
+                {
+                TPtrC8 tempPtr2;
+                tempPtr2.Set(tempPtr.Left(SecondSpacePosition));
+                return tempPtr2;
+                }
+            else
+                return TPtrC8((unsigned char*)"", 0);
+    
+            }
+        else
+            return TPtrC8((unsigned char*)"", 0);
+        
+        }
+
+    return TPtrC8((unsigned char*)"", 0);
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetPendingRequest
+// Sets the private member iPendingRequest.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetPendingRequest(TAny* aPointer)
+    {
+    iPendingRequest=aPointer;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::PendingRequest
+// Returns iPendingRequest pointer.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TAny* CUpnpHttpMessage::PendingRequest()
+    {
+    return iPendingRequest;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetInFilenameL
+// Sets the filename where to save incoming content.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetInFilenameL(const TDesC8& aFilename, TBool aOverwriteExisting)
+    {
+    if ( iInFilename )
+        {
+        delete iInFilename;
+        iInFilename = NULL;
+        }
+    
+    iInFilename=HBufC8::NewL(aFilename.Length());
+    iInFilename->Des().Zero();
+    iInFilename->Des().Append(aFilename);    
+
+    iOverwriteExisting  = aOverwriteExisting;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::InFilename
+// Returns the name of file where to save incoming content.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CUpnpHttpMessage::InFilename()
+    {
+    if(iInFilename->Length()>0)
+        {
+        return iInFilename->Des();
+        }
+    else
+        {
+        return (TDesC8&) KNullDesC8();
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::OverwriteExisting
+// Returns if the existing file should be overwritten with the requested content.
+// If not then the new file with name: aFilename_serialNumber will be created.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::OverwriteExisting()
+    {
+    return iOverwriteExisting;        
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetRangeL
+// Sets the range of remote filename which will be requested.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetRangeL(TInt aOffset, TInt aLength, TBool aSaveAtOffset)
+    {
+    iOffset = aOffset;
+    iLength = aLength;
+    iSaveAtOffset = aSaveAtOffset;    
+
+    
+    TPtrC8 method = Method();
+    // Check method, because sending POST with range is not supported.
+    if( method.Find( KHttpGet ) == 0 || method.Find( KHttpHead ) == 0)
+        {
+        // If one of those values are different from default then it means that 
+        // the Range header should be added.
+        if( iOffset != 0 || iLength != 0 ) 
+            {
+            TBuf8<KMaxIntegerLength> num;
+            HBufC8* rangeValue = HBufC8::NewLC(    UpnpHTTP::KBytes().Length() +
+                                                UpnpString::KEqual().Length() +
+                                                KMaxIntegerLength + 
+                                                   UpnpString::KMinus().Length() +
+                                                   KMaxIntegerLength );
+            rangeValue->Des().Zero();
+            
+            rangeValue->Des().Append( UpnpHTTP::KBytes() );
+            rangeValue->Des().Append( UpnpString::KEqual() );
+            
+            num.Num( iOffset );
+            rangeValue->Des().Append( num );
+            rangeValue->Des().Append( UpnpString::KMinus() );
+            
+            // If length == 0 and offset is specified then it should looks: offset-
+            if( iLength )
+                {
+                // In the Range header the second value specyfies last byte position
+                // so there must be done simple transformation last-byte-pos = offset+lenght-1.
+                // There is 1 subtracted because we inlucde the byte indicated by offset
+                TInt lastBytePos = iOffset + iLength - 1; 
+                num.Num( lastBytePos );
+                rangeValue->Des().Append( num );
+                }
+            
+            AddPairL( UpnpHTTP::KHdrRange(), *rangeValue );
+                                               
+            CleanupStack::PopAndDestroy( rangeValue );
+            }
+        else if( iOffset == 0 && iLength == 0 && !iSaveAtOffset ) 
+            {
+            // Set values indicate that there should be no Range header, so remove it.
+            CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+            while ( hdr != NULL )
+                {
+                if( hdr->Name().Length() == UpnpHTTP::KHdrRange().Length() )
+                    {
+                    if (hdr->Name().FindC( UpnpHTTP::KHdrRange() ) == 0)
+                        {
+                        // Header was found so remove it and exit function.
+                        iHeaderList->Remove( hdr );
+                        delete hdr;
+                        return;
+                        }
+                    }
+                hdr = iHeaderList->Next( hdr );
+                }
+            }
+        }
+    else
+        {
+        User::Leave( KErrGeneral );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Offset
+// Returns the offset of the file that should be requested from server.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::Offset()
+    {
+    return iOffset;    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Length
+// Returns the length of file content to be requested.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::Length()
+    {
+    return iLength;        
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::InFilename
+// Return if the requested offset of the remote file should be saved at physical offset of
+// the local file.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::SaveAtOffset()
+    {
+    return iSaveAtOffset;        
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetOutFilenameL
+// Sets the filename which will be used as message body.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetOutFilenameL(const TDesC8& aFilename)
+    {
+
+    if(iOutFilename)
+        {
+        delete iOutFilename;
+        iOutFilename=NULL;
+        }
+    
+    iOutFilename=HBufC8::NewL(aFilename.Length());
+    iOutFilename->Des().Zero();
+    iOutFilename->Des().Append(aFilename);    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::OutFilename
+// Returns the name of file which will be set as body of message to send.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CUpnpHttpMessage::OutFilename()
+    {
+    if(iOutFilename->Length()>0)
+        {
+        return iOutFilename->Des();
+        }
+    else
+        {
+        return (TDesC8&) KNullDesC8();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::GetHeaderValue
+// Returns value of the header.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TDesC8& CUpnpHttpMessage::GetHeaderValue(const TDesC8& aHeaderName)
+    {
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+    while (hdr != NULL)
+        {
+        if(hdr->Name().Length() == aHeaderName.Length())
+            {
+            if (hdr->Name().FindC(aHeaderName) == 0)
+                {
+                return hdr->Value();
+                }
+            }
+        hdr = iHeaderList->Next(hdr);
+        }
+    
+    return (TDesC8&) KNullDesC8();
+    }
+
+// -----------------------------------------------------------------------------
+//    Check if header exists, also return value of header if exists
+//    @param aHeaderName Name of the header.
+//    @param aExist True if header exist, false if not.
+//    @result Value of the header (if exist, otherwise KNullDesC).
+// -----------------------------------------------------------------------------
+
+EXPORT_C TDesC8& CUpnpHttpMessage::IsHeader(const TDesC8& aHeaderName, TBool& aExist)
+{ 
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    aExist = EFalse;
+    while (hdr != NULL)
+        {
+        if(hdr->Name().Length() == aHeaderName.Length())
+            {
+            if (hdr->Name().FindC(aHeaderName) == 0)
+                {
+                aExist = ETrue;
+                return hdr->Value();
+                }
+            }
+        hdr = iHeaderList->Next(hdr);
+        }
+    return ( TDesC8& )KNullDesC8();
+}
+
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetSessionId
+// Sets messages Session id.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetSessionId(TInt aId)
+    {
+    iSessionId = aId;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SessionId
+// Returns the SessionId of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::SessionId() const
+    {
+    return iSessionId;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::NewSessionIdL
+// Creates new, unused Session id value.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::NewSessionIdL()
+    {
+    TInt id;
+    TInt r;
+    TBool newID=EFalse;
+
+    RSemaphore accessSemaphore;        
+    
+    r=accessSemaphore.OpenGlobal(KSessionIdAccessSemaphoreName());
+    //if failed to open
+    if(r!=KErrNone)
+        {
+        User::LeaveIfError (accessSemaphore.CreateGlobal(KSessionIdAccessSemaphoreName(), 0) );
+        accessSemaphore.Signal();
+        }
+    
+            
+          
+    accessSemaphore.Wait();
+    
+    // Use Publish and Subscribe to generate new session ID. 
+    RProperty idCounter;
+    
+    // Attach to the idCounter, property defined in MessageHandler
+    r = idCounter.Attach(KUPnPUtilsCat,EUPnPUtilsCounter);
+    if (r == KErrNone) 
+        {
+        r = idCounter.Get(id);
+        }
+
+    if (r == KErrNone) 
+        {
+        // Increment id and save
+        id++;
+        r=idCounter.Set(id);
+        if (r==KErrNone) 
+            {
+            newID = ETrue; 
+            }
+        }
+
+    accessSemaphore.Signal();
+    accessSemaphore.Close();       
+
+    // Close the idCounter property
+    idCounter.Close();      
+    
+    
+    if(!newID)
+        User::Leave(r);
+
+    return id;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SessionIdMatch
+// Compares if two messages have same session id.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::SessionIdMatch(const CUpnpHttpMessage& aFirst, const CUpnpHttpMessage& aSecond)
+    {
+    return aFirst.iSessionId == aSecond.iSessionId;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::BodyLength
+// Returns length of message body.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::BodyLength() const
+    {
+    return iTextBody->Length();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::DevicePath
+// Returns the service used from http message, for example MediaServer:1 
+// from Mediaserver:1/ContentDirectory.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TPtrC8 CUpnpHttpMessage::DevicePath()
+    {
+
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+    if (hdr != NULL)
+        {
+        TInt FirstSlashIndex = hdr->Name().Find(UpnpString::KSlash());
+        if (FirstSlashIndex == KErrNotFound)
+            {
+            return KNullDesC8();
+            }
+        TPtrC8 tempPtr;
+        tempPtr.Set(hdr->Name().Right(hdr->Name().Length() - (FirstSlashIndex + 1)));
+        TInt SecondSlashIndex = tempPtr.Find(UpnpString::KSlash());
+        if (SecondSlashIndex == KErrNotFound)
+            {
+            return KNullDesC8();
+            }
+        TPtrC8 tempPtr2;
+        tempPtr2.Set(tempPtr.Left(SecondSlashIndex));
+        return tempPtr2;
+        }
+    
+    return KNullDesC8();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::ServicePath
+// Returns the service used from http message, for example ContentDirectory 
+// from Mediaserver:1/ContentDirectory.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TPtrC8 CUpnpHttpMessage::ServicePath() const
+    {
+    TInt firstSlashIndex(-1);
+    
+    TInt httpSchema  = iDestinationPath->Find( UpnpHTTP::KHTTPUrl() );
+    if( httpSchema != KErrNotFound)
+    {
+        TPtrC8 schemaPtr( iDestinationPath->Mid( UpnpHTTP::KHTTPUrl().Length() ) );    
+        TInt relativePath = schemaPtr.Find( UpnpString::KSlash() );        
+        firstSlashIndex = relativePath + UpnpHTTP::KHTTPUrl().Length() ;
+    }    
+    else
+    {
+        firstSlashIndex = iDestinationPath->Find(UpnpString::KSlash());
+    }
+    
+    if(firstSlashIndex == KErrNotFound)
+        return KNullDesC8();    
+    
+    TPtrC8 devicePtr(iDestinationPath->Right(iDestinationPath->Length() - (firstSlashIndex + 1)));
+
+    TInt secondSlashIndex = devicePtr.Find(UpnpString::KSlash());
+    TPtrC8 servicePtr(devicePtr.Right(devicePtr.Length() - (secondSlashIndex + 1)));
+    TInt third = servicePtr.Find(UpnpString::KSlash());
+    TInt sp = servicePtr.Find(UpnpString::KSpace());
+
+    if (third != KErrNotFound && ((third < sp && sp != KErrNotFound) || sp == KErrNotFound))
+        {
+        return servicePtr.Left(third);
+        }
+    else
+        {
+        TInt space = servicePtr.Find(UpnpString::KSpace());
+        if (space != KErrNotFound)
+            {
+            return servicePtr.Left(space);
+            }
+        return servicePtr;
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::IsSoap
+// Checks if message is SOAP message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::IsSoap() const
+    {
+    
+    TInt envelope = iTextBody->Find(KEnvelope());
+    if( envelope == KErrNotFound )
+        {
+        CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+        while (hdr != NULL)
+            {
+            if ( hdr->Value().FindC( UpnpSSDP::KUPnPServiceSchema() ) != KErrNotFound && hdr->Name().FindC( KSoapAction() ) != KErrNotFound )
+                {
+                return ETrue;
+                }
+
+            hdr = iHeaderList->Next(hdr);
+            }
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::IsGena
+// Checks if message is GENA message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::IsGena()
+    {
+
+    if (Method().CompareC(UpnpGENA::KGenaSubscribe()) == 0)
+        {
+        return ETrue;
+        }
+    else if (Method().CompareC(UpnpGENA::KGenaUnSubscribe()) == 0)
+        {
+        return ETrue;
+        }
+    else if (Method().CompareC(UpnpGENA::KGenaNotify()) == 0)
+        {
+        return ETrue;
+        }
+
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    
+    while (hdr != NULL)
+        {
+        if (hdr->Name().CompareC(UpnpGENA::KSid()) == 0)
+            {
+            return ETrue;
+            }
+
+        hdr = iHeaderList->Next(hdr);
+        }    
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Method
+// Returns the method of message, like GET, POST etc.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TPtrC8 CUpnpHttpMessage::Method()
+    {
+    TBool ValueFound=EFalse;
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+
+    TPtrC8 returnPtr;
+    
+    if (hdr != NULL)
+        {
+        TInt index = hdr->Name().Find(UpnpString::KSpace());
+        if    (index!= KErrNotFound)
+        {
+        returnPtr.Set(hdr->Name().Left(index));
+        ValueFound=ETrue;    
+        }
+        
+        }
+    
+    if(!ValueFound)
+        {
+        returnPtr.Set(KNullDesC8);
+        }
+    return returnPtr;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::HTTPVersion
+//Returns version of HTTP, like HTTP/1.1, HTTP/1.0 etc.
+//-----------------------------------------------------------------------------
+//
+EXPORT_C const TPtrC8 CUpnpHttpMessage::RequestHTTPVersion()
+    {
+    CUpnpHttpHeader* hdr = iHeaderList->First();
+    TPtrC8 returnPtr;
+
+    if (hdr != NULL)
+        {
+        TInt index = hdr->Name().LocateReverse(UpnpString::KSpace()[0]);
+        if (index >= 0)
+            {
+                returnPtr.Set(hdr->Name().Right(hdr->Name().Length()-index-1));    
+            }
+            else
+            {
+                returnPtr.Set(KNullDesC8);
+            }
+        }
+        else
+        {
+            returnPtr.Set(KNullDesC8);
+        }
+    return returnPtr;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::HeaderList
+// Returns a pointer to this message's headerlist.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpHttpHeaderList* CUpnpHttpMessage::HeaderList()
+    {
+    return iHeaderList;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetType
+// Sets the type of message. Used by ControlPoint
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetType(THTTPMsgType aType)
+    {
+    iType = aType;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Type
+// Returns the Http message type, used by controlpoint.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C THTTPMsgType CUpnpHttpMessage::Type() const
+    {
+    return iType;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::UpnpError
+// Returns textual presentation of the given error.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TDesC8& CUpnpHttpMessage::UpnpError(TUpnpErrorCode aError)
+    {
+    switch(aError)    
+        {    
+        case EHttpOk:
+            return KHttpOk();
+            
+        case EBadRequest:
+            return KBadRequest();
+        case EInvalidAction:
+            return KInvalidAction();
+        case EInvalidArgs:
+            return KInvalidArgs();
+        case EInvalidVar:
+            return KInvalidVar();
+        case EPreconditionFailed:
+            return KPreconditionFailed();
+            
+        case EInternalServerError:
+            return KInternalServerError();
+        case EActionFailed:
+            return KActionFailed();
+            
+        // 600-699 Common action errors:    
+        case EArgumentValue:
+            return KArgumentValue();
+        case EArgumentRange:
+            return KArgumentRange();
+        case ENotImplemented:
+            return KNotImplemented();
+        case EOutOfMemory:
+            return KOutOfMemory();
+        case EHumanIntervention:
+            return KHumanIntervention();
+        case EStringTooLong:
+            return KStringTooLong();
+        case ENotAuthorized:
+            return KNotAuthorized();
+        case ESignatureFailure:
+            return KSignatureFailure();
+        case ESignatureMissing:
+            return KSignatureMissing();
+        case ENotEncrypted:
+            return KNotEncrypted();
+        case EInvalidSequence:
+            return KInvalidSequence();
+        case EInvalidUrl:
+            return KInvalidUrl();
+        case ENoSession:
+            return KNoSession();
+            
+        // 700-799 Action specific errors:    
+        case ENoSuchObject:
+            return KNoSuchObject();
+        case EInvalidCurrentTag:
+            return KInvalidCurrentTag();
+        case EInvalidNewTag:
+            return KInvalidNewTag();
+        case ERequiredTag:
+            return KRequiredTag();
+        case EReadOnlyTag:
+            return KReadOnlyTag();
+        case EParameterMismatch:
+            return KParameterMismatch();
+        case EInvalidSearch:
+            return KInvalidSearch();
+        case EInvalidSort:
+            return KInvalidSort();
+        case ENoContainer:
+            return KNoContainer();
+        case ERestrictedObject:
+            return KRestrictedObject();
+        case EBadMetadata:
+            return KBadMetadata();
+        case ERestrictedParentObject:
+            return KRestrictedParentObject();
+        case ENoSourceResource:
+            return KNoSourceResource();
+        case ESourceAccess:
+            return KSourceAccess();
+        case ETransferBusy:
+            return KTransferBusy();
+        case ENoFileTransfer:
+            return KNoFileTransfer();
+        case ENoDestinationResource:
+            return KNoDestinationResource();
+        case EDestinationAccess:
+            return KDestinationAccess();
+        case ECannotProcess:
+            return KCannotProcess();
+        default:
+            return KNullDesC8();
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::UpnpErrorL
+// Returns textual presentation of the given error.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CUpnpHttpMessage::UpnpErrorL(TUpnpErrorCode aError)
+    {
+    return UpnpError(aError).AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::HttpError
+// Returns the textual error message of given error code.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TDesC8& CUpnpHttpMessage::HttpError(THttpStatusCode aError)
+    {
+    switch(aError)    
+        {    
+            // 100
+        case EHttpContinue:
+            return KHttpContinue();
+        case EHttpSwitchingProtocols:
+            return KHttpSwitchingProtocols();
+            
+            // 200
+        case EHttp200Ok:
+            return KHttpOk();
+        case EHttpCreated:
+            return KHttpCreated();
+        case EHttpAccepted:
+            return KHttpAccepted();
+        case EHttpNonAuthoritative:
+            return KHttpNonAutohorative();
+        case EHttpNoContent:
+            return KHttpNoContent();
+        case EHttpResetContent:
+            return KHttpResetContent();
+        case EHttpPartialContent:
+            return KHttpPartialContent();
+        
+            // 300
+
+        case EHttpMultipleChoises:
+            return     KHttpMultipleChoises();
+        case EHttpMovedPermanently:
+            return KHttpMovedPermanently();
+        case EHttpFound:
+            return KHttpFound();
+        case EHttpSeeOther:
+            return KHttpSeeOther();
+        case EHttpNotModified:
+            return KHttpNotModified();
+        case EHttpUseProxy:
+            return KHttpUseProxy();
+        case EHttpTemporaryRedirect:
+            return KHttpTemporaryRedirect();
+            
+            // 400
+            
+        case EHttpBadRequest:
+            return KHttpBadRequest();
+        case EHttpUnAuthorized:
+            return KHttpUnauthorized();
+        case EHttpPaymentRequired:
+            return KHttpPaymentRequired();
+        case EHttpForbidden:
+            return KHttpForbidden();
+        case EHttpNotFound:
+            return KHttpNotFound();
+        case EHttpMethodNotAllowed:
+            return KHttpMethodNotAllowed();
+        case EHttpNotAcceptable:
+            return KHttpNotAcceptable();
+        case EHttpProxyAuthenticationRequired:
+            return KHttpProxyAuthenticationRequired();
+            
+        case EHttpRequestTimeout:
+            return KHttpRequestTimeout();
+        case EHttpConflict:
+            return KHttpConflict();
+        case EHttpGone:
+            return KHttpGone();
+        case EHttpLengthRequired:
+            return KHttpLengthRequired();
+        case EHttpPreconditionFailed:
+            return KHttpPreconditionFailed();
+        case EHttpEntityTooLarge:
+            return KHttpEntityTooLarge();
+        case EHttpUriTooLong:
+            return KHttpUriTooLarge();
+        case EHttpUnsupportedMediaType:
+            return KHttpUnsupprotedMediaType();
+        case EHttpRequestedRangeNotSatisfiable:
+            return KHttpRequestedRangeNotSatisfiable();
+        case EHttpExpectationFailed:
+            return KHttpExpectationFailed();
+
+            // 500                
+        case EHttpInternalServerError:
+            return KHttpInternalServerError();
+        case EHttpNotImplemented:
+            return KHttpNotImplemented();
+        case EHttpBadGateway:
+            return KHttpBadGateway();
+        case EHttpServiceUnavailable:
+            return KHttpServiceUnavailable();
+        case EHttpGatewayTimeout:
+            return KHttpGatewayTimeout();
+        case EHttpVersionNotSupported:
+            return KHttpVersionNotSupported();
+        case EHttpInsufficientStorage:
+            return KHttpInsufficientStorage();
+            
+        default:
+            return KNullDesC8();
+        }    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Error
+// Returns the error code of the message.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::Error()
+    {
+    if(iHeaderList && iHeaderList->Count())
+        {
+        CUpnpHttpHeader* hdr = iHeaderList->First();
+
+        if (hdr != NULL)
+            {            
+            TDesC8& first = hdr->Name();
+        
+            if(first.Length() == 0)
+                {
+                return KErrNotFound;
+                }
+
+            TInt space1 = first.Find(KSpace8());
+
+            if (space1 != KErrNotFound)
+                {
+                TPtrC8 right = first.Mid(space1+1);
+                TInt space2 = right.Find(KSpace8());
+
+                if (space2 != KErrNotFound)
+                    {
+                    TLex8 lex(right.Left(space2));
+
+                    TInt error;
+                    lex.Val(error);
+
+                    return error;                
+                    }
+                }
+            }
+        }
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Is3xx
+// Returns True if message is a 3xx response
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::Is3xx()
+    { TInt err = Error();
+        return (err>=300 && err<400);
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Is1xx
+// Returns True if message is a 1xx response
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::Is1xx()
+    { TInt err = Error();
+        return (err>=100 && err<200);
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Is2xx
+// Returns True if message is a 2xx response
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::Is2xx()
+    { TInt err = Error();
+        return (err>=200 && err<300);
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::AddrOutput
+// Sets the aBuf as string presentation of aAddr
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::AddrOutput(const TInetAddr& aAddr, TDes8& aBuf)
+    {
+    aBuf.SetLength(0);
+    if (aAddr.Family() == KAfInet || aAddr.Family() == KAfInet6)
+        {
+        TUint32 a = aAddr.Address();
+        aBuf.Format(_L8("%d.%d.%d.%d"), a>>24, (a>>16)&0xff, (a>>8)&0xff, a&0xff);
+        }
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::AddrInput
+// Sets the TInetAddr object value to given aBuf.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::AddrInput(TInetAddr& aAddr, const TDesC8& aBuf)
+    {
+    
+    TPtrC8 ptr(aBuf);
+    TInt addr[4] = {0, 0, 0, 0};
+    for (TInt i=0; i<4; i++)
+        {
+        TInt posOfDot=ptr.Find(UpnpString::KDot8);
+        if(posOfDot != KErrNotFound)
+            {
+            TLex8 lex(ptr.Left(posOfDot));
+            lex.Val(addr[i]);    
+            ptr.Set(ptr.Mid(posOfDot+1));
+            }
+        else
+            {
+            if(i==3)
+                {
+                TLex8 lex(ptr);
+                lex.Val(addr[i]);                
+                }
+            }
+
+        }    
+    aAddr.SetAddress((addr[0]<<24) | (addr[1]<<16) | (addr[2]<<8) | addr[3]);
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::RetryCounter
+// Returns the current iRetryCounter value.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::RetryCounter()
+    {
+    return iRetryCounter;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetRetryCounter
+// Sets the retry counter value
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetRetryCounter(TInt aValue)
+    {
+    iRetryCounter=aValue;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetHttpPriority
+// Sets the priority on session sending this message
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetHttpPriority( TThreadPriority aPriority )
+    {
+    iSessionPriority = aPriority;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::HttpPriority
+// Returns the priority of this message
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TThreadPriority CUpnpHttpMessage::HttpPriority()
+    {
+    return iSessionPriority;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetOutUri
+// Sets the uri to find the local file.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetOutUriL( const TDesC8& aUri )
+    {
+    if( iOutUri )
+        {
+        delete iOutUri;
+        iOutUri = NULL;
+        }
+    iOutUri = HBufC8::NewL( aUri.Length() );
+    iOutUri->Des().Zero();
+    iOutUri->Des().Append( aUri );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::OutUri
+// Returns the value of OutUri.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TDesC8& CUpnpHttpMessage::OutUri()
+    {
+    if( iOutUri )
+        {
+        return *iOutUri;
+        }
+    else
+        {
+        return KNullDesC8();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetLocal
+// Sets if message is a local requests
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetLocal( TBool aLocal )
+    {
+    iLocal = aLocal;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Local
+// Returns if message is a local requests.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::Local()
+    {
+    return iLocal;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetClientRequest
+// Sets if message is a client request
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetClientRequest( TBool aClientRequest )
+    {
+    iClientRequest = aClientRequest;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Local
+// Returns if message is a client request.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CUpnpHttpMessage::ClientRequest()
+    {
+    return iClientRequest;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetTimeout
+// Sets the value for a TCP timeout (valid for cleint sessions)
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetTcpTimeout( TInt aTimeout )
+    {
+    iTcpTimeout = aTimeout;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::Timeout
+// Returns the value of TCP timeout
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::TcpTimeout()
+    {
+    return iTcpTimeout;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetInternalError
+// Sets internal error code
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpHttpMessage::SetInternalError(TInt aErrorCode)
+    {
+    iInternalError = aErrorCode;
+    }    
+// -----------------------------------------------------------------------------
+// CUpnpHttpMessage::SetInternalError
+// Sets internal error code
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpHttpMessage::InternalError()
+    {
+    return iInternalError;
+    }        
+//  End of File