1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // includes --------------------------------------------------------------
30 #include <com/sun/star/beans/PropertyValue.hpp>
31 #include <com/sun/star/beans/XPropertyAccess.hpp>
32 #include <com/sun/star/frame/XFrame.hpp>
33 #include <com/sun/star/frame/XModel.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/ucb/CommandAbortedException.hpp>
36 #include <com/sun/star/uno/Reference.h>
37 #include <com/sun/star/util/XURLTransformer.hpp>
38 #include <com/sun/star/system/XSimpleMailClientSupplier.hpp>
39 #include <com/sun/star/system/SimpleMailClientFlags.hpp>
40 #include <com/sun/star/embed/XStorage.hpp>
41 #include <com/sun/star/embed/ElementModes.hpp>
42 #include <com/sun/star/embed/XTransactedObject.hpp>
43 #include <com/sun/star/container/XContainerQuery.hpp>
44 #include <com/sun/star/util/XModifiable.hpp>
45 #include <com/sun/star/frame/XModuleManager.hpp>
46 #include <com/sun/star/frame/XStorable.hpp>
47 #include <com/sun/star/beans/XPropertySet.hpp>
48 #include <com/sun/star/security/CertificateValidity.hpp>
49 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
50 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
51 #include <com/sun/star/frame/XDispatchProvider.hpp>
52 #include <com/sun/star/frame/XDispatch.hpp>
53 #include <com/sun/star/frame/XStatusListener.hpp>
54 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
55 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
56 #include <com/sun/star/document/XExporter.hpp>
57 #include <rtl/textenc.h>
59 #include <rtl/uri.hxx>
60 #include <rtl/ustrbuf.hxx>
61 #include <vcl/msgbox.hxx>
63 #include <sfx2/mailmodelapi.hxx>
64 #include "sfxtypes.hxx"
65 #include "sfx2/sfxresid.hxx"
66 #include <sfx2/sfxsids.hrc>
69 #include <unotools/tempfile.hxx>
70 #include <unotools/configitem.hxx>
71 #include <ucbhelper/content.hxx>
72 #include <tools/urlobj.hxx>
73 #include <unotools/useroptions.hxx>
74 #include <comphelper/extract.hxx>
75 #include <comphelper/mediadescriptor.hxx>
76 #include <comphelper/processfactory.hxx>
77 #include <comphelper/sequenceashashmap.hxx>
78 #include <comphelper/sequenceasvector.hxx>
79 #include <comphelper/storagehelper.hxx>
80 #include <comphelper/string.hxx>
81 #include <toolkit/helper/vclunohelper.hxx>
82 #include <vcl/svapp.hxx>
83 #include <cppuhelper/implbase1.hxx>
85 // --------------------------------------------------------------
86 using namespace ::com::sun::star
;
87 using namespace ::com::sun::star::beans
;
88 using namespace ::com::sun::star::frame
;
89 using namespace ::com::sun::star::io
;
90 using namespace ::com::sun::star::lang
;
91 using namespace ::com::sun::star::ucb
;
92 using namespace ::com::sun::star::uno
;
93 using namespace ::com::sun::star::util
;
94 using namespace ::com::sun::star::system
;
95 using namespace ::rtl
;
97 namespace css
= ::com::sun::star
;
98 // - class PrepareListener_Impl ------------------------------------------
99 class PrepareListener_Impl
: public ::cppu::WeakImplHelper1
< css::frame::XStatusListener
>
103 PrepareListener_Impl();
104 virtual ~PrepareListener_Impl();
106 // css.frame.XStatusListener
107 virtual void SAL_CALL
statusChanged(const css::frame::FeatureStateEvent
& aEvent
)
108 throw(css::uno::RuntimeException
);
110 // css.lang.XEventListener
111 virtual void SAL_CALL
disposing(const css::lang::EventObject
& aEvent
)
112 throw(css::uno::RuntimeException
);
114 bool IsSet() const {return m_bState
;}
117 /*-- 25.08.2010 14:32:49---------------------------------------------------
119 -----------------------------------------------------------------------*/
120 PrepareListener_Impl::PrepareListener_Impl() :
124 /*-- 25.08.2010 14:32:51---------------------------------------------------
126 -----------------------------------------------------------------------*/
127 PrepareListener_Impl::~PrepareListener_Impl()
130 /*-- 25.08.2010 14:32:51---------------------------------------------------
132 -----------------------------------------------------------------------*/
133 void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent
& rEvent
) throw(css::uno::RuntimeException
)
135 if( rEvent
.IsEnabled
)
136 rEvent
.State
>>= m_bState
;
138 m_bState
= sal_False
;
140 /*-- 25.08.2010 14:32:52---------------------------------------------------
142 -----------------------------------------------------------------------*/
143 void PrepareListener_Impl::disposing(const css::lang::EventObject
& /*rEvent*/) throw(css::uno::RuntimeException
)
147 // class SfxMailModel -----------------------------------------------
149 static const char PDF_DOCUMENT_TYPE
[] = "pdf_Portable_Document_Format";
150 static const sal_uInt32 PDF_DOCUMENT_TYPE_LEN
= 28;
152 void SfxMailModel::ClearList( AddressList_Impl
* pList
)
156 for( size_t i
= 0, n
= pList
->size(); i
< n
; ++i
)
162 sal_Bool
HasDocumentValidSignature( const css::uno::Reference
< css::frame::XModel
>& xModel
)
166 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( xModel
, css::uno::UNO_QUERY
);
169 Any a
= xPropSet
->getPropertyValue( rtl::OUString( "HasValidSignatures" ));
170 sal_Bool bReturn
= sal_Bool();
175 catch ( css::uno::RuntimeException
& )
179 catch ( css::uno::Exception
& )
186 SfxMailModel::SaveResult
SfxMailModel::ShowFilterOptionsDialog(
187 uno::Reference
< lang::XMultiServiceFactory
> xSMGR
,
188 uno::Reference
< frame::XModel
> xModel
,
189 const rtl::OUString
& rFilterName
,
190 const rtl::OUString
& rType
,
193 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& rArgs
)
195 SaveResult
eRet( SAVE_ERROR
);
199 uno::Sequence
< beans::PropertyValue
> aProps
;
200 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xFilterCFG
=
201 uno::Reference
< container::XNameAccess
>(
202 xSMGR
->createInstance(
203 ::rtl::OUString("com.sun.star.document.FilterFactory") ), uno::UNO_QUERY
);
204 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
206 if ( !xFilterCFG
.is() )
209 uno::Any aAny
= xFilterCFG
->getByName( rFilterName
);
211 if ( aAny
>>= aProps
)
213 sal_Int32 nPropertyCount
= aProps
.getLength();
214 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
216 if( aProps
[nProperty
].Name
== "UIComponent" )
218 ::rtl::OUString aServiceName
;
219 aProps
[nProperty
].Value
>>= aServiceName
;
220 if( !aServiceName
.isEmpty() )
222 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog(
223 xSMGR
->createInstance( aServiceName
), uno::UNO_QUERY
);
224 uno::Reference
< beans::XPropertyAccess
> xFilterProperties(
225 xFilterDialog
, uno::UNO_QUERY
);
227 if( xFilterDialog
.is() && xFilterProperties
.is() )
229 uno::Sequence
< beans::PropertyValue
> aPropsForDialog(1);
230 uno::Reference
< document::XExporter
> xExporter( xFilterDialog
, uno::UNO_QUERY
);
232 if ( rType
.equalsAsciiL( PDF_DOCUMENT_TYPE
, PDF_DOCUMENT_TYPE_LEN
))
234 //add an internal property, used to tell the dialog we want to set a different
235 //string for the ok button
236 //used in filter/source/pdf/impdialog.cxx
237 String
aOkSendText( SfxResId( STR_PDF_EXPORT_SEND
));
239 uno::Sequence
< beans::PropertyValue
> aFilterDataValue(1);
240 aFilterDataValue
[0].Name
= ::rtl::OUString( "_OkButtonString" );
241 aFilterDataValue
[0].Value
= css::uno::makeAny( ::rtl::OUString( aOkSendText
));
243 //add to the filterdata property, the only one the PDF export filter dialog will care for
244 aPropsForDialog
[0].Name
= ::rtl::OUString( "FilterData" );
245 aPropsForDialog
[0].Value
= css::uno::makeAny( aFilterDataValue
);
247 //when executing the dialog will merge the persistent FilterData properties
248 xFilterProperties
->setPropertyValues( aPropsForDialog
);
252 xExporter
->setSourceDocument(
253 uno::Reference
< lang::XComponent
>( xModel
, uno::UNO_QUERY
) );
255 if( xFilterDialog
->execute() )
257 //get the filter data
258 uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= xFilterProperties
->getPropertyValues();
260 //add them to the args
261 for ( sal_Int32 nInd
= 0; nInd
< aPropsFromDialog
.getLength(); nInd
++ )
263 if( aPropsFromDialog
[ nInd
].Name
== "FilterData" )
265 //found the filterdata, add to the storing argument
266 rArgs
.realloc( ++rNumArgs
);
267 rArgs
[rNumArgs
-1].Name
= aPropsFromDialog
[ nInd
].Name
;
268 rArgs
[rNumArgs
-1].Value
= aPropsFromDialog
[ nInd
].Value
;
272 eRet
= SAVE_SUCCESSFULL
;
276 // cancel from dialog, then do not send
277 // If the model is not modified, it could be modified by the dispatch calls.
278 // Therefore set back to modified = false. This should not hurt if we call
279 // on a non-modified model.
284 xModifiable
->setModified( sal_False
);
286 catch( com::sun::star::beans::PropertyVetoException
& )
290 eRet
= SAVE_CANCELLED
;
299 catch( css::uno::RuntimeException
& )
303 catch( uno::Exception
& )
310 sal_Bool
SfxMailModel::IsEmpty() const
312 return maAttachedDocuments
.empty();
315 SfxMailModel::SaveResult
SfxMailModel::SaveDocumentAsFormat(
316 const rtl::OUString
& aSaveFileName
,
317 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
318 const rtl::OUString
& rType
,
319 rtl::OUString
& rFileNamePath
)
321 SaveResult
eRet( SAVE_ERROR
);
322 bool bSendAsPDF
= (rType
.equalsAsciiL( PDF_DOCUMENT_TYPE
, PDF_DOCUMENT_TYPE_LEN
));
324 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
328 const rtl::OUString
aModuleManager( "com.sun.star.frame.ModuleManager" );
329 css::uno::Reference
< css::frame::XModuleManager
> xModuleManager( xSMGR
->createInstance( aModuleManager
), css::uno::UNO_QUERY_THROW
);
330 if ( !xModuleManager
.is() )
333 rtl::OUString aModule
;
336 aModule
= xModuleManager
->identify( xFrameOrModel
);
338 catch ( css::uno::RuntimeException
& )
342 catch ( css::uno::Exception
& )
346 css::uno::Reference
< css::frame::XFrame
> xFrame( xFrameOrModel
, css::uno::UNO_QUERY
);
347 css::uno::Reference
< css::frame::XModel
> xModel( xFrameOrModel
, css::uno::UNO_QUERY
);
350 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
351 if ( xController
.is() )
352 xModel
= xController
->getModel();
355 // We need at least a valid module name and model reference
356 if ( !aModule
.isEmpty() && xModel
.is() )
358 bool bModified( false );
359 bool bHasLocation( false );
360 bool bStoreTo( false );
362 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
363 css::uno::Reference
< css::frame::XStorable
> xStorable( xModel
, css::uno::UNO_QUERY
);
365 if ( xModifiable
.is() )
366 bModified
= xModifiable
->isModified();
367 if ( xStorable
.is() )
369 rtl::OUString aLocation
= xStorable
->getLocation();
370 INetURLObject
aFileObj( aLocation
);
372 bool bPrivateProtocol
= ( aFileObj
.GetProtocol() == INET_PROT_PRIV_SOFFICE
);
374 bHasLocation
= !aLocation
.isEmpty() && !bPrivateProtocol
;
375 OSL_ASSERT( !bPrivateProtocol
);
377 if ( !rType
.isEmpty() )
380 if ( xStorable
.is() )
382 rtl::OUString aFilterName
;
383 rtl::OUString
aTypeName( rType
);
384 rtl::OUString aFileName
;
385 rtl::OUString aExtension
;
387 css::uno::Reference
< css::container::XContainerQuery
> xContainerQuery(
388 xSMGR
->createInstance( rtl::OUString(
389 "com.sun.star.document.FilterFactory" )),
390 css::uno::UNO_QUERY
);
394 // Retrieve filter from type
395 css::uno::Sequence
< css::beans::NamedValue
> aQuery( bSendAsPDF
? 3 : 2 );
396 aQuery
[0].Name
= rtl::OUString( "Type" );
397 aQuery
[0].Value
= css::uno::makeAny( aTypeName
);
398 aQuery
[1].Name
= rtl::OUString( "DocumentService" );
399 aQuery
[1].Value
= css::uno::makeAny( aModule
);
403 // FIXME: we want just an export filter. However currently we need
404 // exact flag value as detailed in the filter configuration to get it
405 // this seems to be a bug
406 // without flags we get an import filter here, which is also unwanted
407 aQuery
[2].Name
= rtl::OUString( "Flags" );
408 aQuery
[2].Value
= css::uno::makeAny( sal_Int32(0x80042) ); // EXPORT ALIEN 3RDPARTY
411 css::uno::Reference
< css::container::XEnumeration
> xEnumeration
=
412 xContainerQuery
->createSubSetEnumerationByProperties( aQuery
);
414 if ( xEnumeration
->hasMoreElements() )
416 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xEnumeration
->nextElement() );
417 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
418 ::rtl::OUString("Name"),
424 // Retrieve filter from media descriptor
425 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
426 rtl::OUString aOrgFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
427 ::rtl::OUString( "FilterName" ),
429 if ( aOrgFilterName
== aFilterName
)
431 // We should save the document in the original format. Therefore this
432 // is not a storeTo operation. To support signing in this case, reset
442 // Retrieve filter from media descriptor
443 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
444 aFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
445 ::rtl::OUString( "FilterName" ),
449 if ( !bHasLocation
|| aFilterName
.isEmpty())
451 // Retrieve the user defined default filter
452 css::uno::Reference
< css::container::XNameAccess
> xNameAccess( xModuleManager
, css::uno::UNO_QUERY
);
455 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xNameAccess
->getByName( aModule
) );
456 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
457 ::rtl::OUString("ooSetupFactoryDefaultFilter"),
459 css::uno::Reference
< css::container::XNameAccess
> xNameAccess2(
460 xContainerQuery
, css::uno::UNO_QUERY
);
461 if ( xNameAccess2
.is() )
463 ::comphelper::SequenceAsHashMap
aFilterPropsHM2( xNameAccess2
->getByName( aFilterName
) );
464 aTypeName
= aFilterPropsHM2
.getUnpackedValueOrDefault(
465 ::rtl::OUString("Type"),
469 catch ( css::container::NoSuchElementException
& )
472 catch ( css::beans::UnknownPropertyException
& )
478 // No filter found => error
479 // No type and no location => error
480 if (( aFilterName
.isEmpty() ) ||
481 ( aTypeName
.isEmpty() && !bHasLocation
))
484 // Determine filen name and extension
485 if ( bHasLocation
&& !bStoreTo
)
487 INetURLObject
aFileObj( xStorable
->getLocation() );
488 aExtension
= (rtl::OUString
)aFileObj
.getExtension();
492 css::uno::Reference
< container::XNameAccess
> xTypeDetection(
493 xSMGR
->createInstance( ::rtl::OUString(
494 "com.sun.star.document.TypeDetection" )),
495 css::uno::UNO_QUERY
);
498 if ( xTypeDetection
.is() )
502 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( xTypeDetection
->getByName( aTypeName
) );
503 uno::Sequence
< ::rtl::OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
504 ::rtl::OUString("Extensions"),
505 ::uno::Sequence
< ::rtl::OUString
>() );
506 if ( aExtensions
.getLength() )
507 aExtension
= aExtensions
[0];
509 catch ( css::container::NoSuchElementException
& )
515 // Use provided save file name. If empty determine file name
516 aFileName
= aSaveFileName
;
517 if ( aFileName
.isEmpty() )
521 // Create a noname file name with the correct extension
522 const rtl::OUString
aNoNameFileName( "noname" );
523 aFileName
= aNoNameFileName
;
527 // Determine file name from model
528 INetURLObject
aFileObj( xStorable
->getLocation() );
529 aFileName
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::NO_DECODE
);
533 // No file name => error
534 if ( aFileName
.isEmpty() )
537 OSL_ASSERT( !aFilterName
.isEmpty() );
538 OSL_ASSERT( !aFileName
.isEmpty() );
540 // Creates a temporary directory to store a predefined file into it.
541 // This makes it possible to store the file for "send document as e-mail"
542 // with the original file name. We cannot use the original file as
543 // some mail programs need exclusive access.
544 ::utl::TempFile
aTempDir( NULL
, sal_True
);
546 INetURLObject
aFilePathObj( aTempDir
.GetURL() );
547 aFilePathObj
.insertName( aFileName
);
548 aFilePathObj
.setExtension( aExtension
);
550 rtl::OUString aFileURL
= aFilePathObj
.GetMainURL( INetURLObject::NO_DECODE
);
552 sal_Int32
nNumArgs(0);
553 const rtl::OUString
aPasswordPropName( "Password" );
554 css::uno::Sequence
< css::beans::PropertyValue
> aArgs( ++nNumArgs
);
555 aArgs
[nNumArgs
-1].Name
= rtl::OUString( "FilterName" );
556 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( aFilterName
);
558 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
559 rtl::OUString aPassword
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
562 if ( !aPassword
.isEmpty() )
564 aArgs
.realloc( ++nNumArgs
);
565 aArgs
[nNumArgs
-1].Name
= aPasswordPropName
;
566 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( aPassword
);
569 bool bNeedsPreparation
= false;
570 css::util::URL aPrepareURL
;
571 css::uno::Reference
< css::frame::XDispatch
> xPrepareDispatch
;
572 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider( xFrame
, css::uno::UNO_QUERY
);
573 css::uno::Reference
< css::util::XURLTransformer
> xURLTransformer(
574 xSMGR
->createInstance( rtl::OUString( "com.sun.star.util.URLTransformer" )),
575 css::uno::UNO_QUERY
);
580 // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content)
582 if ( xURLTransformer
.is() )
584 aPrepareURL
.Complete
= rtl::OUString( ".uno:PrepareMailExport" );
585 xURLTransformer
->parseStrict( aPrepareURL
);
588 if ( xDispatchProvider
.is() )
590 xPrepareDispatch
= css::uno::Reference
< css::frame::XDispatch
>(
591 xDispatchProvider
->queryDispatch( aPrepareURL
, ::rtl::OUString(), 0 ));
592 if ( xPrepareDispatch
.is() )
594 PrepareListener_Impl
* pPrepareListener
;
595 uno::Reference
< css::frame::XStatusListener
> xStatusListener
= pPrepareListener
= new PrepareListener_Impl
;
596 xPrepareDispatch
->addStatusListener( xStatusListener
, aPrepareURL
);
597 bNeedsPreparation
= pPrepareListener
->IsSet();
598 xPrepareDispatch
->removeStatusListener( xStatusListener
, aPrepareURL
);
602 catch ( css::uno::RuntimeException
& )
606 catch ( css::uno::Exception
& )
611 if ( bModified
|| !bHasLocation
|| bStoreTo
|| bNeedsPreparation
)
613 // Document is modified, is newly created or should be stored in a special format
616 if( bNeedsPreparation
&& xPrepareDispatch
.is() )
618 if ( xPrepareDispatch
.is() )
622 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
623 xPrepareDispatch
->dispatch( aPrepareURL
, aDispatchArgs
);
625 catch ( css::uno::RuntimeException
& )
629 catch ( css::uno::Exception
& )
635 //check if this is the pdf otput filter (i#64555)
638 SaveResult eShowPDFFilterDialog
= ShowFilterOptionsDialog(
639 xSMGR
, xModel
, aFilterName
, rType
, bModified
, nNumArgs
, aArgs
);
641 // don't continue on dialog cancel or error
642 if ( eShowPDFFilterDialog
!= SAVE_SUCCESSFULL
)
643 return eShowPDFFilterDialog
;
646 xStorable
->storeToURL( aFileURL
, aArgs
);
647 rFileNamePath
= aFileURL
;
648 eRet
= SAVE_SUCCESSFULL
;
653 // #i30432# notify that export is finished - the Writer may want to restore removed content
654 if ( xURLTransformer
.is() )
656 aURL
.Complete
= rtl::OUString( ".uno:MailExportFinished" );
657 xURLTransformer
->parseStrict( aURL
);
660 if ( xDispatchProvider
.is() )
662 css::uno::Reference
< css::frame::XDispatch
> xDispatch
= css::uno::Reference
< css::frame::XDispatch
>(
663 xDispatchProvider
->queryDispatch( aURL
, ::rtl::OUString(), 0 ));
664 if ( xDispatch
.is() )
668 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
669 xDispatch
->dispatch( aURL
, aDispatchArgs
);
671 catch ( css::uno::RuntimeException
& )
675 catch ( css::uno::Exception
& )
681 // If the model is not modified, it could be modified by the dispatch calls.
682 // Therefore set back to modified = false. This should not hurt if we call
683 // on a non-modified model.
688 xModifiable
->setModified( sal_False
);
690 catch( com::sun::star::beans::PropertyVetoException
& )
695 catch ( com::sun::star::io::IOException
& )
702 // We need 1:1 copy of the document to preserve an added signature.
703 aArgs
.realloc( ++nNumArgs
);
704 aArgs
[nNumArgs
-1].Name
= ::rtl::OUString( "CopyStreamIfPossible" );
705 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( (sal_Bool
)sal_True
);
709 xStorable
->storeToURL( aFileURL
, aArgs
);
710 rFileNamePath
= aFileURL
;
711 eRet
= SAVE_SUCCESSFULL
;
713 catch ( com::sun::star::io::IOException
& )
724 SfxMailModel::SfxMailModel() :
728 mePriority ( PRIO_NORMAL
),
729 mbLoadDone ( sal_True
)
733 SfxMailModel::~SfxMailModel()
735 ClearList( mpToList
);
737 ClearList( mpCcList
);
739 ClearList( mpBccList
);
743 void SfxMailModel::AddAddress( const String
& rAddress
, AddressRole eRole
)
745 // don't add a empty address
746 if ( rAddress
.Len() > 0 )
748 AddressList_Impl
* pList
= NULL
;
749 if ( ROLE_TO
== eRole
)
753 mpToList
= new AddressList_Impl();
756 else if ( ROLE_CC
== eRole
)
760 mpCcList
= new AddressList_Impl();
763 else if ( ROLE_BCC
== eRole
)
767 mpBccList
= new AddressList_Impl();
772 SAL_WARN( "sfx2.dialog", "invalid address role" );
777 // add address to list
778 AddressItemPtr_Impl pAddress
= new String( rAddress
);
779 pList
->push_back( pAddress
);
784 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument(
785 const ::rtl::OUString
& sDocumentType
,
786 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
787 const ::rtl::OUString
& sAttachmentTitle
)
789 rtl::OUString sFileName
;
791 SaveResult eSaveResult
= SaveDocumentAsFormat( sAttachmentTitle
, xFrameOrModel
, sDocumentType
, sFileName
);
792 if ( eSaveResult
== SAVE_SUCCESSFULL
&& !sFileName
.isEmpty() )
793 maAttachedDocuments
.push_back(sFileName
);
794 return eSaveResult
== SAVE_SUCCESSFULL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
797 SfxMailModel::SendMailResult
SfxMailModel::Send( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
799 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
800 SendMailResult eResult
= SEND_MAIL_ERROR
;
801 if ( !maAttachedDocuments
.empty() )
803 css::uno::Reference
< XMultiServiceFactory
> xMgr
= ::comphelper::getProcessServiceFactory();
806 css::uno::Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
808 // Prefer the SimpleSystemMail service if available
809 xSimpleMailClientSupplier
= css::uno::Reference
< XSimpleMailClientSupplier
>(
810 xMgr
->createInstance( OUString( "com.sun.star.system.SimpleSystemMail" )),
813 if ( ! xSimpleMailClientSupplier
.is() )
815 xSimpleMailClientSupplier
= css::uno::Reference
< XSimpleMailClientSupplier
>(
816 xMgr
->createInstance( OUString( "com.sun.star.system.SimpleCommandMail" )),
820 if ( xSimpleMailClientSupplier
.is() )
822 css::uno::Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
824 if ( !xSimpleMailClient
.is() )
826 // no mail client support => message box!
827 return SEND_MAIL_ERROR
;
830 // we have a simple mail client
831 css::uno::Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
832 if ( xSimpleMailMessage
.is() )
834 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
835 if ( maFromAddress
.Len() == 0 )
837 // from address not set, try figure out users e-mail address
838 CreateFromAddress_Impl( maFromAddress
);
840 xSimpleMailMessage
->setOriginator( maFromAddress
);
842 size_t nToCount
= mpToList
? mpToList
->size() : 0;
843 size_t nCcCount
= mpCcList
? mpCcList
->size() : 0;
844 size_t nCcSeqCount
= nCcCount
;
846 // set recipient (only one) for this simple mail server!!
849 nCcSeqCount
= nToCount
- 1 + nCcCount
;
850 xSimpleMailMessage
->setRecipient( *mpToList
->at( 0 ) );
851 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
853 else if ( nToCount
== 1 )
855 xSimpleMailMessage
->setRecipient( *mpToList
->at( 0 ) );
856 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
859 // all other recipient must be handled with CC recipients!
860 if ( nCcSeqCount
> 0 )
863 Sequence
< OUString
> aCcRecipientSeq
;
865 aCcRecipientSeq
.realloc( nCcSeqCount
);
866 if ( nCcSeqCount
> nCcCount
)
868 for ( size_t i
= 1; i
< nToCount
; ++i
)
870 aCcRecipientSeq
[nIndex
++] = *mpToList
->at(i
);
874 for ( size_t i
= 0; i
< nCcCount
; i
++ )
876 aCcRecipientSeq
[nIndex
++] = *mpCcList
->at(i
);
878 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
881 size_t nBccCount
= mpBccList
? mpBccList
->size() : 0;
884 Sequence
< OUString
> aBccRecipientSeq( nBccCount
);
885 for ( size_t i
= 0; i
< nBccCount
; ++i
)
887 aBccRecipientSeq
[i
] = *mpBccList
->at(i
);
889 xSimpleMailMessage
->setBccRecipient( aBccRecipientSeq
);
892 Sequence
< OUString
> aAttachmentSeq(&(maAttachedDocuments
[0]),maAttachedDocuments
.size());
894 if ( xSimpleMailMessage
->getSubject().isEmpty() ) {
895 OUString
baseName( maAttachedDocuments
[0].copy( maAttachedDocuments
[0].lastIndexOf( '/' ) + 1 ) );
896 OUString
subject( baseName
);
897 if ( maAttachedDocuments
.size() > 1 )
898 subject
+= OUString(", ...");
899 xSimpleMailMessage
->setSubject( subject
);
901 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
903 sal_Bool
bSend( sal_False
);
906 xSimpleMailClient
->sendSimpleMailMessage( xSimpleMailMessage
, nSendFlags
);
909 catch ( IllegalArgumentException
& )
916 if ( bSend
== sal_False
)
918 css::uno::Reference
< css::awt::XWindow
> xParentWindow
= xFrame
->getContainerWindow();
920 SolarMutexGuard aGuard
;
921 Window
* pParentWindow
= VCLUnoHelper::GetWindow( xParentWindow
);
923 ErrorBox
aBox( pParentWindow
, SfxResId( RID_ERRBOX_MAIL_CONFIG
));
925 eResult
= SEND_MAIL_CANCELLED
;
928 eResult
= SEND_MAIL_OK
;
934 eResult
= SEND_MAIL_CANCELLED
;
939 SfxMailModel::SendMailResult
SfxMailModel::SaveAndSend( const css::uno::Reference
< css::frame::XFrame
>& xFrame
, const rtl::OUString
& rTypeName
)
941 SaveResult eSaveResult
;
942 SendMailResult eResult
= SEND_MAIL_ERROR
;
943 rtl::OUString aFileName
;
945 eSaveResult
= SaveDocumentAsFormat( rtl::OUString(), xFrame
, rTypeName
, aFileName
);
947 if ( eSaveResult
== SAVE_SUCCESSFULL
)
949 maAttachedDocuments
.push_back( aFileName
);
950 return Send( xFrame
);
952 else if ( eSaveResult
== SAVE_CANCELLED
)
953 eResult
= SEND_MAIL_CANCELLED
;
958 // functions -------------------------------------------------------------
960 sal_Bool
CreateFromAddress_Impl( String
& rFrom
)
964 This function tries to create a From-address with the help of IniManagers.
965 For this the fields 'first name', 'Name' and 'Email' are read from the
966 application-ini-data. If these fields are not set, FALSE is returned.
970 sal_True: Address could be created.
971 sal_False: Address could not be created.
975 SvtUserOptions aUserCFG
;
976 String aName
= aUserCFG
.GetLastName ();
977 String aFirstName
= aUserCFG
.GetFirstName ();
978 if ( aFirstName
.Len() || aName
.Len() )
980 if ( aFirstName
.Len() )
982 rFrom
= TRIM( aFirstName
);
987 rFrom
+= TRIM( aName
);
988 // remove illegal characters
989 rFrom
= comphelper::string::remove(rFrom
, '<');
990 rFrom
= comphelper::string::remove(rFrom
, '>');
991 rFrom
= comphelper::string::remove(rFrom
, '@');
993 String aEmailName
= aUserCFG
.GetEmail();
995 // remove illegal characters
996 aEmailName
= comphelper::string::remove(aEmailName
, '<');
997 aEmailName
= comphelper::string::remove(aEmailName
, '>');
999 if ( aEmailName
.Len() )
1003 ( ( rFrom
+= '<' ) += TRIM( aEmailName
) ) += '>';
1007 return ( rFrom
.Len() > 0 );
1010 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */