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