Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/io/XActiveDataControl.hpp>
30 : : #include <com/sun/star/io/XActiveDataSource.hpp>
31 : : #include <com/sun/star/frame/XConfigManager.hpp>
32 : : #include <com/sun/star/io/XInputStream.hpp>
33 : : #include <com/sun/star/io/XActiveDataSink.hpp>
34 : : #include <com/sun/star/beans/PropertyValue.hpp>
35 : : #include <com/sun/star/beans/NamedValue.hpp>
36 : : #include <com/sun/star/container/XNamed.hpp>
37 : : #include <com/sun/star/container/XChild.hpp>
38 : : #include <com/sun/star/util/XChangesBatch.hpp>
39 : :
40 : :
41 : : #include <comphelper/oslfile2streamwrap.hxx>
42 : : #include <comphelper/storagehelper.hxx>
43 : : #include <unotools/streamwrap.hxx>
44 : : #include <tools/stream.hxx>
45 : : #include <tools/urlobj.hxx>
46 : : #include <unotools/tempfile.hxx>
47 : : #include <svl/urihelper.hxx>
48 : : #include <osl/file.hxx>
49 : :
50 : : #include <rtl/uri.hxx>
51 : :
52 : : #include "xmlfilterjar.hxx"
53 : : #include "xmlfilterdialogstrings.hrc"
54 : : #include "xmlfiltersettingsdialog.hxx"
55 : : #include "typedetectionexport.hxx"
56 : : #include "typedetectionimport.hxx"
57 : :
58 : : using namespace osl;
59 : : using namespace comphelper;
60 : : using namespace com::sun::star;
61 : : using namespace com::sun::star::lang;
62 : : using namespace com::sun::star::frame;
63 : : using namespace com::sun::star::uno;
64 : : using namespace com::sun::star::util;
65 : : using namespace com::sun::star::container;
66 : : using namespace com::sun::star::beans;
67 : : using namespace com::sun::star::io;
68 : :
69 : : using ::rtl::OUString;
70 : : using ::rtl::Uri;
71 : :
72 : 0 : XMLFilterJarHelper::XMLFilterJarHelper( Reference< XMultiServiceFactory >& xMSF )
73 : : : mxMSF( xMSF ),
74 : : sVndSunStarPackage( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package:" ) ),
75 : : sXSLTPath( RTL_CONSTASCII_USTRINGPARAM( "$(user)/xslt/" ) ),
76 : : sDTDPath( RTL_CONSTASCII_USTRINGPARAM( "$(user)/dtd/" ) ),
77 : : sTemplatePath( RTL_CONSTASCII_USTRINGPARAM( "$(user)/template/") ),
78 : : sSpecialConfigManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.config.SpecialConfigManager" ) ),
79 : : sPump( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.Pump" ) ),
80 : 0 : sProgPath( RTL_CONSTASCII_USTRINGPARAM( "$(prog)/" ) )
81 : : {
82 : : try
83 : : {
84 : 0 : Reference< XConfigManager > xCfgMgr( xMSF->createInstance(OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.config.SpecialConfigManager" ))), UNO_QUERY );
85 : 0 : if( xCfgMgr.is() )
86 : : {
87 : 0 : sProgPath = xCfgMgr->substituteVariables( sProgPath );
88 : 0 : sXSLTPath = xCfgMgr->substituteVariables( sXSLTPath );
89 : 0 : sDTDPath = xCfgMgr->substituteVariables( sDTDPath );
90 : 0 : sTemplatePath = xCfgMgr->substituteVariables( sTemplatePath );
91 : 0 : }
92 : : }
93 : 0 : catch(const Exception&)
94 : : {
95 : : }
96 : 0 : }
97 : :
98 : 0 : static OUString encodeZipUri( const OUString& rURI )
99 : : {
100 : 0 : return Uri::encode( rURI, rtl_UriCharClassUric, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
101 : : }
102 : :
103 : 0 : static Reference< XInterface > addFolder( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, const OUString& rName ) throw( Exception )
104 : : {
105 : 0 : if ( rName == ".." || rName == "." )
106 : 0 : throw lang::IllegalArgumentException();
107 : :
108 : 0 : Sequence< Any > aArgs(1);
109 : 0 : aArgs[0] <<= (sal_Bool)sal_True;
110 : :
111 : 0 : Reference< XInterface > xFolder( xFactory->createInstanceWithArguments(aArgs) );
112 : 0 : Reference< XNamed > xNamed( xFolder, UNO_QUERY );
113 : 0 : Reference< XChild > xChild( xFolder, UNO_QUERY );
114 : :
115 : 0 : if( xNamed.is() && xChild.is() )
116 : : {
117 : 0 : OUString aName( encodeZipUri( rName ) );
118 : 0 : xNamed->setName( aName );
119 : 0 : xChild->setParent( xRootFolder );
120 : : }
121 : :
122 : 0 : return xFolder;
123 : : }
124 : :
125 : 0 : static void _addFile( Reference< XInterface >& xRootFolder, Reference< XSingleServiceFactory >& xFactory, Reference< XInputStream >& xInput, OUString aName ) throw( Exception )
126 : : {
127 : :
128 : 0 : Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
129 : 0 : Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
130 : 0 : if( xSink.is() && xTunnel.is())
131 : : {
132 : 0 : Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
133 : 0 : xNameContainer->insertByName(aName = encodeZipUri( aName ), makeAny(xTunnel));
134 : 0 : xSink->setInputStream( xInput );
135 : 0 : }
136 : 0 : }
137 : :
138 : 0 : void XMLFilterJarHelper::addFile( Reference< XInterface > xRootFolder, Reference< XSingleServiceFactory > xFactory, const OUString& rSourceFile ) throw( Exception )
139 : : {
140 : 0 : if( !rSourceFile.isEmpty() &&
141 : 0 : (rSourceFile.compareToAscii( RTL_CONSTASCII_STRINGPARAM("http:") ) != 0) &&
142 : 0 : (rSourceFile.compareToAscii( RTL_CONSTASCII_STRINGPARAM("shttp:") ) != 0) &&
143 : 0 : (rSourceFile.compareToAscii( RTL_CONSTASCII_STRINGPARAM("jar:") ) != 0) &&
144 : 0 : (rSourceFile.compareToAscii( RTL_CONSTASCII_STRINGPARAM("ftp:") ) != 0))
145 : : {
146 : 0 : OUString aFileURL( rSourceFile );
147 : :
148 : 0 : if( !aFileURL.matchIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("file://") ) ) )
149 : : {
150 : 0 : aFileURL = URIHelper::SmartRel2Abs( sProgPath, aFileURL, Link(), false );
151 : : }
152 : :
153 : 0 : INetURLObject aURL( aFileURL );
154 : 0 : OUString aName( aURL.getName() );
155 : :
156 : 0 : SvFileStream* pStream = new SvFileStream(aFileURL, STREAM_READ );
157 : 0 : Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
158 : 0 : _addFile( xRootFolder, xFactory, xInput, aName );
159 : : }
160 : 0 : }
161 : :
162 : 0 : bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const XMLFilterVector& rFilters )
163 : : {
164 : : try
165 : : {
166 : 0 : osl::File::remove( rPackageURL );
167 : :
168 : : // create the package jar file
169 : :
170 : 0 : Sequence< Any > aArguments( 2 );
171 : 0 : aArguments[ 0 ] <<= rPackageURL;
172 : :
173 : : // let ZipPackage be used ( no manifest.xml is required )
174 : 0 : beans::NamedValue aArg;
175 : 0 : aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
176 : 0 : aArg.Value <<= ZIP_STORAGE_FORMAT_STRING;
177 : 0 : aArguments[ 1 ] <<= aArg;
178 : :
179 : : Reference< XHierarchicalNameAccess > xIfc(
180 : 0 : mxMSF->createInstanceWithArguments(
181 : : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.packages.comp.ZipPackage" )),
182 : 0 : aArguments ), UNO_QUERY );
183 : :
184 : 0 : if( xIfc.is() )
185 : : {
186 : 0 : Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
187 : :
188 : : // get root zip folder
189 : 0 : Reference< XInterface > xRootFolder;
190 : 0 : OUString szRootFolder( RTL_CONSTASCII_USTRINGPARAM("/") );
191 : 0 : xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
192 : :
193 : : // export filters files
194 : 0 : XMLFilterVector::const_iterator aIter( rFilters.begin() );
195 : 0 : while( aIter != rFilters.end() )
196 : : {
197 : 0 : const filter_info_impl* pFilter = (*aIter);
198 : :
199 : 0 : Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, pFilter->maFilterName ) );
200 : :
201 : 0 : if( xFilterRoot.is() )
202 : : {
203 : 0 : if( !pFilter->maDTD.isEmpty() )
204 : 0 : addFile( xFilterRoot, xFactory, pFilter->maDTD );
205 : :
206 : 0 : if( !pFilter->maExportXSLT.isEmpty() )
207 : 0 : addFile( xFilterRoot, xFactory, pFilter->maExportXSLT );
208 : : try
209 : : {
210 : 0 : if( !pFilter->maImportXSLT.isEmpty() )
211 : 0 : addFile( xFilterRoot, xFactory, pFilter->maImportXSLT );
212 : : }
213 : 0 : catch(const com::sun::star::container::ElementExistException&)
214 : : {
215 : : // in case of same named import / export XSLT the latter
216 : : // is ignored
217 : : OSL_FAIL( "XMLFilterJarHelper::same named xslt filter exception!" );
218 : : }
219 : :
220 : 0 : if( !pFilter->maImportTemplate.isEmpty() )
221 : 0 : addFile( xFilterRoot, xFactory, pFilter->maImportTemplate );
222 : : }
223 : :
224 : 0 : ++aIter;
225 : 0 : }
226 : :
227 : : // create TypeDetection.xcu
228 : 0 : utl::TempFile aTempFile;
229 : 0 : aTempFile.EnableKillingFile();
230 : 0 : OUString aTempFileURL( aTempFile.GetURL() );
231 : :
232 : : {
233 : 0 : osl::File aOutputFile( aTempFileURL );
234 : 0 : /* osl::File::RC rc = */ aOutputFile.open( osl_File_OpenFlag_Write );
235 : 0 : Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
236 : :
237 : 0 : TypeDetectionExporter aExporter( mxMSF );
238 : 0 : aExporter.doExport(xOS,rFilters);
239 : : }
240 : :
241 : 0 : Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( new SvFileStream(aTempFileURL, STREAM_READ ), true ) );
242 : 0 : OUString szTypeDetection( RTL_CONSTASCII_USTRINGPARAM( "TypeDetection.xcu" ) );
243 : 0 : _addFile( xRootFolder, xFactory, XIS, szTypeDetection );
244 : :
245 : 0 : Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
246 : 0 : if( xBatch.is() )
247 : 0 : xBatch->commitChanges();
248 : :
249 : 0 : return true;
250 : 0 : }
251 : : }
252 : 0 : catch( const Exception& )
253 : : {
254 : : OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
255 : : }
256 : :
257 : 0 : osl::File::remove( rPackageURL );
258 : :
259 : 0 : return false;
260 : : }
261 : :
262 : :
263 : :
264 : : //
265 : :
266 : 0 : void XMLFilterJarHelper::openPackage( const OUString& rPackageURL, XMLFilterVector& rFilters )
267 : : {
268 : : try
269 : : {
270 : : // create the package jar file
271 : :
272 : 0 : Sequence< Any > aArguments( 2 );
273 : 0 : aArguments[ 0 ] <<= rPackageURL;
274 : :
275 : : // let ZipPackage be used ( no manifest.xml is required )
276 : 0 : beans::NamedValue aArg;
277 : 0 : aArg.Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StorageFormat" ) );
278 : 0 : aArg.Value <<= ZIP_STORAGE_FORMAT_STRING;
279 : 0 : aArguments[ 1 ] <<= aArg;
280 : :
281 : : Reference< XHierarchicalNameAccess > xIfc(
282 : 0 : mxMSF->createInstanceWithArguments(
283 : : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.packages.comp.ZipPackage" )),
284 : 0 : aArguments ), UNO_QUERY );
285 : :
286 : 0 : if( xIfc.is() )
287 : : {
288 : 0 : Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
289 : :
290 : : // get root zip folder
291 : 0 : Reference< XInterface > xRootFolder;
292 : 0 : OUString szRootFolder( RTL_CONSTASCII_USTRINGPARAM("/") );
293 : 0 : xIfc->getByHierarchicalName( szRootFolder ) >>= xRootFolder;
294 : :
295 : 0 : OUString szTypeDetection( RTL_CONSTASCII_USTRINGPARAM("TypeDetection.xcu") );
296 : 0 : if( xIfc->hasByHierarchicalName( szTypeDetection ) )
297 : : {
298 : 0 : Reference< XActiveDataSink > xTypeDetection;
299 : 0 : xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
300 : :
301 : 0 : if( xTypeDetection.is() )
302 : : {
303 : 0 : Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
304 : :
305 : 0 : XMLFilterVector aFilters;
306 : 0 : TypeDetectionImporter::doImport( mxMSF, xIS, aFilters );
307 : :
308 : : // copy all files used by the filters imported from the
309 : : // typedetection to office/user/xslt
310 : 0 : XMLFilterVector::iterator aIter( aFilters.begin() );
311 : 0 : while( aIter != aFilters.end() )
312 : : {
313 : 0 : if( copyFiles( xIfc, (*aIter) ) )
314 : : {
315 : 0 : rFilters.push_back( (*aIter) );
316 : : }
317 : : else
318 : : {
319 : : // failed to copy all files
320 : 0 : delete (*aIter);
321 : : }
322 : 0 : ++aIter;
323 : 0 : }
324 : 0 : }
325 : 0 : }
326 : 0 : }
327 : : }
328 : 0 : catch( const Exception& )
329 : : {
330 : : OSL_FAIL( "XMLFilterJarHelper::savePackage exception catched!" );
331 : : }
332 : 0 : }
333 : :
334 : 0 : bool XMLFilterJarHelper::copyFiles( Reference< XHierarchicalNameAccess > xIfc, filter_info_impl* pFilter )
335 : : {
336 : 0 : bool bOk = copyFile( xIfc, pFilter->maDTD, sDTDPath );
337 : :
338 : 0 : if( bOk )
339 : 0 : bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
340 : :
341 : 0 : if( bOk )
342 : 0 : bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
343 : :
344 : 0 : if( bOk )
345 : 0 : bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
346 : :
347 : 0 : return bOk;
348 : : }
349 : :
350 : 0 : bool XMLFilterJarHelper::copyFile( Reference< XHierarchicalNameAccess > xIfc, OUString& rURL, const OUString& rTargetURL )
351 : : {
352 : 0 : if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
353 : 0 : return true;
354 : :
355 : : try
356 : : {
357 : 0 : OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
358 : :
359 : 0 : if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( RTL_CONSTASCII_USTRINGPARAM( ".." ) ) )
360 : 0 : || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) ) )
361 : 0 : throw lang::IllegalArgumentException();
362 : :
363 : 0 : if( xIfc->hasByHierarchicalName( szPackagePath ) )
364 : : {
365 : 0 : Reference< XActiveDataSink > xFileEntry;
366 : 0 : xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
367 : :
368 : 0 : if( xFileEntry.is() )
369 : : {
370 : 0 : Reference< XInputStream > xIS( xFileEntry->getInputStream() );
371 : :
372 : 0 : INetURLObject aBaseURL( rTargetURL );
373 : :
374 : 0 : rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link(), false );
375 : :
376 : 0 : if( !rURL.isEmpty() )
377 : : {
378 : : // create output directory if needed
379 : 0 : if( !createDirectory( rURL ) )
380 : 0 : return false;
381 : :
382 : 0 : ::osl::File file(rURL);
383 : : ::osl::FileBase::RC rc =
384 : 0 : file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
385 : 0 : if (::osl::FileBase::E_EXIST == rc) {
386 : 0 : rc = file.open(osl_File_OpenFlag_Write);
387 : 0 : if (::osl::FileBase::E_None == rc) {
388 : 0 : file.setSize(0); // #i97170# truncate
389 : : }
390 : : }
391 : 0 : if (::osl::FileBase::E_None != rc) {
392 : 0 : throw RuntimeException();
393 : : }
394 : : Reference< XOutputStream > const xOS(
395 : 0 : new comphelper::OSLOutputStreamWrapper(file));
396 : :
397 : 0 : return copyStreams( xIS, xOS );
398 : 0 : }
399 : 0 : }
400 : 0 : }
401 : : }
402 : 0 : catch( const Exception& )
403 : : {
404 : : OSL_FAIL( "XMLFilterJarHelper::copyFile exception catched" );
405 : : }
406 : 0 : return false;
407 : : }
408 : :
409 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|