1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sfx2.hxx" 26 // includes -------------------------------------------------------------- 27 #include <com/sun/star/beans/PropertyValue.hpp> 28 #include <com/sun/star/beans/XPropertyAccess.hpp> 29 #include <com/sun/star/frame/XFrame.hpp> 30 #include <com/sun/star/frame/XModel.hpp> 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #include <com/sun/star/ucb/CommandAbortedException.hpp> 33 #include <com/sun/star/uno/Reference.h> 34 #include <com/sun/star/util/XURLTransformer.hpp> 35 #include <com/sun/star/system/SystemMailProvider.hpp> 36 #include <com/sun/star/system/MailClientFlags.hpp> 37 #include <com/sun/star/embed/XStorage.hpp> 38 #include <com/sun/star/embed/ElementModes.hpp> 39 #include <com/sun/star/embed/XTransactedObject.hpp> 40 #include <com/sun/star/container/XContainerQuery.hpp> 41 #include <com/sun/star/util/XModifiable.hpp> 42 #include <com/sun/star/frame/XModuleManager.hpp> 43 #include <com/sun/star/frame/XStorable.hpp> 44 #include <com/sun/star/beans/XPropertySet.hpp> 45 #include <com/sun/star/security/CertificateValidity.hpp> 46 #include <com/sun/star/security/DocumentSignatureInformation.hpp> 47 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp> 48 #include <com/sun/star/frame/XDispatchProvider.hpp> 49 #include <com/sun/star/frame/XDispatch.hpp> 50 #include <com/sun/star/frame/XStatusListener.hpp> 51 #include <com/sun/star/ucb/InsertCommandArgument.hpp> 52 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> 53 #include <com/sun/star/document/XExporter.hpp> 54 #include <rtl/textenc.h> 55 #include <rtl/uri.h> 56 #include <rtl/uri.hxx> 57 #include <rtl/ustrbuf.hxx> 58 #include <vcl/msgbox.hxx> 59 60 #include <sfx2/mailmodelapi.hxx> 61 #include "sfxtypes.hxx" 62 #include "sfx2/sfxresid.hxx" 63 #include <sfx2/sfxsids.hrc> 64 #include "dialog.hrc" 65 66 #include <unotools/tempfile.hxx> 67 #include <unotools/configitem.hxx> 68 #include <ucbhelper/content.hxx> 69 #include <tools/urlobj.hxx> 70 #include <unotools/useroptions.hxx> 71 #include <comphelper/processfactory.hxx> 72 #include <comphelper/extract.hxx> 73 #include <comphelper/storagehelper.hxx> 74 #include <comphelper/sequenceasvector.hxx> 75 #include <comphelper/sequenceashashmap.hxx> 76 #include <comphelper/mediadescriptor.hxx> 77 #include <toolkit/helper/vclunohelper.hxx> 78 #include <vcl/svapp.hxx> 79 #include <cppuhelper/implbase1.hxx> 80 81 // -------------------------------------------------------------- 82 using namespace ::com::sun::star; 83 using namespace ::com::sun::star::beans; 84 using namespace ::com::sun::star::frame; 85 using namespace ::com::sun::star::io; 86 using namespace ::com::sun::star::lang; 87 using namespace ::com::sun::star::ucb; 88 using namespace ::com::sun::star::uno; 89 using namespace ::com::sun::star::util; 90 91 using ::com::sun::star::system::SystemMailProvider; 92 using ::com::sun::star::system::XMailClient; 93 using ::com::sun::star::system::XMailMessage; 94 using ::com::sun::star::system::XSystemMailProvider; 95 using rtl::OUString; 96 97 namespace MailClientFlags = ::com::sun::star::system::MailClientFlags; 98 namespace css = ::com::sun::star; 99 100 101 // - class PrepareListener_Impl ------------------------------------------ 102 class PrepareListener_Impl : public ::cppu::WeakImplHelper1< css::frame::XStatusListener > 103 { 104 bool m_bState; 105 public: 106 PrepareListener_Impl(); 107 virtual ~PrepareListener_Impl(); 108 109 // css.frame.XStatusListener 110 virtual void SAL_CALL statusChanged(const css::frame::FeatureStateEvent& aEvent); 111 112 // css.lang.XEventListener 113 virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent); 114 115 bool IsSet() const {return m_bState;} 116 }; 117 118 /*-- 25.08.2010 14:32:49--------------------------------------------------- 119 120 -----------------------------------------------------------------------*/ 121 PrepareListener_Impl::PrepareListener_Impl() : 122 m_bState( false ) 123 { 124 } 125 /*-- 25.08.2010 14:32:51--------------------------------------------------- 126 127 -----------------------------------------------------------------------*/ 128 PrepareListener_Impl::~PrepareListener_Impl() 129 { 130 } 131 /*-- 25.08.2010 14:32:51--------------------------------------------------- 132 133 -----------------------------------------------------------------------*/ 134 void PrepareListener_Impl::statusChanged(const css::frame::FeatureStateEvent& rEvent) 135 { 136 if( rEvent.IsEnabled ) 137 rEvent.State >>= m_bState; 138 else 139 m_bState = sal_False; 140 } 141 /*-- 25.08.2010 14:32:52--------------------------------------------------- 142 143 -----------------------------------------------------------------------*/ 144 void PrepareListener_Impl::disposing(const css::lang::EventObject& /*rEvent*/) 145 { 146 } 147 148 // class AddressList_Impl ------------------------------------------------ 149 150 typedef String* AddressItemPtr_Impl; 151 DECLARE_LIST( AddressList_Impl, AddressItemPtr_Impl ) 152 153 // class SfxMailModel ----------------------------------------------- 154 155 static const char PDF_DOCUMENT_TYPE[] = "pdf_Portable_Document_Format"; 156 static const sal_uInt32 PDF_DOCUMENT_TYPE_LEN = 28; 157 158 void SfxMailModel::ClearList( AddressList_Impl* pList ) 159 { 160 if ( pList ) 161 { 162 sal_uIntPtr i, nCount = pList->Count(); 163 for ( i = 0; i < nCount; ++i ) 164 delete pList->GetObject(i); 165 pList->Clear(); 166 } 167 } 168 169 void SfxMailModel::MakeValueList( AddressList_Impl* pList, String& rValueList ) 170 { 171 rValueList.Erase(); 172 if ( pList ) 173 { 174 sal_uIntPtr i, nCount = pList->Count(); 175 for ( i = 0; i < nCount; ++i ) 176 { 177 if ( rValueList.Len() > 0 ) 178 rValueList += ','; 179 rValueList += *pList->GetObject(i); 180 } 181 } 182 } 183 184 sal_Bool HasDocumentValidSignature( const css::uno::Reference< css::frame::XModel >& xModel ) 185 { 186 try 187 { 188 css::uno::Reference< css::beans::XPropertySet > xPropSet( xModel, css::uno::UNO_QUERY ); 189 if ( xPropSet.is() ) 190 { 191 Any a = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HasValidSignatures" ))); 192 sal_Bool bReturn = sal_Bool(); 193 if ( a >>= bReturn ) 194 return bReturn; 195 } 196 } 197 catch ( css::uno::RuntimeException& ) 198 { 199 throw; 200 } 201 catch ( css::uno::Exception& ) 202 { 203 } 204 205 return sal_False; 206 } 207 208 SfxMailModel::SaveResult SfxMailModel::ShowFilterOptionsDialog( 209 uno::Reference< lang::XMultiServiceFactory > xSMGR, 210 uno::Reference< frame::XModel > xModel, 211 const rtl::OUString& rFilterName, 212 const rtl::OUString& rType, 213 bool bModified, 214 sal_Int32& rNumArgs, 215 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rArgs ) 216 { 217 SaveResult eRet( SAVE_ERROR ); 218 219 try 220 { 221 uno::Sequence < beans::PropertyValue > aProps; 222 ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess > xFilterCFG = 223 uno::Reference< container::XNameAccess >( 224 xSMGR->createInstance( 225 ::rtl::OUString::createFromAscii( "com.sun.star.document.FilterFactory" ) ), uno::UNO_QUERY ); 226 css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); 227 228 if ( !xFilterCFG.is() ) 229 return eRet; 230 231 uno::Any aAny = xFilterCFG->getByName( rFilterName ); 232 233 if ( aAny >>= aProps ) 234 { 235 sal_Int32 nPropertyCount = aProps.getLength(); 236 for( sal_Int32 nProperty=0; nProperty < nPropertyCount; ++nProperty ) 237 { 238 if( aProps[nProperty].Name.equals( ::rtl::OUString::createFromAscii( "UIComponent" )) ) 239 { 240 ::rtl::OUString aServiceName; 241 aProps[nProperty].Value >>= aServiceName; 242 if( aServiceName.getLength() ) 243 { 244 uno::Reference< ui::dialogs::XExecutableDialog > xFilterDialog( 245 xSMGR->createInstance( aServiceName ), uno::UNO_QUERY ); 246 uno::Reference< beans::XPropertyAccess > xFilterProperties( 247 xFilterDialog, uno::UNO_QUERY ); 248 249 if( xFilterDialog.is() && xFilterProperties.is() ) 250 { 251 uno::Sequence< beans::PropertyValue > aPropsForDialog(1); 252 uno::Reference< document::XExporter > xExporter( xFilterDialog, uno::UNO_QUERY ); 253 254 if ( rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )) 255 { 256 //add an internal property, used to tell the dialog we want to set a different 257 //string for the ok button 258 //used in filter/source/pdf/impdialog.cxx 259 String aOkSendText( SfxResId( STR_PDF_EXPORT_SEND )); 260 261 uno::Sequence< beans::PropertyValue > aFilterDataValue(1); 262 aFilterDataValue[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_OkButtonString" )); 263 aFilterDataValue[0].Value = css::uno::makeAny( ::rtl::OUString( aOkSendText )); 264 265 //add to the filterdata property, the only one the PDF export filter dialog will care for 266 aPropsForDialog[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterData" )); 267 aPropsForDialog[0].Value = css::uno::makeAny( aFilterDataValue ); 268 269 //when executing the dialog will merge the persistent FilterData properties 270 xFilterProperties->setPropertyValues( aPropsForDialog ); 271 } 272 273 if( xExporter.is() ) 274 xExporter->setSourceDocument( 275 uno::Reference< lang::XComponent >( xModel, uno::UNO_QUERY ) ); 276 277 if( xFilterDialog->execute() ) 278 { 279 //get the filter data 280 uno::Sequence< beans::PropertyValue > aPropsFromDialog = xFilterProperties->getPropertyValues(); 281 282 //add them to the args 283 for ( sal_Int32 nInd = 0; nInd < aPropsFromDialog.getLength(); nInd++ ) 284 { 285 if( aPropsFromDialog[ nInd ].Name.equals( ::rtl::OUString::createFromAscii( "FilterData" ) ) ) 286 { 287 //found the filterdata, add to the storing argument 288 rArgs.realloc( ++rNumArgs ); 289 rArgs[rNumArgs-1].Name = aPropsFromDialog[ nInd ].Name; 290 rArgs[rNumArgs-1].Value = aPropsFromDialog[ nInd ].Value; 291 break; 292 } 293 } 294 eRet = SAVE_SUCCESSFULL; 295 } 296 else 297 { 298 // cancel from dialog, then do not send 299 // If the model is not modified, it could be modified by the dispatch calls. 300 // Therefore set back to modified = false. This should not hurt if we call 301 // on a non-modified model. 302 if ( !bModified ) 303 { 304 try 305 { 306 xModifiable->setModified( sal_False ); 307 } 308 catch( com::sun::star::beans::PropertyVetoException& ) 309 { 310 } 311 } 312 eRet = SAVE_CANCELLED; 313 } 314 } 315 break; 316 } 317 } 318 } 319 } 320 } 321 catch( css::uno::RuntimeException& ) 322 { 323 throw; 324 } 325 catch( uno::Exception& ) 326 { 327 } 328 329 return eRet; 330 } 331 332 sal_Int32 SfxMailModel::GetCount() const 333 { 334 return maAttachedDocuments.size(); 335 } 336 337 sal_Bool SfxMailModel::IsEmpty() const 338 { 339 return maAttachedDocuments.empty(); 340 } 341 342 SfxMailModel::SaveResult SfxMailModel::SaveDocumentAsFormat( 343 const rtl::OUString& aSaveFileName, 344 const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, 345 const rtl::OUString& rType, 346 rtl::OUString& rFileNamePath ) 347 { 348 SaveResult eRet( SAVE_ERROR ); 349 bool bSendAsPDF = (rType.equalsAsciiL( PDF_DOCUMENT_TYPE, PDF_DOCUMENT_TYPE_LEN )); 350 351 css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); 352 if (!xSMGR.is()) 353 return eRet; 354 355 const rtl::OUString aModuleManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" )); 356 css::uno::Reference< css::frame::XModuleManager > xModuleManager( xSMGR->createInstance( aModuleManager ), css::uno::UNO_QUERY_THROW ); 357 if ( !xModuleManager.is() ) 358 return eRet; 359 360 rtl::OUString aModule; 361 try 362 { 363 aModule = xModuleManager->identify( xFrameOrModel ); 364 } 365 catch ( css::uno::RuntimeException& ) 366 { 367 throw; 368 } 369 catch ( css::uno::Exception& ) 370 { 371 } 372 373 css::uno::Reference< css::frame::XFrame > xFrame( xFrameOrModel, css::uno::UNO_QUERY ); 374 css::uno::Reference< css::frame::XModel > xModel( xFrameOrModel, css::uno::UNO_QUERY ); 375 if ( xFrame.is() ) 376 { 377 css::uno::Reference< css::frame::XController > xController = xFrame->getController(); 378 if ( xController.is() ) 379 xModel = xController->getModel(); 380 } 381 382 // We need at least a valid module name and model reference 383 if (( aModule.getLength() > 0 ) && xModel.is() ) 384 { 385 bool bModified( false ); 386 bool bHasLocation( false ); 387 bool bStoreTo( false ); 388 389 css::uno::Reference< css::util::XModifiable > xModifiable( xModel, css::uno::UNO_QUERY ); 390 css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); 391 392 if ( xModifiable.is() ) 393 bModified = xModifiable->isModified(); 394 if ( xStorable.is() ) 395 { 396 rtl::OUString aLocation = xStorable->getLocation(); 397 INetURLObject aFileObj( aLocation ); 398 399 bool bPrivateProtocol = ( aFileObj.GetProtocol() == INET_PROT_PRIV_SOFFICE ); 400 401 bHasLocation = ( aLocation.getLength() > 0 ) && !bPrivateProtocol; 402 OSL_ASSERT( !bPrivateProtocol ); 403 } 404 if ( rType.getLength() > 0 ) 405 bStoreTo = true; 406 407 if ( xStorable.is() ) 408 { 409 rtl::OUString aFilterName; 410 rtl::OUString aTypeName( rType ); 411 rtl::OUString aFileName; 412 rtl::OUString aExtension; 413 414 css::uno::Reference< css::container::XContainerQuery > xContainerQuery( 415 xSMGR->createInstance( rtl::OUString( 416 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ))), 417 css::uno::UNO_QUERY ); 418 419 if ( bStoreTo ) 420 { 421 // Retrieve filter from type 422 css::uno::Sequence< css::beans::NamedValue > aQuery( bSendAsPDF ? 3 : 2 ); 423 aQuery[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" )); 424 aQuery[0].Value = css::uno::makeAny( aTypeName ); 425 aQuery[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentService" )); 426 aQuery[1].Value = css::uno::makeAny( aModule ); 427 if( bSendAsPDF ) 428 { 429 // #i91419# 430 // FIXME: we want just an export filter. However currently we need 431 // exact flag value as detailed in the filter configuration to get it 432 // this seems to be a bug 433 // without flags we get an import filter here, which is also unwanted 434 aQuery[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Flags" )); 435 aQuery[2].Value = css::uno::makeAny( sal_Int32(0x80042) ); // EXPORT ALIEN 3RDPARTY 436 } 437 438 css::uno::Reference< css::container::XEnumeration > xEnumeration = 439 xContainerQuery->createSubSetEnumerationByProperties( aQuery ); 440 441 if ( xEnumeration->hasMoreElements() ) 442 { 443 ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() ); 444 aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( 445 ::rtl::OUString::createFromAscii( "Name" ), 446 ::rtl::OUString() ); 447 } 448 449 if ( bHasLocation ) 450 { 451 // Retrieve filter from media descriptor 452 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); 453 rtl::OUString aOrgFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( 454 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), 455 ::rtl::OUString() ); 456 if ( aOrgFilterName == aFilterName ) 457 { 458 // We should save the document in the original format. Therefore this 459 // is not a storeTo operation. To support signing in this case, reset 460 // bStoreTo flag. 461 bStoreTo = false; 462 } 463 } 464 } 465 else 466 { 467 if ( bHasLocation ) 468 { 469 // Retrieve filter from media descriptor 470 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); 471 aFilterName = aMediaDescrPropsHM.getUnpackedValueOrDefault( 472 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )), 473 ::rtl::OUString() ); 474 } 475 476 if ( !bHasLocation || ( aFilterName.getLength() == 0 )) 477 { 478 // Retrieve the user defined default filter 479 css::uno::Reference< css::container::XNameAccess > xNameAccess( xModuleManager, css::uno::UNO_QUERY ); 480 try 481 { 482 ::comphelper::SequenceAsHashMap aFilterPropsHM( xNameAccess->getByName( aModule ) ); 483 aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( 484 ::rtl::OUString::createFromAscii( "ooSetupFactoryDefaultFilter" ), 485 ::rtl::OUString() ); 486 css::uno::Reference< css::container::XNameAccess > xNameAccess2( 487 xContainerQuery, css::uno::UNO_QUERY ); 488 if ( xNameAccess2.is() ) 489 { 490 ::comphelper::SequenceAsHashMap aFilterPropsHM2( xNameAccess2->getByName( aFilterName ) ); 491 aTypeName = aFilterPropsHM2.getUnpackedValueOrDefault( 492 ::rtl::OUString::createFromAscii( "Type" ), 493 ::rtl::OUString() ); 494 } 495 } 496 catch ( css::container::NoSuchElementException& ) 497 { 498 } 499 catch ( css::beans::UnknownPropertyException& ) 500 { 501 } 502 } 503 } 504 505 // No filter found => error 506 // No type and no location => error 507 if (( aFilterName.getLength() == 0 ) || 508 (( aTypeName.getLength() == 0 ) && !bHasLocation )) 509 return eRet; 510 511 // Determine filen name and extension 512 if ( bHasLocation && !bStoreTo ) 513 { 514 INetURLObject aFileObj( xStorable->getLocation() ); 515 aExtension = (rtl::OUString)aFileObj.getExtension(); 516 } 517 else 518 { 519 css::uno::Reference< container::XNameAccess > xTypeDetection( 520 xSMGR->createInstance( ::rtl::OUString( 521 RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.TypeDetection" ))), 522 css::uno::UNO_QUERY ); 523 524 525 if ( xTypeDetection.is() ) 526 { 527 try 528 { 529 ::comphelper::SequenceAsHashMap aTypeNamePropsHM( xTypeDetection->getByName( aTypeName ) ); 530 uno::Sequence< ::rtl::OUString > aExtensions = aTypeNamePropsHM.getUnpackedValueOrDefault( 531 ::rtl::OUString::createFromAscii( "Extensions" ), 532 ::uno::Sequence< ::rtl::OUString >() ); 533 if ( aExtensions.getLength() ) 534 aExtension = aExtensions[0]; 535 } 536 catch ( css::container::NoSuchElementException& ) 537 { 538 } 539 } 540 } 541 542 // Use provided save file name. If empty determine file name 543 aFileName = aSaveFileName; 544 if ( aFileName.getLength() == 0 ) 545 { 546 if ( !bHasLocation ) 547 { 548 // Create a noname file name with the correct extension 549 const rtl::OUString aNoNameFileName( RTL_CONSTASCII_USTRINGPARAM( "noname" )); 550 aFileName = aNoNameFileName; 551 } 552 else 553 { 554 // Determine file name from model 555 INetURLObject aFileObj( xStorable->getLocation() ); 556 aFileName = aFileObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ); 557 } 558 } 559 560 // No file name => error 561 if ( aFileName.getLength() == 0 ) 562 return eRet; 563 564 OSL_ASSERT( aFilterName.getLength() > 0 ); 565 OSL_ASSERT( aFileName.getLength() > 0 ); 566 567 // Creates a temporary directory to store a predefined file into it. 568 // This makes it possible to store the file for "send document as e-mail" 569 // with the original file name. We cannot use the original file as 570 // some mail programs need exclusive access. 571 ::utl::TempFile aTempDir( NULL, sal_True ); 572 573 INetURLObject aFilePathObj( aTempDir.GetURL() ); 574 aFilePathObj.insertName( aFileName ); 575 aFilePathObj.setExtension( aExtension ); 576 577 rtl::OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::NO_DECODE ); 578 579 sal_Int32 nNumArgs(0); 580 const rtl::OUString aPasswordPropName( RTL_CONSTASCII_USTRINGPARAM( "Password" )); 581 css::uno::Sequence< css::beans::PropertyValue > aArgs( ++nNumArgs ); 582 aArgs[nNumArgs-1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); 583 aArgs[nNumArgs-1].Value = css::uno::makeAny( aFilterName ); 584 585 ::comphelper::SequenceAsHashMap aMediaDescrPropsHM( xModel->getArgs() ); 586 rtl::OUString aPassword = aMediaDescrPropsHM.getUnpackedValueOrDefault( 587 aPasswordPropName, 588 ::rtl::OUString() ); 589 if ( aPassword.getLength() > 0 ) 590 { 591 aArgs.realloc( ++nNumArgs ); 592 aArgs[nNumArgs-1].Name = aPasswordPropName; 593 aArgs[nNumArgs-1].Value = css::uno::makeAny( aPassword ); 594 } 595 596 bool bNeedsPreparation = false; 597 css::util::URL aPrepareURL; 598 css::uno::Reference< css::frame::XDispatch > xPrepareDispatch; 599 css::uno::Reference< css::frame::XDispatchProvider > xDispatchProvider( xFrame, css::uno::UNO_QUERY ); 600 css::uno::Reference< css::util::XURLTransformer > xURLTransformer( 601 xSMGR->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.URLTransformer" ))), 602 css::uno::UNO_QUERY ); 603 if( !bSendAsPDF ) 604 { 605 try 606 { 607 // check if the document needs to be prepared for sending as mail (embedding of links, removal of invisible content) 608 609 if ( xURLTransformer.is() ) 610 { 611 aPrepareURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:PrepareMailExport" )); 612 xURLTransformer->parseStrict( aPrepareURL ); 613 } 614 615 if ( xDispatchProvider.is() ) 616 { 617 xPrepareDispatch = css::uno::Reference< css::frame::XDispatch >( 618 xDispatchProvider->queryDispatch( aPrepareURL, ::rtl::OUString(), 0 )); 619 if ( xPrepareDispatch.is() ) 620 { 621 PrepareListener_Impl* pPrepareListener; 622 uno::Reference< css::frame::XStatusListener > xStatusListener = pPrepareListener = new PrepareListener_Impl; 623 xPrepareDispatch->addStatusListener( xStatusListener, aPrepareURL ); 624 bNeedsPreparation = pPrepareListener->IsSet(); 625 xPrepareDispatch->removeStatusListener( xStatusListener, aPrepareURL ); 626 } 627 } 628 } 629 catch ( css::uno::RuntimeException& ) 630 { 631 throw; 632 } 633 catch ( css::uno::Exception& ) 634 { 635 } 636 } 637 638 if ( bModified || !bHasLocation || bStoreTo || bNeedsPreparation ) 639 { 640 // Document is modified, is newly created or should be stored in a special format 641 try 642 { 643 if( bNeedsPreparation && xPrepareDispatch.is() ) 644 { 645 if ( xPrepareDispatch.is() ) 646 { 647 try 648 { 649 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; 650 xPrepareDispatch->dispatch( aPrepareURL, aDispatchArgs ); 651 } 652 catch ( css::uno::RuntimeException& ) 653 { 654 throw; 655 } 656 catch ( css::uno::Exception& ) 657 { 658 } 659 } 660 } 661 662 //check if this is the pdf output filter (i#64555) 663 if( bSendAsPDF ) 664 { 665 SaveResult eShowPDFFilterDialog = ShowFilterOptionsDialog( 666 xSMGR, xModel, aFilterName, rType, bModified, nNumArgs, aArgs ); 667 668 // don't continue on dialog cancel or error 669 if ( eShowPDFFilterDialog != SAVE_SUCCESSFULL ) 670 return eShowPDFFilterDialog; 671 } 672 673 xStorable->storeToURL( aFileURL, aArgs ); 674 rFileNamePath = aFileURL; 675 eRet = SAVE_SUCCESSFULL; 676 677 if( !bSendAsPDF ) 678 { 679 css::util::URL aURL; 680 // #i30432# notify that export is finished - the Writer may want to restore removed content 681 if ( xURLTransformer.is() ) 682 { 683 aURL.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:MailExportFinished" )); 684 xURLTransformer->parseStrict( aURL ); 685 } 686 687 if ( xDispatchProvider.is() ) 688 { 689 css::uno::Reference< css::frame::XDispatch > xDispatch = css::uno::Reference< css::frame::XDispatch >( 690 xDispatchProvider->queryDispatch( aURL, ::rtl::OUString(), 0 )); 691 if ( xDispatch.is() ) 692 { 693 try 694 { 695 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs; 696 xDispatch->dispatch( aURL, aDispatchArgs ); 697 } 698 catch ( css::uno::RuntimeException& ) 699 { 700 throw; 701 } 702 catch ( css::uno::Exception& ) 703 { 704 } 705 } 706 } 707 } 708 // If the model is not modified, it could be modified by the dispatch calls. 709 // Therefore set back to modified = false. This should not hurt if we call 710 // on a non-modified model. 711 if ( !bModified ) 712 { 713 try 714 { 715 xModifiable->setModified( sal_False ); 716 } 717 catch( com::sun::star::beans::PropertyVetoException& ) 718 { 719 } 720 } 721 } 722 catch ( com::sun::star::io::IOException& ) 723 { 724 eRet = SAVE_ERROR; 725 } 726 } 727 else 728 { 729 // We need 1:1 copy of the document to preserve an added signature. 730 aArgs.realloc( ++nNumArgs ); 731 aArgs[nNumArgs-1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CopyStreamIfPossible" ) ); 732 aArgs[nNumArgs-1].Value = css::uno::makeAny( (sal_Bool)sal_True ); 733 734 try 735 { 736 xStorable->storeToURL( aFileURL, aArgs ); 737 rFileNamePath = aFileURL; 738 eRet = SAVE_SUCCESSFULL; 739 } 740 catch ( com::sun::star::io::IOException& ) 741 { 742 eRet = SAVE_ERROR; 743 } 744 } 745 } 746 } 747 748 return eRet; 749 } 750 751 SfxMailModel::SfxMailModel() : 752 mpToList ( NULL ), 753 mpCcList ( NULL ), 754 mpBccList ( NULL ), 755 mePriority ( PRIO_NORMAL ), 756 mbLoadDone ( sal_True ) 757 { 758 } 759 760 SfxMailModel::~SfxMailModel() 761 { 762 ClearList( mpToList ); 763 delete mpToList; 764 ClearList( mpCcList ); 765 delete mpCcList; 766 ClearList( mpBccList ); 767 delete mpBccList; 768 } 769 770 void SfxMailModel::AddAddress( const String& rAddress, AddressRole eRole ) 771 { 772 // don't add a empty address 773 if ( rAddress.Len() > 0 ) 774 { 775 AddressList_Impl* pList = NULL; 776 if ( ROLE_TO == eRole ) 777 { 778 if ( !mpToList ) 779 // create the list 780 mpToList = new AddressList_Impl; 781 pList = mpToList; 782 } 783 else if ( ROLE_CC == eRole ) 784 { 785 if ( !mpCcList ) 786 // create the list 787 mpCcList = new AddressList_Impl; 788 pList = mpCcList; 789 } 790 else if ( ROLE_BCC == eRole ) 791 { 792 if ( !mpBccList ) 793 // create the list 794 mpBccList = new AddressList_Impl; 795 pList = mpBccList; 796 } 797 else 798 { 799 DBG_ERRORFILE( "invalid address role" ); 800 } 801 802 if ( pList ) 803 { 804 // add address to list 805 AddressItemPtr_Impl pAddress = new String( rAddress ); 806 pList->Insert( pAddress, LIST_APPEND ); 807 } 808 } 809 } 810 811 SfxMailModel::SendMailResult SfxMailModel::AttachDocument( 812 const ::rtl::OUString& sDocumentType, 813 const css::uno::Reference< css::uno::XInterface >& xFrameOrModel, 814 const ::rtl::OUString& sAttachmentTitle ) 815 { 816 rtl::OUString sFileName; 817 818 SaveResult eSaveResult = SaveDocumentAsFormat( sAttachmentTitle, xFrameOrModel, sDocumentType, sFileName ); 819 if ( eSaveResult == SAVE_SUCCESSFULL && ( sFileName.getLength() > 0 ) ) 820 maAttachedDocuments.push_back(sFileName); 821 return eSaveResult == SAVE_SUCCESSFULL ? SEND_MAIL_OK : SEND_MAIL_ERROR; 822 } 823 824 SfxMailModel::SendMailResult SfxMailModel::Send( const css::uno::Reference< css::frame::XFrame >& xFrame ) 825 { 826 OSL_ENSURE(!maAttachedDocuments.empty(),"No document added!"); 827 SendMailResult eResult = SEND_MAIL_ERROR; 828 if ( !maAttachedDocuments.empty() ) 829 { 830 css::uno::Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext(); 831 if ( xContext.is() ) 832 { 833 css::uno::Reference< XSystemMailProvider > xSystemMailProvider( SystemMailProvider::create( xContext ) ); 834 835 if ( xSystemMailProvider.is() ) 836 { 837 css::uno::Reference< XMailClient > xMailClient = xSystemMailProvider->queryMailClient(); 838 839 if ( !xMailClient.is() ) 840 { 841 // no mail client support => message box! 842 return SEND_MAIL_ERROR; 843 } 844 845 // we have a simple mail client 846 css::uno::Reference< XMailMessage > xMailMessage = xMailClient->createMailMessage(); 847 if ( xMailMessage.is() ) 848 { 849 sal_Int32 nSendFlags = MailClientFlags::DEFAULTS; 850 if ( maFromAddress.Len() == 0 ) 851 { 852 // from address not set, try figure out users e-mail address 853 CreateFromAddress_Impl( maFromAddress ); 854 } 855 xMailMessage->setOriginator( maFromAddress ); 856 857 sal_Int32 nToCount = mpToList ? mpToList->Count() : 0; 858 sal_Int32 nCcCount = mpCcList ? mpCcList->Count() : 0; 859 sal_Int32 nCcSeqCount = nCcCount; 860 861 // set recipient (only one) for this simple mail server!! 862 if ( nToCount > 1 ) 863 { 864 nCcSeqCount = nToCount - 1 + nCcCount; 865 xMailMessage->setRecipient( *mpToList->GetObject( 0 )); 866 nSendFlags = MailClientFlags::NO_USER_INTERFACE; 867 } 868 else if ( nToCount == 1 ) 869 { 870 xMailMessage->setRecipient( *mpToList->GetObject( 0 )); 871 nSendFlags = MailClientFlags::NO_USER_INTERFACE; 872 } 873 874 // all other recipient must be handled with CC recipients! 875 if ( nCcSeqCount > 0 ) 876 { 877 sal_Int32 nIndex = 0; 878 Sequence< OUString > aCcRecipientSeq; 879 880 aCcRecipientSeq.realloc( nCcSeqCount ); 881 if ( nCcSeqCount > nCcCount ) 882 { 883 for ( sal_Int32 i = 1; i < nToCount; ++i ) 884 { 885 aCcRecipientSeq[nIndex++] = *mpToList->GetObject(i); 886 } 887 } 888 889 for ( sal_Int32 i = 0; i < nCcCount; i++ ) 890 { 891 aCcRecipientSeq[nIndex++] = *mpCcList->GetObject(i); 892 } 893 xMailMessage->setCcRecipient( aCcRecipientSeq ); 894 } 895 896 sal_Int32 nBccCount = mpBccList ? mpBccList->Count() : 0; 897 if ( nBccCount > 0 ) 898 { 899 Sequence< OUString > aBccRecipientSeq( nBccCount ); 900 for ( sal_Int32 i = 0; i < nBccCount; ++i ) 901 { 902 aBccRecipientSeq[i] = *mpBccList->GetObject(i); 903 } 904 xMailMessage->setBccRecipient( aBccRecipientSeq ); 905 } 906 907 Sequence< OUString > aAttachmentSeq(&(maAttachedDocuments[0]),maAttachedDocuments.size()); 908 909 xMailMessage->setSubject( maSubject ); 910 xMailMessage->setAttachement( aAttachmentSeq ); 911 912 sal_Bool bSend( sal_False ); 913 try 914 { 915 xMailClient->sendMailMessage( xMailMessage, nSendFlags ); 916 bSend = sal_True; 917 } 918 catch ( IllegalArgumentException& ) 919 { 920 } 921 catch ( Exception& ) 922 { 923 } 924 925 if ( bSend == sal_False ) 926 { 927 css::uno::Reference< css::awt::XWindow > xParentWindow = xFrame->getContainerWindow(); 928 929 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 930 Window* pParentWindow = VCLUnoHelper::GetWindow( xParentWindow ); 931 932 ErrorBox aBox( pParentWindow, SfxResId( RID_ERRBOX_MAIL_CONFIG )); 933 aBox.Execute(); 934 eResult = SEND_MAIL_CANCELLED; 935 } 936 else 937 eResult = SEND_MAIL_OK; 938 } 939 } 940 } 941 } 942 else 943 eResult = SEND_MAIL_CANCELLED; 944 945 return eResult; 946 } 947 948 SfxMailModel::SendMailResult SfxMailModel::SaveAndSend( const css::uno::Reference< css::frame::XFrame >& xFrame, const rtl::OUString& rTypeName ) 949 { 950 SaveResult eSaveResult; 951 SendMailResult eResult = SEND_MAIL_ERROR; 952 rtl::OUString aFileName; 953 954 eSaveResult = SaveDocumentAsFormat( rtl::OUString(), xFrame, rTypeName, aFileName ); 955 956 if ( eSaveResult == SAVE_SUCCESSFULL ) 957 { 958 maAttachedDocuments.push_back( aFileName ); 959 return Send( xFrame ); 960 } 961 else if ( eSaveResult == SAVE_CANCELLED ) 962 eResult = SEND_MAIL_CANCELLED; 963 964 return eResult; 965 } 966 967 // functions ------------------------------------------------------------- 968 969 sal_Bool CreateFromAddress_Impl( String& rFrom ) 970 971 /* [Beschreibung] 972 973 Diese Funktion versucht mit Hilfe des IniManagers eine From-Adresse 974 zu erzeugen. daf"ur werden die Felder 'Vorname', 'Name' und 'EMail' 975 aus der Applikations-Ini-Datei ausgelesen. Sollten diese Felder 976 nicht gesetzt sein, wird FALSE zur"uckgegeben. 977 978 [R"uckgabewert] 979 980 sal_True: Adresse konnte erzeugt werden. 981 sal_False: Adresse konnte nicht erzeugt werden. 982 */ 983 984 { 985 SvtUserOptions aUserCFG; 986 String aName = aUserCFG.GetLastName (); 987 String aFirstName = aUserCFG.GetFirstName (); 988 if ( aFirstName.Len() || aName.Len() ) 989 { 990 if ( aFirstName.Len() ) 991 { 992 rFrom = TRIM( aFirstName ); 993 994 if ( aName.Len() ) 995 rFrom += ' '; 996 } 997 rFrom += TRIM( aName ); 998 // unerlaubte Zeichen entfernen 999 rFrom.EraseAllChars( '<' ); 1000 rFrom.EraseAllChars( '>' ); 1001 rFrom.EraseAllChars( '@' ); 1002 } 1003 String aEmailName = aUserCFG.GetEmail(); 1004 1005 // unerlaubte Zeichen entfernen 1006 aEmailName.EraseAllChars( '<' ); 1007 aEmailName.EraseAllChars( '>' ); 1008 1009 if ( aEmailName.Len() ) 1010 { 1011 if ( rFrom.Len() ) 1012 rFrom += ' '; 1013 ( ( rFrom += '<' ) += TRIM( aEmailName ) ) += '>'; 1014 } 1015 else 1016 rFrom.Erase(); 1017 return ( rFrom.Len() > 0 ); 1018 } 1019