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