LibreOffice Module desktop (master)  1
dispatchwatcher.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <sal/log.hxx>
23 #include <sfx2/docfile.hxx>
24 #include <sfx2/docfilt.hxx>
25 #include <sfx2/fcontnr.hxx>
26 #include <svl/fstathelper.hxx>
27 
28 #include <app.hxx>
29 #include "dispatchwatcher.hxx"
30 #include "officeipcthread.hxx"
31 #include <rtl/ustring.hxx>
34 #include <com/sun/star/io/IOException.hpp>
35 #include <com/sun/star/util/XCloseable.hpp>
36 #include <com/sun/star/util/CloseVetoException.hpp>
37 #include <com/sun/star/task/InteractionHandler.hpp>
38 #include <com/sun/star/util/URL.hpp>
39 #include <com/sun/star/frame/Desktop.hpp>
40 #include <com/sun/star/container/XContainerQuery.hpp>
41 #include <com/sun/star/container/XEnumeration.hpp>
42 #include <com/sun/star/frame/XDispatch.hpp>
43 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/view/XPrintable.hpp>
46 #include <com/sun/star/util/URLTransformer.hpp>
47 #include <com/sun/star/util/XURLTransformer.hpp>
48 #include <com/sun/star/document/MacroExecMode.hpp>
49 #include <com/sun/star/document/XTypeDetection.hpp>
50 #include <com/sun/star/document/UpdateDocMode.hpp>
51 #include <com/sun/star/frame/XStorable.hpp>
52 #include <com/sun/star/script/XLibraryContainer2.hpp>
53 #include <com/sun/star/document/XEmbeddedScripts.hpp>
54 
55 #include <comphelper/sequence.hxx>
56 #include <tools/diagnose_ex.h>
57 #include <tools/urlobj.hxx>
59 #include <unotools/tempfile.hxx>
60 
61 #include <osl/thread.hxx>
62 #include <osl/file.hxx>
63 #include <iostream>
64 #include <string_view>
65 
66 using namespace ::osl;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::util;
69 using namespace ::com::sun::star::lang;
70 using namespace ::com::sun::star::frame;
71 using namespace ::com::sun::star::container;
72 using namespace ::com::sun::star::beans;
73 using namespace ::com::sun::star::view;
74 using namespace ::com::sun::star::task;
75 using namespace ::com::sun::star::document;
76 
77 namespace document = ::com::sun::star::document;
78 
79 namespace desktop
80 {
81 
82 namespace {
83 
84 struct DispatchHolder
85 {
86  DispatchHolder( const URL& rURL, Reference< XDispatch > const & rDispatch ) :
87  aURL( rURL ), xDispatch( rDispatch ) {}
88 
90  Reference< XDispatch > xDispatch;
91 };
92 
93 std::shared_ptr<const SfxFilter> impl_lookupExportFilterForUrl( std::u16string_view rUrl, std::u16string_view rFactory )
94 {
95  // create the list of filters
96  OUStringBuffer sQuery(256);
97  sQuery.append("getSortedFilterList()");
98  sQuery.append(":module=");
99  sQuery.append(rFactory); // use long name here !
100  sQuery.append(":iflags=");
101  sQuery.append(OUString::number(static_cast<sal_Int32>(SfxFilterFlags::EXPORT)));
102  sQuery.append(":eflags=");
103  sQuery.append(OUString::number(static_cast<int>(SFX_FILTER_NOTINSTALLED)));
104 
106  const Reference< XContainerQuery > xFilterFactory(
107  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", xContext ),
108  UNO_QUERY_THROW );
109 
110  std::shared_ptr<const SfxFilter> pBestMatch;
111 
112  const Reference< XEnumeration > xFilterEnum(
113  xFilterFactory->createSubSetEnumerationByQuery( sQuery.makeStringAndClear() ), UNO_SET_THROW );
114  while ( xFilterEnum->hasMoreElements() )
115  {
116  comphelper::SequenceAsHashMap aFilterProps( xFilterEnum->nextElement() );
117  const OUString aName( aFilterProps.getUnpackedValueOrDefault( "Name", OUString() ) );
118  if ( !aName.isEmpty() )
119  {
120  std::shared_ptr<const SfxFilter> pFilter( SfxFilter::GetFilterByName( aName ) );
121  if ( pFilter && pFilter->CanExport() && pFilter->GetWildcard().Matches( rUrl ) )
122  {
123  if ( !pBestMatch || ( SfxFilterFlags::PREFERED & pFilter->GetFilterFlags() ) )
124  pBestMatch = pFilter;
125  }
126  }
127  }
128 
129  return pBestMatch;
130 }
131 
132 std::shared_ptr<const SfxFilter> impl_getExportFilterFromUrl(
133  const OUString& rUrl, const OUString& rFactory)
134 {
135  try
136  {
138  const Reference< document::XTypeDetection > xTypeDetector(
139  xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", xContext ),
140  UNO_QUERY_THROW );
141  const OUString aTypeName( xTypeDetector->queryTypeByURL( rUrl ) );
142 
143  std::shared_ptr<const SfxFilter> pFilter( SfxFilterMatcher( rFactory ).GetFilter4EA( aTypeName, SfxFilterFlags::EXPORT ) );
144  if ( !pFilter )
145  pFilter = impl_lookupExportFilterForUrl( rUrl, rFactory );
146  if ( !pFilter )
147  {
148  OUString aTempName;
149  FileBase::getSystemPathFromFileURL( rUrl, aTempName );
150  OString aSource = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
151  std::cerr << "Error: no export filter for " << aSource << " found, aborting." << std::endl;
152  }
153 
154  return pFilter;
155  }
156  catch ( const Exception& )
157  {
158  return nullptr;
159  }
160 }
161 
162 OUString impl_GuessFilter( const OUString& rUrlOut, const OUString& rDocService )
163 {
164  OUString aOutFilter;
165  std::shared_ptr<const SfxFilter> pOutFilter = impl_getExportFilterFromUrl( rUrlOut, rDocService );
166  if (pOutFilter)
167  aOutFilter = pOutFilter->GetFilterName();
168 
169  return aOutFilter;
170 }
171 
173 void scriptCat(const Reference< XModel >& xDoc )
174 {
175  Reference< XEmbeddedScripts > xScriptAccess( xDoc, UNO_QUERY );
176  if (!xScriptAccess)
177  {
178  std::cout << "No script access\n";
179  return;
180  }
181 
182  // ignore xScriptAccess->getDialogLibraries() for now
183  Reference< css::script::XLibraryContainer2 > xLibraries(
184  xScriptAccess->getBasicLibraries() );
185 
186  if ( !xLibraries.is() )
187  {
188  std::cout << "No script libraries\n";
189  return;
190  }
191 
192  const Sequence< OUString > aLibNames = xLibraries->getElementNames();
193  std::cout << "Libraries: " << aLibNames.getLength() << "\n";
194  for (OUString const & libName : aLibNames)
195  {
196  std::cout << "Library: '" << libName << "' children: ";
197  Reference< XNameContainer > xContainer;
198  try {
199  if (!xLibraries->isLibraryLoaded( libName ))
200  xLibraries->loadLibrary( libName );
201  xContainer = Reference< XNameContainer >(
202  xLibraries->getByName( libName ), UNO_QUERY );
203  }
204  catch (const css::uno::Exception &e)
205  {
206  std::cout << "[" << libName << "] - failed to load library: " << e.Message << "\n";
207  continue;
208  }
209  if( !xContainer.is() )
210  std::cout << "0\n";
211  else
212  {
213  Sequence< OUString > aObjectNames = xContainer->getElementNames();
214 
215  std::cout << aObjectNames.getLength() << "\n\n";
216  for ( sal_Int32 j = 0 ; j < aObjectNames.getLength() ; ++j )
217  {
218  OUString &rObjectName = aObjectNames[j];
219 
220  try
221  {
222  Any aCode = xContainer->getByName( rObjectName );
223  OUString aCodeString;
224 
225  if (! (aCode >>= aCodeString ) )
226  std::cout << "[" << rObjectName << "] - error fetching code\n";
227  else
228  std::cout << "[" << rObjectName << "]\n"
229  << aCodeString.trim()
230  << "\n[/" << rObjectName << "]\n";
231  }
232  catch (const css::uno::Exception &e)
233  {
234  std::cout << "[" << rObjectName << "] - exception " << e.Message << " fetching code\n";
235  }
236 
237  if (j < aObjectNames.getLength() - 1)
238  std::cout << "\n----------------------------------------------------------\n";
239  std::cout << "\n";
240  }
241  }
242  }
243 }
244 
245 // Perform batch print
246 void batchPrint( const OUString &rPrinterName, const Reference< XPrintable > &xDoc,
247  const INetURLObject &aObj, const OUString &aName )
248 {
249  OUString aFilterOut;
250  OUString aPrinterName;
251  sal_Int32 nPathIndex = rPrinterName.lastIndexOf( ';' );
252  if( nPathIndex != -1 )
253  aFilterOut=rPrinterName.copy( nPathIndex+1 );
254  if( nPathIndex != 0 )
255  aPrinterName=rPrinterName.copy( 0, nPathIndex );
256 
257  INetURLObject aOutFilename( aObj );
258  aOutFilename.SetExtension( "pdf" );
259  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
260  OUString aOutFile = aFilterOut + "/" + aOutFilename.getName();
261 
262  OUString aTempName;
263  FileBase::getSystemPathFromFileURL( aName, aTempName );
264  OString aSource8 = OUStringToOString ( aTempName, osl_getThreadTextEncoding() );
265  FileBase::getSystemPathFromFileURL( aOutFile, aTempName );
266  OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding() );
267 
268  std::cout << "print " << aSource8 << " -> " << aTargetURL8;
269  std::cout << " using " << (aPrinterName.isEmpty() ? "<default_printer>" : OUStringToOString( aPrinterName, osl_getThreadTextEncoding() ));
270  std::cout << std::endl;
271 
272  // create the custom printer, if given
273  Sequence < PropertyValue > aPrinterArgs( 1 );
274  if( !aPrinterName.isEmpty() )
275  {
276  aPrinterArgs[0].Name = "Name";
277  aPrinterArgs[0].Value <<= aPrinterName;
278  xDoc->setPrinter( aPrinterArgs );
279  }
280 
281  // print ( also without user interaction )
282  aPrinterArgs.realloc(2);
283  aPrinterArgs[0].Name = "FileName";
284  aPrinterArgs[0].Value <<= aOutFile;
285  aPrinterArgs[1].Name = "Wait";
286  aPrinterArgs[1].Value <<= true;
287  xDoc->print( aPrinterArgs );
288 }
289 
290 } // anonymous namespace
291 
293  : m_nRequestCount(0)
294 {
295 }
296 
297 
299 {
300 }
301 
302 
303 bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest>& aDispatchRequestsList, bool bNoTerminate )
304 {
305  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
306 
307  std::vector< DispatchHolder > aDispatches;
308  bool bSetInputFilter = false;
309  OUString aForcedInputFilter;
310 
311  for (auto const & aDispatchRequest: aDispatchRequestsList)
312  {
313  // Set Input Filter
314  if ( aDispatchRequest.aRequestType == REQUEST_INFILTER )
315  {
316  bSetInputFilter = true;
317  aForcedInputFilter = aDispatchRequest.aURL;
319  continue;
320  }
321 
322  // create parameter array
323  std::vector<PropertyValue> aArgs;
324 
325  // mark request as user interaction from outside
326  aArgs.emplace_back("Referer", 0, Any(OUString("private:OpenEvent")),
327  PropertyState_DIRECT_VALUE);
328 
329  OUString aTarget("_default");
330 
331  if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
332  aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
333  aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
334  aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
335  aDispatchRequest.aRequestType == REQUEST_CAT ||
336  aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT)
337  {
338  // documents opened for printing are opened readonly because they must be opened as a
339  // new document and this document could be open already
340  aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
341  // always open a new document for printing, because it must be disposed afterwards
342  aArgs.emplace_back("OpenNewView", 0, Any(true), PropertyState_DIRECT_VALUE);
343  // printing is done in a hidden view
344  aArgs.emplace_back("Hidden", 0, Any(true), PropertyState_DIRECT_VALUE);
345  // load document for printing without user interaction
346  aArgs.emplace_back("Silent", 0, Any(true), PropertyState_DIRECT_VALUE);
347 
348  // hidden documents should never be put into open tasks
349  aTarget = "_blank";
350  }
351  else
352  {
353  Reference < XInteractionHandler2 > xInteraction(
354  InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
355 
356  aArgs.emplace_back("InteractionHandler", 0, Any(xInteraction),
357  PropertyState_DIRECT_VALUE);
358 
359  aArgs.emplace_back("MacroExecutionMode", 0,
360  Any(css::document::MacroExecMode::USE_CONFIG),
361  PropertyState_DIRECT_VALUE);
362 
363  aArgs.emplace_back("UpdateDocMode", 0,
364  Any(css::document::UpdateDocMode::ACCORDING_TO_CONFIG),
365  PropertyState_DIRECT_VALUE);
366  }
367 
368  if ( !aDispatchRequest.aPreselectedFactory.isEmpty() )
369  {
370  aArgs.emplace_back(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), 0,
371  Any(aDispatchRequest.aPreselectedFactory),
372  PropertyState_DIRECT_VALUE);
373  }
374 
375  OUString aName( GetURL_Impl( aDispatchRequest.aURL, aDispatchRequest.aCwdUrl ) );
376 
377  // load the document ... if they are loadable!
378  // Otherwise try to dispatch it ...
379  Reference < XPrintable > xDoc;
380  if(
381  ( aName.startsWith( ".uno" ) ) ||
382  ( aName.startsWith( "slot:" ) ) ||
383  ( aName.startsWith( "macro:" ) ) ||
384  ( aName.startsWith("vnd.sun.star.script") )
385  )
386  {
387  // Attention: URL must be parsed full. Otherwise some detections on it will fail!
388  // It doesn't matter, if parser isn't available. Because; We try loading of URL then ...
389  URL aURL ;
390  aURL.Complete = aName;
391 
392  Reference < XDispatch > xDispatcher ;
393  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
394 
395  if( xParser.is() )
396  xParser->parseStrict( aURL );
397 
398  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
399  SAL_WARN_IF(
400  !xDispatcher.is(), "desktop.app",
401  "unsupported dispatch request <" << aName << ">");
402  if( xDispatcher.is() )
403  {
404  {
405  osl::MutexGuard aGuard(m_mutex);
406  // Remember request so we can find it in statusChanged!
407  m_nRequestCount++;
408  }
409 
410  // Use local vector to store dispatcher because we have to fill our request container before
411  // we can dispatch. Otherwise it would be possible that statusChanged is called before we dispatched all requests!!
412  aDispatches.emplace_back( aURL, xDispatcher );
413  }
414  }
415  else if ( aName.startsWith( "service:" ) )
416  {
417  // TODO: the dispatch has to be done for loadComponentFromURL as well.
418  URL aURL ;
419  aURL.Complete = aName;
420 
421  Reference < XDispatch > xDispatcher ;
422  Reference < XURLTransformer > xParser ( URLTransformer::create(::comphelper::getProcessComponentContext()) );
423 
424  if( xParser.is() )
425  xParser->parseStrict( aURL );
426 
427  xDispatcher = xDesktop->queryDispatch( aURL, OUString(), 0 );
428 
429  if( xDispatcher.is() )
430  {
431  try
432  {
433  // We have to be listener to catch errors during dispatching URLs.
434  // Otherwise it would be possible to have an office running without an open
435  // window!!
436  Sequence < PropertyValue > aArgs2(1);
437  aArgs2[0].Name = "SynchronMode";
438  aArgs2[0].Value <<= true;
439  Reference < XNotifyingDispatch > xDisp( xDispatcher, UNO_QUERY );
440  if ( xDisp.is() )
441  xDisp->dispatchWithNotification( aURL, aArgs2, this );
442  else
443  xDispatcher->dispatch( aURL, aArgs2 );
444  }
445  catch (const css::uno::Exception&)
446  {
448  "desktop.app",
449  "Desktop::OpenDefault() ignoring Exception while calling XNotifyingDispatch");
450  }
451  }
452  }
453  else
454  {
455  INetURLObject aObj( aName );
456  if ( aObj.GetProtocol() == INetProtocol::PrivSoffice )
457  aTarget = "_default";
458 
459  // Set "AsTemplate" argument according to request type
460  if ( aDispatchRequest.aRequestType == REQUEST_FORCENEW ||
461  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN )
462  {
463  aArgs.emplace_back("AsTemplate", 0,
464  Any(aDispatchRequest.aRequestType == REQUEST_FORCENEW),
465  PropertyState_DIRECT_VALUE);
466  }
467 
468  // if we are called in viewmode, open document read-only
469  if(aDispatchRequest.aRequestType == REQUEST_VIEW) {
470  aArgs.emplace_back("ReadOnly", 0, Any(true), PropertyState_DIRECT_VALUE);
471  }
472 
473  // if we are called with --show set Start in mediadescriptor
474  if(aDispatchRequest.aRequestType == REQUEST_START) {
475  aArgs.emplace_back("StartPresentation", 0, Any(true), PropertyState_DIRECT_VALUE);
476  }
477 
478  // Force input filter, if possible
479  if( bSetInputFilter )
480  {
481  sal_Int32 nFilterOptionsIndex = 0;
482  aArgs.emplace_back("FilterName", 0,
483  Any(aForcedInputFilter.getToken(0, ':', nFilterOptionsIndex)),
484  PropertyState_DIRECT_VALUE);
485 
486  if (0 < nFilterOptionsIndex)
487  {
488  aArgs.emplace_back("FilterOptions", 0,
489  Any(aForcedInputFilter.copy(nFilterOptionsIndex)),
490  PropertyState_DIRECT_VALUE);
491  }
492  }
493 
494  // This is a synchron loading of a component so we don't have to deal with our statusChanged listener mechanism.
495  try
496  {
498  xDesktop, aName, aTarget, comphelper::containerToSequence(aArgs)),
499  UNO_QUERY);
500  }
501  catch (const css::lang::IllegalArgumentException&)
502  {
504  "desktop.app",
505  "Dispatchwatcher IllegalArgumentException while calling loadComponentFromURL");
506  }
507  catch (const css::io::IOException&)
508  {
510  "desktop.app",
511  "Dispatchwatcher IOException while calling loadComponentFromURL");
512  }
513  if ( aDispatchRequest.aRequestType == REQUEST_OPEN ||
514  aDispatchRequest.aRequestType == REQUEST_VIEW ||
515  aDispatchRequest.aRequestType == REQUEST_START ||
516  aDispatchRequest.aRequestType == REQUEST_FORCEOPEN ||
517  aDispatchRequest.aRequestType == REQUEST_FORCENEW )
518  {
519  // request is completed
521  }
522  else if ( aDispatchRequest.aRequestType == REQUEST_PRINT ||
523  aDispatchRequest.aRequestType == REQUEST_PRINTTO ||
524  aDispatchRequest.aRequestType == REQUEST_BATCHPRINT ||
525  aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
526  aDispatchRequest.aRequestType == REQUEST_CAT ||
527  aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
528  {
529  if ( xDoc.is() )
530  {
531  // Do we need to save the document in a different format?
532  if ( aDispatchRequest.aRequestType == REQUEST_CONVERSION ||
533  aDispatchRequest.aRequestType == REQUEST_CAT )
534  {
535 // FIXME: factor out into a method ...
536  Reference< XStorable > xStorable( xDoc, UNO_QUERY );
537  if ( xStorable.is() ) {
538  OUString aParam = aDispatchRequest.aPrinterName;
539  sal_Int32 nPathIndex = aParam.lastIndexOf( ';' );
540  sal_Int32 nFilterIndex = aParam.indexOf( ':' );
541  sal_Int32 nImgFilterIndex = aParam.lastIndexOf( '|' );
542  if( nPathIndex < nFilterIndex )
543  nFilterIndex = -1;
544 
545  OUString aFilterOut;
546  OUString aImgOut;
547  OUString aFilter;
548  OUString aFilterExt;
549  bool bGuess = false;
550 
551  if( nFilterIndex >= 0 )
552  {
553  aFilter = aParam.copy( nFilterIndex+1, nPathIndex-nFilterIndex-1 );
554  aFilterExt = aParam.copy( 0, nFilterIndex );
555  }
556  else
557  {
558  // Guess
559  bGuess = true;
560  aFilterExt = aParam.copy( 0, nPathIndex );
561  }
562 
563  if( nImgFilterIndex >= 0 )
564  {
565  aImgOut = aParam.copy( nImgFilterIndex+1 );
566  aFilterOut = aParam.copy( nPathIndex+1, nImgFilterIndex-nPathIndex-1 );
567  }
568  else
569  aFilterOut = aParam.copy( nPathIndex+1 );
570 
571  FileBase::getFileURLFromSystemPath( aFilterOut, aFilterOut );
572  INetURLObject aOutFilename(aFilterOut);
573  aOutFilename.Append(aObj.getName(INetURLObject::LAST_SEGMENT, true,
575  aOutFilename.SetExtension(aFilterExt);
576  OUString aOutFile
578 
579  std::unique_ptr<utl::TempFile> fileForCat;
580  if( aDispatchRequest.aRequestType == REQUEST_CAT )
581  {
582  fileForCat = std::make_unique<utl::TempFile>();
583  if (fileForCat->IsValid())
584  fileForCat->EnableKillingFile();
585  else
586  std::cerr << "Error: Cannot create temporary file..." << std::endl ;
587  aOutFile = fileForCat->GetURL();
588  }
589 
590  if ( bGuess )
591  {
592  OUString aDocService;
593  Reference< XModel > xModel( xDoc, UNO_QUERY );
594  if ( xModel.is() )
595  {
596  utl::MediaDescriptor aMediaDesc( xModel->getArgs() );
597  aDocService = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE(), OUString() );
598  }
599  aFilter = impl_GuessFilter( aOutFile, aDocService );
600  }
601 
602  if (aFilter.isEmpty())
603  {
604  std::cerr << "Error: no export filter" << std::endl;
605  }
606  else
607  {
608  sal_Int32 nFilterOptionsIndex = aFilter.indexOf(':');
609  sal_Int32 nProps = ( 0 < nFilterOptionsIndex ) ? 3 : 2;
610 
611  if ( !aImgOut.isEmpty() )
612  nProps +=1;
613  Sequence<PropertyValue> conversionProperties( nProps );
614  conversionProperties[0].Name = "Overwrite";
615  conversionProperties[0].Value <<= true;
616 
617  conversionProperties[1].Name = "FilterName";
618  if( 0 < nFilterOptionsIndex )
619  {
620  conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex);
621 
622  conversionProperties[2].Name = "FilterOptions";
623  conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1);
624  }
625  else
626  {
627  conversionProperties[1].Value <<= aFilter;
628  }
629 
630  if ( !aImgOut.isEmpty() )
631  {
632  conversionProperties[nProps-1].Name = "ImageFilter";
633  conversionProperties[nProps-1].Value <<= aImgOut;
634  }
635 
636  OUString aTempName;
637  FileBase::getSystemPathFromFileURL(aName, aTempName);
638  OString aSource8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
639  FileBase::getSystemPathFromFileURL(aOutFile, aTempName);
640  OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding());
641  if (aDispatchRequest.aRequestType != REQUEST_CAT)
642  {
643  std::cout << "convert " << aSource8 << " -> " << aTargetURL8;
644  std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl;
645  if (FStatHelper::IsDocument(aOutFile))
646  std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ;
647  }
648  try
649  {
650  xStorable->storeToURL(aOutFile, conversionProperties);
651  }
652  catch (const Exception& rException)
653  {
654  std::cerr << "Error: Please verify input parameters...";
655  if (!rException.Message.isEmpty())
656  std::cerr << " (" << rException.Message << ")";
657  std::cerr << std::endl;
658  }
659 
660  if (fileForCat && fileForCat->IsValid())
661  {
662  SvStream* aStream = fileForCat->GetStream(StreamMode::STD_READ);
663  while (aStream->good())
664  {
665  OString aStr;
666  aStream->ReadLine(aStr, SAL_MAX_INT32);
667  for (sal_Int32 i = 0; i < aStr.getLength(); ++i)
668  {
669  std::cout << aStr[i];
670  }
671  std::cout << std::endl;
672  }
673  }
674  }
675  }
676  }
677  else if ( aDispatchRequest.aRequestType == REQUEST_SCRIPT_CAT )
678  {
679  Reference< XModel > xModel( xDoc, UNO_QUERY );
680  if( xModel.is() )
681  scriptCat( xModel );
682  }
683  else if ( aDispatchRequest.aRequestType == REQUEST_BATCHPRINT )
684  {
685  batchPrint( aDispatchRequest.aPrinterName, xDoc, aObj, aName );
686  }
687  else
688  {
689  if ( aDispatchRequest.aRequestType == REQUEST_PRINTTO )
690  {
691  // create the printer
692  Sequence < PropertyValue > aPrinterArgs( 1 );
693  aPrinterArgs[0].Name = "Name";
694  aPrinterArgs[0].Value <<= aDispatchRequest.aPrinterName;
695  xDoc->setPrinter( aPrinterArgs );
696  }
697 
698  // print ( also without user interaction )
699  Sequence < PropertyValue > aPrinterArgs( 1 );
700  aPrinterArgs[0].Name = "Wait";
701  aPrinterArgs[0].Value <<= true;
702  xDoc->print( aPrinterArgs );
703  }
704  }
705  else
706  {
707  std::cerr << "Error: source file could not be loaded" << std::endl;
708  }
709 
710  // remove the document
711  try
712  {
713  Reference < XCloseable > xClose( xDoc, UNO_QUERY );
714  if ( xClose.is() )
715  xClose->close( true );
716  else
717  {
718  Reference < XComponent > xComp( xDoc, UNO_QUERY );
719  if ( xComp.is() )
720  xComp->dispose();
721  }
722  }
723  catch (const css::util::CloseVetoException&)
724  {
725  }
726 
727  // request is completed
729  }
730  }
731  }
732 
733  if ( !aDispatches.empty() )
734  {
735  // Execute all asynchronous dispatches now after we placed them into our request container!
736  Sequence < PropertyValue > aArgs( 2 );
737  aArgs[0].Name = "Referer";
738  aArgs[0].Value <<= OUString("private:OpenEvent");
739  aArgs[1].Name = "SynchronMode";
740  aArgs[1].Value <<= true;
741 
742  for (const DispatchHolder & aDispatche : aDispatches)
743  {
744  Reference< XDispatch > xDispatch = aDispatche.xDispatch;
745  Reference < XNotifyingDispatch > xDisp( xDispatch, UNO_QUERY );
746  if ( xDisp.is() )
747  xDisp->dispatchWithNotification( aDispatche.aURL, aArgs, this );
748  else
749  {
750  {
751  osl::MutexGuard aGuard(m_mutex);
752  m_nRequestCount--;
753  }
754  xDispatch->dispatch( aDispatche.aURL, aArgs );
755  }
756  }
757  }
758 
759  ::osl::ClearableMutexGuard aGuard(m_mutex);
760  bool bEmpty = (m_nRequestCount == 0);
761  aGuard.clear();
762 
763  // No more asynchronous requests?
764  // The requests are removed from the request container after they called back to this
765  // implementation via statusChanged!!
766  if ( bEmpty && !bNoTerminate /*m_aRequestContainer.empty()*/ )
767  {
768  // We have to check if we have an open task otherwise we have to shutdown the office.
769  Reference< XElementAccess > xList = xDesktop->getFrames();
770 
771  if ( !xList->hasElements() )
772  {
773  // We don't have any task open so we have to shutdown ourself!!
774  return xDesktop->terminate();
775  }
776  }
777 
778  return false;
779 }
780 
781 
782 void SAL_CALL DispatchWatcher::disposing( const css::lang::EventObject& )
783 {
784 }
785 
786 
787 void SAL_CALL DispatchWatcher::dispatchFinished( const DispatchResultEvent& )
788 {
789  osl::ClearableMutexGuard aGuard(m_mutex);
790  sal_Int16 nCount = --m_nRequestCount;
791  aGuard.clear();
793  if ( !nCount && !RequestHandler::AreRequestsPending() )
794  {
795  // We have to check if we have an open task otherwise we have to shutdown the office.
796  Reference< XDesktop2 > xDesktop = css::frame::Desktop::create( ::comphelper::getProcessComponentContext() );
797  Reference< XElementAccess > xList = xDesktop->getFrames();
798 
799  if ( !xList->hasElements() )
800  {
801  // We don't have any task open so we have to shutdown ourself!!
802  xDesktop->terminate();
803  }
804  }
805 }
806 
807 } // namespace desktop
808 
809 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SVL_DLLPUBLIC bool IsDocument(const OUString &rURL)
URL aURL
OUString GetURL_Impl(const OUString &rName, std::optional< OUString > const &cwdUrl)
Definition: app.cxx:2176
#define SFX_FILTER_NOTINSTALLED
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Definition: app.cxx:160
bool ReadLine(OString &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
int nCount
static COMPHELPER_DLLPUBLIC css::uno::Reference< css::lang::XComponent > dispatch(const css::uno::Reference< css::uno::XInterface > &xStartPoint, const OUString &sURL, const OUString &sTarget, const css::uno::Sequence< css::beans::PropertyValue > &lArguments)
void SetExtension(OUString const &rTheExtension)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define SAL_MAX_INT32
static bool AreRequestsPending()
int i
bool Append(OUString const &rTheSegment, EncodeMechanism eMechanism=EncodeMechanism::WasEncoded, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString getName(sal_Int32 nIndex=LAST_SEGMENT, bool bIgnoreFinalSlash=true, DecodeMechanism eMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static std::shared_ptr< const SfxFilter > GetFilterByName(const OUString &rName)
OUString GetMainURL(DecodeMechanism eMechanism, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8) const
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2170
Reference< XDispatch > xDispatch
#define SAL_WARN_IF(condition, area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OUString aName
INetProtocol GetProtocol() const
Reference< XComponentContext > getProcessComponentContext()
bool good() const
Reference< XModel > xModel
virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent &aEvent) override
static const OUString & PROP_DOCUMENTSERVICE()
aStr
virtual ~DispatchWatcher() override
bool executeDispatchRequests(const std::vector< DispatchRequest > &aDispatches, bool bNoTerminate)