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