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