| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| // includes -------------------------------------------------------------- |
| #include <com/sun/star/beans/PropertyValue.hpp> |
| #include <com/sun/star/beans/XPropertyAccess.hpp> |
| #include <com/sun/star/frame/XFrame.hpp> |
| #include <com/sun/star/frame/XModel.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/ucb/CommandAbortedException.hpp> |
| #include <com/sun/star/uno/Reference.h> |
| #include <com/sun/star/util/XURLTransformer.hpp> |
| #include <com/sun/star/system/SystemMailProvider.hpp> |
| #include <com/sun/star/system/MailClientFlags.hpp> |
| #include <com/sun/star/embed/XStorage.hpp> |
| #include <com/sun/star/embed/ElementModes.hpp> |
| #include <com/sun/star/embed/XTransactedObject.hpp> |
| #include <com/sun/star/container/XContainerQuery.hpp> |
| #include <com/sun/star/util/XModifiable.hpp> |
| #include <com/sun/star/frame/XModuleManager.hpp> |
| #include <com/sun/star/frame/XStorable.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/security/CertificateValidity.hpp> |
| #include <com/sun/star/security/DocumentSignatureInformation.hpp> |
| #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> |
| #include <com/sun/star/frame/XDispatchProvider.hpp> |
| #include <com/sun/star/frame/XDispatch.hpp> |
| #include <com/sun/star/frame/XStatusListener.hpp> |
| #include <com/sun/star/ucb/InsertCommandArgument.hpp> |
| #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> |
| #include <com/sun/star/document/XExporter.hpp> |
| #include <rtl/textenc.h> |
| #include <rtl/uri.h> |
| #include <rtl/uri.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <vcl/msgbox.hxx> |
| |
| #include <sfx2/mailmodelapi.hxx> |
| #include "sfxtypes.hxx" |
| #include "sfx2/sfxresid.hxx" |
| #include <sfx2/sfxsids.hrc> |
| #include "dialog.hrc" |
| |
| #include <unotools/tempfile.hxx> |
| #include <unotools/configitem.hxx> |
| #include <ucbhelper/content.hxx> |
| #include <tools/urlobj.hxx> |
| #include <unotools/useroptions.hxx> |
| #include <comphelper/processfactory.hxx> |
| #include <comphelper/extract.hxx> |
| #include <comphelper/storagehelper.hxx> |
| #include <comphelper/sequenceasvector.hxx> |
| #include <comphelper/sequenceashashmap.hxx> |
| #include <comphelper/mediadescriptor.hxx> |
| #include <toolkit/helper/vclunohelper.hxx> |
| #include <vcl/svapp.hxx> |
| #include <cppuhelper/implbase1.hxx> |
| |
| // -------------------------------------------------------------- |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::frame; |
| using namespace ::com::sun::star::io; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::ucb; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::util; |
| |
| using ::com::sun::star::system::SystemMailProvider; |
| using ::com::sun::star::system::XMailClient; |
| using ::com::sun::star::system::XMailMessage; |
| using ::com::sun::star::system::XSystemMailProvider; |
| using rtl::OUString; |
| |
| namespace MailClientFlags = ::com::sun::star::system::MailClientFlags; |
| namespace css = ::com::sun::star; |
| |
| |
| // - class PrepareListener_Impl ------------------------------------------ |
| class PrepareListener_Impl : public ::cppu::WeakImplHelper1< css::frame::XStatusListener > |
| { |
| bool m_bState; |
| public: |
| PrepareListener_Impl(); |
| virtual ~PrepareListener_Impl(); |
| |
| // css.frame.XStatusListener |
| virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& aEvent) |
| throw(css::uno::RuntimeException); |
| |
| // css.lang.XEventListener |
| virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) |
| throw(css::uno::RuntimeException); |
| |
| bool IsSet() const {return m_bState;} |
| }; |
| |
| /*-- 25.08.2010 14:32:49--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| PrepareListener_Impl::PrepareListener_Impl() : |
| m_bState( false ) |
| { |
| } |
| /*-- 25.08.2010 14:32:51--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| PrepareListener_Impl::~PrepareListener_Impl() |
| { |
| } |
| /*-- 25.08.2010 14:32:51--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent& rEvent) throw(css::uno::RuntimeException) |
| { |
| if( rEvent.IsEnabled ) |
| rEvent.State >>= m_bState; |
| else |
| m_bState = sal_False; |
| } |
| /*-- 25.08.2010 14:32:52--------------------------------------------------- |
| |
| -----------------------------------------------------------------------*/ |
| void PrepareListener_Impl::disposing(const css::lang::EventObject& /*rEvent*/) throw(css::uno::RuntimeException) |
| { |
| } |
| |
| // class AddressList_Impl ------------------------------------------------ |
| |
| typedef String* AddressItemPtr_Impl; |
| DECLARE_LIST( AddressList_Impl, AddressItemPtr_Impl ) |
| |
| // class SfxMailModel ----------------------------------------------- |
| |
| static const char PDF_DOCUMENT_TYPE[] = "pdf_Portable_Document_Format"; |
| static const sal_uInt32 PDF_DOCUMENT_TYPE_LEN = 28; |
| |
| void SfxMailModel::ClearList( AddressList_Impl* pList ) |
| { |
| if ( pList ) |
| { |
| sal_uIntPtr i, nCount = pList->Count(); |
| for ( i = 0; i < nCount; ++i ) |
| delete pList->GetObject(i); |
| pList->Clear(); |
| } |
| } |
| |
| void SfxMailModel::MakeValueList( AddressList_Impl* pList, String& rValueList ) |
| { |
| rValueList.Erase(); |
| if ( pList ) |
| { |
| sal_uIntPtr i, nCount = pList->Count(); |
| for ( i = 0; i < nCount; ++i ) |
| { |
| if ( rValueList.Len() > 0 ) |
| rValueList += ','; |
| rValueList += *pList->GetObject(i); |
| } |
| } |
| } |
| |
| sal_Bool HasDocumentValidSignature( const css::uno::Reference< css::frame::XModel >& xModel ) |
| { |
| try |
| { |
| css::uno::Reference< css::beans::XPropertySet > xPropSet( xModel, css::uno::UNO_QUERY ); |
| if ( xPropSet.is() ) |
| { |
| Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasValidSignatures" ))); |
| sal_Bool bReturn = sal_Bool(); |
| if ( a >>= bReturn ) |
| return bReturn; |
| } |
| } |
| catch ( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch ( css::uno::Exception& ) |
| { |
| } |
| |
| return sal_False; |
| } |
| |
| SfxMailModel::SaveResult SfxMailModel::ShowFilterOptionsDialog( |
| uno::Reference< lang::XMultiServiceFactory > xSMGR, |
| uno::Reference< frame::XModel > xModel, |
| const rtl::OUString& rFilterName, |
| const rtl::OUString& rType, |
| bool bModified, |
| sal_Int32& rNumArgs, |
| ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) |
| { |
| SaveResult eRet( SAVE_ERROR ); |
| |
| try |
| { |
| uno::Sequence < beans::PropertyValue > aProps; |
| ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG = |
| uno::Reference< container::XNameAccess >( |
| xSMGR->createInstance( |
| ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); |
| css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); |
| |
| if ( !xFilterCFG.is() ) |
| return eRet; |
| |
| uno::Any aAny = xFilterCFG->getByName( rFilterName ); |
| |
| if ( aAny >>= aProps ) |
| { |
| sal_Int32 nPropertyCount = aProps.getLength(); |
| for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) |
| { |
| if( aProps[nProperty].Name.equals( ::rtl::OUString::createFromAscii( "UIComponent" )) ) |
| { |
| ::rtl::OUString aServiceName; |
| aProps[nProperty].Value >>= aServiceName; |
| if( aServiceName.getLength() ) |
| { |
| uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog( |
| xSMGR->createInstance( aServiceName ), uno::UNO_QUERY ); |
| uno::Reference< beans::XPropertyAccess > xFilterProperties( |
| xFilterDialog, uno::UNO_QUERY ); |
| |
| if( xFilterDialog.is() && xFilterProperties.is() ) |
| { |
| uno::Sequence< beans::PropertyValue > aPropsForDialog(1); |
| uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY ); |
| |
| if ( rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )) |
| { |
| //add an internal property, used to tell the dialog we want to set a different |
| //string for the ok button |
| //used in filter/source/pdf/impdialog.cxx |
| String aOkSendText( SfxResId( STR_PDF_EXPORT_SEND )); |
| |
| uno::Sequence< beans::PropertyValue > aFilterDataValue(1); |
| aFilterDataValue[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_OkButtonString" )); |
| aFilterDataValue[0].Value = css::uno::makeAny( ::rtl::OUString( aOkSendText )); |
| |
| //add to the filterdata property, the only one the PDF export filter dialog will care for |
| aPropsForDialog[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterData" )); |
| aPropsForDialog[0].Value = css::uno::makeAny( aFilterDataValue ); |
| |
| //when executing the dialog will merge the persistent FilterData properties |
| xFilterProperties->setPropertyValues( aPropsForDialog ); |
| } |
| |
| if( xExporter.is() ) |
| xExporter->setSourceDocument( |
| uno::Reference< lang::XComponent >( xModel, uno::UNO_QUERY ) ); |
| |
| if( xFilterDialog->execute() ) |
| { |
| //get the filter data |
| uno::Sequence< beans::PropertyValue > aPropsFromDialog = xFilterProperties->getPropertyValues(); |
| |
| //add them to the args |
| for ( sal_Int32 nInd = 0; nInd < aPropsFromDialog.getLength(); nInd++ ) |
| { |
| if( aPropsFromDialog[ nInd ].Name.equals( ::rtl::OUString::createFromAscii( "FilterData" ) ) ) |
| { |
| //found the filterdata, add to the storing argument |
| rArgs.realloc( ++rNumArgs ); |
| rArgs[rNumArgs-1].Name = aPropsFromDialog[ nInd ].Name; |
| rArgs[rNumArgs-1].Value = aPropsFromDialog[ nInd ].Value; |
| break; |
| } |
| } |
| eRet = SAVE_SUCCESSFULL; |
| } |
| else |
| { |
| // cancel from dialog, then do not send |
| // If the model is not modified, it could be modified by the dispatch calls. |
| // Therefore set back to modified = false. This should not hurt if we call |
| // on a non-modified model. |
| if ( !bModified ) |
| { |
| try |
| { |
| xModifiable->setModified( sal_False ); |
| } |
| catch( com::sun::star::beans::PropertyVetoException& ) |
| { |
| } |
| } |
| eRet = SAVE_CANCELLED; |
| } |
| } |
| break; |
| } |
| } |
| } |
| } |
| } |
| catch( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch( uno::Exception& ) |
| { |
| } |
| |
| return eRet; |
| } |
| |
| sal_Int32 SfxMailModel::GetCount() const |
| { |
| return maAttachedDocuments.size(); |
| } |
| |
| sal_Bool SfxMailModel::IsEmpty() const |
| { |
| return maAttachedDocuments.empty(); |
| } |
| |
| SfxMailModel::SaveResult SfxMailModel::SaveDocumentAsFormat( |
| const rtl::OUString& aSaveFileName, |
| const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, |
| const rtl::OUString& rType, |
| rtl::OUString& rFileNamePath ) |
| { |
| SaveResult eRet( SAVE_ERROR ); |
| bool bSendAsPDF = (rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )); |
| |
| css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); |
| if (!xSMGR.is()) |
| return eRet; |
| |
| const rtl::OUString aModuleManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" )); |
| css::uno::Reference< css::frame::XModuleManager > xModuleManager( xSMGR->createInstance( aModuleManager ), css::uno::UNO_QUERY_THROW ); |
| if ( !xModuleManager.is() ) |
| return eRet; |
| |
| rtl::OUString aModule; |
| try |
| { |
| aModule = xModuleManager->identify( xFrameOrModel ); |
| } |
| catch ( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch ( css::uno::Exception& ) |
| { |
| } |
| |
| css::uno::Reference< css::frame::XFrame > xFrame( xFrameOrModel, css::uno::UNO_QUERY ); |
| css::uno::Reference< css::frame::XModel > xModel( xFrameOrModel, css::uno::UNO_QUERY ); |
| if ( xFrame.is() ) |
| { |
| css::uno::Reference< css::frame::XController > xController = xFrame->getController(); |
| if ( xController.is() ) |
| xModel = xController->getModel(); |
| } |
| |
| // We need at least a valid module name and model reference |
| if (( aModule.getLength() > 0 ) && xModel.is() ) |
| { |
| bool bModified( false ); |
| bool bHasLocation( false ); |
| bool bStoreTo( false ); |
| |
| css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); |
| css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); |
| |
| if ( xModifiable.is() ) |
| bModified = xModifiable->isModified(); |
| if ( xStorable.is() ) |
| { |
| rtl::OUString aLocation = xStorable->getLocation(); |
| INetURLObject aFileObj( aLocation ); |
| |
| bool bPrivateProtocol = ( aFileObj.GetProtocol() == INET_PROT_PRIV_SOFFICE ); |
| |
| bHasLocation = ( aLocation.getLength() > 0 ) && !bPrivateProtocol; |
| OSL_ASSERT( !bPrivateProtocol ); |
| } |
| if ( rType.getLength() > 0 ) |
| bStoreTo = true; |
| |
| if ( xStorable.is() ) |
| { |
| rtl::OUString aFilterName; |
| rtl::OUString aTypeName( rType ); |
| rtl::OUString aFileName; |
| rtl::OUString aExtension; |
| |
| css::uno::Reference< css::container::XContainerQuery > xContainerQuery( |
| xSMGR->createInstance( rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ))), |
| css::uno::UNO_QUERY ); |
| |
| if ( bStoreTo ) |
| { |
| // Retrieve filter from type |
| css::uno::Sequence< css::beans::NamedValue > aQuery( bSendAsPDF ? 3 : 2 ); |
| aQuery[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" )); |
| aQuery[0].Value = css::uno::makeAny( aTypeName ); |
| aQuery[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentService" )); |
| aQuery[1].Value = css::uno::makeAny( aModule ); |
| if( bSendAsPDF ) |
| { |
| // #i91419# |
| // FIXME: we want just an export filter. However currently we need |
| // exact flag value as detailed in the filter configuration to get it |
| // this seems to be a bug |
| // without flags we get an import filter here, which is also unwanted |
| aQuery[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Flags" )); |
| aQuery[2].Value = css::uno::makeAny( sal_Int32(0x80042) ); // EXPORT ALIEN 3RDPARTY |
| } |
| |
| css::uno::Reference< css::container::XEnumeration > xEnumeration = |
| xContainerQuery->createSubSetEnumerationByProperties( aQuery ); |
| |
| if ( xEnumeration->hasMoreElements() ) |
| { |
| ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() ); |
| aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( |
| ::rtl::OUString::createFromAscii( "Name" ), |
| ::rtl::OUString() ); |
| } |
| |
| if ( bHasLocation ) |
| { |
| // Retrieve filter from media descriptor |
| ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); |
| rtl::OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), |
| ::rtl::OUString() ); |
| if ( aOrgFilterName == aFilterName ) |
| { |
| // We should save the document in the original format. Therefore this |
| // is not a storeTo operation. To support signing in this case, reset |
| // bStoreTo flag. |
| bStoreTo = false; |
| } |
| } |
| } |
| else |
| { |
| if ( bHasLocation ) |
| { |
| // Retrieve filter from media descriptor |
| ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); |
| aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), |
| ::rtl::OUString() ); |
| } |
| |
| if ( !bHasLocation || ( aFilterName.getLength() == 0 )) |
| { |
| // Retrieve the user defined default filter |
| css::uno::Reference< css::container::XNameAccess > xNameAccess( xModuleManager, css::uno::UNO_QUERY ); |
| try |
| { |
| ::comphelper::SequenceAsHashMap aFilterPropsHM( xNameAccess->getByName( aModule ) ); |
| aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( |
| ::rtl::OUString::createFromAscii( "ooSetupFactoryDefaultFilter" ), |
| ::rtl::OUString() ); |
| css::uno::Reference< css::container::XNameAccess > xNameAccess2( |
| xContainerQuery, css::uno::UNO_QUERY ); |
| if ( xNameAccess2.is() ) |
| { |
| ::comphelper::SequenceAsHashMap aFilterPropsHM2( xNameAccess2->getByName( aFilterName ) ); |
| aTypeName = aFilterPropsHM2.getUnpackedValueOrDefault( |
| ::rtl::OUString::createFromAscii( "Type" ), |
| ::rtl::OUString() ); |
| } |
| } |
| catch ( css::container::NoSuchElementException& ) |
| { |
| } |
| catch ( css::beans::UnknownPropertyException& ) |
| { |
| } |
| } |
| } |
| |
| // No filter found => error |
| // No type and no location => error |
| if (( aFilterName.getLength() == 0 ) || |
| (( aTypeName.getLength() == 0 ) && !bHasLocation )) |
| return eRet; |
| |
| // Determine filen name and extension |
| if ( bHasLocation && !bStoreTo ) |
| { |
| INetURLObject aFileObj( xStorable->getLocation() ); |
| aExtension = (rtl::OUString)aFileObj.getExtension(); |
| } |
| else |
| { |
| css::uno::Reference< container::XNameAccess > xTypeDetection( |
| xSMGR->createInstance( ::rtl::OUString( |
| RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ))), |
| css::uno::UNO_QUERY ); |
| |
| |
| if ( xTypeDetection.is() ) |
| { |
| try |
| { |
| ::comphelper::SequenceAsHashMap aTypeNamePropsHM( xTypeDetection->getByName( aTypeName ) ); |
| uno::Sequence< ::rtl::OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault( |
| ::rtl::OUString::createFromAscii( "Extensions" ), |
| ::uno::Sequence< ::rtl::OUString >() ); |
| if ( aExtensions.getLength() ) |
| aExtension = aExtensions[0]; |
| } |
| catch ( css::container::NoSuchElementException& ) |
| { |
| } |
| } |
| } |
| |
| // Use provided save file name. If empty determine file name |
| aFileName = aSaveFileName; |
| if ( aFileName.getLength() == 0 ) |
| { |
| if ( !bHasLocation ) |
| { |
| // Create a noname file name with the correct extension |
| const rtl::OUString aNoNameFileName( RTL_CONSTASCII_USTRINGPARAM( "noname" )); |
| aFileName = aNoNameFileName; |
| } |
| else |
| { |
| // Determine file name from model |
| INetURLObject aFileObj( xStorable->getLocation() ); |
| aFileName = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ); |
| } |
| } |
| |
| // No file name => error |
| if ( aFileName.getLength() == 0 ) |
| return eRet; |
| |
| OSL_ASSERT( aFilterName.getLength() > 0 ); |
| OSL_ASSERT( aFileName.getLength() > 0 ); |
| |
| // Creates a temporary directory to store a predefined file into it. |
| // This makes it possible to store the file for "send document as e-mail" |
| // with the original file name. We cannot use the original file as |
| // some mail programs need exclusive access. |
| ::utl::TempFile aTempDir( NULL, sal_True ); |
| |
| INetURLObject aFilePathObj( aTempDir.GetURL() ); |
| aFilePathObj.insertName( aFileName ); |
| aFilePathObj.setExtension( aExtension ); |
| |
| rtl::OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::NO_DECODE ); |
| |
| sal_Int32 nNumArgs(0); |
| const rtl::OUString aPasswordPropName( RTL_CONSTASCII_USTRINGPARAM( "Password" )); |
| css::uno::Sequence< css::beans::PropertyValue > aArgs( ++nNumArgs ); |
| aArgs[nNumArgs-1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); |
| aArgs[nNumArgs-1].Value = css::uno::makeAny( aFilterName ); |
| |
| ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); |
| rtl::OUString aPassword = aMediaDescrPropsHM.getUnpackedValueOrDefault( |
| aPasswordPropName, |
| ::rtl::OUString() ); |
| if ( aPassword.getLength() > 0 ) |
| { |
| aArgs.realloc( ++nNumArgs ); |
| aArgs[nNumArgs-1].Name = aPasswordPropName; |
| aArgs[nNumArgs-1].Value = css::uno::makeAny( aPassword ); |
| } |
| |
| bool bNeedsPreparation = false; |
| css::util::URL aPrepareURL; |
| css::uno::Reference< css::frame::XDispatch > xPrepareDispatch; |
| css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xFrame, css::uno::UNO_QUERY ); |
| css::uno::Reference< css::util::XURLTransformer > xURLTransformer( |
| xSMGR->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), |
| css::uno::UNO_QUERY ); |
| if( !bSendAsPDF ) |
| { |
| try |
| { |
| // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content) |
| |
| if ( xURLTransformer.is() ) |
| { |
| aPrepareURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:PrepareMailExport" )); |
| xURLTransformer->parseStrict( aPrepareURL ); |
| } |
| |
| if ( xDispatchProvider.is() ) |
| { |
| xPrepareDispatch = css::uno::Reference< css::frame::XDispatch >( |
| xDispatchProvider->queryDispatch( aPrepareURL, ::rtl::OUString(), 0 )); |
| if ( xPrepareDispatch.is() ) |
| { |
| PrepareListener_Impl* pPrepareListener; |
| uno::Reference< css::frame::XStatusListener > xStatusListener = pPrepareListener = new PrepareListener_Impl; |
| xPrepareDispatch->addStatusListener( xStatusListener, aPrepareURL ); |
| bNeedsPreparation = pPrepareListener->IsSet(); |
| xPrepareDispatch->removeStatusListener( xStatusListener, aPrepareURL ); |
| } |
| } |
| } |
| catch ( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch ( css::uno::Exception& ) |
| { |
| } |
| } |
| |
| if ( bModified || !bHasLocation || bStoreTo || bNeedsPreparation ) |
| { |
| // Document is modified, is newly created or should be stored in a special format |
| try |
| { |
| if( bNeedsPreparation && xPrepareDispatch.is() ) |
| { |
| if ( xPrepareDispatch.is() ) |
| { |
| try |
| { |
| css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; |
| xPrepareDispatch->dispatch( aPrepareURL, aDispatchArgs ); |
| } |
| catch ( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch ( css::uno::Exception& ) |
| { |
| } |
| } |
| } |
| |
| //check if this is the pdf otput filter (i#64555) |
| if( bSendAsPDF ) |
| { |
| SaveResult eShowPDFFilterDialog = ShowFilterOptionsDialog( |
| xSMGR, xModel, aFilterName, rType, bModified, nNumArgs, aArgs ); |
| |
| // don't continue on dialog cancel or error |
| if ( eShowPDFFilterDialog != SAVE_SUCCESSFULL ) |
| return eShowPDFFilterDialog; |
| } |
| |
| xStorable->storeToURL( aFileURL, aArgs ); |
| rFileNamePath = aFileURL; |
| eRet = SAVE_SUCCESSFULL; |
| |
| if( !bSendAsPDF ) |
| { |
| css::util::URL aURL; |
| // #i30432# notify that export is finished - the Writer may want to restore removed content |
| if ( xURLTransformer.is() ) |
| { |
| aURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:MailExportFinished" )); |
| xURLTransformer->parseStrict( aURL ); |
| } |
| |
| if ( xDispatchProvider.is() ) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatch = css::uno::Reference< css::frame::XDispatch >( |
| xDispatchProvider->queryDispatch( aURL, ::rtl::OUString(), 0 )); |
| if ( xDispatch.is() ) |
| { |
| try |
| { |
| css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; |
| xDispatch->dispatch( aURL, aDispatchArgs ); |
| } |
| catch ( css::uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch ( css::uno::Exception& ) |
| { |
| } |
| } |
| } |
| } |
| // If the model is not modified, it could be modified by the dispatch calls. |
| // Therefore set back to modified = false. This should not hurt if we call |
| // on a non-modified model. |
| if ( !bModified ) |
| { |
| try |
| { |
| xModifiable->setModified( sal_False ); |
| } |
| catch( com::sun::star::beans::PropertyVetoException& ) |
| { |
| } |
| } |
| } |
| catch ( com::sun::star::io::IOException& ) |
| { |
| eRet = SAVE_ERROR; |
| } |
| } |
| else |
| { |
| // We need 1:1 copy of the document to preserve an added signature. |
| aArgs.realloc( ++nNumArgs ); |
| aArgs[nNumArgs-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyStreamIfPossible" ) ); |
| aArgs[nNumArgs-1].Value = css::uno::makeAny( (sal_Bool)sal_True ); |
| |
| try |
| { |
| xStorable->storeToURL( aFileURL, aArgs ); |
| rFileNamePath = aFileURL; |
| eRet = SAVE_SUCCESSFULL; |
| } |
| catch ( com::sun::star::io::IOException& ) |
| { |
| eRet = SAVE_ERROR; |
| } |
| } |
| } |
| } |
| |
| return eRet; |
| } |
| |
| SfxMailModel::SfxMailModel() : |
| mpToList ( NULL ), |
| mpCcList ( NULL ), |
| mpBccList ( NULL ), |
| mePriority ( PRIO_NORMAL ), |
| mbLoadDone ( sal_True ) |
| { |
| } |
| |
| SfxMailModel::~SfxMailModel() |
| { |
| ClearList( mpToList ); |
| delete mpToList; |
| ClearList( mpCcList ); |
| delete mpCcList; |
| ClearList( mpBccList ); |
| delete mpBccList; |
| } |
| |
| void SfxMailModel::AddAddress( const String& rAddress, AddressRole eRole ) |
| { |
| // don't add a empty address |
| if ( rAddress.Len() > 0 ) |
| { |
| AddressList_Impl* pList = NULL; |
| if ( ROLE_TO == eRole ) |
| { |
| if ( !mpToList ) |
| // create the list |
| mpToList = new AddressList_Impl; |
| pList = mpToList; |
| } |
| else if ( ROLE_CC == eRole ) |
| { |
| if ( !mpCcList ) |
| // create the list |
| mpCcList = new AddressList_Impl; |
| pList = mpCcList; |
| } |
| else if ( ROLE_BCC == eRole ) |
| { |
| if ( !mpBccList ) |
| // create the list |
| mpBccList = new AddressList_Impl; |
| pList = mpBccList; |
| } |
| else |
| { |
| DBG_ERRORFILE( "invalid address role" ); |
| } |
| |
| if ( pList ) |
| { |
| // add address to list |
| AddressItemPtr_Impl pAddress = new String( rAddress ); |
| pList->Insert( pAddress, LIST_APPEND ); |
| } |
| } |
| } |
| |
| SfxMailModel::SendMailResult SfxMailModel::AttachDocument( |
| const ::rtl::OUString& sDocumentType, |
| const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, |
| const ::rtl::OUString& sAttachmentTitle ) |
| { |
| rtl::OUString sFileName; |
| |
| SaveResult eSaveResult = SaveDocumentAsFormat( sAttachmentTitle, xFrameOrModel, sDocumentType, sFileName ); |
| if ( eSaveResult == SAVE_SUCCESSFULL && ( sFileName.getLength() > 0 ) ) |
| maAttachedDocuments.push_back(sFileName); |
| return eSaveResult == SAVE_SUCCESSFULL ? SEND_MAIL_OK : SEND_MAIL_ERROR; |
| } |
| |
| SfxMailModel::SendMailResult SfxMailModel::Send( const css::uno::Reference< css::frame::XFrame >& xFrame ) |
| { |
| OSL_ENSURE(!maAttachedDocuments.empty(),"No document added!"); |
| SendMailResult eResult = SEND_MAIL_ERROR; |
| if ( !maAttachedDocuments.empty() ) |
| { |
| css::uno::Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext(); |
| if ( xContext.is() ) |
| { |
| css::uno::Reference< XSystemMailProvider > xSystemMailProvider( SystemMailProvider::create( xContext ) ); |
| |
| if ( xSystemMailProvider.is() ) |
| { |
| css::uno::Reference< XMailClient > xMailClient = xSystemMailProvider->queryMailClient(); |
| |
| if ( !xMailClient.is() ) |
| { |
| // no mail client support => message box! |
| return SEND_MAIL_ERROR; |
| } |
| |
| // we have a simple mail client |
| css::uno::Reference< XMailMessage > xMailMessage = xMailClient->createMailMessage(); |
| if ( xMailMessage.is() ) |
| { |
| sal_Int32 nSendFlags = MailClientFlags::DEFAULTS; |
| if ( maFromAddress.Len() == 0 ) |
| { |
| // from address not set, try figure out users e-mail address |
| CreateFromAddress_Impl( maFromAddress ); |
| } |
| xMailMessage->setOriginator( maFromAddress ); |
| |
| sal_Int32 nToCount = mpToList ? mpToList->Count() : 0; |
| sal_Int32 nCcCount = mpCcList ? mpCcList->Count() : 0; |
| sal_Int32 nCcSeqCount = nCcCount; |
| |
| // set recipient (only one) for this simple mail server!! |
| if ( nToCount > 1 ) |
| { |
| nCcSeqCount = nToCount - 1 + nCcCount; |
| xMailMessage->setRecipient( *mpToList->GetObject( 0 )); |
| nSendFlags = MailClientFlags::NO_USER_INTERFACE; |
| } |
| else if ( nToCount == 1 ) |
| { |
| xMailMessage->setRecipient( *mpToList->GetObject( 0 )); |
| nSendFlags = MailClientFlags::NO_USER_INTERFACE; |
| } |
| |
| // all other recipient must be handled with CC recipients! |
| if ( nCcSeqCount > 0 ) |
| { |
| sal_Int32 nIndex = 0; |
| Sequence< OUString > aCcRecipientSeq; |
| |
| aCcRecipientSeq.realloc( nCcSeqCount ); |
| if ( nCcSeqCount > nCcCount ) |
| { |
| for ( sal_Int32 i = 1; i < nToCount; ++i ) |
| { |
| aCcRecipientSeq[nIndex++] = *mpToList->GetObject(i); |
| } |
| } |
| |
| for ( sal_Int32 i = 0; i < nCcCount; i++ ) |
| { |
| aCcRecipientSeq[nIndex++] = *mpCcList->GetObject(i); |
| } |
| xMailMessage->setCcRecipient( aCcRecipientSeq ); |
| } |
| |
| sal_Int32 nBccCount = mpBccList ? mpBccList->Count() : 0; |
| if ( nBccCount > 0 ) |
| { |
| Sequence< OUString > aBccRecipientSeq( nBccCount ); |
| for ( sal_Int32 i = 0; i < nBccCount; ++i ) |
| { |
| aBccRecipientSeq[i] = *mpBccList->GetObject(i); |
| } |
| xMailMessage->setBccRecipient( aBccRecipientSeq ); |
| } |
| |
| Sequence< OUString > aAttachmentSeq(&(maAttachedDocuments[0]),maAttachedDocuments.size()); |
| |
| xMailMessage->setSubject( maSubject ); |
| xMailMessage->setAttachement( aAttachmentSeq ); |
| |
| sal_Bool bSend( sal_False ); |
| try |
| { |
| xMailClient->sendMailMessage( xMailMessage, nSendFlags ); |
| bSend = sal_True; |
| } |
| catch ( IllegalArgumentException& ) |
| { |
| } |
| catch ( Exception& ) |
| { |
| } |
| |
| if ( bSend == sal_False ) |
| { |
| css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow(); |
| |
| ::vos::OGuard aGuard( Application::GetSolarMutex() ); |
| Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); |
| |
| ErrorBox aBox( pParentWindow, SfxResId( RID_ERRBOX_MAIL_CONFIG )); |
| aBox.Execute(); |
| eResult = SEND_MAIL_CANCELLED; |
| } |
| else |
| eResult = SEND_MAIL_OK; |
| } |
| } |
| } |
| } |
| else |
| eResult = SEND_MAIL_CANCELLED; |
| |
| return eResult; |
| } |
| |
| SfxMailModel::SendMailResult SfxMailModel::SaveAndSend( const css::uno::Reference< css::frame::XFrame >& xFrame, const rtl::OUString& rTypeName ) |
| { |
| SaveResult eSaveResult; |
| SendMailResult eResult = SEND_MAIL_ERROR; |
| rtl::OUString aFileName; |
| |
| eSaveResult = SaveDocumentAsFormat( rtl::OUString(), xFrame, rTypeName, aFileName ); |
| |
| if ( eSaveResult == SAVE_SUCCESSFULL ) |
| { |
| maAttachedDocuments.push_back( aFileName ); |
| return Send( xFrame ); |
| } |
| else if ( eSaveResult == SAVE_CANCELLED ) |
| eResult = SEND_MAIL_CANCELLED; |
| |
| return eResult; |
| } |
| |
| // functions ------------------------------------------------------------- |
| |
| sal_Bool CreateFromAddress_Impl( String& rFrom ) |
| |
| /* [Beschreibung] |
| |
| Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse |
| zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail' |
| aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder |
| nicht gesetzt sein, wird FALSE zur"uckgegeben. |
| |
| [R"uckgabewert] |
| |
| sal_True: Adresse konnte erzeugt werden. |
| sal_False: Adresse konnte nicht erzeugt werden. |
| */ |
| |
| { |
| SvtUserOptions aUserCFG; |
| String aName = aUserCFG.GetLastName (); |
| String aFirstName = aUserCFG.GetFirstName (); |
| if ( aFirstName.Len() || aName.Len() ) |
| { |
| if ( aFirstName.Len() ) |
| { |
| rFrom = TRIM( aFirstName ); |
| |
| if ( aName.Len() ) |
| rFrom += ' '; |
| } |
| rFrom += TRIM( aName ); |
| // unerlaubte Zeichen entfernen |
| rFrom.EraseAllChars( '<' ); |
| rFrom.EraseAllChars( '>' ); |
| rFrom.EraseAllChars( '@' ); |
| } |
| String aEmailName = aUserCFG.GetEmail(); |
| |
| // unerlaubte Zeichen entfernen |
| aEmailName.EraseAllChars( '<' ); |
| aEmailName.EraseAllChars( '>' ); |
| |
| if ( aEmailName.Len() ) |
| { |
| if ( rFrom.Len() ) |
| rFrom += ' '; |
| ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>'; |
| } |
| else |
| rFrom.Erase(); |
| return ( rFrom.Len() > 0 ); |
| } |