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: mailmodel.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/beans/XPropertyAccess.hpp>
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <com/sun/star/ucb/CommandAbortedException.hpp>
40 #include <com/sun/star/uno/Reference.h>
41 #include <com/sun/star/util/XURLTransformer.hpp>
42 #include <com/sun/star/system/XSimpleMailClientSupplier.hpp>
43 #include <com/sun/star/system/SimpleMailClientFlags.hpp>
44 #include <com/sun/star/embed/XStorage.hpp>
45 #include <com/sun/star/embed/ElementModes.hpp>
46 #include <com/sun/star/embed/XTransactedObject.hpp>
47 #include <com/sun/star/container/XContainerQuery.hpp>
48 #include <com/sun/star/util/XModifiable.hpp>
49 #include <com/sun/star/frame/XModuleManager.hpp>
50 #include <com/sun/star/frame/XStorable.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/security/CertificateValidity.hpp>
53 #ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_
54 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
56 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
57 #include <com/sun/star/frame/XDispatchProvider.hpp>
58 #include <com/sun/star/frame/XDispatch.hpp>
59 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
60 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
61 #include <com/sun/star/document/XExporter.hpp>
63 #ifndef _RTL_TEXTENC_H
64 #include <rtl/textench.h>
67 #include <rtl/uri.hxx>
68 #include <rtl/ustrbuf.hxx>
69 #include <vcl/msgbox.hxx>
71 #include <mailmodelapi.hxx>
72 #include "sfxtypes.hxx"
73 #include "sfxresid.hxx"
74 #include <sfx2/sfxsids.hrc>
77 #include <unotools/tempfile.hxx>
78 #include <unotools/configitem.hxx>
79 #include <ucbhelper/content.hxx>
80 #include <tools/urlobj.hxx>
81 #include <svtools/useroptions.hxx>
82 #include <comphelper/processfactory.hxx>
83 #include <comphelper/extract.hxx>
84 #include <comphelper/storagehelper.hxx>
85 #include <comphelper/sequenceasvector.hxx>
86 #include <comphelper/sequenceashashmap.hxx>
87 #include <comphelper/mediadescriptor.hxx>
88 #include <toolkit/helper/vclunohelper.hxx>
89 #include <vcl/svapp.hxx>
91 // --------------------------------------------------------------
92 using namespace ::com::sun::star
;
93 using namespace ::com::sun::star::beans
;
94 using namespace ::com::sun::star::frame
;
95 using namespace ::com::sun::star::io
;
96 using namespace ::com::sun::star::lang
;
97 using namespace ::com::sun::star::ucb
;
98 using namespace ::com::sun::star::uno
;
99 using namespace ::com::sun::star::util
;
100 using namespace ::com::sun::star::system
;
101 using namespace ::rtl
;
103 namespace css
= ::com::sun::star
;
105 // class AddressList_Impl ------------------------------------------------
107 typedef String
* AddressItemPtr_Impl
;
108 DECLARE_LIST( AddressList_Impl
, AddressItemPtr_Impl
)
110 // class SfxMailModel -----------------------------------------------
112 static const char PDF_DOCUMENT_TYPE
[] = "pdf_Portable_Document_Format";
113 static const sal_uInt32 PDF_DOCUMENT_TYPE_LEN
= 28;
115 void SfxMailModel::ClearList( AddressList_Impl
* pList
)
119 ULONG i
, nCount
= pList
->Count();
120 for ( i
= 0; i
< nCount
; ++i
)
121 delete pList
->GetObject(i
);
126 void SfxMailModel::MakeValueList( AddressList_Impl
* pList
, String
& rValueList
)
131 ULONG i
, nCount
= pList
->Count();
132 for ( i
= 0; i
< nCount
; ++i
)
134 if ( rValueList
.Len() > 0 )
136 rValueList
+= *pList
->GetObject(i
);
141 sal_Bool
HasDocumentValidSignature( const css::uno::Reference
< css::frame::XModel
>& xModel
)
145 css::uno::Reference
< css::beans::XPropertySet
> xPropSet( xModel
, css::uno::UNO_QUERY
);
148 Any a
= xPropSet
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasValidSignatures" )));
149 sal_Bool bReturn
= sal_Bool();
154 catch ( css::uno::RuntimeException
& )
158 catch ( css::uno::Exception
& )
165 SfxMailModel::SaveResult
SfxMailModel::ShowFilterOptionsDialog(
166 uno::Reference
< lang::XMultiServiceFactory
> xSMGR
,
167 uno::Reference
< frame::XModel
> xModel
,
168 const rtl::OUString
& rFilterName
,
169 const rtl::OUString
& rType
,
172 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyValue
>& rArgs
)
174 SaveResult
eRet( SAVE_ERROR
);
178 uno::Sequence
< beans::PropertyValue
> aProps
;
179 ::com::sun::star::uno::Reference
< ::com::sun::star::container::XNameAccess
> xFilterCFG
=
180 uno::Reference
< container::XNameAccess
>(
181 xSMGR
->createInstance(
182 ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY
);
183 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
185 if ( !xFilterCFG
.is() )
188 uno::Any aAny
= xFilterCFG
->getByName( rFilterName
);
190 if ( aAny
>>= aProps
)
192 sal_Int32 nPropertyCount
= aProps
.getLength();
193 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
195 if( aProps
[nProperty
].Name
.equals( ::rtl::OUString::createFromAscii( "UIComponent" )) )
197 ::rtl::OUString aServiceName
;
198 aProps
[nProperty
].Value
>>= aServiceName
;
199 if( aServiceName
.getLength() )
201 uno::Reference
< ui::dialogs::XExecutableDialog
> xFilterDialog(
202 xSMGR
->createInstance( aServiceName
), uno::UNO_QUERY
);
203 uno::Reference
< beans::XPropertyAccess
> xFilterProperties(
204 xFilterDialog
, uno::UNO_QUERY
);
206 if( xFilterDialog
.is() && xFilterProperties
.is() )
208 uno::Sequence
< beans::PropertyValue
> aPropsForDialog(1);
209 uno::Reference
< document::XExporter
> xExporter( xFilterDialog
, uno::UNO_QUERY
);
211 if ( rType
.equalsAsciiL( PDF_DOCUMENT_TYPE
, PDF_DOCUMENT_TYPE_LEN
))
213 //add an internal property, used to tell the dialog we want to set a different
214 //string for the ok button
215 //used in filter/source/pdf/impdialog.cxx
216 String
aOkSendText( SfxResId( STR_PDF_EXPORT_SEND
));
218 uno::Sequence
< beans::PropertyValue
> aFilterDataValue(1);
219 aFilterDataValue
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_OkButtonString" ));
220 aFilterDataValue
[0].Value
= css::uno::makeAny( ::rtl::OUString( aOkSendText
));
222 //add to the filterdata property, the only one the PDF export filter dialog will care for
223 aPropsForDialog
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterData" ));
224 aPropsForDialog
[0].Value
= css::uno::makeAny( aFilterDataValue
);
226 //when executing the dialog will merge the persistent FilterData properties
227 xFilterProperties
->setPropertyValues( aPropsForDialog
);
231 xExporter
->setSourceDocument(
232 uno::Reference
< lang::XComponent
>( xModel
, uno::UNO_QUERY
) );
234 if( xFilterDialog
->execute() )
236 //get the filter data
237 uno::Sequence
< beans::PropertyValue
> aPropsFromDialog
= xFilterProperties
->getPropertyValues();
239 //add them to the args
240 for ( sal_Int32 nInd
= 0; nInd
< aPropsFromDialog
.getLength(); nInd
++ )
242 if( aPropsFromDialog
[ nInd
].Name
.equals( ::rtl::OUString::createFromAscii( "FilterData" ) ) )
244 //found the filterdata, add to the storing argument
245 rArgs
.realloc( ++rNumArgs
);
246 rArgs
[rNumArgs
-1].Name
= aPropsFromDialog
[ nInd
].Name
;
247 rArgs
[rNumArgs
-1].Value
= aPropsFromDialog
[ nInd
].Value
;
251 eRet
= SAVE_SUCCESSFULL
;
255 // cancel from dialog, then do not send
256 // If the model is not modified, it could be modified by the dispatch calls.
257 // Therefore set back to modified = false. This should not hurt if we call
258 // on a non-modified model.
263 xModifiable
->setModified( sal_False
);
265 catch( com::sun::star::beans::PropertyVetoException
& )
269 eRet
= SAVE_CANCELLED
;
278 catch( css::uno::RuntimeException
& )
282 catch( uno::Exception
& )
289 sal_Int32
SfxMailModel::GetCount() const
291 return maAttachedDocuments
.size();
294 sal_Bool
SfxMailModel::IsEmpty() const
296 return maAttachedDocuments
.empty();
299 SfxMailModel::SaveResult
SfxMailModel::SaveDocumentAsFormat(
300 const rtl::OUString
& aSaveFileName
,
301 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
302 const rtl::OUString
& rType
,
303 rtl::OUString
& rFileNamePath
)
305 SaveResult
eRet( SAVE_ERROR
);
306 bool bSendAsPDF
= (rType
.equalsAsciiL( PDF_DOCUMENT_TYPE
, PDF_DOCUMENT_TYPE_LEN
));
308 css::uno::Reference
< css::lang::XMultiServiceFactory
> xSMGR
= ::comphelper::getProcessServiceFactory();
312 const rtl::OUString
aModuleManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ));
313 css::uno::Reference
< css::frame::XModuleManager
> xModuleManager( xSMGR
->createInstance( aModuleManager
), css::uno::UNO_QUERY_THROW
);
314 if ( !xModuleManager
.is() )
317 rtl::OUString aModule
;
320 aModule
= xModuleManager
->identify( xFrameOrModel
);
322 catch ( css::uno::RuntimeException
& )
326 catch ( css::uno::Exception
& )
330 css::uno::Reference
< css::frame::XFrame
> xFrame( xFrameOrModel
, css::uno::UNO_QUERY
);
331 css::uno::Reference
< css::frame::XModel
> xModel( xFrameOrModel
, css::uno::UNO_QUERY
);
334 css::uno::Reference
< css::frame::XController
> xController
= xFrame
->getController();
335 if ( xController
.is() )
336 xModel
= xController
->getModel();
339 // We need at least a valid module name and model reference
340 if (( aModule
.getLength() > 0 ) && xModel
.is() )
342 bool bModified( false );
343 bool bHasLocation( false );
344 bool bStoreTo( false );
346 css::uno::Reference
< css::util::XModifiable
> xModifiable( xModel
, css::uno::UNO_QUERY
);
347 css::uno::Reference
< css::frame::XStorable
> xStorable( xModel
, css::uno::UNO_QUERY
);
349 if ( xModifiable
.is() )
350 bModified
= xModifiable
->isModified();
351 if ( xStorable
.is() )
353 rtl::OUString aLocation
= xStorable
->getLocation();
354 INetURLObject
aFileObj( aLocation
);
356 bool bPrivateProtocol
= ( aFileObj
.GetProtocol() == INET_PROT_PRIV_SOFFICE
);
358 bHasLocation
= ( aLocation
.getLength() > 0 ) && !bPrivateProtocol
;
359 OSL_ASSERT( !bPrivateProtocol
);
361 if ( rType
.getLength() > 0 )
364 if ( xStorable
.is() )
366 rtl::OUString aFilterName
;
367 rtl::OUString
aTypeName( rType
);
368 rtl::OUString aFileName
;
369 rtl::OUString aExtension
;
371 css::uno::Reference
< css::container::XContainerQuery
> xContainerQuery(
372 xSMGR
->createInstance( rtl::OUString(
373 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ))),
374 css::uno::UNO_QUERY
);
378 // Retrieve filter from type
379 css::uno::Sequence
< css::beans::NamedValue
> aQuery( bSendAsPDF
? 3 : 2 );
380 aQuery
[0].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" ));
381 aQuery
[0].Value
= css::uno::makeAny( aTypeName
);
382 aQuery
[1].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentService" ));
383 aQuery
[1].Value
= css::uno::makeAny( aModule
);
387 // FIXME: we want just an export filter. However currently we need
388 // exact flag value as detailed in the filter configuration to get it
389 // this seems to be a bug
390 // without flags we get an import filter here, which is also unwanted
391 aQuery
[2].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Flags" ));
392 aQuery
[2].Value
= css::uno::makeAny( sal_Int32(0x80042) ); // EXPORT ALIEN 3RDPARTY
395 css::uno::Reference
< css::container::XEnumeration
> xEnumeration
=
396 xContainerQuery
->createSubSetEnumerationByProperties( aQuery
);
398 if ( xEnumeration
->hasMoreElements() )
400 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xEnumeration
->nextElement() );
401 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
402 ::rtl::OUString::createFromAscii( "Name" ),
408 // Retrieve filter from media descriptor
409 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
410 rtl::OUString aOrgFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
411 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )),
413 if ( aOrgFilterName
== aFilterName
)
415 // We should save the document in the original format. Therefore this
416 // is not a storeTo operation. To support signing in this case, reset
426 // Retrieve filter from media descriptor
427 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
428 aFilterName
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
429 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )),
433 if ( !bHasLocation
|| ( aFilterName
.getLength() == 0 ))
435 // Retrieve the user defined default filter
436 css::uno::Reference
< css::container::XNameAccess
> xNameAccess( xModuleManager
, css::uno::UNO_QUERY
);
439 ::comphelper::SequenceAsHashMap
aFilterPropsHM( xNameAccess
->getByName( aModule
) );
440 aFilterName
= aFilterPropsHM
.getUnpackedValueOrDefault(
441 ::rtl::OUString::createFromAscii( "ooSetupFactoryDefaultFilter" ),
443 css::uno::Reference
< css::container::XNameAccess
> xNameAccess2(
444 xContainerQuery
, css::uno::UNO_QUERY
);
445 if ( xNameAccess2
.is() )
447 ::comphelper::SequenceAsHashMap
aFilterPropsHM2( xNameAccess2
->getByName( aFilterName
) );
448 aTypeName
= aFilterPropsHM2
.getUnpackedValueOrDefault(
449 ::rtl::OUString::createFromAscii( "Type" ),
453 catch ( css::container::NoSuchElementException
& )
456 catch ( css::beans::UnknownPropertyException
& )
462 // No filter found => error
463 // No type and no location => error
464 if (( aFilterName
.getLength() == 0 ) ||
465 (( aTypeName
.getLength() == 0 ) && !bHasLocation
))
468 // Determine filen name and extension
469 if ( bHasLocation
&& !bStoreTo
)
471 INetURLObject
aFileObj( xStorable
->getLocation() );
472 aExtension
= (rtl::OUString
)aFileObj
.getExtension();
476 css::uno::Reference
< container::XNameAccess
> xTypeDetection(
477 xSMGR
->createInstance( ::rtl::OUString(
478 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ))),
479 css::uno::UNO_QUERY
);
482 if ( xTypeDetection
.is() )
486 ::comphelper::SequenceAsHashMap
aTypeNamePropsHM( xTypeDetection
->getByName( aTypeName
) );
487 uno::Sequence
< ::rtl::OUString
> aExtensions
= aTypeNamePropsHM
.getUnpackedValueOrDefault(
488 ::rtl::OUString::createFromAscii( "Extensions" ),
489 ::uno::Sequence
< ::rtl::OUString
>() );
490 if ( aExtensions
.getLength() )
491 aExtension
= aExtensions
[0];
493 catch ( css::container::NoSuchElementException
& )
499 // Use provided save file name. If empty determine file name
500 aFileName
= aSaveFileName
;
501 if ( aFileName
.getLength() == 0 )
505 // Create a noname file name with the correct extension
506 const rtl::OUString
aNoNameFileName( RTL_CONSTASCII_USTRINGPARAM( "noname" ));
507 aFileName
= aNoNameFileName
;
511 // Determine file name from model
512 INetURLObject
aFileObj( xStorable
->getLocation() );
513 aFileName
= aFileObj
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::NO_DECODE
);
517 // No file name => error
518 if ( aFileName
.getLength() == 0 )
521 OSL_ASSERT( aFilterName
.getLength() > 0 );
522 OSL_ASSERT( aFileName
.getLength() > 0 );
524 // Creates a temporary directory to store a predefined file into it.
525 // This makes it possible to store the file for "send document as e-mail"
526 // with the original file name. We cannot use the original file as
527 // some mail programs need exclusive access.
528 ::utl::TempFile
aTempDir( NULL
, sal_True
);
530 INetURLObject
aFilePathObj( aTempDir
.GetURL() );
531 aFilePathObj
.insertName( aFileName
);
532 aFilePathObj
.setExtension( aExtension
);
534 rtl::OUString aFileURL
= aFilePathObj
.GetMainURL( INetURLObject::NO_DECODE
);
536 sal_Int32
nNumArgs(0);
537 const rtl::OUString
aPasswordPropName( RTL_CONSTASCII_USTRINGPARAM( "Password" ));
538 css::uno::Sequence
< css::beans::PropertyValue
> aArgs( ++nNumArgs
);
539 aArgs
[nNumArgs
-1].Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ));
540 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( aFilterName
);
542 ::comphelper::SequenceAsHashMap
aMediaDescrPropsHM( xModel
->getArgs() );
543 rtl::OUString aPassword
= aMediaDescrPropsHM
.getUnpackedValueOrDefault(
546 if ( aPassword
.getLength() > 0 )
548 aArgs
.realloc( ++nNumArgs
);
549 aArgs
[nNumArgs
-1].Name
= aPasswordPropName
;
550 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( aPassword
);
553 if ( bModified
|| !bHasLocation
|| bStoreTo
)
555 // Document is modified, is newly created or should be stored in a special format
558 css::uno::Reference
< css::util::XURLTransformer
> xURLTransformer(
559 xSMGR
->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))),
560 css::uno::UNO_QUERY
);
562 css::uno::Reference
< css::frame::XDispatchProvider
> xDispatchProvider( xFrame
, css::uno::UNO_QUERY
);
563 css::uno::Reference
< css::frame::XDispatch
> xDispatch
;
566 css::uno::Sequence
< css::beans::PropertyValue
> aDispatchArgs
;
570 if ( xURLTransformer
.is() )
572 aURL
.Complete
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:PrepareMailExport" ));
573 xURLTransformer
->parseStrict( aURL
);
576 if ( xDispatchProvider
.is() )
578 xDispatch
= css::uno::Reference
< css::frame::XDispatch
>(
579 xDispatchProvider
->queryDispatch( aURL
, ::rtl::OUString(), 0 ));
580 if ( xDispatch
.is() )
584 xDispatch
->dispatch( aURL
, aDispatchArgs
);
586 catch ( css::uno::RuntimeException
& )
590 catch ( css::uno::Exception
& )
597 //check if this is the pdf otput filter (i#64555)
600 SaveResult eShowPDFFilterDialog
= ShowFilterOptionsDialog(
601 xSMGR
, xModel
, aFilterName
, rType
, bModified
, nNumArgs
, aArgs
);
603 // don't continue on dialog cancel or error
604 if ( eShowPDFFilterDialog
!= SAVE_SUCCESSFULL
)
605 return eShowPDFFilterDialog
;
608 xStorable
->storeToURL( aFileURL
, aArgs
);
609 rFileNamePath
= aFileURL
;
610 eRet
= SAVE_SUCCESSFULL
;
614 // #i30432# notify that export is finished - the Writer may want to restore removed content
615 if ( xURLTransformer
.is() )
617 aURL
.Complete
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:MailExportFinished" ));
618 xURLTransformer
->parseStrict( aURL
);
621 if ( xDispatchProvider
.is() )
623 xDispatch
= css::uno::Reference
< css::frame::XDispatch
>(
624 xDispatchProvider
->queryDispatch( aURL
, ::rtl::OUString(), 0 ));
625 if ( xDispatch
.is() )
629 xDispatch
->dispatch( aURL
, aDispatchArgs
);
631 catch ( css::uno::RuntimeException
& )
635 catch ( css::uno::Exception
& )
641 // If the model is not modified, it could be modified by the dispatch calls.
642 // Therefore set back to modified = false. This should not hurt if we call
643 // on a non-modified model.
648 xModifiable
->setModified( sal_False
);
650 catch( com::sun::star::beans::PropertyVetoException
& )
655 catch ( com::sun::star::io::IOException
& )
662 // We need 1:1 copy of the document to preserve an added signature.
663 aArgs
.realloc( ++nNumArgs
);
664 aArgs
[nNumArgs
-1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyStreamIfPossible" ) );
665 aArgs
[nNumArgs
-1].Value
= css::uno::makeAny( (sal_Bool
)sal_True
);
669 xStorable
->storeToURL( aFileURL
, aArgs
);
670 rFileNamePath
= aFileURL
;
671 eRet
= SAVE_SUCCESSFULL
;
673 catch ( com::sun::star::io::IOException
& )
684 SfxMailModel::SfxMailModel() :
688 mePriority ( PRIO_NORMAL
),
689 mbLoadDone ( sal_True
)
693 SfxMailModel::~SfxMailModel()
695 ClearList( mpToList
);
697 ClearList( mpCcList
);
699 ClearList( mpBccList
);
703 void SfxMailModel::AddAddress( const String
& rAddress
, AddressRole eRole
)
705 // don't add a empty address
706 if ( rAddress
.Len() > 0 )
708 AddressList_Impl
* pList
= NULL
;
709 if ( ROLE_TO
== eRole
)
713 mpToList
= new AddressList_Impl
;
716 else if ( ROLE_CC
== eRole
)
720 mpCcList
= new AddressList_Impl
;
723 else if ( ROLE_BCC
== eRole
)
727 mpBccList
= new AddressList_Impl
;
732 DBG_ERRORFILE( "invalid address role" );
737 // add address to list
738 AddressItemPtr_Impl pAddress
= new String( rAddress
);
739 pList
->Insert( pAddress
, LIST_APPEND
);
744 SfxMailModel::SendMailResult
SfxMailModel::AttachDocument(
745 const ::rtl::OUString
& sDocumentType
,
746 const css::uno::Reference
< css::uno::XInterface
>& xFrameOrModel
,
747 const ::rtl::OUString
& sAttachmentTitle
)
749 rtl::OUString sFileName
;
751 SaveResult eSaveResult
= SaveDocumentAsFormat( sAttachmentTitle
, xFrameOrModel
, sDocumentType
, sFileName
);
752 if ( eSaveResult
== SAVE_SUCCESSFULL
&& ( sFileName
.getLength() > 0 ) )
753 maAttachedDocuments
.push_back(sFileName
);
754 return eSaveResult
== SAVE_SUCCESSFULL
? SEND_MAIL_OK
: SEND_MAIL_ERROR
;
757 SfxMailModel::SendMailResult
SfxMailModel::Send( const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
759 OSL_ENSURE(!maAttachedDocuments
.empty(),"No document added!");
760 SendMailResult eResult
= SEND_MAIL_ERROR
;
761 if ( !maAttachedDocuments
.empty() )
763 css::uno::Reference
< XMultiServiceFactory
> xMgr
= ::comphelper::getProcessServiceFactory();
766 css::uno::Reference
< XSimpleMailClientSupplier
> xSimpleMailClientSupplier
;
768 // Prefer the SimpleSystemMail service if available
769 xSimpleMailClientSupplier
= css::uno::Reference
< XSimpleMailClientSupplier
>(
770 xMgr
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleSystemMail" ))),
773 if ( ! xSimpleMailClientSupplier
.is() )
775 xSimpleMailClientSupplier
= css::uno::Reference
< XSimpleMailClientSupplier
>(
776 xMgr
->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleCommandMail" ))),
780 if ( xSimpleMailClientSupplier
.is() )
782 css::uno::Reference
< XSimpleMailClient
> xSimpleMailClient
= xSimpleMailClientSupplier
->querySimpleMailClient();
784 if ( !xSimpleMailClient
.is() )
786 // no mail client support => message box!
787 return SEND_MAIL_ERROR
;
790 // we have a simple mail client
791 css::uno::Reference
< XSimpleMailMessage
> xSimpleMailMessage
= xSimpleMailClient
->createSimpleMailMessage();
792 if ( xSimpleMailMessage
.is() )
794 sal_Int32 nSendFlags
= SimpleMailClientFlags::DEFAULTS
;
795 if ( maFromAddress
.Len() == 0 )
797 // from address not set, try figure out users e-mail address
798 CreateFromAddress_Impl( maFromAddress
);
800 xSimpleMailMessage
->setOriginator( maFromAddress
);
802 sal_Int32 nToCount
= mpToList
? mpToList
->Count() : 0;
803 sal_Int32 nCcCount
= mpCcList
? mpCcList
->Count() : 0;
804 sal_Int32 nCcSeqCount
= nCcCount
;
806 // set recipient (only one) for this simple mail server!!
809 nCcSeqCount
= nToCount
- 1 + nCcCount
;
810 xSimpleMailMessage
->setRecipient( *mpToList
->GetObject( 0 ));
811 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
813 else if ( nToCount
== 1 )
815 xSimpleMailMessage
->setRecipient( *mpToList
->GetObject( 0 ));
816 nSendFlags
= SimpleMailClientFlags::NO_USER_INTERFACE
;
819 // all other recipient must be handled with CC recipients!
820 if ( nCcSeqCount
> 0 )
822 sal_Int32 nIndex
= 0;
823 Sequence
< OUString
> aCcRecipientSeq
;
825 aCcRecipientSeq
.realloc( nCcSeqCount
);
826 if ( nCcSeqCount
> nCcCount
)
828 for ( sal_Int32 i
= 1; i
< nToCount
; ++i
)
830 aCcRecipientSeq
[nIndex
++] = *mpToList
->GetObject(i
);
834 for ( sal_Int32 i
= 0; i
< nCcCount
; i
++ )
836 aCcRecipientSeq
[nIndex
++] = *mpCcList
->GetObject(i
);
838 xSimpleMailMessage
->setCcRecipient( aCcRecipientSeq
);
841 sal_Int32 nBccCount
= mpBccList
? mpBccList
->Count() : 0;
844 Sequence
< OUString
> aBccRecipientSeq( nBccCount
);
845 for ( sal_Int32 i
= 0; i
< nBccCount
; ++i
)
847 aBccRecipientSeq
[i
] = *mpBccList
->GetObject(i
);
849 xSimpleMailMessage
->setBccRecipient( aBccRecipientSeq
);
852 Sequence
< OUString
> aAttachmentSeq(&(maAttachedDocuments
[0]),maAttachedDocuments
.size());
854 if ( xSimpleMailMessage
->getSubject().getLength() == 0 ) {
855 OUString
baseName( maAttachedDocuments
[0].copy( maAttachedDocuments
[0].lastIndexOf( '/' ) + 1 ) );
856 OUString
subject( baseName
);
857 if ( maAttachedDocuments
.size() > 1 )
858 subject
+= OUString::createFromAscii( ", ..." );
859 xSimpleMailMessage
->setSubject( subject
);
861 xSimpleMailMessage
->setAttachement( aAttachmentSeq
);
863 sal_Bool
bSend( sal_False
);
866 xSimpleMailClient
->sendSimpleMailMessage( xSimpleMailMessage
, nSendFlags
);
869 catch ( IllegalArgumentException
& )
876 if ( bSend
== sal_False
)
878 css::uno::Reference
< css::awt::XWindow
> xParentWindow
= xFrame
->getContainerWindow();
880 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
881 Window
* pParentWindow
= VCLUnoHelper::GetWindow( xParentWindow
);
883 ErrorBox
aBox( pParentWindow
, SfxResId( RID_ERRBOX_MAIL_CONFIG
));
885 eResult
= SEND_MAIL_CANCELLED
;
888 eResult
= SEND_MAIL_OK
;
894 eResult
= SEND_MAIL_CANCELLED
;
899 SfxMailModel::SendMailResult
SfxMailModel::SaveAndSend( const css::uno::Reference
< css::frame::XFrame
>& xFrame
, const rtl::OUString
& rTypeName
)
901 SaveResult eSaveResult
;
902 SendMailResult eResult
= SEND_MAIL_ERROR
;
903 rtl::OUString aFileName
;
905 eSaveResult
= SaveDocumentAsFormat( rtl::OUString(), xFrame
, rTypeName
, aFileName
);
907 if ( eSaveResult
== SAVE_SUCCESSFULL
)
909 maAttachedDocuments
.push_back( aFileName
);
910 return Send( xFrame
);
912 else if ( eSaveResult
== SAVE_CANCELLED
)
913 eResult
= SEND_MAIL_CANCELLED
;
918 // functions -------------------------------------------------------------
920 BOOL
CreateFromAddress_Impl( String
& rFrom
)
924 Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse
925 zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail'
926 aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder
927 nicht gesetzt sein, wird FALSE zur"uckgegeben.
931 TRUE: Adresse konnte erzeugt werden.
932 FALSE: Adresse konnte nicht erzeugt werden.
936 SvtUserOptions aUserCFG
;
937 String aName
= aUserCFG
.GetLastName ();
938 String aFirstName
= aUserCFG
.GetFirstName ();
939 if ( aFirstName
.Len() || aName
.Len() )
941 if ( aFirstName
.Len() )
943 rFrom
= TRIM( aFirstName
);
948 rFrom
+= TRIM( aName
);
949 // unerlaubte Zeichen entfernen
950 rFrom
.EraseAllChars( '<' );
951 rFrom
.EraseAllChars( '>' );
952 rFrom
.EraseAllChars( '@' );
954 String aEmailName
= aUserCFG
.GetEmail();
956 // unerlaubte Zeichen entfernen
957 aEmailName
.EraseAllChars( '<' );
958 aEmailName
.EraseAllChars( '>' );
960 if ( aEmailName
.Len() )
964 ( ( rFrom
+= '<' ) += TRIM( aEmailName
) ) += '>';
968 return ( rFrom
.Len() > 0 );