update dev300-m58
[ooovba.git] / sfx2 / source / dialog / mailmodel.cxx
blob63748ebe9380392bd9911f90004d8f7a0b3c526d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: mailmodel.cxx,v $
10 * $Revision: 1.51 $
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>
55 #endif
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>
65 #endif
66 #include <rtl/uri.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>
75 #include "dialog.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 )
117 if ( pList )
119 ULONG i, nCount = pList->Count();
120 for ( i = 0; i < nCount; ++i )
121 delete pList->GetObject(i);
122 pList->Clear();
126 void SfxMailModel::MakeValueList( AddressList_Impl* pList, String& rValueList )
128 rValueList.Erase();
129 if ( pList )
131 ULONG i, nCount = pList->Count();
132 for ( i = 0; i < nCount; ++i )
134 if ( rValueList.Len() > 0 )
135 rValueList += ',';
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 );
146 if ( xPropSet.is() )
148 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasValidSignatures" )));
149 sal_Bool bReturn = sal_Bool();
150 if ( a >>= bReturn )
151 return bReturn;
154 catch ( css::uno::RuntimeException& )
156 throw;
158 catch ( css::uno::Exception& )
162 return sal_False;
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,
170 bool bModified,
171 sal_Int32& rNumArgs,
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() )
186 return eRet;
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 );
230 if( xExporter.is() )
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;
248 break;
251 eRet = SAVE_SUCCESSFULL;
253 else
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.
259 if ( !bModified )
263 xModifiable->setModified( sal_False );
265 catch( com::sun::star::beans::PropertyVetoException& )
269 eRet = SAVE_CANCELLED;
272 break;
278 catch( css::uno::RuntimeException& )
280 throw;
282 catch( uno::Exception& )
286 return eRet;
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();
309 if (!xSMGR.is())
310 return eRet;
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() )
315 return eRet;
317 rtl::OUString aModule;
320 aModule = xModuleManager->identify( xFrameOrModel );
322 catch ( css::uno::RuntimeException& )
324 throw;
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 );
332 if ( xFrame.is() )
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 )
362 bStoreTo = true;
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 );
376 if ( bStoreTo )
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 );
384 if( bSendAsPDF )
386 // #i91419#
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" ),
403 ::rtl::OUString() );
406 if ( bHasLocation )
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" )),
412 ::rtl::OUString() );
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
417 // bStoreTo flag.
418 bStoreTo = false;
422 else
424 if ( bHasLocation )
426 // Retrieve filter from media descriptor
427 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() );
428 aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault(
429 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )),
430 ::rtl::OUString() );
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" ),
442 ::rtl::OUString() );
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" ),
450 ::rtl::OUString() );
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 ))
466 return eRet;
468 // Determine filen name and extension
469 if ( bHasLocation && !bStoreTo )
471 INetURLObject aFileObj( xStorable->getLocation() );
472 aExtension = (rtl::OUString)aFileObj.getExtension();
474 else
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 )
503 if ( !bHasLocation )
505 // Create a noname file name with the correct extension
506 const rtl::OUString aNoNameFileName( RTL_CONSTASCII_USTRINGPARAM( "noname" ));
507 aFileName = aNoNameFileName;
509 else
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 )
519 return eRet;
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(
544 aPasswordPropName,
545 ::rtl::OUString() );
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;
565 css::util::URL aURL;
566 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs;
568 if( !bSendAsPDF )
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& )
588 throw;
590 catch ( css::uno::Exception& )
597 //check if this is the pdf otput filter (i#64555)
598 if( bSendAsPDF )
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;
612 if( !bSendAsPDF )
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& )
633 throw;
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.
644 if ( !bModified )
648 xModifiable->setModified( sal_False );
650 catch( com::sun::star::beans::PropertyVetoException& )
655 catch ( com::sun::star::io::IOException& )
657 eRet = SAVE_ERROR;
660 else
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& )
675 eRet = SAVE_ERROR;
681 return eRet;
684 SfxMailModel::SfxMailModel() :
685 mpToList ( NULL ),
686 mpCcList ( NULL ),
687 mpBccList ( NULL ),
688 mePriority ( PRIO_NORMAL ),
689 mbLoadDone ( sal_True )
693 SfxMailModel::~SfxMailModel()
695 ClearList( mpToList );
696 delete mpToList;
697 ClearList( mpCcList );
698 delete mpCcList;
699 ClearList( mpBccList );
700 delete 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 )
711 if ( !mpToList )
712 // create the list
713 mpToList = new AddressList_Impl;
714 pList = mpToList;
716 else if ( ROLE_CC == eRole )
718 if ( !mpCcList )
719 // create the list
720 mpCcList = new AddressList_Impl;
721 pList = mpCcList;
723 else if ( ROLE_BCC == eRole )
725 if ( !mpBccList )
726 // create the list
727 mpBccList = new AddressList_Impl;
728 pList = mpBccList;
730 else
732 DBG_ERRORFILE( "invalid address role" );
735 if ( pList )
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();
764 if ( xMgr.is() )
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" ))),
771 UNO_QUERY );
773 if ( ! xSimpleMailClientSupplier.is() )
775 xSimpleMailClientSupplier = css::uno::Reference< XSimpleMailClientSupplier >(
776 xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.system.SimpleCommandMail" ))),
777 UNO_QUERY );
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!!
807 if ( nToCount > 1 )
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;
842 if ( nBccCount > 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 );
867 bSend = sal_True;
869 catch ( IllegalArgumentException& )
872 catch ( Exception& )
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 ));
884 aBox.Execute();
885 eResult = SEND_MAIL_CANCELLED;
887 else
888 eResult = SEND_MAIL_OK;
893 else
894 eResult = SEND_MAIL_CANCELLED;
896 return eResult;
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;
915 return eResult;
918 // functions -------------------------------------------------------------
920 BOOL CreateFromAddress_Impl( String& rFrom )
922 /* [Beschreibung]
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.
929 [R"uckgabewert]
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 );
945 if ( aName.Len() )
946 rFrom += ' ';
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() )
962 if ( rFrom.Len() )
963 rFrom += ' ';
964 ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>';
966 else
967 rFrom.Erase();
968 return ( rFrom.Len() > 0 );