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