diff -r 000000000000 -r 72b543305e3a mobilemessaging/unieditor/model/src/UniDataModel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobilemessaging/unieditor/model/src/UniDataModel.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,596 @@ +/* +* Copyright (c) 2005 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: +* Provides CUniDataModel class methods. +* +*/ + + + + +// ========== INCLUDE FILES ================================ + +#include +#include + +#include // TMsvEntry +#include +#include // Msgs Uids +#include // CBaseMtm +#include +#include +#include + +#include + +#include //Disk space check +#include + +#include +#include +#include + +// Features +#include +#include +#include + +// MsgMedia +#include +#include +#include +#include + +#include + +#include "UniDataModel.h" +#include "UniSmilModel.h" + +#include "UniDataUtils.h" +#include "UniModelConst.h" +#include "UniObjectList.h" +#include "UniSmilList.h" +#include "UniObject.h" +#include "UniTextObject.h" +#include "UniMimeInfo.h" + +#include "UniSmilUtils.h" +#include "UniEditorLogging.h" + +// ========== CONSTANTS ==================================== + +// --------------------------------------------------------- +// CUniDataModel::Constructor +// --------------------------------------------------------- +// +CUniDataModel::CUniDataModel( RFs& aFs, CBaseMtm& aMtm ) : + iFs( aFs ), + iMtm( aMtm ), + iSmilModel( NULL ), + iDom( NULL ) + { + } + +// --------------------------------------------------------- +// CUniDataModel::NewL +// --------------------------------------------------------- +// +EXPORT_C CUniDataModel* CUniDataModel::NewL( RFs& aFs, CBaseMtm& aMtm ) + { + CUniDataModel* self = new ( ELeave ) CUniDataModel( aFs, aMtm ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------- +// CUniDataModel::ConstructL +// --------------------------------------------------------- +// +EXPORT_C void CUniDataModel::ConstructL() + { + iDataUtils = CUniDataUtils::NewL( iFs ); + iObjectList = CUniObjectList::NewL( iMtm, *iDataUtils ); + iAttachmentList = CUniObjectList::NewL( iMtm, *iDataUtils ); + iSmilList = CUniSmilList::NewL( iMtm ); + iSmilModel = CUniSmilModel::NewL( iFs, iMtm, *iDataUtils, *iObjectList ); + + iMediaResolver = CMsgMediaResolver::NewL(); + iMediaResolver->SetCharacterSetRecognition( EFalse ); + + iMmsConformance = CMmsConformance::NewL(); + iMmsConformance->CheckCharacterSet( EFalse ); + } + +// --------------------------------------------------------- +// CUniDataModel::~CUniDataModel +// +// Destructor. +// --------------------------------------------------------- +// +EXPORT_C CUniDataModel::~CUniDataModel() + { + delete iMediaResolver; + delete iMmsConformance; + delete iSmilModel; + delete iObjectList; + delete iAttachmentList; + delete iSmilList; + delete iDataUtils; + delete iParser; + delete iDom; + } + +// --------------------------------------------------------- +// CUniDataModel::RestoreL +// +// Initialise the model. +// --------------------------------------------------------- +// +EXPORT_C void CUniDataModel::RestoreL( + MUniDataModelObserver& aObserver, + TBool aRemoveCorrupted /*= ETrue*/, + TBool aAllowSmil /*= ETrue*/ ) + { + iObserver = &aObserver; + iSmilType = ENoSmil; + + if ( iMtm.Entry().HasStoreL() ) + { + FindAndHandleCorruptL( aRemoveCorrupted ); + + TBool readOnly = iMtm.Entry().Entry().ReadOnly(); + CMsvStore* store = readOnly + ? iMtm.Entry().ReadStoreL() + : iMtm.Entry().EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + CMsvMimeHeaders* msvMime = CMsvMimeHeaders::NewLC(); + + iParseResult = 0; + + iOrigAttachmentCount = manager.AttachmentCount(); + + for ( TInt i = 0; i < iOrigAttachmentCount ; i++ ) + { + CMsvAttachment* attachment = manager.GetAttachmentInfoL( i ); + CleanupStack::PushL( attachment ); + msvMime->RestoreL( *attachment ); + + TBuf8 contentType; + contentType.Copy( msvMime->ContentType() ); + contentType.Append( _L8("/") ); + contentType.Append( msvMime->ContentSubType() ); + + // Put smil attas to own array, except if SendUi + if ( aAllowSmil && + contentType.CompareF( KMsgMimeSmil ) == 0 ) + { + iSmilList->AddSmilAttachmentL( manager, attachment->Id() ); + CleanupStack::PopAndDestroy( attachment ); + continue; + } + + RFile readFile = manager.GetAttachmentFileL( i ); + CleanupClosePushL( readFile ); + CUniObject* newObj = CreateObjectFromAttachmentLC( + contentType, + readFile, + manager, + *attachment ); + + if ( newObj->Attachment() ) + { + iAttachmentList->AddObjectL( newObj ); + } + else + { + iObjectList->AddObjectL( newObj ); + } + + CleanupStack::Pop( newObj ); + CleanupStack::PopAndDestroy( &readFile ); + CleanupStack::PopAndDestroy( attachment ); + } // for + + CleanupStack::PopAndDestroy( msvMime ); + + + + UNILOGGER_WRITE_TIMESTAMP("CUniDataModel::RestoreL commit start"); + + if ( !readOnly && iOrigAttachmentCount > 0 ) + { + store->CommitL(); + } + + UNILOGGER_WRITE_TIMESTAMP("CUniDataModel::RestoreL commit end"); + CleanupStack::PopAndDestroy( store ); + + if ( iSmilList->Count() == 1 ) + { + RFile smilFile = iDataUtils->GetAttachmentFileL( iMtm, iSmilList->GetSmilAttachmentByIndex( 0 ) ); + iParser = CMDXMLParser::NewL( this ); + iParser->ParseFile( smilFile ); + } + else + { + if ( iSmilList->Count() > 1 ) + { + iSmilType = EMultipleSmil; + } + iParseResult = iSmilModel->ParseL( NULL ); // Try to create something anyway + FinalizeRestoreL( KErrNone ); + } + } + else + { + FinalizeRestoreL( KErrNone ); + } + } + +// --------------------------------------------------------- +// CUniDataModel::AddAttachmentL +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniDataModel::AddAttachmentL( + MUniObjectSaveObserver& aObserver, + CMsgMediaInfo* aMedia, + CMsvAttachment::TMsvAttachmentType aSaveType /*= CMsvAttachment::EMsvLinkedFile*/ ) + { + CUniObject* obj = CUniObject::NewLC( iFs, iMtm, *iDataUtils, aMedia ); + + // Update attachment list + iAttachmentList->AddObjectL( obj ); + obj->SetAttachment( ETrue ); + + CleanupStack::Pop( obj ); + obj->Save( aObserver, aSaveType ); + + return obj; + } + +// --------------------------------------------------------- +// CUniDataModel::AddStoredAttachmentL +// --------------------------------------------------------- +// +EXPORT_C CUniObject* CUniDataModel::AddStoredAttachmentL( TMsvAttachmentId aAttachmentId, + CMsgMediaInfo* aMedia ) + { + CMsvStore* store = iMtm.Entry().EditStoreL(); + CleanupStack::PushL( store ); + + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL(); + CMsvAttachment* attachment = manager.GetAttachmentInfoL( aAttachmentId ); + CleanupStack::PushL( attachment ); + + CUniObject* obj = CUniObject::NewLC( iFs, iMtm, *iDataUtils, aMedia, manager, *attachment ); + + managerSync.ModifyAttachmentInfoL( attachment ); + CleanupStack::Pop( 2, attachment ); //obj, attachment + CleanupStack::PushL( obj ); + store->CommitL(); + + // Update attachment list + iAttachmentList->AddObjectL( obj ); + obj->SetAttachment( ETrue ); + + CleanupStack::Pop( obj ); + CleanupStack::PopAndDestroy( store ); + return obj; + } + +// --------------------------------------------------------- +// CUniDataModel::FinalizeMediaParse +// --------------------------------------------------------- +// +EXPORT_C void CUniDataModel::FinalizeMediaParse() + { + while ( iObjectToParse ) + { + iObjWait.Start(); + } + } + +// --------------------------------------------------------- +// CUniDataModel::MediaInfoParsed +// --------------------------------------------------------- +// +void CUniDataModel::MediaInfoParsed() + { + if ( iObjectToParse->MediaInfo()->Corrupt() ) + { + iObjectToParse->SetCorrupted( ETrue ); + } + ParseNextObject(); + if ( iObjWait.IsStarted() ) + { + iObjWait.AsyncStop(); + } + } + +// --------------------------------------------------------- +// CUniDataModel::ParseNextObject +// --------------------------------------------------------- +// +void CUniDataModel::ParseNextObject() + { + CUniObjectList* list = iObjectList; + + while ( list ) + { + for ( TInt i = 0; i < list->Count(); i++ ) + { + iObjectToParse = list->GetByIndex( i ); + if ( !iObjectToParse->MediaInfo()->Parsed() && + !iObjectToParse->MediaInfo()->ParseError() ) + { + RFile file; + TRAPD( error, file = iDataUtils->GetAttachmentFileL( iMtm, iObjectToParse->AttachmentId() ) ); + + if ( error == KErrNone ) + { + iObjectToParse->MediaInfo()->ParseInfoDetails( file, *( iMediaResolver->DRMHelper() ), *this ); + file.Close(); + return; + } + else + { + iObjectToParse->SetCorrupted( ETrue ); + file.Close(); + } + } + } + if ( list == iObjectList ) + { + list = iAttachmentList; + } + else + { + list = NULL; + } + } + iObjectToParse = NULL; + } + +// --------------------------------------------------------- +// CUniDataModel::ParseFileCompleteL +// --------------------------------------------------------- +// +void CUniDataModel::ParseFileCompleteL() + { + TRAPD( err, DoParseFileCompleteL() ); + FinalizeRestoreL( err ); + } + +// --------------------------------------------------------- +// CUniDataModel::DoParseFileCompleteL +// --------------------------------------------------------- +// +void CUniDataModel::DoParseFileCompleteL() + { + iDom = iParser->DetachXMLDoc(); + iSmilType = UniSmilUtils::GetSmilTypeL( iDom ); + if ( iSmilType == ENoSmil ) + { + iParseResult = iSmilModel->ParseL( NULL ); + } + else if ( iSmilType == EMmsSmil ) + { + TRAPD( err, ( iParseResult = iSmilModel->ParseL( iDom ) ) ); + if ( err ) + { + iSmilType = E3GPPSmil; + iParseResult = 0; + FindDomObjectRefCountsL(); + } + } + else + { + FindDomObjectRefCountsL(); + } + } + + +// --------------------------------------------------------- +// CUniDataModel::FinalizeRestoreL +// --------------------------------------------------------- +// +void CUniDataModel::FinalizeRestoreL( TInt aError ) + { + if ( !aError ) + { + // Won't leave. + FindAttachmentsL(); + } + iObserver->RestoreReady( iParseResult, aError ); + ParseNextObject(); + } + +// --------------------------------------------------------- +// CUniSmilModel::FindAttachmentsL +// +// +// --------------------------------------------------------- +// +void CUniDataModel::FindAttachmentsL() + { + for ( TInt i = iObjectList->Count(); --i >= 0; ) + { + CUniObject* obj = iObjectList->GetByIndex( i ); + if ( !obj->ReferenceCount() ) + { + //don't remove from store -> cannot leave + iObjectList->RemoveObjectL( obj, EFalse ); + iAttachmentList->AddObjectL( obj ); + obj->SetAttachment( ETrue ); + } + } + } + +// --------------------------------------------------------- +// FindAndHandleCorruptL +// +// --------------------------------------------------------- +void CUniDataModel::FindAndHandleCorruptL( TBool aRemoveCorrupted ) + { + CMsvEntrySelection* corSel = FindCorruptLC(); + iCorruptedCount = corSel->Count(); + + if ( iCorruptedCount > 0 ) + { + if ( aRemoveCorrupted ) + { + CMsvStore* store = iMtm.Entry().EditStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + MMsvAttachmentManagerSync& managerSync = store->AttachmentManagerExtensionsL(); + + for (TInt i = iCorruptedCount; --i >= 0 ;) + { + // Editor tries to recover by deleting corrupted ones + // Note: This means that SMIL parsing will fail with ESmil_Missing_Objects. + // and object order is not maintained. But better to do it this + // way so that message can be opened. + TRAP_IGNORE ( managerSync.RemoveAttachmentL( + CUniDataUtils::IndexPositionOfAttachmentL( manager, corSel->At( i ) ) ) ); + } + store->CommitL(); + CleanupStack::PopAndDestroy( store ); + } + else + { + // In viewer case consider message corrupted and leave. + // Model not made viewer should exit. + User::Leave( KErrCorrupt ); + } + } + + CleanupStack::PopAndDestroy( corSel ); + } + +// --------------------------------------------------------- +// FindCorruptLC +// +// --------------------------------------------------------- +CMsvEntrySelection* CUniDataModel::FindCorruptLC() + { + CMsvEntrySelection* corrupts = new(ELeave) CMsvEntrySelection(); + CleanupStack::PushL( corrupts ); + + if ( iMtm.Entry().HasStoreL() ) + { + CMsvStore* store = iMtm.Entry().ReadStoreL(); + CleanupStack::PushL( store ); + MMsvAttachmentManager& manager = store->AttachmentManagerL(); + + TInt count = manager.AttachmentCount(); + for( TInt i = count; --i >= 0; ) + { + CMsvAttachment* atta = manager.GetAttachmentInfoL( i ); + TMsvAttachmentId attaId = atta->Id(); + delete atta; + + RFile attaFile; + TRAPD( err, attaFile = manager.GetAttachmentFileL( attaId ) ); + // if error, hardly no need to close + attaFile.Close(); + if ( err ) + { + corrupts->AppendL( attaId ); + } + } + + CleanupStack::PopAndDestroy( store ); + } + return corrupts; + } + +// --------------------------------------------------------- +// CreateObjectFromAttachmentLC +// +// --------------------------------------------------------- +CUniObject* CUniDataModel::CreateObjectFromAttachmentLC( + const TPtrC8& aMimeType, + RFile& aFile, + MMsvAttachmentManager& aManager, + CMsvAttachment& aAttachment ) + { + // Linked attachments are handles similarly as ordinary ones. + CUniObject* object = NULL; + CMsgMediaInfo* info = NULL; + if ( aMimeType.CompareF( KMsgMimeTextPlain ) == 0 ) + { + TDataType mimeType( aMimeType ); + info = iMediaResolver->CreateMediaInfoL( aFile, mimeType ); + } + else + { + info = iMediaResolver->CreateMediaInfoL( aFile ); + } + + if ( info->MediaType() == EMsgMediaText || + info->MediaType() == EMsgMediaXhtml ) + { + object = CUniTextObject::NewLC( + iFs, + iMtm, + *iDataUtils, + static_cast< CMsgTextInfo* >( info ), + aManager, + aAttachment ); + } + else + { + object = CUniObject::NewLC( + iFs, + iMtm, + *iDataUtils, + info, + aManager, + aAttachment ); + } + // Media info is to be parsed asynchronously! + + return object; + } + +// --------------------------------------------------------- +// GetDomObjectRefCounts +// +// --------------------------------------------------------- +void CUniDataModel::FindDomObjectRefCountsL() + { + CMDXMLNode* node = iDom->DocumentElement()->FirstChild(); + CUniObject* obj = NULL; + + while ( node ) + { + if ( UniSmilUtils::IsMediaElem( node ) ) // Filtering of structural nodes. + { + obj = iObjectList->GetByNodeL( node ); + if ( obj ) + { + obj->SetReferenceCount( obj->ReferenceCount() + 1 ); + } + + } + node = UniSmilUtils::NextNode( node ); + } + + } + +// End of File