blob: 7d220fee60eca0d5d5654bcbec8e39148078022a [file] [log] [blame]
/**************************************************************
*
* 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 );
}