diff -r bd7edf625bdd -r 97232defd20e calendarengines/caldav/src/httpclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/calendarengines/caldav/src/httpclient.cpp Tue Sep 14 21:17:03 2010 +0300 @@ -0,0 +1,687 @@ +/* +* Copyright (c) 2010 Sun Microsystems, Inc. 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 Contributor: +* Maximilian Odendahl +* +* Contributors: +* +* Description: basic http/webdav functionality +* handles all needed internet access for Caldav +*/ + +#include "httpclient.h" +#include "caldavutils.h" +#include +#include +#include + +_LIT8(KTextXml,"text/xml"); +_LIT8(KTextCalendar,"text/calendar"); +_LIT8(KDepth,"depth"); + +/** + * CHttpClient::CHttpClient + * default constructor + */ +CHttpClient::CHttpClient() : + iUser(0), iPassword(0), iEtag(0), iCredentialCount(0) + { + } + +/** + * CHttpClient::~CHttpClient + * default destructor + */ +CHttpClient::~CHttpClient() + { + delete iUser; + delete iPassword; + delete iEtag; + + iSess.Close(); + iRConnection.Close(); + iSocketServ.Close(); + + } + +/** + * CHttpClient::NewLC + * first phase constructor + */ +CHttpClient* CHttpClient::NewLC() + { + CHttpClient* me = new (ELeave) CHttpClient; + CleanupStack::PushL(me); + me->ConstructL(); + return me; + } + +/** + * CHttpClient::NewL + * first phase construction + */ +CHttpClient* CHttpClient::NewL() + { + CHttpClient* me = NewLC(); + CleanupStack::Pop(me); + return me; + } + +/** + * CHttpClient::OpenSessionL + * open session and instal authentification + */ +void CHttpClient::OpenSessionL() + { + TRAPD(err, iSess.OpenL()); + + if (err != KErrNone) + { + _LIT(KErrMsg, "Cannot create session. Is internet access point configured?"); + _LIT(KExitingApp, "Exiting app."); + CEikonEnv::Static()->InfoWinL(KErrMsg, KExitingApp); + User::Leave(err); + } + + // Install this class as the callback for authentication requests + InstallAuthenticationL(iSess); + + // Set the session's connection info... + RHTTPConnectionInfo connInfo = iSess.ConnectionInfo(); + // ...to use the socket server + connInfo.SetPropertyL(iSess.StringPool().StringF(HTTP::EHttpSocketServ, + RHTTPSession::GetTable()), THTTPHdrVal(iSocketServ.Handle())); + // ...to use the connection + connInfo.SetPropertyL( + iSess.StringPool().StringF(HTTP::EHttpSocketConnection, + RHTTPSession::GetTable()), + THTTPHdrVal(REINTERPRET_CAST(TInt, &(iRConnection)))); + + } + +/** + * CHttpClient::ConstructL + * second phase construction + */ +void CHttpClient::ConstructL() + { + User::LeaveIfError(iSocketServ.Connect()); + User::LeaveIfError(iRConnection.Open(iSocketServ)); + + iExtPrefs.SetSnapPurpose( CMManager::ESnapPurposeInternet ); + iExtPrefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnDisableNotes); + iPrefList.AppendL(&iExtPrefs); + iRConnection.Start(iPrefList); + + OpenSessionL(); + } + +/** + * CHttpClient::DeleteL + * HTTP DELETE + */ +TInt CHttpClient::DeleteL(const TDesC8 &aUrl, const TDesC8 &aETag) + { + iReturnCode = ERROR; + + TUriParser8 uri; + uri.Parse(aUrl); + + iTrans = iSess.OpenTransactionL(uri, *this, iSess.StringPool().StringF( + HTTP::EDELETE, RHTTPSession::GetTable())); + if (aETag != KNullDesC8) + SetHeaderL(iTrans.Request().GetHeaderCollection(), HTTP::EIfMatch, + aETag); + SetHeaderL(iTrans.Request().GetHeaderCollection(), HTTP::EUserAgent, + KUserAgent); + iTrans.SubmitL(); + + CActiveScheduler::Start(); + return iReturnCode; + } + +/** + * CHttpClient::HeadL + * HTTP HEAD + */ +TInt CHttpClient::HeadL(const TDesC8 &aUrl) + { + iReturnCode = ERROR; + + TUriParser8 uri; + uri.Parse(aUrl); + + iTrans = iSess.OpenTransactionL(uri, *this, iSess.StringPool().StringF( + HTTP::EHEAD, RHTTPSession::GetTable())); + SetHeaderL(iTrans.Request().GetHeaderCollection(), HTTP::EUserAgent, + KUserAgent); + iTrans.SubmitL(); + CActiveScheduler::Start(); + return iReturnCode; + } + +/** + * CHttpClient::GetL + * HTTP Get + */ +TInt CHttpClient::GetL(const TDesC8 &aUrl, CBufFlat *aResponse) + { + iReturnCode = ERROR; + + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + iTrans = iSess.OpenTransactionL(uri, *this, iSess.StringPool().StringF( + HTTP::EGET, RHTTPSession::GetTable())); + SetHeaderL(iTrans.Request().GetHeaderCollection(), HTTP::EUserAgent, + KUserAgent); + iTrans.SubmitL(); + CActiveScheduler::Start(); + iBodyResponse = NULL; + return iReturnCode; + } + +/** + * CHttpClient::MkCalendarL + * Caldav MKCALENDAR + */ +TInt CHttpClient::MkCalendarL(const TDesC8 &aUrl, const TDesC8 &aBody, + CBufFlat *aResponse) + { + iReturnCode = ERROR; + + if (aBody != KNullDesC8) + { + iBodyRequest = aBody.Alloc(); + iTrans.Request().SetBody(*this); + } + + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + RStringF mkcalendar = iSess.StringPool().OpenFStringL(MKCALENDAR); + iTrans = iSess.OpenTransactionL(uri, *this, mkcalendar); + RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); + + SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); + SetHeaderL(hdr, HTTP::EContentType, KTextXml); + + iTrans.SubmitL(); + CActiveScheduler::Start(); + + mkcalendar.Close(); + if (iBodyRequest) + { + delete iBodyRequest; + iBodyRequest = NULL; + } + iBodyResponse = NULL; + + return iReturnCode; + } + +/** + * CHttpClient::PutL + * HTTP PUT + */ +TInt CHttpClient::PutL(const TDesC8 &aUrl, const TDesC8 &aIcs, + CBufFlat *aResponse, const TDesC8 &aEtag) + { + iReturnCode = ERROR; + + iBodyRequest = aIcs.Alloc(); + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + iTrans = iSess.OpenTransactionL(uri, *this, iSess.StringPool().StringF( + HTTP::EPUT, RHTTPSession::GetTable())); + RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); + + iTrans.Request().SetBody(*this); + + if (aEtag == KNullDesC8) + { + _LIT8(KStar, "*"); + SetHeaderL(hdr, HTTP::EIfNoneMatch, KStar); + } + else + { +#ifdef ETAG + SetHeaderL(hdr,HTTP::EIfMatch,aEtag); +#endif + } + + SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); + SetHeaderL(hdr, HTTP::EContentType, KTextCalendar); + + iTrans.SubmitL(); + CActiveScheduler::Start(); + + delete iBodyRequest; + iBodyRequest = NULL; + iBodyResponse = NULL; + + return iReturnCode; + } + +/** + * CHttpClient::ReportL + * Caldav REPORT + */ +TInt CHttpClient::ReportL(const TDesC8 &aUrl, const TDesC8 &aBodyRequest, + CBufFlat *aResponse) + { + iReturnCode = ERROR; + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + RStringF report = iSess.StringPool().OpenFStringL(REPORT); + iTrans = iSess.OpenTransactionL(uri, *this, report); + if (aBodyRequest.Length()) + { + iBodyRequest = aBodyRequest.Alloc(); + iTrans.Request().SetBody(*this); + } + + RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); + SetHeaderL(hdr, HTTP::EContentType, KTextXml); + SetHeaderL(hdr, KDepth, ONE); + SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); + iTrans.SubmitL(); + CActiveScheduler::Start(); + + report.Close(); + + delete iBodyRequest; + iBodyRequest = NULL; + iBodyResponse = NULL; + + return iReturnCode; + } + +/** + * CHttpClient::PropfindL + * WebDAV PROPFIND + */ +TInt CHttpClient::PropfindL(const TDesC8 &aUrl, const TDesC8 &aBodyRequest, + CBufFlat *aResponse, TBool depth) + { + iReturnCode = ERROR; + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + RStringF propfind = iSess.StringPool().OpenFStringL(PROPFIND); + iTrans = iSess.OpenTransactionL(uri, *this, propfind); + if (aBodyRequest.Length()) + { + iBodyRequest = aBodyRequest.Alloc(); + iTrans.Request().SetBody(*this); + } + + RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); + SetHeaderL(hdr, HTTP::EContentType, KTextXml); + SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); + if (depth) + SetHeaderL(hdr, KDepth, ZERO); + else + SetHeaderL(hdr, KDepth, ONE); + + iTrans.SubmitL(); + CActiveScheduler::Start(); + + propfind.Close(); + + delete iBodyRequest; + iBodyRequest = NULL; + iBodyResponse = NULL; + + return iReturnCode; + } + +/** + * CHttpClient::ProppatchL + * Webdav PROPPATCH + */ +TInt CHttpClient::ProppatchL(const TDesC8 &aUrl, const TDesC8 &aBodyRequest, CBufFlat *aResponse) + { + iReturnCode = ERROR; + iBodyResponse = aResponse; + + TUriParser8 uri; + uri.Parse(aUrl); + + RStringF proppatch = iSess.StringPool().OpenFStringL(PROPPATCH); + iTrans = iSess.OpenTransactionL(uri, *this, proppatch); + RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); + SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); + SetHeaderL(hdr, HTTP::EContentType, KTextXml); + + iBodyRequest = aBodyRequest.Alloc(); + iTrans.Request().SetBody(*this); + + iTrans.SubmitL(); + CActiveScheduler::Start(); + + proppatch.Close(); + + delete iBodyRequest; + iBodyRequest = NULL; + iBodyResponse = NULL; + + return iReturnCode; + } + +/** + * CHttpClient::GetServerOptionsL + * HTTP OPTIONS + */ +TInt CHttpClient::GetServerOptionsL(const TDesC8 &aUrl, + TCalDAVOptions &aOptions) + { + iReturnCode = ERROR; + iAction = EActionOption; + iOptions = &aOptions; + + TUriParser8 uri; + uri.Parse(aUrl); + + RStringF options = iSess.StringPool().OpenFStringL(OPTIONS); + iTrans = iSess.OpenTransactionL(uri, *this, options); + SetHeaderL(iTrans.Request().GetHeaderCollection(), HTTP::EUserAgent, + KUserAgent); + iTrans.SubmitL(); + + CActiveScheduler::Start(); + + options.Close(); + + iAction = EActionNone; + return iReturnCode; + } + +/** + * CHttpClient::GetNextDataPart + * GetNextDataPart callback + */ +TBool CHttpClient::GetNextDataPart(TPtrC8& aDataPart) + { + aDataPart.Set(iBodyRequest->Des()); + return ETrue; + } + +/** + * CHttpClient::ReleaseData + * ReleaseData callback + */ +void CHttpClient::ReleaseData() + { + } + +/** + * CHttpClient::OverallDataSize + * OverallDataSize callback + */ +TInt CHttpClient::OverallDataSize() + { + if (iBodyRequest) + return iBodyRequest->Length(); + else + return 0; + } + +/** + * CHttpClient::Reset + * Reset callback + */ +TInt CHttpClient::Reset() + { + return KErrNone; + } + +/** + * CHttpClient::SetHeaderL + * sets int header at session headers + */ +void CHttpClient::SetHeaderL(RHTTPHeaders aHeaders, TInt aHdrField, + const TDesC8& aHdrValue) + { + RStringF valStr = iSess.StringPool().OpenFStringL(aHdrValue); + CleanupClosePushL(valStr); + THTTPHdrVal val(valStr); + aHeaders.SetFieldL(iSess.StringPool().StringF(aHdrField, + RHTTPSession::GetTable()), val); + CleanupStack::PopAndDestroy(&valStr); + } + +/** + * CHttpClient::SetHeaderL + * set string header at session headers + */ +void CHttpClient::SetHeaderL(RHTTPHeaders aHeaders, const TDesC8 &aField, + const TDesC8 &aValue) + { + RStringF FieldVal = iSess.StringPool().OpenFStringL(aField); + CleanupClosePushL(FieldVal); + RStringF valStr = iSess.StringPool().OpenFStringL(aValue); + CleanupClosePushL(valStr); + THTTPHdrVal val(valStr); + aHeaders.SetFieldL(FieldVal, val); + CleanupStack::PopAndDestroy(&valStr); + CleanupStack::PopAndDestroy(&FieldVal); + } + +/** + * CHttpClient::GetCredentialsL + * ask for username and password for authentification + */ +TBool CHttpClient::GetCredentialsL(const TUriC8& /*aURI*/, RString aRealm, + RStringF /*aAuthenticationType*/, RString& aUsername, + RString& aPassword) + { + if (iCredentialCount) + { + iCredentialCount = 0; + User::Leave(KErrAccessDenied); + } + iCredentialCount++; + aUsername = aRealm.Pool().OpenStringL(*iUser); + aPassword = aRealm.Pool().OpenStringL(*iPassword); + return ETrue; + } + +/** + * CHttpClient::GetEtagHeaderL + * check for ETag and save it + */ +void CHttpClient::GetEtagHeaderL(RHTTPTransaction &aTransaction) + { + RStringF Header = aTransaction.Session().StringPool().StringF(HTTP::EETag, + RHTTPSession::GetTable()); + THTTPHdrVal HeaderVal; + if (aTransaction.Response().GetHeaderCollection().GetField(Header, 0, + HeaderVal) == KErrNone) + { + RStringF FieldValStr = aTransaction.Session().StringPool().StringF( + HeaderVal.StrF()); + const TDesC8 &FieldValDesC = FieldValStr.DesC(); + delete iEtag; + iEtag = NULL; + iEtag = FieldValDesC.AllocL(); + } + } + +/** + * CHttpClient::MHFRunL + * http state machine callback + */ +void CHttpClient::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(); + iReturnCode = resp.StatusCode(); + + if (iAction == EActionOption) + { + CalDavUtils::ScanAllowHeaderL(aTransaction, *iOptions); + CalDavUtils::ScanDAVHeaderL(aTransaction, *iOptions); + } + + GetEtagHeaderL(aTransaction); + + TBool cancelling = ETrue; + if (resp.HasBody() && (iReturnCode >= OK) && (iReturnCode + < MUTIPLECHOICES)) + cancelling = EFalse; + + if (cancelling) + { + aTransaction.Close(); + CActiveScheduler::Stop(); + } + } + break; + case THTTPEvent::EGotResponseBodyData: + { + // Get the body data supplier + MHTTPDataSupplier* body = aTransaction.Response().Body(); + TPtrC8 dataChunk; + TBool isLast = body->GetNextDataPart(dataChunk); + if (iBodyResponse) + iBodyResponse->InsertL(iBodyResponse->Size(), dataChunk); + // Done with that bit of body data + body->ReleaseData(); + } + break; + case THTTPEvent::EResponseComplete: + { + // The transaction's response is complete + } + break; + case THTTPEvent::ESucceeded: + { + aTransaction.Close(); + CActiveScheduler::Stop(); + } + break; + case THTTPEvent::EFailed: + { + aTransaction.Close(); + CActiveScheduler::Stop(); + } + break; + case THTTPEvent::ERedirectedPermanently: + { + } + break; + case THTTPEvent::ERedirectedTemporarily: + { + } + break; + default: + { + // close off the transaction if it's an error + if (aEvent.iStatus < 0) + { + iReturnCode = aEvent.iStatus; + aTransaction.Close(); + CActiveScheduler::Stop(); + } + } + break; + } + } + +/** + * CHttpClient::MHFRunError + * http stack erros + */ +TInt CHttpClient::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, + const THTTPEvent& /*aEvent*/) + { + iReturnCode = aError; + return KErrNone; + } + +/** + * CHttpClient::SetUserL + * set username for authentification + */ +void CHttpClient::SetUserL(const TDesC8 &aUser) + { + if (iUser) + delete iUser; + iUser = aUser.Alloc(); + iSess.Close(); + OpenSessionL(); + } + +/** + * CHttpClient::SetPasswordL + * Set Password for authentification + */ +void CHttpClient::SetPasswordL(const TDesC8 &aPassword) + { + if (iPassword) + delete iPassword; + iPassword = aPassword.Alloc(); + iSess.Close(); + OpenSessionL(); + } + +/** + * CHttpClient::User + * get username + */ +TPtrC8 CHttpClient::User() + { + return iUser ? *iUser : KNullDesC8(); + } + +/** + * CHttpClient::Password + * get password + */ +TPtrC8 CHttpClient::Password() + { + return iPassword ? *iPassword : KNullDesC8(); + } + +/** + * CHttpClient::ReturnCode + * get returned HTTP code + */ +TInt CHttpClient::ReturnCode() + { + return iReturnCode; + } + +/** + * CHttpClient::ETag + * get ETag + */ +TPtrC8 CHttpClient::ETag() + { + return iEtag ? *iEtag : KNullDesC8(); + }