calendarengines/caldav/src/caldavutils.cpp
branchRCL_3
changeset 31 97232defd20e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarengines/caldav/src/caldavutils.cpp	Tue Sep 14 21:17:03 2010 +0300
@@ -0,0 +1,375 @@
+/*
+* 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: 	various utility classes and functions
+*				used in Caldav client and server code
+*/
+
+#include "caldavutils.h"
+
+#include <http\MHTTPAuthenticationCallback.h>
+#include <http\mhttptransactioncallback.h>
+#include <http\mhttpdatasupplier.h>
+#include <http\rhttpheaders.h> 
+
+/**
+ * CalDavUtils::CalDavUtils
+ * default constructor
+ */
+CalDavUtils::CalDavUtils()
+	{
+	// No implementation required
+	}
+
+/**
+ * CalDavUtils::~CalDavUtils
+ * default destructor
+ */
+CalDavUtils::~CalDavUtils()
+	{
+	}
+
+/**
+ * CalDavUtils::NewLC
+ * first phase construction
+ */
+CalDavUtils* CalDavUtils::NewLC()
+	{
+	CalDavUtils* self = new (ELeave) CalDavUtils();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+/**
+ * CalDavUtils::NewL
+ * first phase construction
+ */
+CalDavUtils* CalDavUtils::NewL()
+	{
+	CalDavUtils* self = CalDavUtils::NewLC();
+	CleanupStack::Pop(self); // self;
+	return self;
+	}
+
+/**
+ * CalDavUtils::ConstructL
+ * second phase construction
+ */
+void CalDavUtils::ConstructL()
+	{
+	}
+
+/**
+ * CalDavUtils::FixImportIssues
+ * fix import issues
+ */
+void CalDavUtils::FixImportIssues(TDes8 &aDes)
+	{
+	const TUint KICalCarriageReturnChar('\r');
+	_LIT8(KICalNewlineChar,"\n");
+	_LIT8(KICalCarriageReturnLineFeed,"\r\n");
+
+	TInt ret = aDes.Find(KICalNewlineChar);
+
+	while ((ret != KErrNotFound) && (ret == 0 ? ETrue : (aDes[ret - 1]
+			!= KICalCarriageReturnChar)))
+		{
+		aDes.Replace(ret, 1, KICalCarriageReturnLineFeed);
+		TInt mid = aDes.Mid(ret + 2).Find(KICalNewlineChar);
+		ret = mid != KErrNone ? mid + ret + 2 : KErrNotFound;
+		}
+	}
+
+/**
+ * CalDavUtils::FixExportIssues
+ * fix export issues, hopefully can be removed in the future
+ */
+void CalDavUtils::FixExportIssues(TDes8 &aDes)
+	{
+	FixSameTime(aDes);
+	FindAndRemoveMethod(aDes);
+	FixBYMONTHDAY(aDes);
+	FixLineFeed(aDes);
+	//TODO: using public, nothing is exported
+	}
+
+/**
+ * CalDavUtils::FixLineFeed
+ * fix lidne feed
+ */
+void CalDavUtils::FixLineFeed(TDes8 &aDes)
+	{
+	_LIT8(lf1,"
");
+	_LIT8(KBackSlashN,"\\n");
+	TInt ret = aDes.Find(lf1);
+	while (ret != KErrNotFound)
+		{
+		aDes.Replace(ret, lf1().Length(), KBackSlashN);
+		ret = aDes.Find(lf1);
+		}
+	}
+
+/**
+ * CalDavUtils::FixSameTime
+ * fix same time
+ */
+void CalDavUtils::FixSameTime(TDes8 &aDes)
+	{
+#define DATELENGTH	15
+	_LIT8(DTSTART,"DTSTART:");
+	_LIT8(DTEND,"DTEND:");
+	_LIT8(DUE,"DUE:");
+	_LIT8(nine,"9");
+	_LIT8(five,"5");
+	_LIT8(VEVENT,"VEVENT");
+	_LIT8(VTODO,"VTODO");
+
+	// add one second if DTSTART and DTEND is the same
+	// ATTENTION: works only for very simple cases right now
+	// DTSTART:20090630T000000
+	// DTEND:20090630T000000
+	if (aDes.Find(VEVENT) != KErrNone)
+		{
+		TInt PosStart = aDes.Find(DTSTART);
+		TInt PosDue = aDes.Find(DTEND);
+
+		if ((PosStart != KErrNone) && (PosDue != KErrNone))
+			{
+			TPtrC8 PtrStart = aDes.Mid(PosStart + DTSTART().Length(),
+					DATELENGTH);
+			TPtrC8 PtrStop = aDes.Mid(PosDue + DTEND().Length(), DATELENGTH);
+
+			if (PtrStart == PtrStop)
+				{
+				aDes.Replace(PosDue + DTEND().Length() + DATELENGTH - 1, 1,
+						nine);
+				aDes.Replace(PosDue + DTEND().Length() + DATELENGTH - 2, 1,
+						five);
+				aDes.Replace(PosDue + DTEND().Length() + DATELENGTH - 3, 1,
+						nine);
+				}
+			}
+		}
+
+	// add one second if DTSTART and DUE is the same
+	// ATTENTION: works only for very simple cases right now
+	// DTSTART:20090630T000000
+	// DUE:20090630T000000
+
+	if (aDes.Find(VTODO) != KErrNone)
+		{
+		TInt PosStart = aDes.Find(DTSTART);
+		TInt PosDue = aDes.Find(DUE);
+
+		if ((PosStart != KErrNone) && (PosDue != KErrNone))
+			{
+			TPtrC8 PtrStart = aDes.Mid(PosStart + DTSTART().Length(),
+					DATELENGTH);
+			TPtrC8 PtrStop = aDes.Mid(PosDue + DUE().Length(), DATELENGTH);
+
+			if (PtrStart == PtrStop)
+				{
+				aDes.Replace(PosDue + DUE().Length() + DATELENGTH - 1, 1, nine);
+				aDes.Replace(PosDue + DUE().Length() + DATELENGTH - 2, 1, five);
+				aDes.Replace(PosDue + DUE().Length() + DATELENGTH - 3, 1, nine);
+				}
+			}
+		}
+	}
+
+/**
+ * CalDavUtils::FindAndRemoveMethod
+ * fix wrong method export
+ */
+void CalDavUtils::FindAndRemoveMethod(TDes8 &aDes)
+	{
+	_LIT8(method,"METHOD:PUBLISH\r\n");
+	TInt Ret = aDes.Find(method);
+	while (Ret != KErrNotFound)
+		{
+		aDes.Delete(Ret, method().Length());
+		Ret = aDes.Find(method);
+		}
+	}
+
+/**
+ * CalDavUtils::FixBYMONTHDAY
+ * fix wrong BYMONTHDAY export
+ */
+void CalDavUtils::FixBYMONTHDAY(TDes8 &aDes)
+	{
+	_LIT8(method0,"BYMONTHDAY=0");
+	_LIT8(method1,"BYMONTHDAY=1");
+	TInt ret = aDes.Find(method0);
+	while (ret != KErrNotFound)
+		{
+		aDes.Replace(ret, method1().Length(), method1);
+		ret = aDes.Find(method0);
+		}
+	}
+
+/**
+ * CalDavUtils::ScanAllowHeaderL
+ * fix scan allow header
+ */
+void CalDavUtils::ScanAllowHeaderL(RHTTPTransaction &aTransaction,
+		TCalDAVOptions &aOptions)
+	{
+	RStringF Header = aTransaction.Session().StringPool().OpenFStringL(ALLOW);
+	THTTPHdrVal HeaderVal;
+	if (aTransaction.Response().GetHeaderCollection().GetField(Header, 0,
+			HeaderVal) == KErrNone)
+		{
+		RStringF FieldValStr = aTransaction.Session().StringPool().StringF(
+				HeaderVal.StrF());
+		const TDesC8 &FieldValDesC = FieldValStr.DesC();
+		HBufC8 *FieldVal = FieldValDesC.AllocLC();
+		// delete all colons
+		TInt Pos = FieldVal->Find(colon);
+		while (Pos != KErrNotFound)
+			{
+			FieldVal->Des().Delete(Pos, 1);
+			Pos = FieldVal->Find(colon);
+			}
+		TLex8 Lex(FieldVal->Des());
+		TBool stop = EFalse;
+		while (!stop)
+			{
+			TPtrC8 Ptr = Lex.NextToken();
+			stop = Ptr.Length() == 0;
+			if (Ptr == DELETE)
+				aOptions.DELETE = ETrue;
+			else if (Ptr == GET)
+				aOptions.GET = ETrue;
+			else if (Ptr == HEAD)
+				aOptions.HEAD = ETrue;
+			else if (Ptr == MKCALENDAR)
+				aOptions.MKCALENDAR = ETrue;
+			else if (Ptr == MKCOL)
+				aOptions.MKCOL = ETrue;
+			else if (Ptr == OPTIONS)
+				aOptions.OPTIONS = ETrue;
+			else if (Ptr == PROPFIND)
+				aOptions.PROPFIND = ETrue;
+			else if (Ptr == PROPPATCH)
+				aOptions.PROPPATCH = ETrue;
+			else if (Ptr == PUT)
+				aOptions.PUT = ETrue;
+			else if (Ptr == REPORT)
+				aOptions.REPORT = ETrue;
+			else if (Ptr == COPY)
+				aOptions.COPY = ETrue;
+			else if (Ptr == POST)
+				aOptions.POST = ETrue;
+			else if (Ptr == MOVE)
+				aOptions.MOVE = ETrue;
+			else if (Ptr == ACL)
+				aOptions.ACL = ETrue;
+			else if (Ptr == LOCK)
+				aOptions.LOCK = ETrue;
+			else if (Ptr == UNLOCK)
+				aOptions.UNLOCK = ETrue;
+			}
+		CleanupStack::PopAndDestroy(FieldVal);
+		}
+	Header.Close();
+	}
+
+/**
+ * CalDavUtils::ScanDAVHeaderL
+ * scan DAV header
+ */
+void CalDavUtils::ScanDAVHeaderL(RHTTPTransaction &aTransaction,
+		TCalDAVOptions &aOptions)
+	{
+	RStringF Header = aTransaction.Session().StringPool().OpenFStringL(DAV);
+	THTTPHdrVal aHeaderVal;
+	if (aTransaction.Response().GetHeaderCollection().GetField(Header, 0,
+			aHeaderVal) == KErrNone)
+		{
+		RStringF FieldValStr = aTransaction.Session().StringPool().StringF(
+				aHeaderVal.StrF());
+		const TDesC8 &FieldValDesC = FieldValStr.DesC();
+		HBufC8 *FieldVal = FieldValDesC.AllocLC();
+		// delete all colons
+		TInt Pos = FieldVal->Find(colon);
+		while (Pos != KErrNotFound)
+			{
+			FieldVal->Des().Delete(Pos, 1);
+			Pos = FieldVal->Find(colon);
+			}
+		TLex8 Lex(FieldVal->Des());
+		TBool stop = EFalse;
+		while (!stop)
+			{
+			TPtrC8 Ptr = Lex.NextToken();
+			stop = Ptr.Length() == 0;
+			if (Ptr == ONE)
+				aOptions.ONE = ETrue;
+			else if (Ptr == TWO)
+				aOptions.TWO = ETrue;
+			else if (Ptr == THREE)
+				aOptions.THREE = ETrue;
+			else if (Ptr == access_control)
+				aOptions.access_control = ETrue;
+			else if (Ptr == calendar_access)
+				{
+				aOptions.calendar_access = ETrue;
+				// this is a CalDAV server for sure, MULTIGET and calendar-query is required
+				// we do not check for this anymore in CCaldavEngine::GetOptions()
+				aOptions.MULTIGET = ETrue;
+				aOptions.QUERY = ETrue;
+				}
+			else if (Ptr == calendar_schedule)
+				aOptions.calendar_schedule = ETrue;
+			else if (Ptr == calendar_auto_schedule)
+				aOptions.calendar_auto_schedule = ETrue;
+			else if (Ptr == sync_collection)
+				aOptions.sync_collection = ETrue;
+			else if (Ptr == extended_mkcol)
+				aOptions.extended_mkcol = ETrue;
+			}
+		CleanupStack::PopAndDestroy(FieldVal);
+		}
+	Header.Close();
+	}
+
+/**
+ * CalDavUtils::EnsureSlashL
+ * ensure trailing slash
+ */
+HBufC8* CalDavUtils::EnsureSlashL(HBufC8* aIn)
+	{
+	if ((aIn == NULL) || (aIn->Right(KSlash().Length()) == KSlash))
+		return aIn;
+	else
+		{
+		HBufC8 *out = HBufC8::NewL(aIn->Length() + KSlash().Length());
+		out->Des().Append(*aIn);
+		out->Des().Append(KSlash);
+		delete aIn;
+		aIn = NULL;
+		return out;
+		}
+	}
+
+/**
+ * CalDavUtils::EnsureSlashL
+ * ensure trailing slash
+ */
+HBufC8* CalDavUtils::EnsureSlashL(const TDesC8 &aIn)
+	{
+	HBufC8 *out = aIn.AllocL();
+	return CalDavUtils::EnsureSlashL(out);
+	}