// --------------------------------------------------------- // CUniObjectList::EnsureAllObjectsHaveContentLocationL // // EnsureAllObjectsHaveContentLocationL // --------------------------------------------------------- // EXPORT_C void CUniObjectList::EnsureAllObjectsHaveContentLocationL() { CMsvStore* store = iMtm.Entry().EditStoreL(); CleanupStack::PushL( store ); MMsvAttachmentManager& manager = store->AttachmentManagerL(); MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL(); TBool commit( EFalse ); TInt a = iObjectArray->Count(); while ( a-- ) { CUniObject* obj = iObjectArray->At( a ); if ( !obj->MimeInfo()->ContentLocation().Length() && obj->AttachmentId( ) ) { CMsvAttachment* attachment = manager.GetAttachmentInfoL( obj->AttachmentId() ); CleanupStack::PushL( attachment ); TParsePtrC parse( obj->MediaInfo()->FullFilePath() ); TPtrC nameAndExt( parse.NameAndExt() ); obj->MimeInfo()->EnsureContentLocationL( manager, *attachment, nameAndExt ); managerSync.ModifyAttachmentInfoL( attachment ); CleanupStack::Pop( attachment ); commit = ETrue; } } if ( commit ) { store->CommitL(); } CleanupStack::PopAndDestroy( store ); }
// --------------------------------------------------------- // // --------------------------------------------------------- void CMmsAttachmentHandler::RemoveAttachmentL( TMsvAttachmentId aAttaId, CMsvStore& aStore ) { MMsvAttachmentManager& attaMan = aStore.AttachmentManagerL(); MMsvAttachmentManagerSync& attaManSync = aStore.AttachmentManagerExtensionsL(); // can only remove synchronously if index is known. TInt count = attaMan.AttachmentCount(); TInt i = count - 1; TBool found = EFalse; while ( i >= 0 && !found ) { CMsvAttachment* attachmentInfo = attaMan.GetAttachmentInfoL( i ); CleanupStack::PushL( attachmentInfo ); if ( attachmentInfo->Id() == aAttaId ) { found = ETrue; } else { i--; } CleanupStack::PopAndDestroy( attachmentInfo ); attachmentInfo = NULL; } if ( i >= 0 && found ) { attaManSync.RemoveAttachmentL( i ); } }
// // StoreL() - Store bookmarks as an attachment file // in the .eBM format. If the system runs out of memory while // the bookmarks are being written to the file, the file will be // deleted. For example, if 2 bookmarks have already been written // to the file, and the writing of the third bookmark fails, the // file will be deleted. Otherwise, a failure of file writing would // need to be handled differently from memory allocation failure. // void CWWWHotlistParser::StoreL(CMsvEntry& aEntry) { TInt numberOfItems = iHotlistItemList->Count(); if (numberOfItems>0) // Only create a file if there is something to save! { // Generate fileName from msgId and bookmark file extension. // The file name consists of the msgId in hex format // followed by .eBM. Sizeof operator returns the size of msgId // in bytes and each byte requires 2 hex digits to represent it, // hence sizeof is multipled by 2. Didn't want to make // fileNameLength constant because the size of TMsvId may change // in the future. TMsvId entryId = aEntry.Entry().Id(); TInt fileNameLength = 2*sizeof(entryId) + KEBookmarkExtension().Length(); HBufC *fileName = HBufC::NewLC(fileNameLength); TPtr fileNameDes = fileName->Des(); // The file name uses the hex representation of the entry Id. // If this changes to some other representation then // fileNameLength will need to be calculated differently. fileNameDes.Num(entryId,EHex); fileNameDes.Append(KEBookmarkExtension); // Get the attachment manager and create an empty attachment file CMsvStore* store = aEntry.EditStoreL(); CleanupStack::PushL(store); MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL(); CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); CleanupStack::PushL(attachment); attachment->SetAttachmentNameL(*fileName); RFile file; managerSync.CreateAttachmentL(*fileName, file, attachment); CleanupStack::Pop(attachment); // ownership passed CleanupClosePushL(file); #ifdef SYMBIAN_BOOKMARK_DATABASE // Open the bookmark database ready to add the bookmarks RBkDatabase bookmarkDb; bookmarkDb.OpenL(); CleanupClosePushL(bookmarkDb); #endif // SYMBIAN_BOOKMARK_DATABASE // Stream each bookmark into the file. // The eBookmark file must contain only 8bit ascii. // Add a linefeed to the end of each line. for(TInt count=0; count < numberOfItems; count++) { CWWWHotlistItem &item = *iHotlistItemList->At(count); // Allocate enough space to hold the full bookmark entry. TInt length = item.Name().Length() + item.Url().Length() + KEBookmarkConstantChars; HBufC8 *writeBuf = HBufC8::NewLC(length); TPtr8 des = writeBuf->Des(); des.Append(KEBookmarkItemBegin); des.Append(KEBookmarkItemURL); des.Append(item.Url()); des.Append(KCRLinefeed); des.Append(KEBookmarkItemName); des.Append(item.Name()); des.Append(KCRLinefeed); des.Append(KEBookmarkType); des.Append(KEBookmarkItemEnd); User::LeaveIfError(file.Write(des)); CleanupStack::PopAndDestroy(); #ifdef SYMBIAN_BOOKMARK_DATABASE // Add the bookmark to the bookmark database RBkBookmark bookmark = bookmarkDb.CreateBookmarkL(); CleanupClosePushL(bookmark); bookmark.SetTitleL(item.Name()); // Convert Uri to 8-bit HBufC8* bookmarkUri = HBufC8::NewLC(item.Url().Length()); bookmarkUri->Des().Copy(item.Url()); bookmark.SetUriL(*bookmarkUri); CleanupStack::PopAndDestroy(2, &bookmark); // bookmarkUri, bookmark #endif // SYMBIAN_BOOKMARK_DATABASE } #ifdef SYMBIAN_BOOKMARK_DATABASE // Commit all the added bookmarks and close bookmark db bookmarkDb.CommitL(); CleanupStack::PopAndDestroy(&bookmarkDb); #endif // SYMBIAN_BOOKMARK_DATABASE // File writing has completed, set the size in the attachment TInt fileSize = 0; User::LeaveIfError(file.Size(fileSize)); attachment->SetSize(fileSize); // commit the changes store->CommitL(); CleanupStack::PopAndDestroy(3, fileName); // file, store, fileName } }
// --------------------------------------------------------- // CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL // --------------------------------------------------------- EXPORT_C void CMmsAttachmentHandler::CreateUTF8TextAttachmentFromFileL( CMsvStore& aStore, TMsvAttachmentId& aAttachmentId, RFile& aFile, RFs& aFs, TDriveUnit aMessageDrive ) { _LIT8 ( KMmsCrLf8, "\x00D\x00A" ); // 8 bit line feed TInt size = 0; TInt error = KErrNone; error = aFile.Size( size ); User::LeaveIfError( error ); // if can't get file size, we are in trouble TFileName* filename = new( ELeave ) TFileName; CleanupStack::PushL( filename ); // 256 characters for each read HBufC* textBuffer = HBufC::NewL( KMmsTextBufferSize ); CleanupStack::PushL( textBuffer ); TPtr textPtr = textBuffer->Des(); HBufC8* buffer = HBufC8::NewL( KMmsTextBufferSize * KMmsMaxBytesPerCharacter ); // paranoid. TInt fileSize = 0; // we don't know how big the file will be after conversion CleanupStack::PushL( buffer ); TPtr8 buf8 = buffer->Des(); CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); CleanupStack::PushL( mimeHeaders ); // attaInfo must be on top of stack because the ownership will be transferred // to attacment manager. CMsvAttachment* attaInfo = CMsvAttachment::NewL( CMsvAttachment::EMsvFile ); CleanupStack::PushL( attaInfo ); TPtrC8 contentType; contentType.Set( KMmsTextPlain ); TInt position = contentType.Find( KMmsSlash8 ); mimeHeaders->SetContentTypeL( contentType.Left( position ) ); mimeHeaders->SetContentSubTypeL( contentType.Mid( position + 1 ) ); attaInfo->SetMimeTypeL( contentType ); filename->Copy( TPtrC() ); aFile.Name( *filename ); // if this returns error, filename should be empty - no suggestion. attaInfo->SetAttachmentNameL( *filename ); mimeHeaders->SetSuggestedFilenameL( *filename ); mimeHeaders->SetMimeCharset( KMmsUtf8 ); if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( &aFs, size * KMmsUnicodeToUtf2MaxIncrease + mimeHeaders->Size() + KMmsIndexEntryExtra, aMessageDrive ) ) { // we use standard error code here User::Leave( KErrDiskFull ); } mimeHeaders->StoreL( *attaInfo ); // Mime headers are streamed into atta info MMsvAttachmentManagerSync& attaManSync = aStore.AttachmentManagerExtensionsL(); RFile attaFile; attaManSync.CreateAttachmentL( *filename, attaFile, attaInfo ); CleanupStack::Pop( attaInfo ); // attaInfo ownership was transferred. aAttachmentId = attaInfo->Id(); // Now our file handle is open for writing error = KErrNone; TMmsFileText textFile; textFile.Set( aFile ); while ( error == KErrNone || error == KErrTooBig ) { error = textFile.Read( textPtr ); TBool appendCRLF = ETrue; if ( error == KErrTooBig ) { appendCRLF = EFalse; error = KErrNone; } if ( error != KErrEof ) { // if conversion fails, something is really seriously wrong error = CnvUtfConverter::ConvertFromUnicodeToUtf8( buf8, textPtr ); } if ( error == KErrNone ) { error = attaFile.Write( buf8 ); if ( error == KErrNone ) { fileSize += buf8.Length(); if ( appendCRLF ) { error = attaFile.Write( KMmsCrLf8 ); fileSize += KMmsLengthOfCRlf; // add length of carriage return/line feed } } } } if ( error == KErrEof ) { // end of file has been reached successfully error = KErrNone; } if ( error == KErrNone ) { error = attaFile.Flush(); } attaFile.Close(); if ( error != KErrNone ) { // Something went wrong when we tried to write our data. // We must delete the attachment as it does not contain the // intended data. RemoveAttachmentL( aAttachmentId, aStore ); aAttachmentId = 0; } else { // If data writing was successful, the amount of data written // is now stored in fileSize. // Attachment info structure must be updated MMsvAttachmentManager& attaMan = aStore.AttachmentManagerL(); attaInfo = attaMan.GetAttachmentInfoL( aAttachmentId ); CleanupStack::PushL( attaInfo ); attaInfo->SetSize( fileSize ); attaManSync.ModifyAttachmentInfoL( attaInfo ); // attachment manager now owns the attachment info CleanupStack::Pop( attaInfo ); // attaInfo } CleanupStack::PopAndDestroy( mimeHeaders ); CleanupStack::PopAndDestroy( buffer ); CleanupStack::PopAndDestroy( textBuffer ); CleanupStack::PopAndDestroy( filename ); User::LeaveIfError( error ); }
// --------------------------------------------------------- // CMmsAttachmentHandler::CreateTextAttachmentL // --------------------------------------------------------- EXPORT_C void CMmsAttachmentHandler::CreateTextAttachmentL( CMsvStore& aStore, TMsvAttachmentId& aAttachmentId, const TDesC& aText, const TDesC& aFile, RFs& aFs, TDriveUnit aMessageDrive, TBool aConvertParagraphSeparator /*= ETrue*/ ) { HBufC* convertedText = NULL; TPtrC text; if ( aConvertParagraphSeparator ) { convertedText = CMsgTextUtils::ConvertParagraphSeparatorsLC( aText ); text.Set( convertedText->Des() ); } else { text.Set( aText ); } const TInt KMmsMaxBytesPerCharacter = 4; // coverity[incorrect_multiplication][buffer_alloc] HBufC8* buffer = HBufC8::NewL( text.Length() * KMmsMaxBytesPerCharacter ); // paranoid. CleanupStack::PushL( buffer ); TPtr8 buf8 = buffer->Des(); CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); CleanupStack::PushL( mimeHeaders ); // attaInfo must be on top of stack because the ownership will be transferred // to attacment manager. CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); CleanupStack::PushL( attaInfo ); TPtrC8 contentType; contentType.Set( KMmsTextPlain ); TInt position = contentType.Find( KMmsSlash8 ); mimeHeaders->SetContentTypeL( contentType.Left( position ) ); mimeHeaders->SetContentSubTypeL( contentType.Mid( position + 1 ) ); attaInfo->SetMimeTypeL( contentType ); attaInfo->SetAttachmentNameL( aFile ); mimeHeaders->SetMimeCharset( KMmsUtf8 ); mimeHeaders->SetSuggestedFilenameL( aFile ); // if conversion fails, something is really seriously wrong TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8( buf8, text ); if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( &aFs, buf8.Length() + mimeHeaders->Size() + KMmsIndexEntryExtra, aMessageDrive ) ) { // we use standard error code here User::Leave( KErrDiskFull ); } else { User::LeaveIfError( error ); } attaInfo->SetSize( buf8.Length() ); mimeHeaders->StoreL( *attaInfo ); // Mime headers are streamed into atta info MMsvAttachmentManagerSync& attaManSync = aStore.AttachmentManagerExtensionsL(); RFile attaFile; attaManSync.CreateAttachmentL( aFile, attaFile, attaInfo ); CleanupStack::Pop( attaInfo ); // attaInfo ownership was transferred. aAttachmentId = attaInfo->Id(); // Now our file handle is open for writing if ( buf8.Length() > 0 ) { attaFile.Write( buf8 ); error = attaFile.Flush(); } attaFile.Close(); if ( error != KErrNone ) { // Something went wrong when we tried to write our data. // We must delete the attachment as it does not contain the // intended data. RemoveAttachmentL( aAttachmentId, aStore ); aAttachmentId = 0; } CleanupStack::PopAndDestroy( mimeHeaders ); CleanupStack::PopAndDestroy( buffer ); if ( convertedText ) { CleanupStack::PopAndDestroy( convertedText ); convertedText = NULL; } User::LeaveIfError( error ); }
// --------------------------------------------------------- // CMmsAttachmentHandler::CreateAttachmentL // --------------------------------------------------------- // EXPORT_C void CMmsAttachmentHandler::CreateAttachmentL( CMsvStore& aStore, RFile& aFile, RFs& aFs, TDriveUnit aMessageDrive, TDesC8& aMimeType, CMsvMimeHeaders& aMimeHeaders, CMsvAttachment* aAttachmentInfo, TMsvAttachmentId& aAttaId) { // The ownership of aAttachmentInfo will be transferred to attachment manager // We must keep it safe until that time CleanupStack::PushL( aAttachmentInfo ); // Check that sufficient disk space available // for attachment binary file and index entry TInt error = KErrNone; TInt fileSize = 0; error = aFile.Size( fileSize ); User::LeaveIfError( error ); aAttachmentInfo->SetSize( fileSize ); if ( aMimeHeaders.SuggestedFilename().Length() == 0 ) { TFileName name; error = aFile.Name( name ); if ( error == KErrNone ) { aMimeHeaders.SetSuggestedFilenameL( name ); } } if ( aMimeHeaders.SuggestedFilename().Length() > 0 ) { aAttachmentInfo->SetAttachmentNameL( aMimeHeaders.SuggestedFilename() ); } if ( aMimeType.Length() > 0 ) { aAttachmentInfo->SetMimeTypeL( aMimeType ); } // Check that sufficient disk space available // for attachment binary file and index entry // This does not include mime headers. // The mime headers are covered by KMmsIndexEntryExtra, // however the value may be too small, has to be checked. if ( TMmsGenUtils::DiskSpaceBelowCriticalLevelL( &aFs, fileSize + KMmsIndexEntryExtra, aMessageDrive ) ) { // we use standard error code here User::Leave( KErrDiskFull ); } if ( ( aMimeHeaders.ContentType().Length() == 0 || aMimeHeaders.ContentSubType().Length() == 0 ) && aMimeType.Length() > 0 ) { TInt position = aMimeType.Find( KMmsSlash8 ); if ( position > 0 ) { aMimeHeaders.SetContentTypeL( aMimeType.Left( position ) ); } if ( position < aMimeType.Length() - 1 ) { aMimeHeaders.SetContentSubTypeL( aMimeType.Mid( position + 1 ) ); } } MMsvAttachmentManagerSync& attaManSync = aStore.AttachmentManagerExtensionsL(); RFile attaFile; // ownership of aAttachmentInfo is transferred to attachment manager. attaManSync.CreateAttachmentL( aMimeHeaders.SuggestedFilename(), attaFile, aAttachmentInfo ); aAttaId = aAttachmentInfo->Id(); CleanupStack::Pop( aAttachmentInfo ); // attachment manager now owns aAttachmentInfo // If the previous call was successful, we can now write the data // We need a buffer because we read from one file and write to another CleanupClosePushL( attaFile ); if ( fileSize > 0 ) { // Greedy, but we don't try to swallow large files all in one piece // Small files may be handled in one piece HBufC8* buffer = HBufC8::NewL( Min( fileSize, KMms10kilos ) ); // Try to get at least 10 k CleanupStack::PushL( buffer ); TPtr8 ptr = buffer->Des(); ptr.SetLength( 1 ); // initialized to something larger that 0, size is adjusted later while( ptr.Length() > 0 && error == KErrNone ) { error = aFile.Read( ptr ); if ( ptr.Length() > 0 && error == KErrNone) { error = attaFile.Write( ptr ); } } if ( error == KErrNone ) { error = attaFile.Flush(); } CleanupStack::PopAndDestroy( buffer ); buffer = NULL; } // we must alway close CleanupStack::PopAndDestroy( &attaFile ); // close attaFile // Now actual datafile is ready. // We still have the atta info, and we must store the mimeheaders aMimeHeaders.StoreL( *aAttachmentInfo ); // Now all should be ready. // Caller must commit store (maybe headers still need to be changed, // or maybe several attachments are added before committing store) User::LeaveIfError( error ); }