Bump version to 5.0-14
[LibreOffice.git] / filter / source / xsltdialog / xmlfilterjar.cxx
blobc14917b4f9fb8322cdc9eae1efec32dfb82d9e0a
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/XActiveDataSource.hpp>
22 #include <com/sun/star/frame/XConfigManager.hpp>
23 #include <com/sun/star/io/XInputStream.hpp>
24 #include <com/sun/star/io/XActiveDataSink.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 #include <com/sun/star/beans/NamedValue.hpp>
27 #include <com/sun/star/container/XNamed.hpp>
28 #include <com/sun/star/container/XChild.hpp>
29 #include <com/sun/star/util/XChangesBatch.hpp>
32 #include <comphelper/processfactory.hxx>
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 <tools/stream.hxx>
41 #include <tools/urlobj.hxx>
43 #include <rtl/uri.hxx>
45 #include "xmlfilterjar.hxx"
46 #include "xmlfilterdialogstrings.hrc"
47 #include "xmlfiltersettingsdialog.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::frame;
56 using namespace com::sun::star::uno;
57 using namespace com::sun::star::util;
58 using namespace com::sun::star::container;
59 using namespace com::sun::star::beans;
60 using namespace com::sun::star::io;
62 using ::rtl::Uri;
64 XMLFilterJarHelper::XMLFilterJarHelper( const Reference< XComponentContext >& rxContext )
65 : mxContext( rxContext ),
66 sVndSunStarPackage( "vnd.sun.star.Package:" ),
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 static Reference< XInterface > addFolder( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, const OUString& rName ) throw( Exception )
84 if ( rName == ".." || rName == "." )
85 throw lang::IllegalArgumentException();
87 Sequence< Any > aArgs(1);
88 aArgs[0] <<= 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 static void _addFile( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, Reference< XInputStream >& xInput, const OUString& aName ) throw( Exception )
106 Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
107 Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
108 if( xSink.is() && xTunnel.is())
110 Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
111 xNameContainer->insertByName(encodeZipUri( aName ), makeAny(xTunnel));
112 xSink->setInputStream( xInput );
116 void XMLFilterJarHelper::addFile( Reference< XInterface > xRootFolder, Reference< XSingleServiceFactory > xFactory, const OUString& rSourceFile ) throw( Exception )
118 if( !rSourceFile.isEmpty() &&
119 !rSourceFile.startsWith("http:") &&
120 !rSourceFile.startsWith("https:") &&
121 !rSourceFile.startsWith("jar:") &&
122 !rSourceFile.startsWith("ftp:") )
124 OUString aFileURL( rSourceFile );
126 if( !aFileURL.matchIgnoreAsciiCase( OUString("file://") ) )
128 aFileURL = URIHelper::SmartRel2Abs( INetURLObject(sProgPath), aFileURL, Link<OUString *, bool>(), false );
131 INetURLObject aURL( aFileURL );
132 OUString aName( aURL.getName() );
134 SvFileStream* pStream = new SvFileStream(aFileURL, StreamMode::READ );
135 Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
136 _addFile( xRootFolder, xFactory, xInput, aName );
140 bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const XMLFilterVector& rFilters )
144 osl::File::remove( rPackageURL );
146 // create the package jar file
148 Sequence< Any > aArguments( 2 );
149 aArguments[ 0 ] <<= rPackageURL;
151 // let ZipPackage be used ( no manifest.xml is required )
152 beans::NamedValue aArg;
153 aArg.Name = "StorageFormat";
154 aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
155 aArguments[ 1 ] <<= aArg;
157 Reference< XHierarchicalNameAccess > xIfc(
158 mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
159 "com.sun.star.packages.comp.ZipPackage",
160 aArguments, mxContext ), UNO_QUERY );
162 if( xIfc.is() )
164 Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
166 // get root zip folder
167 Reference< XInterface > xRootFolder;
168 OUString szRootFolder("/");
169 xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
171 // export filters files
172 XMLFilterVector::const_iterator aIter( rFilters.begin() );
173 while( aIter != rFilters.end() )
175 const filter_info_impl* pFilter = (*aIter);
177 Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, pFilter->maFilterName ) );
179 if( xFilterRoot.is() )
181 if( !pFilter->maExportXSLT.isEmpty() )
182 addFile( xFilterRoot, xFactory, pFilter->maExportXSLT );
185 if( !pFilter->maImportXSLT.isEmpty() )
186 addFile( xFilterRoot, xFactory, pFilter->maImportXSLT );
188 catch(const com::sun::star::container::ElementExistException&)
190 // in case of same named import / export XSLT the latter
191 // is ignored
192 OSL_FAIL( "XMLFilterJarHelper::same named xslt filter exception!" );
195 if( !pFilter->maImportTemplate.isEmpty() )
196 addFile( xFilterRoot, xFactory, pFilter->maImportTemplate );
199 ++aIter;
202 // create TypeDetection.xcu
203 utl::TempFile aTempFile;
204 aTempFile.EnableKillingFile();
205 OUString aTempFileURL( aTempFile.GetURL() );
208 osl::File aOutputFile( aTempFileURL );
209 /* osl::File::RC rc = */ aOutputFile.open( osl_File_OpenFlag_Write );
210 Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
212 TypeDetectionExporter aExporter( mxContext );
213 aExporter.doExport(xOS,rFilters);
216 Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( new SvFileStream(aTempFileURL, StreamMode::READ ), true ) );
217 OUString szTypeDetection( "TypeDetection.xcu" );
218 _addFile( xRootFolder, xFactory, XIS, szTypeDetection );
220 Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
221 if( xBatch.is() )
222 xBatch->commitChanges();
224 return true;
227 catch( const Exception& )
229 OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
232 osl::File::remove( rPackageURL );
234 return false;
241 void XMLFilterJarHelper::openPackage( const OUString& rPackageURL, XMLFilterVector& rFilters )
245 // create the package jar file
247 Sequence< Any > aArguments( 2 );
248 aArguments[ 0 ] <<= rPackageURL;
250 // let ZipPackage be used ( no manifest.xml is required )
251 beans::NamedValue aArg;
252 aArg.Name = "StorageFormat";
253 aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
254 aArguments[ 1 ] <<= aArg;
256 Reference< XHierarchicalNameAccess > xIfc(
257 mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
258 "com.sun.star.packages.comp.ZipPackage",
259 aArguments, mxContext ), UNO_QUERY );
261 if( xIfc.is() )
263 Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
265 // get root zip folder
266 Reference< XInterface > xRootFolder;
267 OUString szRootFolder("/");
268 xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
270 OUString szTypeDetection("TypeDetection.xcu");
271 if( xIfc->hasByHierarchicalName( szTypeDetection ) )
273 Reference< XActiveDataSink > xTypeDetection;
274 xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
276 if( xTypeDetection.is() )
278 Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
280 XMLFilterVector aFilters;
281 TypeDetectionImporter::doImport( mxContext, xIS, aFilters );
283 // copy all files used by the filters imported from the
284 // typedetection to office/user/xslt
285 XMLFilterVector::iterator aIter( aFilters.begin() );
286 while( aIter != aFilters.end() )
288 if( copyFiles( xIfc, (*aIter) ) )
290 rFilters.push_back( (*aIter) );
292 else
294 // failed to copy all files
295 delete (*aIter);
297 ++aIter;
303 catch( const Exception& )
305 OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
309 bool XMLFilterJarHelper::copyFiles( Reference< XHierarchicalNameAccess > xIfc, filter_info_impl* pFilter )
311 bool bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
313 if( bOk )
314 bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
316 if( bOk )
317 bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
319 return bOk;
322 bool XMLFilterJarHelper::copyFile( Reference< XHierarchicalNameAccess > xIfc, OUString& rURL, const OUString& rTargetURL )
324 if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
325 return true;
329 OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
331 if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( ".." ) )
332 || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( "." ) ) )
333 throw lang::IllegalArgumentException();
335 if( xIfc->hasByHierarchicalName( szPackagePath ) )
337 Reference< XActiveDataSink > xFileEntry;
338 xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
340 if( xFileEntry.is() )
342 Reference< XInputStream > xIS( xFileEntry->getInputStream() );
344 INetURLObject aBaseURL( rTargetURL );
346 rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link<OUString *, bool>(), false );
348 if( !rURL.isEmpty() )
350 // create output directory if needed
351 if( !createDirectory( rURL ) )
352 return false;
354 ::osl::File file(rURL);
355 ::osl::FileBase::RC rc =
356 file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
357 if (::osl::FileBase::E_EXIST == rc) {
358 rc = file.open(osl_File_OpenFlag_Write);
359 if (::osl::FileBase::E_None == rc) {
360 file.setSize(0); // #i97170# truncate
363 if (::osl::FileBase::E_None != rc) {
364 throw RuntimeException();
366 Reference< XOutputStream > const xOS(
367 new comphelper::OSLOutputStreamWrapper(file));
369 return copyStreams( xIS, xOS );
374 catch( const Exception& )
376 OSL_FAIL( "XMLFilterJarHelper::copyFile exception catched" );
378 return false;
381 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */