diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/client/src/calattachment.cpp --- /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(&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); + } + }