pimappservices/calendar/client/src/calattachment.cpp
changeset 0 f979ecb2b13e
child 12 38571fd2a704
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pimappservices/calendar/client/src/calattachment.cpp	Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,600 @@
+// Copyright (c) 2006-2009 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:
+//
+
+#include "agmattachment.h"
+#include "calclient.h"
+#include "calsessionimpl.h"
+#include "calcommonimpl.h"
+
+
+/** Allocates and constructs a new file attachment from binary data.
+@param aBinaryData The attachment binary data. CCalAttachment takes ownership.
+@return A pointer to the new attachment.
+@leave KErrArgument If the aBinaryData parameter is NULL or if it points to an empty descriptor.
+Otherwise one of the system-wide error codes.
+@pre None
+@post A EFile attachment is created with the given binary data.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment* CCalAttachment::NewFileL(TDesC8* aBinaryData)
+	{
+	__ASSERT_ALWAYS(aBinaryData && aBinaryData->Length() > 0, User::Leave(KErrArgument));
+
+	CCalAttachment* self = new (ELeave) CCalAttachment();
+	CleanupStack::PushL(self);
+	self->ConstructL(EFile, aBinaryData);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/** Allocates and constructs a new file attachment from a file handle.
+The file will be moved to the Calendar store when the entry containing this attachment is stored. 
+To avoid the file being moved to the Calendar store, a copy should be made and a file handle to 
+the copy passed into this function.
+@param aFileHandle The handle to the attachment file. CCalAttachment will make a copy of the handel.
+The file handle must be opened using the mode EFileWrite and it should belong to a shared 
+file server session. 
+@see ShareProtected
+@return A pointer to the new attachment.
+@leave KErrAccessDenied If the file pointed to by this file handle is read only. 
+Otherwise one of the system-wide error codes.
+@panic If the file handle has not been initialised by calling RFs::Open.
+@pre None
+@post A EFile attachment is created with the given file handle.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment* CCalAttachment::NewFileL(RFile& aFileHandle)
+	{
+	CCalAttachment* self = new (ELeave) CCalAttachment();
+	CleanupStack::PushL(self);
+	self->ConstructL(EFile, NULL);
+	self->FileAttachment()->SetResourceL(aFileHandle);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/** Allocates and constructs a new file attachment with a content ID.
+Content IDs are only used during import and export. The actual attachment data is specified 
+by calling SetResourceL. 
+If an entry is stored which references an attachment that only has a content ID and no data, 
+then the StoreL function will leave with KErrArgument.
+@param aContentId A descriptor containing the content ID. CCalAttachment doesn't take ownership.
+@return A pointer to the new attachment.
+@leave KErrArgument if the parameter is an empty descriptor.
+Otherwise any of the system-wide error codes.
+@pre None
+@post A EFile attachment is created with the given content ID.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment* CCalAttachment::NewFileByContentIdL(const TDesC8& aContentId)
+	{
+	__ASSERT_ALWAYS(aContentId.Length() > 0, User::Leave(KErrArgument));
+	CCalAttachment* self = new (ELeave) CCalAttachment();
+	CleanupStack::PushL(self);
+	self->ConstructL(EFile, NULL);
+	self->FileAttachment()->SetContentIdL(aContentId);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/** Allocates and constructs a new URI attachment. URIs are defined in RFC 3986.
+@return A pointer to the new attachment.
+@param aUri A descriptor containing the attachment URI. CCalAttachment doesn't take ownership.
+@return A pointer to the new attachment.
+@leave KErrArgument if the parameter is an empty descriptor.
+Otherwise any of the system-wide error codes.
+@pre None
+@post A EUri attachment is created with the given data.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment* CCalAttachment::NewUriL(const TDesC8& aUri)
+	{
+	__ASSERT_ALWAYS(aUri.Length() > 0, User::Leave(KErrArgument));
+	CCalAttachment* self = new (ELeave) CCalAttachment();
+	CleanupStack::PushL(self);
+	HBufC8* uriCopy = aUri.AllocLC();
+	self->ConstructL(EUri, uriCopy);
+	CleanupStack::Pop(uriCopy);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CCalAttachment* CCalAttachment::NewL(CAgnAttachment& aAttachment, CCalSessionImpl& aSessionImpl)
+	{
+	CCalAttachment* self = new (ELeave) CCalAttachment(aAttachment);
+	CleanupStack::PushL(self);
+	self->CreateFileAttachmentImplIfRequiredL(&aSessionImpl);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CCalAttachment::CCalAttachment()
+	{
+	}
+
+CCalAttachment::CCalAttachment(CAgnAttachment& aAttachment) :
+	iAttachmentImpl(&aAttachment)
+	{
+	}
+	
+void CCalAttachment::ConstructL(TType aType, TDesC8* aData)
+	{
+	switch (aType)
+		{
+		case EFile:
+			iAttachmentImpl = AttachmentFactory::NewAttachmentL(CCalContent::EDispositionInline);
+			iAttachmentImpl->SetAttribute(EExportInline);
+			break;
+		case EUri:
+			iAttachmentImpl = AttachmentFactory::NewAttachmentL(CCalContent::EDispositionUrl);
+			break;
+		default:
+			CalUtils::Panic(EInvalidAttachmentType);
+		}
+	
+	iAttachmentImpl->SetFlag(CAgnAttachment::EOwnedByCalAttachment);
+	CreateFileAttachmentImplIfRequiredL(NULL);
+	
+	// must set data last because ownership is taken
+	if (aData)
+		{
+		iAttachmentImpl->SetValue(aData);
+		iAttachmentImpl->SetFlag(CAgnAttachment::EDataHasBeenSet);
+		}
+	}
+	
+void CCalAttachment::CreateFileAttachmentImplIfRequiredL(CCalSessionImpl* aSessionImpl)
+	{
+	if (Type() == EFile && !iFileAttachment)
+		{
+		iFileAttachment = new (ELeave) CCalAttachmentFile(*this, aSessionImpl);
+		}
+	}
+
+/** The destructor frees all resources owned by the attachment, prior to its destruction.
+@pre An attachment object has been constructed.
+@post The attachment object is destroyed.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment::~CCalAttachment()
+	{
+	if (iAttachmentImpl && iAttachmentImpl->FlagsSet(CAgnAttachment::EOwnedByCalAttachment))
+		{
+		delete iAttachmentImpl;
+		}
+	delete iFileAttachment;
+	}
+
+CAgnAttachment& CCalAttachment::Impl() const
+	{
+	ASSERT(iAttachmentImpl);
+	return *iAttachmentImpl;
+	}
+
+/**Get the type of the attachment, CCalAttachment::TType.
+@return The attachment type.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachment::TType CCalAttachment::Type() const
+	{
+	CCalAttachment::TType calType = CCalAttachment::EUri;
+	switch (iAttachmentImpl->Type())
+		{
+		case CCalContent::EDispositionUrl:
+			calType = CCalAttachment::EUri;
+			break;
+		case CCalContent::EDispositionInline:
+			calType = CCalAttachment::EFile;
+			break;
+		default:
+			CalUtils::Panic(EInvalidAttachmentType);
+			break;
+		}
+	return calType;
+	}
+
+/** Get the value of an attachment, as defined by the VALUE property in vCalendar / iCalendar (RFC 2445).
+Note that content IDs are exported as part the VALUE property, but these are not accessible through this function.
+@return For EUri types, this returns the URI.
+For EFile types, this returns the binary data of the attachment file if present. If the binary data is not present, 
+it may be loaded by calling CCalAttachmentFile::LoadBinaryDataL().
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C const TDesC8& CCalAttachment::Value() const
+	{
+	return iAttachmentImpl->Content();
+	}
+
+/** Set the value of the MIME type (RFC 2046).
+@param aMimeType The MIME type of the attachment.
+@leave KErrArgument If the MIME type is longer than KCalAttachmentMaxMimeTypeLength.
+@pre None
+@post The MIME type of this attachment has been updated.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachment::SetMimeTypeL(const TDesC8& aMimeType)
+	{
+	__ASSERT_ALWAYS(aMimeType.Length() <= KCalAttachmentMaxMimeTypeLength, User::Leave(KErrArgument));
+	iAttachmentImpl->SetMimeTypeL(aMimeType);
+	}
+
+/** Get the MIME type (RFC 2046).
+@return The MIME type of the attachment, or an empty descriptor if none has been set.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C const TDesC8& CCalAttachment::MimeType() const
+	{
+	return iAttachmentImpl->MimeType();
+	}
+
+/** Set the label for the attachment.
+The label is the user-visible name for the attachment. 
+It could be the filename, but does not have to be. Setting the label has no effect on the actual filename.
+@param aName The attachment label.
+@leave KErrArgument If the label is longer than KCalAttachmentMaxLabelLength.
+@pre None
+@post The attachment's label has been updated.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachment::SetLabelL(const TDesC& aName)
+	{
+	iAttachmentImpl->SetLabelL(aName);
+	}
+
+/** Get the label for the attachment.
+@return The label for the attachment, or an empty descriptor if none has been set.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C const TDesC& CCalAttachment::Label() const
+	{
+	return iAttachmentImpl->Label();
+	}
+
+/** Allow access to the file-specific functions of a file attachment.
+@return If this is a EFile attachment, return a pointer to CCalAttachmentFile. 
+The caller does not take ownership.
+Return NULL if this is a EUri attachment. 
+
+This function can be used to test whether an attachment has file-specific data, e.g.
+@code
+	CCalAttachment* attachment = entry->Attachment(aIndex);
+	
+	CCalAttachmentFile* attachmentFile = attachment->FileAttachment();
+	if (attachmentFile)
+		{
+		TInt attachSize = attachmentFile->Size();
+		...
+		}
+@endcode
+
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C CCalAttachmentFile* CCalAttachment::FileAttachment() const
+	{
+	return iFileAttachment;
+	}
+
+/** Sets attributes of an attachment.
+@param aAttribute The attribute or attributes to be set, as defined in CCalAttachment::TAttributes.
+@pre None
+@post The attachment's attribute data has been updated.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachment::SetAttribute(TUint16 aAttribute)
+	{
+	iAttachmentImpl->SetAttribute(aAttribute);
+	}
+
+/** Clears attributes of an attachment.
+@param aAttribute The attribute or attributes to be cleared, as defined in CCalAttachment::TAttributes.
+@pre None
+@post The attachment's attribute data has been updated.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachment::ClearAttribute(TUint16 aAttribute)
+	{
+	iAttachmentImpl->ClearAttribute(aAttribute);
+	}
+
+/** Tests attributes of an attachment, as defined in CCalAttachment::TAttributes.
+@param aAttribute The attribute or attributes to be tested.
+@return ETrue if the attachment has all these attributes. Otherwise EFalse.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C TBool CCalAttachment::IsAttributeSet(TUint16 aAttribute) const
+	{
+	return iAttachmentImpl->IsAttributeSet(aAttribute);
+	}
+
+// CCalAttachmentFile //
+
+CCalAttachmentFile::CCalAttachmentFile(CCalAttachment& aAttachment, CCalSessionImpl* aCalSessionImpl) 
+	{
+	__ASSERT_ALWAYS(aAttachment.Type() == CCalAttachment::EFile, CalUtils::Panic(EInvalidAttachmentType));
+	iAttachmentImpl = static_cast<CAgnAttachmentFile*>(&aAttachment.Impl());
+	
+	iCalSessionImpl = aCalSessionImpl;
+	if (iCalSessionImpl)
+		{
+		iCalSessionImpl->IncrementReferenceCount();
+		}
+	}
+
+CCalAttachmentFile::~CCalAttachmentFile()
+	{
+	if (iCalSessionImpl)
+		{
+		iCalSessionImpl->DecrementReferenceCount();
+		}
+	}
+
+/** Set the content ID of a file attachment. 
+The content ID is only used during import / export of attachments.
+@param aContentId The content ID.
+@pre None
+@post The attachment's content ID has been set.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachmentFile::SetContentIdL(const TDesC8& aContentId)
+	{
+	iAttachmentImpl->SetContentIdL(aContentId);
+	}
+	
+/** Fetch the content ID of a file attachment.
+Note that the content ID of an entry is not stored in the calendar store. Content IDs are intended to 
+be used on import / export only.
+@return The content ID. This will be an empty descriptor if no content ID has been set.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C const TDesC8& CCalAttachmentFile::ContentId() const
+	{
+	return iAttachmentImpl->ContentId();
+	}
+
+/** Set the drive on which to store a file attachment.
+The default value is the same as the current calendar file. 
+@param aDrive The drive on which to store a file attachment.
+The first character of the string specifies the drive letter. The second character, if present, must be a semi-colon.
+The following strings are all valid and will set the drive to D:
+"D"
+"D:"
+"D:\someFolder\someFile.ext"
+The drive letter can be given in either upper or lower case.
+@leave KErrArgument if the parameter is an empty descriptor, or if the first character is not a drive letter (A to Z), or if the 
+second character exists but is not the drive separator ':'.
+Otherwise any of the system-wide error codes.
+@pre None
+@post The attachment's drive has been set.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachmentFile::SetDriveL(const TDesC& aDrive)
+	{
+	__ASSERT_ALWAYS(aDrive.Length() > 0, User::Leave(KErrArgument));
+	TChar driveLetter = aDrive[0];
+	__ASSERT_ALWAYS(driveLetter.IsAlpha(), User::Leave(KErrArgument));
+
+	if (aDrive.Length() == 1)
+		{
+		TDriveName drive(aDrive);
+		drive.Append(':');
+		iAttachmentImpl->SetDriveL(drive);
+		}
+	else
+		{
+		__ASSERT_ALWAYS(aDrive[1] == ':', User::Leave(KErrArgument));
+		iAttachmentImpl->SetDriveL(aDrive);	
+		}
+	}
+
+/** Get the drive on which a file attachment is stored.
+The default value is the same as the current calendar file.
+@return The drive containing the file attachment.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C TDriveName CCalAttachmentFile::Drive() const
+	{
+	return iAttachmentImpl->Drive();
+	}
+
+/** Get the size of the attachment in bytes. 
+This is the same as the size of the attachment file.
+@return The size in bytes.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C TInt CCalAttachmentFile::Size() const
+	{
+	return iAttachmentImpl->Size();
+	}
+
+/** Set the last modified time of an attachment file.
+The user is responsible for setting the last modified time.
+@param aUtcTime The last modified time in UTC. 
+@pre None
+@post The attachment's last modified time has been set.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachmentFile::SetLastModifiedTimeUtc(const TTime& aUtcTime)
+	{
+	return iAttachmentImpl->SetLastModifiedTimeUtc(aUtcTime);
+	}
+
+/** Get the last modified time of a file attachment.
+The user is responsible for setting the last modified time.
+@return The last modified time of the attachment file in UTC.
+@pre None
+@post None
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C const TTime& CCalAttachmentFile::LastModifiedTimeUtc() const
+	{
+	return iAttachmentImpl->LastModifiedTimeUtc();
+	}
+
+/** Sets an attachment's data from a file handle.
+@param aFileHandle The handle to the attachment file. CCalAttachmentFile will make copy of "aFileHandle"
+The file handle must be opened using the mode EFileWrite and it should belong to a shared file server session. 
+@see ShareProtected
+@leave KErrAccessDenied If the file pointed to by this file handle is read only. 
+@leave KErrArgument If this attachment's data has already been set or if the attachment was not created from a content ID.
+Otherwise any of the system-wide error codes.
+@panic If the file handle has not been initialised by calling RFs::Open.
+@pre This attachment has been created from a content ID, and SetResourceL has not been called previously.
+@post The attachment takes ownership of the given file handle.
+@publishedPartner
+@released
+@capability None
+*/
+EXPORT_C void CCalAttachmentFile::SetResourceL(RFile& aFileHandle)
+	{
+	TUint attValue = 0;
+	
+	// Panics if the file handle is invalid:
+	User::LeaveIfError(aFileHandle.Att(attValue));
+	if (attValue & KEntryAttReadOnly)
+		{
+		User::Leave(KErrAccessDenied);
+		}
+	
+	if (iAttachmentImpl->FlagsSet(CAgnAttachment::EDataHasBeenSet))
+		{
+		User::Leave(KErrArgument);
+		}
+	else
+		{
+		iAttachmentImpl->CopyFileHandle(aFileHandle);
+		}
+	}
+
+/** Fetch the file handle for this attachment.
+If a new file handle has been set but the attachment has not been stored, nothing happens.
+@param aFileHandle On return, this file handle will point to the attachment file in the calendar store.
+@leave KErrArgument If this attachment has not been fetched from the calendar store.
+@leave KErrNotFound If the attachment has been deleted from the calendar store.
+@leave KErrNotReady If the attachment file is on a drive where the media has been removed.
+Otherwise any of the system-wide error codes.
+@pre The calendar attachment has been fetched from the calendar store.
+@post None
+@publishedPartner
+@released
+@capability ReadUserData
+*/
+EXPORT_C void CCalAttachmentFile::FetchFileHandleL(RFile& aFileHandle) const
+	{
+	if (iAttachmentImpl->IsFileHandleSet() || ! iCalSessionImpl)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	iCalSessionImpl->Server().FetchFileHandleL(aFileHandle, iAttachmentImpl->Uid(), iCalSessionImpl->FileId());
+	}
+
+/** Load the binary data into the attachment object to be accessed through the CCalAttachment::Value function.
+Note that binary data can be very large so this may use up a lot of RAM.
+If binary data has already been loaded, this function will do nothing. In that case, CCalAttachment::Value will 
+return a non-empty descriptor.
+@leave KErrArgument If this attachment has not been fetched from the calendar store.
+@leave KErrNotFound If the attachment has been deleted from the calendar store.
+@leave KErrNotReady If the attachment file is on a drive where the media has been removed.
+Otherwise any of the system-wide error codes.
+@pre A file attachment object has been fetched from the calendar store.
+@post The attachment object owns a copy of the binary data from the calendar store.
+@publishedPartner
+@released
+@capability ReadUserData
+*/
+EXPORT_C void CCalAttachmentFile::LoadBinaryDataL()
+	{
+	if (iAttachmentImpl->Content().Length() == 0)
+		{
+		// if no binary data present, try to fetch it from the file directly
+		RFile fileHandle;
+		FetchFileHandleL(fileHandle);
+		CleanupClosePushL(fileHandle);
+
+		TInt size;
+		User::LeaveIfError(fileHandle.Size(size));
+		HBufC8* data = HBufC8::NewLC(size);
+		TPtr8 ptr = data->Des();
+		User::LeaveIfError(fileHandle.Read(ptr));
+
+		CleanupStack::Pop(data);
+		CleanupStack::PopAndDestroy(&fileHandle); // fileHandle.Close
+
+		// store binary data in attachment
+		iAttachmentImpl->SetValue(data);
+		}
+	}