/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// #include "msgstoresimpl.h" #include "folderimpl.h" #include "messageimpl.h" #using #include "EntryID.h" #include "ETable.h" #include "ESPropValue.h" #include "EMAPIFolder.h" #include "EMessage.h" #include "MsgStore.h" #include "MsgStoresPreloaded.h" #include "guard.h" #include "temp.h" #include "MsgStoreAdviseSink.h" #include "StringConvertion.h" #include "StringStream.h" #include "CharBuffer.h" #include "FormManager.h" #include "FormViewer.h" #include "AddrBook.h" #include "MailUser.h" #include "emapilib.h" EMAPILib::MsgStoreImpl::MsgStoreImpl( const MsgStoreSPtr& eMsgStore ) : MAPIPropImpl( eMsgStore.get() ) { _eMsgStore = eMsgStore.CloneOnHeap(); _pSink = NULL; } EMAPILib::MsgStoreImpl::~MsgStoreImpl() { } void EMAPILib::MsgStoreImpl::Dispose() { MAPIPropImpl::DisposeImpl(); TypeFactory::Delete( _eMsgStore ); _eMsgStore = NULL; } void EMAPILib::MsgStoreImpl::Advise( IMAPIListener* sink ) { CheckDisposed(); if ( _pSink != NULL ) { Unadvise(); } _pSink = MsgStoreAdviseSink::Create(); (*_eMsgStore)->Advise( _pSink ); _pSink->SetListener( sink ); } void EMAPILib::MsgStoreImpl::Unadvise() { CheckDisposed(); if ( _pSink != NULL ) { _pSink->Release(); } (*_eMsgStore)->Unadvise(); } bool EMAPILib::MsgStoreImpl::CreateNewMessage( String* subject, String* body, MailBodyFormat bodyFormat, ArrayList* recipients, ArrayList* attachments, int codePage ) { Debug::WriteLine( "MsgStoreImpl::CreateNewMessage" ); EMAPIFolderSPtr folder = (*_eMsgStore)->GetFolderForMessageCreation(); if ( folder.IsNull() ) { throw new System::ApplicationException( "Cannot get folder for message creation" ); return false; } EMessageSPtr message = folder->CreateMessage(); if ( message.IsNull() ) { Debug::WriteLine( "MsgStoreImpl::CreateNewMessage cannot CreateMessage" ); return false; } message->setStringProp( (int)PR_MESSAGE_CLASS, "IPM.Note" ); if ( subject != NULL ) { //Debug::WriteLine( subject ); message->setStringProp( (int)PR_SUBJECT, Temp::GetANSIString( subject )->GetChars() ); } if ( body != NULL ) { //Debug::WriteLine( body ); if ( EMAPILib::MailBodyFormat::PlainText == bodyFormat ) { message->writeStringStreamProp( (int)PR_BODY, Temp::GetANSIString( body )->GetChars(), body->get_Length() ); } else { ESPropValueSPtr maskProp = message->getSingleProp( (int)PR_STORE_SUPPORT_MASK ); int mask = maskProp->GetLong(); bool bSupportRTF = ( mask & (int)STORE_RTF_OK ) == 1; bSupportRTF = true; if ( bSupportRTF ) { StringStreamSPtr streamComp = message->openStreamPropertyToWrite( (int)PR_RTF_COMPRESSED ); if ( !streamComp.IsNull() ) { OutputDebugString( "Compressed RTF is open" ); StringStreamSPtr stream = streamComp->GetWrapCompressedRTFStream( (int)MAPI_MODIFY | ( (int)STORE_UNCOMPRESSED_RTF & mask ) ); if ( !stream.IsNull() ) { OutputDebugString( "Compressed RTF is wrapped" ); CharBufferSPtr buffer = stream->Html2Rtf( Temp::GetANSIString( body )->GetChars() ); stream->Write( buffer->GetRawChars(), buffer->Length() ); stream->Commit(); streamComp->Commit(); message->RTFSyncRTF(); message->setLongProp( (int)PR_MSG_EDITOR_FORMAT, (int)EDITOR_FORMAT_HTML ); message->setLongProp( (int)PR_INET_MAIL_OVERRIDE_FORMAT, (int)ENCODING_PREFERENCE | (int)ENCODING_MIME | (int)BODY_ENCODING_TEXT_AND_HTML ); if ( codePage != 0 ) { message->setLongProp( (int)0x3FDE0003, codePage ); } //message->writeStringStreamProp( (int)PR_BODY, "BEBE", 4 ); } } } else { OutputDebugString( "Try to write to PR_HTML" ); StringStreamSPtr streamComp = message->openStreamPropertyToWrite( (int)PR_BODY_HTML ); //PR_BODY_HTML if ( !streamComp.IsNull() ) { OutputDebugString( "PR_HTML is opened" ); streamComp->Write( Temp::GetANSIString( body )->GetChars(), body->get_Length() ); streamComp->Commit(); } message->setLongProp( (int)PR_MSG_EDITOR_FORMAT, (int)EDITOR_FORMAT_HTML ); message->setLongProp( (int)PR_INET_MAIL_OVERRIDE_FORMAT, (int)ENCODING_PREFERENCE | (int)ENCODING_MIME | (int)BODY_ENCODING_TEXT_AND_HTML ); } } } Debug::WriteLine( "OpenForm" ); if ( recipients != NULL ) { Temp::AddRecipients( message, (*_eMsgStore), recipients, MAPI_TO ); } if ( attachments != NULL ) { Temp::AttachFiles( message, attachments ); } (*_eMsgStore)->OpenForm( message, (int)EXCHIVERB_OPEN ); return true; } bool EMAPILib::MsgStoreImpl::IsStandartReply( const EMessageSPtr& eMessage ) { StringStreamSPtr streamComp = eMessage->openStreamProperty( (int)PR_RTF_COMPRESSED ); if ( !streamComp.IsNull() ) { StringStreamSPtr stream = streamComp->GetWrapCompressedRTFStream(); if ( !stream.IsNull() ) { stream->Read(); StringStream::Format format = stream->GetStreamFormat(); if ( format != StringStream::Format::PlainText ) { return true; } return false; } } CharBufferSPtr prHTML = eMessage->openStringProperty( (int)0x10130102 ); if ( !prHTML.IsNull() ) { return true; } return false; } bool EMAPILib::MsgStoreImpl::ReplyMessage( String* strEntryID, IEMsgStore* defaultMsgStore ) { return ReplyMessageImpl( strEntryID, (int)EXCHIVERB_REPLYTOSENDER, defaultMsgStore ); } bool EMAPILib::MsgStoreImpl::ReplyAllMessage( String* entryID, IEMsgStore* defaultMsgStore ) { return ReplyMessageImpl( entryID, (int)EXCHIVERB_REPLYTOALL, defaultMsgStore ); } bool EMAPILib::MsgStoreImpl::ReplyMessageImpl( String* strEntryID, int verbID, IEMsgStore* defaultMsgStore ) { CheckDisposed(); MsgStoreImpl* defMsgStoreImpl = dynamic_cast( defaultMsgStore ); MsgStoreSPtr defMsgStore = (*defMsgStoreImpl->_eMsgStore); EntryIDSPtr entryID = Helper::HexToEntryID( strEntryID ); EMessageSPtr eMessage = (*_eMsgStore)->OpenMessage( entryID ); if ( eMessage.IsNull() ) return false; if ( IsStandartReply( eMessage ) ) { EMessageSPtr msg; return (*_eMsgStore)->ActionMessage( entryID, verbID, msg, defMsgStore ); } EMAPIFolderSPtr folder = defMsgStore->GetFolderForMessageCreation(); if ( folder.IsNull() ) return false; EMessageSPtr newMessage = folder->CreateMessage(); if ( newMessage.IsNull() ) return false; CharBufferSPtr body = eMessage->openStringProperty( (int)PR_BODY ); String* str = String::Empty; if ( !body.IsNull() ) { str = new String( body->GetRawChars() ); } EMAPILib::IQuoting* quoter = EMAPILib::EMAPISession::GetQuoter(); if ( quoter != NULL ) { String* body = quoter->QuoteReply( str ); newMessage->writeStringStreamProp( (int)PR_BODY, Temp::GetANSIString( body )->GetChars(), body->get_Length() ); ESPropValueSPtr propSubj = eMessage->getSingleProp( (int)PR_NORMALIZED_SUBJECT ); String* subject = String::Empty; if ( !propSubj.IsNull() && propSubj->GetLPSTR() != NULL ) { subject = new String( propSubj->GetLPSTR() ); } String* reSubject = "RE: "; if ( !subject->StartsWith( reSubject ) ) { subject = String::Concat( reSubject, subject ); } newMessage->setStringProp( (int)PR_SUBJECT, Temp::GetANSIString( subject )->GetChars() ); } newMessage->SetConversation( eMessage ); ESPropValueSPtr propEmail = eMessage->getSingleProp( (int)PR_SENT_REPRESENTING_EMAIL_ADDRESS ); LPSTR email = NULL; if ( !propEmail.IsNull() ) { email = propEmail->GetLPSTR(); } ESPropValueSPtr propName = eMessage->getSingleProp( (int)PR_SENT_REPRESENTING_NAME ); LPSTR name = NULL; if ( !propName.IsNull() ) { name = propName->GetLPSTR(); } if ( name != NULL || email != NULL ) { ArrayList* replyToRecipients = new ArrayList(); replyToRecipients->Add( new EMAPILib::RecipInfo( name, email ) ); Temp::AddRecipients( newMessage, defMsgStore, replyToRecipients, MAPI_TO ); } if ( (int)EXCHIVERB_REPLYTOALL == verbID ) { ETableSPtr table = eMessage->GetRecipientsTable(); if ( !table.IsNull() ) { for ( int i = 0; i < table->GetRowCount(); ++i ) { ELPSRowSetSPtr row = table->GetNextRow(); ESPropValueSPtr prop = row->FindProp( PR_RECIPIENT_TYPE ); if ( !prop.IsNull() ) { newMessage->AddRecipient( row, MAPI_TO ); } } } } newMessage->setLongProp( (int)PR_MSG_EDITOR_FORMAT, (int)EDITOR_FORMAT_PLAINTEXT ); return (*_eMsgStore)->ActionMessage( entryID, (int)EXCHIVERB_OPEN, newMessage, defMsgStore ); //return (*_eMsgStore)->ActionMessage( Helper::HexToEntryID( strEntryID ), (int)EXCHIVERB_REPLYTOSENDER ); } bool EMAPILib::MsgStoreImpl::DisplayMessage( String* entryID, IEMsgStore* defaultMsgStore ) { CheckDisposed(); MsgStoreImpl* defMsgStoreImpl = dynamic_cast( defaultMsgStore ); MsgStoreSPtr defMsgStore = (*defMsgStoreImpl->_eMsgStore); EMessageSPtr msg; return (*_eMsgStore)->ActionMessage( Helper::HexToEntryID( entryID ), (int)EXCHIVERB_OPEN, msg, defMsgStore ); } bool EMAPILib::MsgStoreImpl::ForwardMessage( String* entryID, IEMsgStore* defaultMsgStore ) { CheckDisposed(); MsgStoreImpl* defMsgStoreImpl = dynamic_cast( defaultMsgStore ); MsgStoreSPtr defMsgStore = (*defMsgStoreImpl->_eMsgStore); EMessageSPtr msg; return (*_eMsgStore)->ActionMessage( Helper::HexToEntryID( entryID ), (int)EXCHIVERB_FORWARD, msg, defMsgStore ); } void EMAPILib::MsgStoreImpl::DeleteMessage( String* entryID, bool DeletedItems ) { CheckDisposed(); (*_eMsgStore)->DeleteMessage( Helper::HexToEntryID( entryID ), DeletedItems ); } void EMAPILib::MsgStoreImpl::DeleteFolder( String* entryID, bool DeletedItems ) { CheckDisposed(); (*_eMsgStore)->DeleteFolder( Helper::HexToEntryID( entryID ), DeletedItems ); } EMAPILib::IEFolder* EMAPILib::MsgStoreImpl::GetRootFolder() { CheckDisposed(); EMAPIFolderSPtr folder = (*_eMsgStore)->GetRootFolder(); if ( !folder.IsNull() ) { return new FolderImpl( folder ); } return NULL; } EMAPILib::IEMessage* EMAPILib::MsgStoreImpl::OpenMessage( String* entryID ) { CheckDisposed(); if ( entryID != NULL && entryID->get_Length() > 0 ) { EMessageSPtr message = (*_eMsgStore)->OpenMessage( Helper::HexToEntryID( entryID ) ); if ( !message.IsNull() ) { return new MessageImpl( message ); } } return NULL; } EMAPILib::IEFolder* EMAPILib::MsgStoreImpl::OpenFolder( String* entryID ) { CheckDisposed(); if ( entryID != NULL && entryID->get_Length() > 0 ) { EMAPIFolderSPtr folder = (*_eMsgStore)->OpenFolder( Helper::HexToEntryID( entryID ) ); if ( !folder.IsNull() ) { return new FolderImpl( folder ); } } return NULL; } EMAPILib::IEFolder* EMAPILib::MsgStoreImpl::OpenDraftsFolder() { CheckDisposed(); EMAPIFolderSPtr folder = (*_eMsgStore)->OpenDefaultFolder( PR_IPM_DRAFTS_ENTRYID ); if ( !folder.IsNull() ) { return new FolderImpl( folder ); } return NULL; } EMAPILib::IEFolder* EMAPILib::MsgStoreImpl::OpenTasksFolder() { CheckDisposed(); EMAPIFolderSPtr folder = (*_eMsgStore)->OpenDefaultFolder( PR_IPM_TASK_ENTRYID ); if ( !folder.IsNull() ) { return new FolderImpl( folder ); } return NULL; } String* EMAPILib::MsgStoreImpl::GetDefaultTaskFolderID() { CheckDisposed(); ETableSPtr table = (*_eMsgStore)->GetReceiveFolderTable(); if ( table.IsNull() || table->GetRowCount() == 0 ) return NULL; ELPSRowSetSPtr row = table->GetNextRow( ); if ( row.IsNull() ) return NULL; ESPropValueSPtr entryID = row->FindProp( (int)PR_ENTRYID ); if ( entryID.IsNull() ) return NULL; EMAPIFolderSPtr folder = (*_eMsgStore)->OpenFolder( entryID ); if ( folder.IsNull() ) return NULL; ESPropValueSPtr taskEntryID = folder->getSingleProp( (int)0x36D40102 );//PR_IPM_TASK_ENTRYID if ( !taskEntryID.IsNull() && taskEntryID->GetBinCB() > 0 ) { return Helper::EntryIDToHex( taskEntryID->GetBinLPBYTE(), taskEntryID->GetBinCB() ); } return NULL; } EMAPILib::MAPIIDs* EMAPILib::MsgStoreImpl::GetInboxIDs() { CheckDisposed(); ESPropValueSPtr prop = (*_eMsgStore)->getSingleProp( (int)PR_ENTRYID ); String* storeID = Helper::BinPropToString( prop ); if ( storeID == NULL ) { return NULL; } EMAPIFolderSPtr folder = (*_eMsgStore)->GetReceiveFolder( "IPM.Note" ); if ( folder.IsNull() ) { return NULL; } ESPropValueSPtr propEntryID = folder->getSingleProp( (int)PR_ENTRYID ); if ( propEntryID.IsNull() ) { return NULL; } String* entryID = Helper::EntryIDToHex( propEntryID->GetBinLPBYTE(), propEntryID->GetBinCB() ); if ( entryID == NULL ) { return NULL; } return new EMAPILib::MAPIIDs( storeID, entryID ); } EMAPILib::MsgStoresImpl::MsgStoresImpl( const MsgStoresSPtr& eMsgStores ) { if ( eMsgStores.IsNull() ) { Guard::ThrowArgumentNullException( "eMsgStores" ); } _eMsgStores = eMsgStores.CloneOnHeap(); } EMAPILib::MsgStoresImpl::~MsgStoresImpl() { } void EMAPILib::MsgStoresImpl::Dispose() { Disposable::DisposeImpl(); TypeFactory::Delete( _eMsgStores ); _eMsgStores = NULL; } EMAPILib::IEMsgStore* EMAPILib::MsgStoresImpl::GetMsgStore( int index ) { CheckDisposed(); if ( index >= GetCount() ) { Guard::ThrowArgumentOutOfRangeException( "index" ); } MsgStoreSPtr msgStore = (*_eMsgStores)->OpenStorage( index ); if ( !msgStore.IsNull() ) { return new MsgStoreImpl( msgStore ); } return NULL; } int EMAPILib::MsgStoresImpl::GetCount() { CheckDisposed(); return (*_eMsgStores)->GetCount(); } String* EMAPILib::MsgStoresImpl::GetStorageID( int index ) { CheckDisposed(); Debug::WriteLine( "EMAPILib::MsgStoresImpl::GetStorageID" ); Debug::WriteLine( __box( index ) ); Debug::WriteLine( __box( GetCount() ) ); if ( index >= GetCount() ) { Debug::WriteLine( "ERROR: index >= GetCount" ); throw new System::ApplicationException( "index >= GetCount" ); } LPSPropValue lpProp = (*_eMsgStores)->GetStorageID( index ); if ( lpProp != NULL ) { return Helper::EntryIDToHex( lpProp->Value.bin.lpb, lpProp->Value.bin.cb ); } return NULL; } String* EMAPILib::MsgStoresImpl::GetDisplayName( int index ) { CheckDisposed(); return new String( (*_eMsgStores)->GetDisplayName( index ) ); } bool EMAPILib::MsgStoresImpl::IsDefaultStore( int index ) { CheckDisposed(); return (*_eMsgStores)->IsDefaultStore( index ); }