// ---------------------------------------------------------
// 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 );
        }
    }
Пример #3
0
//
//  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 );
    }