--- /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