Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / dialog / mailmodel.cxx
bloba6362bdb6cd812ee437542d7a9a10fc191e135be
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>
58 #include <rtl/uri.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>
67 #include "dialog.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 >
101 bool m_bState;
102 public:
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() :
121 m_bState( false )
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;
137 else
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 )
154 if ( pList )
156 for( size_t i = 0, n = pList->size(); i < n; ++i )
157 delete pList->at(i);
158 pList->clear();
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 );
167 if ( xPropSet.is() )
169 Any a = xPropSet->getPropertyValue( rtl::OUString( "HasValidSignatures" ));
170 sal_Bool bReturn = sal_Bool();
171 if ( a >>= bReturn )
172 return bReturn;
175 catch ( css::uno::RuntimeException& )
177 throw;
179 catch ( css::uno::Exception& )
183 return sal_False;
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,
191 bool bModified,
192 sal_Int32& rNumArgs,
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() )
207 return eRet;
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 );
251 if( xExporter.is() )
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;
269 break;
272 eRet = SAVE_SUCCESSFULL;
274 else
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.
280 if ( !bModified )
284 xModifiable->setModified( sal_False );
286 catch( com::sun::star::beans::PropertyVetoException& )
290 eRet = SAVE_CANCELLED;
293 break;
299 catch( css::uno::RuntimeException& )
301 throw;
303 catch( uno::Exception& )
307 return eRet;
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();
325 if (!xSMGR.is())
326 return eRet;
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() )
331 return eRet;
333 rtl::OUString aModule;
336 aModule = xModuleManager->identify( xFrameOrModel );
338 catch ( css::uno::RuntimeException& )
340 throw;
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 );
348 if ( xFrame.is() )
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() )
378 bStoreTo = true;
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 );
392 if ( bStoreTo )
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 );
400 if( bSendAsPDF )
402 // #i91419#
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"),
419 ::rtl::OUString() );
422 if ( bHasLocation )
424 // Retrieve filter from media descriptor
425 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() );
426 rtl::OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault(
427 ::rtl::OUString( "FilterName" ),
428 ::rtl::OUString() );
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
433 // bStoreTo flag.
434 bStoreTo = false;
438 else
440 if ( bHasLocation )
442 // Retrieve filter from media descriptor
443 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() );
444 aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault(
445 ::rtl::OUString( "FilterName" ),
446 ::rtl::OUString() );
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"),
458 ::rtl::OUString() );
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"),
466 ::rtl::OUString() );
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 ))
482 return eRet;
484 // Determine filen name and extension
485 if ( bHasLocation && !bStoreTo )
487 INetURLObject aFileObj( xStorable->getLocation() );
488 aExtension = (rtl::OUString)aFileObj.getExtension();
490 else
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() )
519 if ( !bHasLocation )
521 // Create a noname file name with the correct extension
522 const rtl::OUString aNoNameFileName( "noname" );
523 aFileName = aNoNameFileName;
525 else
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() )
535 return eRet;
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(
560 aPasswordPropName,
561 ::rtl::OUString() );
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 );
576 if( !bSendAsPDF )
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& )
604 throw;
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& )
627 throw;
629 catch ( css::uno::Exception& )
635 //check if this is the pdf otput filter (i#64555)
636 if( bSendAsPDF )
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;
650 if( !bSendAsPDF )
652 css::util::URL aURL;
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& )
673 throw;
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.
684 if ( !bModified )
688 xModifiable->setModified( sal_False );
690 catch( com::sun::star::beans::PropertyVetoException& )
695 catch ( com::sun::star::io::IOException& )
697 eRet = SAVE_ERROR;
700 else
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& )
715 eRet = SAVE_ERROR;
721 return eRet;
724 SfxMailModel::SfxMailModel() :
725 mpToList ( NULL ),
726 mpCcList ( NULL ),
727 mpBccList ( NULL ),
728 mePriority ( PRIO_NORMAL ),
729 mbLoadDone ( sal_True )
733 SfxMailModel::~SfxMailModel()
735 ClearList( mpToList );
736 delete mpToList;
737 ClearList( mpCcList );
738 delete mpCcList;
739 ClearList( mpBccList );
740 delete 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 )
751 if ( !mpToList )
752 // create the list
753 mpToList = new AddressList_Impl();
754 pList = mpToList;
756 else if ( ROLE_CC == eRole )
758 if ( !mpCcList )
759 // create the list
760 mpCcList = new AddressList_Impl();
761 pList = mpCcList;
763 else if ( ROLE_BCC == eRole )
765 if ( !mpBccList )
766 // create the list
767 mpBccList = new AddressList_Impl();
768 pList = mpBccList;
770 else
772 SAL_WARN( "sfx2.dialog", "invalid address role" );
775 if ( pList )
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();
804 if ( xMgr.is() )
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" )),
811 UNO_QUERY );
813 if ( ! xSimpleMailClientSupplier.is() )
815 xSimpleMailClientSupplier = css::uno::Reference< XSimpleMailClientSupplier >(
816 xMgr->createInstance( OUString( "com.sun.star.system.SimpleCommandMail" )),
817 UNO_QUERY );
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!!
847 if ( nToCount > 1 )
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 )
862 size_t nIndex = 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;
882 if ( nBccCount > 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 );
907 bSend = sal_True;
909 catch ( IllegalArgumentException& )
912 catch ( Exception& )
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 ));
924 aBox.Execute();
925 eResult = SEND_MAIL_CANCELLED;
927 else
928 eResult = SEND_MAIL_OK;
933 else
934 eResult = SEND_MAIL_CANCELLED;
936 return eResult;
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;
955 return eResult;
958 // functions -------------------------------------------------------------
960 sal_Bool CreateFromAddress_Impl( String& rFrom )
962 /* [Description]
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.
968 [Return value]
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 );
984 if ( aName.Len() )
985 rFrom += ' ';
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() )
1001 if ( rFrom.Len() )
1002 rFrom += ' ';
1003 ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>';
1005 else
1006 rFrom.Erase();
1007 return ( rFrom.Len() > 0 );
1010 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */