1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: mailmodelapi.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
33 // includes --------------------------------------------------------------
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/frame/XFrame.hpp>
36 #include <com/sun/star/io/XActiveDataSink.hpp>
37 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
38 #include <com/sun/star/mozilla/XPluginInstance.hpp>
39 #include <com/sun/star/ucb/XDataContainer.hpp>
40 #include <com/sun/star/ucb/CommandAbortedException.hpp>
41 #include <com/sun/star/uno/Reference.h>
42 #include <com/sun/star/util/XURLTransformer.hpp>
43 #include <com/sun/star/frame/XStorable.hpp>
44 #include <com/sun/star/frame/XDispatchProvider.hpp>
45 #include <com/sun/star/frame/XDispatch.hpp>
46 #include <com/sun/star/util/XModifiable.hpp>
47 #include <com/sun/star/system/XSimpleMailClientSupplier.hpp>
48 #include <com/sun/star/system/SimpleMailClientFlags.hpp>
49 #include <com/sun/star/frame/XModuleManager.hpp>
50 #ifndef _RTL_TEXTENC_H
51 #include <rtl/textench.h>
53 #include <vos/mutex.hxx>
55 #include <rtl/uri.hxx>
56 #include <rtl/ustrbuf.hxx>
57 #include <unotools/streamhelper.hxx>
58 #include <unotools/configitem.hxx>
59 #include <comphelper/mediadescriptor.hxx>
60 #include <vos/thread.hxx>
61 #include <vcl/msgbox.hxx>
63 #include "mailmodelapi.hxx"
64 #include <sfx2/docfilt.hxx>
65 #include <sfx2/docfac.hxx>
66 #include "sfxtypes.hxx"
69 #include "sfxresid.hxx"
70 #include <sfx2/sfxuno.hxx>
71 #include <sfx2/fcontnr.hxx>
72 #include "guisaveas.hxx"
74 #include <unotools/tempfile.hxx>
75 #include <vcl/svapp.hxx>
76 #include <svtools/stritem.hxx>
77 #include <svtools/eitem.hxx>
78 #include <svtools/useroptions.hxx>
79 #include <comphelper/processfactory.hxx>
80 #include <comphelper/extract.hxx>
81 #include <ucbhelper/content.hxx>
82 #include <toolkit/helper/vclunohelper.hxx>
83 #include <tools/urlobj.hxx>
85 extern sal_Bool
GetPasswd_Impl( const SfxItemSet
* pSet
, String
& rPasswd
);
87 // --------------------------------------------------------------
88 using namespace ::com::sun::star::beans
;
89 using namespace ::com::sun::star::frame
;
90 using namespace ::com::sun::star::frame
;
91 using namespace ::com::sun::star::io
;
92 using namespace ::com::sun::star::lang
;
93 using namespace ::com::sun::star::mozilla
;
94 using namespace ::com::sun::star::ucb
;
95 using namespace ::com::sun::star::uno
;
96 using namespace ::com::sun::star::util
;
97 using namespace ::com::sun::star::system
;
98 using namespace ::rtl
;
102 // functions -------------------------------------------------------------
104 BOOL
CreateFromAddress_Impl( String
& rFrom
)
108 Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse
109 zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail'
110 aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder
111 nicht gesetzt sein, wird FALSE zur"uckgegeben.
115 TRUE: Adresse konnte erzeugt werden.
116 FALSE: Adresse konnte nicht erzeugt werden.
120 SvtUserOptions aUserCFG
;
121 String aName
= aUserCFG
.GetLastName ();
122 String aFirstName
= aUserCFG
.GetFirstName ();
123 if ( aFirstName
.Len() || aName
.Len() )
125 if ( aFirstName
.Len() )
127 rFrom
= TRIM( aFirstName
);
132 rFrom
+= TRIM( aName
);
133 // unerlaubte Zeichen entfernen
134 rFrom
.EraseAllChars( '<' );
135 rFrom
.EraseAllChars( '>' );
136 rFrom
.EraseAllChars( '@' );
138 String aEmailName
= aUserCFG
.GetEmail();
139 // unerlaubte Zeichen entfernen
140 aEmailName
.EraseAllChars( '<' );
141 aEmailName
.EraseAllChars( '>' );
143 if ( aEmailName
.Len() )
147 ( ( rFrom
+= '<' ) += TRIM( aEmailName
) ) += '>';
151 return ( rFrom
.Len() > 0 );
157 class OMailSendThreadImpl
: public ::vos::OThread
161 Reference
< XSimpleMailClient
> xSimpleMailClient
,
162 Reference
< XSimpleMailMessage
> xSimpleMailMessage
,
163 const Reference
< XFrame
>& _xCurrentFrame
,
165 m_nSendFlags( nSendFlags
),
166 m_bSend( sal_False
),
167 m_xSimpleMailClient( xSimpleMailClient
),
168 m_xSimpleMailMessage( xSimpleMailMessage
),
169 m_xCurrentFrame(_xCurrentFrame
) {}
171 virtual ~OMailSendThreadImpl();
173 virtual void SAL_CALL
run();
174 virtual void SAL_CALL
onTerminated();
179 Reference
< XSimpleMailClient
> m_xSimpleMailClient
;
180 Reference
< XSimpleMailMessage
> m_xSimpleMailMessage
;
181 Reference
< XFrame
> m_xCurrentFrame
;
184 OMailSendThreadImpl::~OMailSendThreadImpl()
188 void SAL_CALL
OMailSendThreadImpl::run()
192 m_xSimpleMailClient
->sendSimpleMailMessage( m_xSimpleMailMessage
, m_nSendFlags
);
195 catch ( IllegalArgumentException
& )
204 if ( m_bSend
== sal_False
)
206 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
207 Reference
< ::com::sun::star::awt::XWindow
> xParentWindow
= m_xCurrentFrame
->getContainerWindow();
208 Window
* pParentWindow
= VCLUnoHelper::GetWindow( xParentWindow
);
210 ErrorBox
aBox( pParentWindow
, SfxResId( RID_ERRBOX_MAIL_CONFIG
));
215 void SAL_CALL
OMailSendThreadImpl::onTerminated()
220 // class AddressList_Impl ------------------------------------------------
222 typedef String
* AddressItemPtr_Impl
;
223 DECLARE_LIST( AddressList_Impl
, AddressItemPtr_Impl
)
225 // class SfxMailModel -----------------------------------------------
227 void SfxMailModel::ClearList( AddressList_Impl
* pList
)
231 ULONG i
, nCount
= pList
->Count();
232 for ( i
= 0; i
< nCount
; ++i
)
233 delete pList
->GetObject(i
);
238 void SfxMailModel::MakeValueList( AddressList_Impl
* pList
, String
& rValueList
)
243 ULONG i
, nCount
= pList
->Count();
244 for ( i
= 0; i
< nCount
; ++i
)
246 if ( rValueList
.Len() > 0 )
248 rValueList
+= *pList
->GetObject(i
);
254 String
lcl_getFactoryName(const Reference
<XInterface
>& _xModel
)
256 rtl::OUString sModuleIdentifier
;
257 rtl::OUString sFactoryShortName
;
258 Reference
< XModuleManager
> xModuleManager( ::comphelper::getProcessServiceFactory()->createInstance(
259 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.ModuleManager")) ), UNO_QUERY
);
265 sModuleIdentifier
= xModuleManager
->identify( _xModel
);
267 catch ( ::com::sun::star::frame::UnknownModuleException
& )
269 DBG_WARNING( "SfxHelp::GetHelpModuleName_Impl(): unknown module (help in help?)" );
273 DBG_ERRORFILE( "SfxHelp::GetHelpModuleName_Impl(): exception of XModuleManager::identif y()" );
277 return sModuleIdentifier
;
280 String
lcl_createTempFileName(const Reference
< XModel
>& _xModel
,const ::rtl::OUString
& _sAttachmentTitle
)
282 // create temp file name with leading chars and extension
283 Reference
< XStorable
> xStor( _xModel
, UNO_QUERY
);
287 sal_Bool bHasName
= xStor
->hasLocation();
291 if ( _sAttachmentTitle
.getLength() )
292 aLeadingStr
= _sAttachmentTitle
;
294 aLeadingStr
= String( DEFINE_CONST_UNICODE("noname") );
298 INetURLObject
aFileObj(_xModel
->getURL());
299 if ( aFileObj
.hasExtension() )
301 aFileObj
.removeExtension();
302 if ( _sAttachmentTitle
.getLength() )
303 aLeadingStr
= _sAttachmentTitle
;
305 aLeadingStr
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
306 aLeadingStr
+= String::CreateFromAscii( "_" );
310 if ( _sAttachmentTitle
.getLength() )
311 aLeadingStr
= _sAttachmentTitle
;
313 aLeadingStr
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
);
314 aLeadingStr
+= String::CreateFromAscii( "_" );
322 SfxMailModel::SaveResult
SfxMailModel::SaveDocument( const ::rtl::OUString
& _sAttachmentTitle
323 , const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
>& _xModel
326 SaveResult eRet
= SAVE_CANCELLED
;
329 Reference
<XModifiable
> xMod(_xModel
,UNO_QUERY
);
336 BOOL bModified = xMod->isModified();
337 // prepare for mail export
339 SfxDispatcher* pDisp = pTopViewFrm->GetDispatcher();
340 pDisp->Execute( SID_MAIL_PREPAREEXPORT, SFX_CALLMODE_SYNCHRON );
343 const SfxFilter
* pFilter
= SfxFilter::GetDefaultFilter(lcl_getFactoryName(_xModel
));
344 // sal_Bool bHasFilter = pFilter != NULL;
346 sal_Bool bRet
= sal_False
;
347 // create temp file name with leading chars and extension
348 Reference
< XStorable
> xStor( _xModel
, UNO_QUERY
);
352 INetURLObject
aFileObj(_xModel
->getURL());
353 if ( aFileObj
.hasExtension() )
354 pExt
= new String( String::CreateFromAscii( "." ) + (OUString
) aFileObj
.getExtension() );
356 String aLeadingStr
= lcl_createTempFileName(_xModel
,_sAttachmentTitle
);
358 if ( pFilter
&& !pExt
)
360 pExt
= new String( pFilter
->GetWildcard()().GetToken(0) );
361 // erase the '*' from the extension (e.g. "*.sdw")
366 ::utl::TempFile
aTempFile( aLeadingStr
, pExt
);
367 rFileName
= aTempFile
.GetURL();
370 // save document to temp file
372 // save document to temp file
373 Sequence
< PropertyValue
> aArgs( _xModel
->getArgs() );
374 ::comphelper::MediaDescriptor
aMedia(aArgs
);
378 ::rtl::OUString
sFilter(pFilter
->GetFilterName());
379 ::rtl::OUString
sFilterName(RTL_CONSTASCII_USTRINGPARAM("FilterName"));
380 if ( !aMedia
.createItemIfMissing(sFilterName
,sFilter
) )
381 aMedia
[sFilterName
] <<= sFilter
;
384 ::rtl::OUString
sURL(RTL_CONSTASCII_USTRINGPARAM("URL"));
385 if ( !aMedia
.createItemIfMissing(sURL
,::rtl::OUString(rFileName
)) )
386 aMedia
[sURL
] <<= ::rtl::OUString(rFileName
);
388 ::rtl::OUString
sSaveTo(RTL_CONSTASCII_USTRINGPARAM("SaveTo"));
389 if ( !aMedia
.createItemIfMissing(sSaveTo
,sal_True
) )
390 aMedia
[sSaveTo
] <<= sal_True
;
392 ::rtl::OUString
sReadOnly(RTL_CONSTASCII_USTRINGPARAM("ReadOnly"));
393 if ( !aMedia
.createItemIfMissing(sReadOnly
,sal_False
) )
394 aMedia
[sReadOnly
] <<= sal_False
;
400 Reference
< XMultiServiceFactory
> xMgr
= ::comphelper::getProcessServiceFactory();
401 SfxStoringHelper
aHelper(xMgr
);
402 aHelper
.GUIStoreModel(_xModel
,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SaveAs")),aArgs
, sal_False
, ::rtl::OUString() );
403 // xStor->storeToURL(rFileName,aArgs);
411 // restore old settings
413 if ( !bModified && xDocShell->IsEnableSetModified() )
414 xDocShell->SetModified( FALSE );
416 eRet
= bRet
? SAVE_SUCCESSFULL
: SAVE_ERROR
;
421 OSL_ENSURE(0,"Exception catched!");
426 SfxMailModel::SaveResult
SfxMailModel::SaveDocAsPDF( const ::rtl::OUString
& _sAttachmentTitle
427 , const ::com::sun::star::uno::Reference
< ::com::sun::star::frame::XModel
>& _xModel
430 SaveResult eRet
= SAVE_CANCELLED
;
433 Reference
<XModifiable
> xMod(_xModel
,UNO_QUERY
);
440 BOOL bModified = xMod->isModified();
441 // prepare for mail export
442 SfxDispatcher* pDisp = pTopViewFrm->GetDispatcher();
443 pDisp->Execute( SID_MAIL_PREPAREEXPORT, SFX_CALLMODE_SYNCHRON );
446 // Get PDF Filter from document
447 ::rtl::OUString
sPDFMediaType(RTL_CONSTASCII_USTRINGPARAM("application/pdf"));
449 sal_Bool bRet
= sal_False
;
450 // create temp file name with leading chars and extension
451 Reference
< XStorable
> xStor( _xModel
, UNO_QUERY
);
454 String aLeadingStr
= lcl_createTempFileName(_xModel
,_sAttachmentTitle
);
455 String aPDFExtension
= String::CreateFromAscii( ".pdf" );
456 ::utl::TempFile
aTempFile( aLeadingStr
, &aPDFExtension
);
458 rFileName
= aTempFile
.GetURL();
460 // save document to temp file
461 Sequence
< PropertyValue
> aArgs( _xModel
->getArgs() );
462 ::comphelper::MediaDescriptor
aMedia(aArgs
);
464 ::rtl::OUString
sMediaType(RTL_CONSTASCII_USTRINGPARAM("MediaType"));
465 if ( !aMedia
.createItemIfMissing(sMediaType
,sPDFMediaType
) )
466 aMedia
[sMediaType
] <<= sPDFMediaType
;
468 ::rtl::OUString
sURL(RTL_CONSTASCII_USTRINGPARAM("URL"));
469 if ( !aMedia
.createItemIfMissing(sURL
,::rtl::OUString(rFileName
)) )
470 aMedia
[sURL
] <<= ::rtl::OUString(rFileName
);
475 Reference
< XMultiServiceFactory
> xMgr
= ::comphelper::getProcessServiceFactory();
476 SfxStoringHelper
aHelper(xMgr
);
477 aHelper
.GUIStoreModel(_xModel
,::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ExportToPDF")),aArgs
, sal_False
, ::rtl::OUString
);
478 // xStor->storeToURL(rFileName,aArgs);
485 eRet
= bRet
? SAVE_SUCCESSFULL
: SAVE_CANCELLED
;
487 // restore old settings
489 if ( !bModified && xDocShell->IsEnableSetModified() )
490 xDocShell->SetModified( FALSE );
497 OSL_ENSURE(0,"Exception catched!");
502 // -----------------------------------------------------------------------------
503 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument( MailDocType _eMailDocType
504 , const Reference
< XModel
>& _xModel
505 , const ::rtl::OUString
& _sAttachmentTitle
)
507 SaveResult eSaveResult
;
510 // sal_Bool bSuccessfull = sal_False;
511 if ( _eMailDocType
== TYPE_SELF
)
512 eSaveResult
= SaveDocument( _sAttachmentTitle
,_xModel
,aFileName
);
514 eSaveResult
= SaveDocAsPDF( _sAttachmentTitle
,_xModel
,aFileName
);
516 if ( eSaveResult
== SAVE_SUCCESSFULL
&& aFileName
.Len() )
517 maAttachedDocuments
.push_back(aFileName
);
518 return eSaveResult
== SAVE_SUCCESSFULL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
520 // -----------------------------------------------------------------------------
522 IMPL_LINK_INLINE_START( SfxMailModel
, DoneHdl
, void*, EMPTYARG
)
524 mbLoadDone
= sal_True
;
527 // -----------------------------------------------------------------------------
528 IMPL_LINK_INLINE_END( SfxMailModel
, DoneHdl
, void*, EMPTYARG
)
530 SfxMailModel::SfxMailModel( const Reference
< XFrame
>& _xFrame
) :
535 m_xCurrentFrame ( _xFrame
),
536 mePriority ( PRIO_NORMAL
),
537 mbLoadDone ( sal_True
)
542 SfxMailModel::~SfxMailModel()
544 ClearList( mpToList
);
546 ClearList( mpCcList
);
548 ClearList( mpBccList
);
552 void SfxMailModel::AddAddress( const String
& rAddress
, AddressRole eRole
)
554 // don't add a empty address
555 if ( rAddress
.Len() > 0 )
557 AddressList_Impl
* pList
= NULL
;
558 if ( ROLE_TO
== eRole
)
562 mpToList
= new AddressList_Impl
;
565 else if ( ROLE_CC
== eRole
)
569 mpCcList
= new AddressList_Impl
;
572 else if ( ROLE_BCC
== eRole
)
576 mpBccList
= new AddressList_Impl
;
581 DBG_ERRORFILE( "invalid address role" );
586 // add address to list
587 AddressItemPtr_Impl pAddress
= new String( rAddress
);
588 pList
->Insert( pAddress
, LIST_APPEND
);
593 SfxMailModel::SendMailResult
SfxMailModel::Send( )
595 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
596 SendMailResult eResult
= SEND_MAIL_ERROR
;
597 if ( !maAttachedDocuments
.empty() )
600 Reference
< XMultiServiceFactory
> xMgr
= ::comphelper::getProcessServiceFactory();
603 Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
605 // Prefer the SimpleSystemMail service if available
606 xSimpleMailClientSupplier
= Reference
< XSimpleMailClientSupplier
>(
607 xMgr
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleSystemMail" ))),
610 if ( ! xSimpleMailClientSupplier
.is() )
612 xSimpleMailClientSupplier
= Reference
< XSimpleMailClientSupplier
>(
613 xMgr
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleCommandMail" ))),
617 if ( xSimpleMailClientSupplier
.is() )
619 Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
621 if ( !xSimpleMailClient
.is() )
623 // no mail client support => message box!
624 return SEND_MAIL_ERROR
;
627 // we have a simple mail client
628 Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
629 if ( xSimpleMailMessage
.is() )
631 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
632 if ( maFromAddress
.Len() == 0 )
634 // from address not set, try figure out users e-mail address
635 CreateFromAddress_Impl( maFromAddress
);
637 xSimpleMailMessage
->setOriginator( maFromAddress
);
639 sal_Int32 nToCount
= mpToList
? mpToList
->Count() : 0;
640 sal_Int32 nCcCount
= mpCcList
? mpCcList
->Count() : 0;
641 sal_Int32 nCcSeqCount
= nCcCount
;
643 // set recipient (only one) for this simple mail server!!
646 nCcSeqCount
= nToCount
- 1 + nCcCount
;
647 xSimpleMailMessage
->setRecipient( *mpToList
->GetObject( 0 ));
648 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
650 else if ( nToCount
== 1 )
652 xSimpleMailMessage
->setRecipient( *mpToList
->GetObject( 0 ));
653 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
656 // all other recipient must be handled with CC recipients!
657 if ( nCcSeqCount
> 0 )
659 sal_Int32 nIndex
= 0;
660 Sequence
< OUString
> aCcRecipientSeq
;
662 aCcRecipientSeq
.realloc( nCcSeqCount
);
663 if ( nCcSeqCount
> nCcCount
)
665 for ( sal_Int32 i
= 1; i
< nToCount
; ++i
)
667 aCcRecipientSeq
[nIndex
++] = *mpToList
->GetObject(i
);
671 for ( sal_Int32 i
= 0; i
< nCcCount
; i
++ )
673 aCcRecipientSeq
[nIndex
++] = *mpCcList
->GetObject(i
);
675 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
678 sal_Int32 nBccCount
= mpBccList
? mpBccList
->Count() : 0;
681 Sequence
< OUString
> aBccRecipientSeq( nBccCount
);
682 for ( sal_Int32 i
= 0; i
< nBccCount
; ++i
)
684 aBccRecipientSeq
[i
] = *mpBccList
->GetObject(i
);
686 xSimpleMailMessage
->setBccRecipient( aBccRecipientSeq
);
689 Sequence
< OUString
> aAttachmentSeq(&(maAttachedDocuments
[0]),maAttachedDocuments
.size());
691 xSimpleMailMessage
->setSubject( maSubject
);
692 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
695 // Due to the current clipboard implementation we cannot stop the main thread
696 // because the clipboard implementation calls the main thread from another thread
697 // and this would result in a deadlock!
698 // Currently we create a thread to send a message and process all remaining error
699 // handling in this thread!!
701 OMailSendThreadImpl
* pMailSendThread
= new OMailSendThreadImpl( xSimpleMailClient
, xSimpleMailMessage
, m_xCurrentFrame
,nSendFlags
);
702 pMailSendThread
->create();
704 // Return always true as the real error handling occurss in the OMailSendThreadImpl-implementation!
705 eResult
= SEND_MAIL_OK
;
711 eResult
= SEND_MAIL_CANCELLED
;