android: Update app-specific/MIME type icons
[LibreOffice.git] / filter / source / xsltdialog / xmlfilterjar.cxx
blob5177606ee2de2efac5a8784be108c23ae1b56e2b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/io/XActiveDataControl.hpp>
21 #include <com/sun/star/io/XInputStream.hpp>
22 #include <com/sun/star/io/XActiveDataSink.hpp>
23 #include <com/sun/star/beans/NamedValue.hpp>
24 #include <com/sun/star/container/XNameContainer.hpp>
25 #include <com/sun/star/container/XNamed.hpp>
26 #include <com/sun/star/container/XChild.hpp>
27 #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 #include <com/sun/star/lang/XUnoTunnel.hpp>
29 #include <com/sun/star/util/XChangesBatch.hpp>
30 #include <com/sun/star/uno/XComponentContext.hpp>
33 #include <comphelper/oslfile2streamwrap.hxx>
34 #include <comphelper/storagehelper.hxx>
35 #include <osl/file.hxx>
36 #include <unotools/pathoptions.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <unotools/tempfile.hxx>
39 #include <svl/urihelper.hxx>
40 #include <comphelper/diagnose_ex.hxx>
41 #include <tools/stream.hxx>
42 #include <tools/urlobj.hxx>
44 #include <rtl/uri.hxx>
46 #include "xmlfiltercommon.hxx"
47 #include "xmlfilterjar.hxx"
48 #include "typedetectionexport.hxx"
49 #include "typedetectionimport.hxx"
51 using namespace osl;
52 using namespace comphelper;
53 using namespace com::sun::star;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::uno;
56 using namespace com::sun::star::util;
57 using namespace com::sun::star::container;
58 using namespace com::sun::star::beans;
59 using namespace com::sun::star::io;
61 using ::rtl::Uri;
63 constexpr OUStringLiteral sVndSunStarPackage(u"vnd.sun.star.Package:");
65 XMLFilterJarHelper::XMLFilterJarHelper( const Reference< XComponentContext >& rxContext )
66 : mxContext( rxContext ),
67 sXSLTPath( "$(user)/xslt/" ),
68 sTemplatePath( "$(user)/template/" ),
69 sProgPath( "$(prog)/" )
71 SvtPathOptions aOptions;
72 sProgPath = aOptions.SubstituteVariable( sProgPath );
73 sXSLTPath = aOptions.SubstituteVariable( sXSLTPath );
74 sTemplatePath = aOptions.SubstituteVariable( sTemplatePath );
77 static OUString encodeZipUri( const OUString& rURI )
79 return Uri::encode( rURI, rtl_UriCharClassUric, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
82 /// @throws Exception
83 static Reference< XInterface > addFolder( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rName )
85 if ( rName == ".." || rName == "." )
86 throw lang::IllegalArgumentException();
88 Sequence< Any > aArgs{ Any(true) };
90 Reference< XInterface > xFolder( xFactory->createInstanceWithArguments(aArgs) );
91 Reference< XNamed > xNamed( xFolder, UNO_QUERY );
92 Reference< XChild > xChild( xFolder, UNO_QUERY );
94 if( xNamed.is() && xChild.is() )
96 OUString aName( encodeZipUri( rName ) );
97 xNamed->setName( aName );
98 xChild->setParent( xRootFolder );
101 return xFolder;
104 /// @throws Exception
105 static void addFile_( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, Reference< XInputStream > const & xInput, const OUString& aName )
107 Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
108 Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
109 if( xSink.is() && xTunnel.is())
111 Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
112 xNameContainer->insertByName(encodeZipUri( aName ), Any(xTunnel));
113 xSink->setInputStream( xInput );
117 void XMLFilterJarHelper::addFile( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rSourceFile )
119 if( rSourceFile.isEmpty() ||
120 rSourceFile.startsWith("http:") ||
121 rSourceFile.startsWith("https:") ||
122 rSourceFile.startsWith("jar:") ||
123 rSourceFile.startsWith("ftp:") )
124 return;
126 OUString aFileURL( rSourceFile );
128 if( !aFileURL.matchIgnoreAsciiCase("file://") )
130 aFileURL = URIHelper::SmartRel2Abs( INetURLObject(sProgPath), aFileURL, Link<OUString *, bool>(), false );
133 INetURLObject aURL( aFileURL );
134 OUString aName( aURL.getName() );
136 SvFileStream* pStream = new SvFileStream(aFileURL, StreamMode::READ );
137 Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
138 addFile_( xRootFolder, xFactory, xInput, aName );
141 bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const std::vector<filter_info_impl*>& rFilters )
145 osl::File::remove( rPackageURL );
147 // create the package jar file
149 Sequence< Any > aArguments{ Any(rPackageURL),
150 // let ZipPackage be used ( no manifest.xml is required )
151 Any(beans::NamedValue(
152 "StorageFormat", Any(OUString(ZIP_STORAGE_FORMAT_STRING)))) };
154 Reference< XHierarchicalNameAccess > xIfc(
155 mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
156 "com.sun.star.packages.comp.ZipPackage",
157 aArguments, mxContext ), UNO_QUERY );
159 if( xIfc.is() )
161 Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
163 // get root zip folder
164 Reference< XInterface > xRootFolder;
165 xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
167 // export filters files
168 for (auto const& filter : rFilters)
170 Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, filter->maFilterName ) );
172 if( xFilterRoot.is() )
174 if( !filter->maExportXSLT.isEmpty() )
175 addFile( xFilterRoot, xFactory, filter->maExportXSLT );
178 if( !filter->maImportXSLT.isEmpty() )
179 addFile( xFilterRoot, xFactory, filter->maImportXSLT );
181 catch(const css::container::ElementExistException&)
183 // in case of same named import / export XSLT the latter
184 // is ignored
185 TOOLS_WARN_EXCEPTION("filter.xslt", "same named xslt filter exception!");
188 if( !filter->maImportTemplate.isEmpty() )
189 addFile( xFilterRoot, xFactory, filter->maImportTemplate );
193 // create TypeDetection.xcu
194 utl::TempFileFast aTempFile;
195 SvStream* pStream = aTempFile.GetStream(StreamMode::READWRITE);
198 Reference< XOutputStream > xOS( new ::utl::OOutputStreamWrapper( *pStream ) );
200 TypeDetectionExporter aExporter( mxContext );
201 aExporter.doExport(xOS,rFilters);
204 pStream->Seek(0);
205 Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( *pStream ) );
206 addFile_( xRootFolder, xFactory, XIS, "TypeDetection.xcu" );
208 Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
209 if( xBatch.is() )
210 xBatch->commitChanges();
212 return true;
215 catch( const Exception& )
217 TOOLS_WARN_EXCEPTION("filter.xslt", "");
220 osl::File::remove( rPackageURL );
222 return false;
226 void XMLFilterJarHelper::openPackage( const OUString& rPackageURL,
227 std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
231 // create the package jar file
233 // let ZipPackage be used ( no manifest.xml is required )
234 beans::NamedValue aArg;
235 aArg.Name = "StorageFormat";
236 aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
237 Sequence< Any > aArguments{ Any(rPackageURL), Any(aArg) };
239 Reference< XHierarchicalNameAccess > xIfc(
240 mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
241 "com.sun.star.packages.comp.ZipPackage",
242 aArguments, mxContext ), UNO_QUERY );
244 if( xIfc.is() )
246 // get root zip folder
247 Reference< XInterface > xRootFolder;
248 xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
250 OUString szTypeDetection("TypeDetection.xcu");
251 if( xIfc->hasByHierarchicalName( szTypeDetection ) )
253 Reference< XActiveDataSink > xTypeDetection;
254 xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
256 if( xTypeDetection.is() )
258 Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
260 std::vector< std::unique_ptr<filter_info_impl> > aFilters;
261 TypeDetectionImporter::doImport( mxContext, xIS, aFilters );
263 // copy all files used by the filters imported from the
264 // typedetection to office/user/xslt
265 for (auto& filter : aFilters)
267 if( copyFiles( xIfc, filter.get() ) )
269 rFilters.push_back(std::move(filter));
271 else
273 // failed to copy all files
274 filter.reset();
281 catch( const Exception& )
283 TOOLS_WARN_EXCEPTION("filter.xslt", "");
287 bool XMLFilterJarHelper::copyFiles( const Reference< XHierarchicalNameAccess >& xIfc, filter_info_impl* pFilter )
289 bool bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
291 if( bOk )
292 bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
294 if( bOk )
295 bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
297 return bOk;
300 bool XMLFilterJarHelper::copyFile( const Reference< XHierarchicalNameAccess >& xIfc, OUString& rURL, std::u16string_view rTargetURL )
302 if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
303 return true;
307 OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
309 if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u".." )
310 || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u"." ) )
311 throw lang::IllegalArgumentException();
313 if( xIfc->hasByHierarchicalName( szPackagePath ) )
315 Reference< XActiveDataSink > xFileEntry;
316 xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
318 if( xFileEntry.is() )
320 Reference< XInputStream > xIS( xFileEntry->getInputStream() );
322 INetURLObject aBaseURL( rTargetURL );
324 rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link<OUString *, bool>(), false );
326 if( !rURL.isEmpty() )
328 // create output directory if needed
329 if( !createDirectory( rURL ) )
330 return false;
332 ::osl::File file(rURL);
333 ::osl::FileBase::RC rc =
334 file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
335 if (::osl::FileBase::E_EXIST == rc) {
336 rc = file.open(osl_File_OpenFlag_Write);
337 if (::osl::FileBase::E_None == rc) {
338 file.setSize(0); // #i97170# truncate
341 if (::osl::FileBase::E_None != rc) {
342 throw RuntimeException();
344 Reference< XOutputStream > const xOS(
345 new comphelper::OSLOutputStreamWrapper(file));
347 return copyStreams( xIS, xOS );
352 catch( const Exception& )
354 TOOLS_WARN_EXCEPTION("filter.xslt", "");
356 return false;
359 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */