--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarengines/caldav/src/httpclient.cpp Fri Feb 05 10:16:42 2010 +0100
@@ -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 <uri8.h>
+#include <http.h>
+#include <EIKENV.H>
+
+_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();
+ }