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