Line data Source code
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 <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>
30 :
31 :
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>
42 :
43 : #include <rtl/uri.hxx>
44 :
45 : #include "xmlfilterjar.hxx"
46 : #include "xmlfilterdialogstrings.hrc"
47 : #include "xmlfiltersettingsdialog.hxx"
48 : #include "typedetectionexport.hxx"
49 : #include "typedetectionimport.hxx"
50 :
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;
61 :
62 : using ::rtl::Uri;
63 :
64 0 : XMLFilterJarHelper::XMLFilterJarHelper( const Reference< XComponentContext >& rxContext )
65 : : mxContext( rxContext ),
66 : sVndSunStarPackage( "vnd.sun.star.Package:" ),
67 : sXSLTPath( "$(user)/xslt/" ),
68 : sTemplatePath( "$(user)/template/" ),
69 0 : sProgPath( "$(prog)/" )
70 : {
71 0 : SvtPathOptions aOptions;
72 0 : sProgPath = aOptions.SubstituteVariable( sProgPath );
73 0 : sXSLTPath = aOptions.SubstituteVariable( sXSLTPath );
74 0 : sTemplatePath = aOptions.SubstituteVariable( sTemplatePath );
75 0 : }
76 :
77 0 : static OUString encodeZipUri( const OUString& rURI )
78 : {
79 0 : return Uri::encode( rURI, rtl_UriCharClassUric, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
80 : }
81 :
82 0 : static Reference< XInterface > addFolder( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, const OUString& rName ) throw( Exception )
83 : {
84 0 : if ( rName == ".." || rName == "." )
85 0 : throw lang::IllegalArgumentException();
86 :
87 0 : Sequence< Any > aArgs(1);
88 0 : aArgs[0] <<= true;
89 :
90 0 : Reference< XInterface > xFolder( xFactory->createInstanceWithArguments(aArgs) );
91 0 : Reference< XNamed > xNamed( xFolder, UNO_QUERY );
92 0 : Reference< XChild > xChild( xFolder, UNO_QUERY );
93 :
94 0 : if( xNamed.is() && xChild.is() )
95 : {
96 0 : OUString aName( encodeZipUri( rName ) );
97 0 : xNamed->setName( aName );
98 0 : xChild->setParent( xRootFolder );
99 : }
100 :
101 0 : return xFolder;
102 : }
103 :
104 0 : static void _addFile( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, Reference< XInputStream >& xInput, const OUString& aName ) throw( Exception )
105 : {
106 0 : Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
107 0 : Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
108 0 : if( xSink.is() && xTunnel.is())
109 : {
110 0 : Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
111 0 : xNameContainer->insertByName(encodeZipUri( aName ), makeAny(xTunnel));
112 0 : xSink->setInputStream( xInput );
113 0 : }
114 0 : }
115 :
116 0 : void XMLFilterJarHelper::addFile( Reference< XInterface > xRootFolder, Reference< XSingleServiceFactory > xFactory, const OUString& rSourceFile ) throw( Exception )
117 : {
118 0 : if( !rSourceFile.isEmpty() &&
119 0 : !rSourceFile.startsWith("http:") &&
120 0 : !rSourceFile.startsWith("https:") &&
121 0 : !rSourceFile.startsWith("jar:") &&
122 0 : !rSourceFile.startsWith("ftp:") )
123 : {
124 0 : OUString aFileURL( rSourceFile );
125 :
126 0 : if( !aFileURL.matchIgnoreAsciiCase( OUString("file://") ) )
127 : {
128 0 : aFileURL = URIHelper::SmartRel2Abs( INetURLObject(sProgPath), aFileURL, Link<OUString *, bool>(), false );
129 : }
130 :
131 0 : INetURLObject aURL( aFileURL );
132 0 : OUString aName( aURL.getName() );
133 :
134 0 : SvFileStream* pStream = new SvFileStream(aFileURL, StreamMode::READ );
135 0 : Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
136 0 : _addFile( xRootFolder, xFactory, xInput, aName );
137 : }
138 0 : }
139 :
140 0 : bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const XMLFilterVector& rFilters )
141 : {
142 : try
143 : {
144 0 : osl::File::remove( rPackageURL );
145 :
146 : // create the package jar file
147 :
148 0 : Sequence< Any > aArguments( 2 );
149 0 : aArguments[ 0 ] <<= rPackageURL;
150 :
151 : // let ZipPackage be used ( no manifest.xml is required )
152 0 : beans::NamedValue aArg;
153 0 : aArg.Name = "StorageFormat";
154 0 : aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
155 0 : aArguments[ 1 ] <<= aArg;
156 :
157 : Reference< XHierarchicalNameAccess > xIfc(
158 0 : mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
159 : "com.sun.star.packages.comp.ZipPackage",
160 0 : aArguments, mxContext ), UNO_QUERY );
161 :
162 0 : if( xIfc.is() )
163 : {
164 0 : Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
165 :
166 : // get root zip folder
167 0 : Reference< XInterface > xRootFolder;
168 0 : OUString szRootFolder("/");
169 0 : xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
170 :
171 : // export filters files
172 0 : XMLFilterVector::const_iterator aIter( rFilters.begin() );
173 0 : while( aIter != rFilters.end() )
174 : {
175 0 : const filter_info_impl* pFilter = (*aIter);
176 :
177 0 : Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, pFilter->maFilterName ) );
178 :
179 0 : if( xFilterRoot.is() )
180 : {
181 0 : if( !pFilter->maExportXSLT.isEmpty() )
182 0 : addFile( xFilterRoot, xFactory, pFilter->maExportXSLT );
183 : try
184 : {
185 0 : if( !pFilter->maImportXSLT.isEmpty() )
186 0 : addFile( xFilterRoot, xFactory, pFilter->maImportXSLT );
187 : }
188 0 : catch(const com::sun::star::container::ElementExistException&)
189 : {
190 : // in case of same named import / export XSLT the latter
191 : // is ignored
192 : OSL_FAIL( "XMLFilterJarHelper::same named xslt filter exception!" );
193 : }
194 :
195 0 : if( !pFilter->maImportTemplate.isEmpty() )
196 0 : addFile( xFilterRoot, xFactory, pFilter->maImportTemplate );
197 : }
198 :
199 0 : ++aIter;
200 0 : }
201 :
202 : // create TypeDetection.xcu
203 0 : utl::TempFile aTempFile;
204 0 : aTempFile.EnableKillingFile();
205 0 : OUString aTempFileURL( aTempFile.GetURL() );
206 :
207 : {
208 0 : osl::File aOutputFile( aTempFileURL );
209 0 : /* osl::File::RC rc = */ aOutputFile.open( osl_File_OpenFlag_Write );
210 0 : Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
211 :
212 0 : TypeDetectionExporter aExporter( mxContext );
213 0 : aExporter.doExport(xOS,rFilters);
214 : }
215 :
216 0 : Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( new SvFileStream(aTempFileURL, StreamMode::READ ), true ) );
217 0 : OUString szTypeDetection( "TypeDetection.xcu" );
218 0 : _addFile( xRootFolder, xFactory, XIS, szTypeDetection );
219 :
220 0 : Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
221 0 : if( xBatch.is() )
222 0 : xBatch->commitChanges();
223 :
224 0 : return true;
225 0 : }
226 : }
227 0 : catch( const Exception& )
228 : {
229 : OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
230 : }
231 :
232 0 : osl::File::remove( rPackageURL );
233 :
234 0 : return false;
235 : }
236 :
237 :
238 :
239 :
240 :
241 0 : void XMLFilterJarHelper::openPackage( const OUString& rPackageURL, XMLFilterVector& rFilters )
242 : {
243 : try
244 : {
245 : // create the package jar file
246 :
247 0 : Sequence< Any > aArguments( 2 );
248 0 : aArguments[ 0 ] <<= rPackageURL;
249 :
250 : // let ZipPackage be used ( no manifest.xml is required )
251 0 : beans::NamedValue aArg;
252 0 : aArg.Name = "StorageFormat";
253 0 : aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
254 0 : aArguments[ 1 ] <<= aArg;
255 :
256 : Reference< XHierarchicalNameAccess > xIfc(
257 0 : mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
258 : "com.sun.star.packages.comp.ZipPackage",
259 0 : aArguments, mxContext ), UNO_QUERY );
260 :
261 0 : if( xIfc.is() )
262 : {
263 0 : Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
264 :
265 : // get root zip folder
266 0 : Reference< XInterface > xRootFolder;
267 0 : OUString szRootFolder("/");
268 0 : xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
269 :
270 0 : OUString szTypeDetection("TypeDetection.xcu");
271 0 : if( xIfc->hasByHierarchicalName( szTypeDetection ) )
272 : {
273 0 : Reference< XActiveDataSink > xTypeDetection;
274 0 : xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
275 :
276 0 : if( xTypeDetection.is() )
277 : {
278 0 : Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
279 :
280 0 : XMLFilterVector aFilters;
281 0 : TypeDetectionImporter::doImport( mxContext, xIS, aFilters );
282 :
283 : // copy all files used by the filters imported from the
284 : // typedetection to office/user/xslt
285 0 : XMLFilterVector::iterator aIter( aFilters.begin() );
286 0 : while( aIter != aFilters.end() )
287 : {
288 0 : if( copyFiles( xIfc, (*aIter) ) )
289 : {
290 0 : rFilters.push_back( (*aIter) );
291 : }
292 : else
293 : {
294 : // failed to copy all files
295 0 : delete (*aIter);
296 : }
297 0 : ++aIter;
298 0 : }
299 0 : }
300 0 : }
301 0 : }
302 : }
303 0 : catch( const Exception& )
304 : {
305 : OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
306 : }
307 0 : }
308 :
309 0 : bool XMLFilterJarHelper::copyFiles( Reference< XHierarchicalNameAccess > xIfc, filter_info_impl* pFilter )
310 : {
311 0 : bool bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
312 :
313 0 : if( bOk )
314 0 : bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
315 :
316 0 : if( bOk )
317 0 : bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
318 :
319 0 : return bOk;
320 : }
321 :
322 0 : bool XMLFilterJarHelper::copyFile( Reference< XHierarchicalNameAccess > xIfc, OUString& rURL, const OUString& rTargetURL )
323 : {
324 0 : if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
325 0 : return true;
326 :
327 : try
328 : {
329 0 : OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
330 :
331 0 : if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( ".." ) )
332 0 : || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( "." ) ) )
333 0 : throw lang::IllegalArgumentException();
334 :
335 0 : if( xIfc->hasByHierarchicalName( szPackagePath ) )
336 : {
337 0 : Reference< XActiveDataSink > xFileEntry;
338 0 : xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
339 :
340 0 : if( xFileEntry.is() )
341 : {
342 0 : Reference< XInputStream > xIS( xFileEntry->getInputStream() );
343 :
344 0 : INetURLObject aBaseURL( rTargetURL );
345 :
346 0 : rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link<OUString *, bool>(), false );
347 :
348 0 : if( !rURL.isEmpty() )
349 : {
350 : // create output directory if needed
351 0 : if( !createDirectory( rURL ) )
352 0 : return false;
353 :
354 0 : ::osl::File file(rURL);
355 : ::osl::FileBase::RC rc =
356 0 : file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
357 0 : if (::osl::FileBase::E_EXIST == rc) {
358 0 : rc = file.open(osl_File_OpenFlag_Write);
359 0 : if (::osl::FileBase::E_None == rc) {
360 0 : file.setSize(0); // #i97170# truncate
361 : }
362 : }
363 0 : if (::osl::FileBase::E_None != rc) {
364 0 : throw RuntimeException();
365 : }
366 : Reference< XOutputStream > const xOS(
367 0 : new comphelper::OSLOutputStreamWrapper(file));
368 :
369 0 : return copyStreams( xIS, xOS );
370 0 : }
371 0 : }
372 0 : }
373 : }
374 0 : catch( const Exception& )
375 : {
376 : OSL_FAIL( "XMLFilterJarHelper::copyFile exception catched" );
377 : }
378 0 : return false;
379 3 : }
380 :
381 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|