diff -r 5f8e5adbbed9 -r 29cda98b007e engine/src/HttpEventHandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/src/HttpEventHandler.cpp Thu Feb 25 14:29:19 2010 +0000 @@ -0,0 +1,406 @@ +/* +* Copyright (c) 2007-2010 Sebastian Brannstrom, Lars Persson, EmbedDev AB +* +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: +* EmbedDev AB - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +// HttpEventHandler.cpp +#include +#include + +#include "HttpEventHandler.h" +#include "bautils.h" +#include "Httpclient.h" + +void CHttpEventHandler::ConstructL() + { + //iVerbose = ETrue; + } + + +CHttpEventHandler::CHttpEventHandler(CHttpClient* aClient, MHttpClientObserver &aCallbacks, RFs& aFs): + iFileServ(aFs), iHttpClient(aClient), iCallbacks(aCallbacks) + { + } + + +CHttpEventHandler::~CHttpEventHandler() + { + } + + +CHttpEventHandler* CHttpEventHandler::NewLC(CHttpClient* aClient, MHttpClientObserver &aCallbacks, RFs& aFs) + { + CHttpEventHandler* me = new(ELeave)CHttpEventHandler(aClient, aCallbacks, aFs); + CleanupStack::PushL(me); + me->ConstructL(); + return me; + } + + +CHttpEventHandler* CHttpEventHandler::NewL(CHttpClient* aClient, MHttpClientObserver &aCallbacks, RFs& aFs) + { + CHttpEventHandler* me = NewLC(aClient, aCallbacks, aFs); + CleanupStack::Pop(me); + return me; + } + +void CHttpEventHandler::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent) + { + switch (aEvent.iStatus) + { + case THTTPEvent::EGotResponseHeaders: + { + // HTTP response headers have been received. We can determine now if there is + // going to be a response body to save. + RHTTPResponse resp = aTransaction.Response(); + iLastStatusCode = resp.StatusCode(); + RStringF statusStr = resp.StatusText(); + TBuf<32> statusStr16; + statusStr16.Copy(statusStr.DesC()); + DP2("Status: %d (%S)", iLastStatusCode, &statusStr16); + + // Dump the headers if we're being verbose + //DumpRespHeadersL(aTransaction); + + // Determine if the body will be saved to disk + iSavingResponseBody = ETrue; + TBool cancelling = EFalse; + if (resp.HasBody() && (iLastStatusCode >= 200) && (iLastStatusCode < 300) && (iLastStatusCode != 204)) + { + //iBytesDownloaded = 0; + TInt dataSize = resp.Body()->OverallDataSize(); + if (dataSize >= 0) { + DP1("Response body size is %d", dataSize); + iBytesTotal = dataSize; + } else { + DP("Response body size is unknown"); + iBytesTotal = -1; + } + iCallbacks.DownloadInfo(iHttpClient, dataSize); + + cancelling = EFalse; + } + + // If we're cancelling, must do it now.. + if (cancelling) + { + DP("Transaction Cancelled"); + aTransaction.Close(); + iHttpClient->ClientRequestCompleteL(KErrCancel); + } + else if (iSavingResponseBody) // If we're saving, then open a file handle for the new file + { + iFileServ.Parse(iFileName, iParsedFileName); + TInt valid = iFileServ.IsValidName(iFileName); + if (!valid) + { + DP("The specified filename is not valid!."); + iSavingResponseBody = EFalse; + } + else + { + if (iContinue) { + TInt err = iRespBodyFile.Open(iFileServ, iParsedFileName.FullName(),EFileWrite); + if (err) + { + DP("There was an error opening file"); + iSavingResponseBody = EFalse; + User::Leave(err); + } else { + int pos = -KByteOverlap; + if((err=iRespBodyFile.Seek(ESeekEnd, pos)) != KErrNone) { + DP("Failed to set position!"); + User::Leave(err); + } + iBytesDownloaded = (pos > 0) ? pos : 0; + iBytesTotal += iBytesDownloaded; + DP1("Total bytes is now %u", iBytesTotal); + DP1("Seeking end: %d", pos); + } + } else { + TInt err = iRespBodyFile.Replace(iFileServ, + iParsedFileName.FullName(), + EFileWrite); + if (err) + { + DP("There was an error replacing file"); + iSavingResponseBody = EFalse; + User::Leave(err); + } + } + } + } + + } break; + case THTTPEvent::EGotResponseBodyData: + { + // Get the body data supplier + iRespBody = aTransaction.Response().Body(); + + // Some (more) body data has been received (in the HTTP response) + //DumpRespBody(aTransaction); + //DP1("Saving: %d", iSavingResponseBody); + // Append to the output file if we're saving responses + if (iSavingResponseBody) + { + TPtrC8 bodyData; + iRespBody->GetNextDataPart(bodyData); + iBytesDownloaded += bodyData.Length(); + TInt error = iRespBodyFile.Write(bodyData); + + // on writing error we close connection + if (error != KErrNone) { + //aTransaction.Close(); + iCallbacks.FileError(error); + iHttpClient->ClientRequestCompleteL(error); + return; + } + + if (!iSilent) { + iCallbacks.Progress(iHttpClient, iBytesDownloaded, iBytesTotal); + } + } + + // Done with that bit of body data + iRespBody->ReleaseData(); + } break; + case THTTPEvent::EResponseComplete: + { + // The transaction's response is complete + + DP("Transaction Complete"); + DP("Closing file"); + iRespBodyFile.Close(); + } break; + case THTTPEvent::ESucceeded: + { + DP("Transaction Successful"); + aTransaction.Close(); + iHttpClient->ClientRequestCompleteL(KErrNone); + } break; + case THTTPEvent::EFailed: + { + DP("Transaction Failed"); + aTransaction.Close(); + + if(iLastStatusCode == HTTPStatus::EOk || iLastStatusCode == HTTPStatus::ECreated || iLastStatusCode == HTTPStatus::EAccepted) + { + iLastStatusCode = KErrNone; + } + + iHttpClient->ClientRequestCompleteL(iLastStatusCode); + } break; + case THTTPEvent::ERedirectedPermanently: + { + DP("Permanent Redirection"); + } break; + case THTTPEvent::ERedirectedTemporarily: + { + DP("Temporary Redirection"); + } break; + default: + { + DP1("", aEvent.iStatus); + // close off the transaction if it's an error + if (aEvent.iStatus < 0) + { + aTransaction.Close(); + iHttpClient->ClientRequestCompleteL(aEvent.iStatus); + } + } break; + } + } + +TInt CHttpEventHandler::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/) + { + DP1("MHFRunError fired with error code %d", aError); + + return KErrNone; + } + +void CHttpEventHandler::SetSaveFileName(const TDesC &fName, TBool aContinue) + { + iFileName.Copy(fName); + iContinue = aContinue; + } + +void CHttpEventHandler::DumpRespHeadersL(RHTTPTransaction& aTrans) + { + RHTTPResponse resp = aTrans.Response(); + RStringPool strP = aTrans.Session().StringPool(); + RHTTPHeaders hdr = resp.GetHeaderCollection(); + THTTPHdrFieldIter it = hdr.Fields(); + + TBuf fieldName16; + TBuf fieldVal16; + + while (it.AtEnd() == EFalse) + { + RStringTokenF fieldName = it(); + RStringF fieldNameStr = strP.StringF(fieldName); + THTTPHdrVal fieldVal; + if (hdr.GetField(fieldNameStr,0,fieldVal) == KErrNone) + { + const TDesC8& fieldNameDesC = fieldNameStr.DesC(); + fieldName16.Copy(fieldNameDesC.Left(KMaxHeaderNameLen)); + switch (fieldVal.Type()) + { + case THTTPHdrVal::KTIntVal: + DP2("%S: %d", &fieldName16, fieldVal.Int()); + break; + case THTTPHdrVal::KStrFVal: + { + RStringF fieldValStr = strP.StringF(fieldVal.StrF()); + const TDesC8& fieldValDesC = fieldValStr.DesC(); + fieldVal16.Copy(fieldValDesC.Left(KMaxHeaderValueLen)); + DP2("%S: %S", &fieldName16, &fieldVal16); + } + break; + case THTTPHdrVal::KStrVal: + { + RString fieldValStr = strP.String(fieldVal.Str()); + const TDesC8& fieldValDesC = fieldValStr.DesC(); + fieldVal16.Copy(fieldValDesC.Left(KMaxHeaderValueLen)); + DP2("%S: %S", &fieldName16, &fieldVal16); + } + break; + case THTTPHdrVal::KDateVal: + { + TDateTime date = fieldVal.DateTime(); + } + break; + default: + DP1("%S: ", &fieldName16); + break; + } + + // Display realm for WWW-Authenticate header + RStringF wwwAuth = strP.StringF(HTTP::EWWWAuthenticate,RHTTPSession::GetTable()); + if (fieldNameStr == wwwAuth) + { + // check the auth scheme is 'basic' + RStringF basic = strP.StringF(HTTP::EBasic,RHTTPSession::GetTable()); + RStringF realm = strP.StringF(HTTP::ERealm,RHTTPSession::GetTable()); + THTTPHdrVal realmVal; + if ((fieldVal.StrF() == basic) && + (!hdr.GetParam(wwwAuth, realm, realmVal))) + { + RStringF realmValStr = strP.StringF(realmVal.StrF()); + fieldVal16.Copy(realmValStr.DesC()); + DP1("Realm is: %S", &fieldVal16); + } + } + } + ++it; + } + } + +void CHttpEventHandler::DumpRespBody(RHTTPTransaction& aTrans) + { + MHTTPDataSupplier* body = aTrans.Response().Body(); + TPtrC8 dataChunk; + TBool isLast = body->GetNextDataPart(dataChunk); + DumpIt(dataChunk); + if (isLast) + DP("Got last data chunk."); + } + + +void CHttpEventHandler::DumpIt(const TDesC8& aData) +//Do a formatted dump of binary data + { + // Iterate the supplied block of data in blocks of cols=80 bytes + const TInt cols=16; + TInt pos = 0; + TBuf logLine; + TBuf anEntry; + const TInt dataLength = aData.Length(); + + while (pos < dataLength) + { + //start-line hexadecimal( a 4 digit number) + anEntry.Format(TRefByValue_L("%04x : "), pos); + logLine.Append(anEntry); + + // Hex output + TInt offset; + for (offset = 0; offset < cols; ++offset) + { + if (pos + offset < aData.Length()) + { + TInt nextByte = aData[pos + offset]; + anEntry.Format(TRefByValue_L("%02x "), nextByte); + logLine.Append(anEntry); + } + else + { + //fill the remaining spaces with blanks untill the cols-th Hex number + anEntry.Format(TRefByValue_L(" ")); + logLine.Append(anEntry); + } + } + anEntry.Format(TRefByValue_L(": ")); + logLine.Append(anEntry); + + // Char output + for (offset = 0; offset < cols; ++offset) + { + if (pos + offset < aData.Length()) + { + TInt nextByte = aData[pos + offset]; + if ((nextByte >= ' ') && (nextByte <= '~')) + { + anEntry.Format(TRefByValue_L("%c"), nextByte); + logLine.Append(anEntry); + } + else + { + anEntry.Format(TRefByValue_L(".")); + logLine.Append(anEntry); + } + } + else + { + anEntry.Format(TRefByValue_L(" ")); + logLine.Append(anEntry); + } + } + logLine.Zero(); + + // Advance to next byte segment (1 seg= cols) + pos += cols; + } + } + +void CHttpEventHandler::SetSilent(TBool aSilent) + { + iSilent = aSilent; + } + +void CHttpEventHandler::CloseSaveFile() +{ + if(iRespBody != NULL) + { + if(iRespBodyFile.SubSessionHandle() != 0) + { + TInt size; + iRespBodyFile.Size(size); + DP2("Closing file at size %d, bytes downloaded %d", size, iBytesDownloaded); + iRespBodyFile.Close(); + } + } +} +