1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER( update_precomp.py ): autogen include statement, do not remove 25 #include "precompiled_package.hxx" 26 #include <ZipPackage.hxx> 27 #include <ZipPackageSink.hxx> 28 #include <ZipEnumeration.hxx> 29 #include <ZipPackageStream.hxx> 30 #include <ZipPackageFolder.hxx> 31 #include <ZipOutputStream.hxx> 32 #include <ZipPackageBuffer.hxx> 33 #include <ZipFile.hxx> 34 #include <PackageConstants.hxx> 35 #include <com/sun/star/beans/PropertyValue.hpp> 36 #include <com/sun/star/beans/NamedValue.hpp> 37 #include <com/sun/star/packages/zip/ZipConstants.hpp> 38 #include <com/sun/star/packages/manifest/XManifestReader.hpp> 39 #include <com/sun/star/packages/manifest/XManifestWriter.hpp> 40 #include <com/sun/star/io/XStream.hpp> 41 #include <com/sun/star/io/XInputStream.hpp> 42 #include <com/sun/star/io/XOutputStream.hpp> 43 #include <com/sun/star/io/XTruncate.hpp> 44 #include <com/sun/star/io/XSeekable.hpp> 45 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 46 #include <com/sun/star/container/XNameContainer.hpp> 47 #include <com/sun/star/ucb/IOErrorCode.hpp> 48 #include <ucbhelper/content.hxx> 49 #include <cppuhelper/factory.hxx> 50 #include <cppuhelper/exc_hlp.hxx> 51 #include <com/sun/star/ucb/TransferInfo.hpp> 52 #include <com/sun/star/ucb/NameClash.hpp> 53 #include <com/sun/star/ucb/OpenCommandArgument2.hpp> 54 #include <com/sun/star/ucb/OpenMode.hpp> 55 #include <com/sun/star/ucb/XProgressHandler.hpp> 56 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 57 #include <com/sun/star/io/XActiveDataStreamer.hpp> 58 #include <com/sun/star/embed/XTransactedObject.hpp> 59 #include <com/sun/star/embed/UseBackupException.hpp> 60 #include <com/sun/star/embed/StorageFormats.hpp> 61 #include <com/sun/star/beans/NamedValue.hpp> 62 #include <com/sun/star/xml/crypto/DigestID.hpp> 63 #include <com/sun/star/xml/crypto/CipherID.hpp> 64 #include <cppuhelper/implbase1.hxx> 65 #include <ContentInfo.hxx> 66 #include <cppuhelper/typeprovider.hxx> 67 #include <rtl/uri.hxx> 68 #include <rtl/random.h> 69 #include <rtl/logfile.hxx> 70 #include <rtl/instance.hxx> 71 #include <osl/time.h> 72 #include <osl/file.hxx> 73 #include "com/sun/star/io/XAsyncOutputMonitor.hpp" 74 75 #include <memory> 76 #include <vector> 77 78 #include <ucbhelper/contentbroker.hxx> 79 #include <ucbhelper/fileidentifierconverter.hxx> 80 #include <comphelper/seekableinput.hxx> 81 #include <comphelper/storagehelper.hxx> 82 #include <comphelper/ofopxmlhelper.hxx> 83 #include <comphelper/documentconstants.hxx> 84 #include <comphelper/sequenceashashmap.hxx> 85 86 using namespace rtl; 87 using namespace std; 88 using namespace osl; 89 using namespace cppu; 90 using namespace ucbhelper; 91 using namespace com::sun::star; 92 using namespace com::sun::star::io; 93 using namespace com::sun::star::uno; 94 using namespace com::sun::star::ucb; 95 using namespace com::sun::star::util; 96 using namespace com::sun::star::lang; 97 using namespace com::sun::star::task; 98 using namespace com::sun::star::beans; 99 using namespace com::sun::star::packages; 100 using namespace com::sun::star::container; 101 using namespace com::sun::star::packages::zip; 102 using namespace com::sun::star::packages::manifest; 103 using namespace com::sun::star::packages::zip::ZipConstants; 104 105 #define LOGFILE_AUTHOR "mg115289" 106 107 108 namespace { 109 110 sal_Bool isLocalFile_Impl( ::rtl::OUString aURL ) 111 { 112 ::rtl::OUString aSystemPath; 113 ContentBroker* pBroker = ContentBroker::get(); 114 if ( !pBroker ) 115 { 116 ::rtl::OUString aRet; 117 if ( FileBase::getSystemPathFromFileURL( aURL, aRet ) == FileBase::E_None ) 118 aSystemPath = aRet; 119 } 120 else 121 { 122 uno::Reference< XContentProviderManager > xManager = 123 pBroker->getContentProviderManagerInterface(); 124 try 125 { 126 aSystemPath = getSystemPathFromFileURL( xManager, aURL ); 127 } 128 catch ( Exception& ) 129 { 130 } 131 } 132 133 return ( aSystemPath.getLength() != 0 ); 134 } 135 136 } 137 138 //=========================================================================== 139 140 class ActiveDataStreamer : public ::cppu::WeakImplHelper1< XActiveDataStreamer > 141 { 142 uno::Reference< XStream > mStream; 143 public: 144 145 virtual uno::Reference< XStream > SAL_CALL getStream() 146 throw( RuntimeException ) 147 { return mStream; } 148 149 virtual void SAL_CALL setStream( const uno::Reference< XStream >& stream ) 150 throw( RuntimeException ) 151 { mStream = stream; } 152 }; 153 154 class DummyInputStream : public ::cppu::WeakImplHelper1< XInputStream > 155 { 156 virtual sal_Int32 SAL_CALL readBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) 157 throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) 158 { return 0; } 159 160 virtual sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) 161 throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) 162 { return 0; } 163 164 virtual void SAL_CALL skipBytes( sal_Int32 ) 165 throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) 166 {} 167 168 virtual sal_Int32 SAL_CALL available() 169 throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) 170 { return 0; } 171 172 virtual void SAL_CALL closeInput() 173 throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) 174 {} 175 }; 176 177 //=========================================================================== 178 179 ZipPackage::ZipPackage ( const uno::Reference < XMultiServiceFactory > &xNewFactory ) 180 : m_aMutexHolder( new SotMutexHolder ) 181 , m_nStartKeyGenerationID( xml::crypto::DigestID::SHA1 ) 182 , m_nChecksumDigestID( xml::crypto::DigestID::SHA1_1K ) 183 , m_nCommonEncryptionID( xml::crypto::CipherID::BLOWFISH_CFB_8 ) 184 , m_bHasEncryptedEntries ( sal_False ) 185 , m_bHasNonEncryptedEntries ( sal_False ) 186 , m_bInconsistent ( sal_False ) 187 , m_bForceRecovery ( sal_False ) 188 , m_bMediaTypeFallbackUsed ( sal_False ) 189 , m_nFormat( embed::StorageFormats::PACKAGE ) // package is the default format 190 , m_bAllowRemoveOnInsert( sal_True ) 191 , m_eMode ( e_IMode_None ) 192 , m_xFactory( xNewFactory ) 193 , m_pRootFolder( NULL ) 194 , m_pZipFile( NULL ) 195 { 196 m_xRootFolder = m_pRootFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); 197 } 198 199 ZipPackage::~ZipPackage( void ) 200 { 201 delete m_pZipFile; 202 203 // All folders and streams contain pointers to their parents, when a parent diappeares 204 // it should disconnect all the children from itself during destruction automatically. 205 // So there is no need in explicit m_pRootFolder->releaseUpwardRef() call here any more 206 // since m_pRootFolder has no parent and cleaning of it's children will be done automatically 207 // during m_pRootFolder dieing by refcount. 208 } 209 210 //-------------------------------------------------------- 211 void ZipPackage::parseManifest() 212 { 213 if ( m_nFormat == embed::StorageFormats::PACKAGE ) 214 { 215 sal_Bool bManifestParsed = sal_False; 216 bool bDifferentStartKeyAlgorithm = false; 217 const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) ); 218 if ( m_xRootFolder->hasByName( sMeta ) ) 219 { 220 const OUString sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ); 221 222 try { 223 uno::Reference< XUnoTunnel > xTunnel; 224 Any aAny = m_xRootFolder->getByName( sMeta ); 225 aAny >>= xTunnel; 226 uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY ); 227 if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) ) 228 { 229 aAny = xMetaInfFolder->getByName( sManifest ); 230 aAny >>= xTunnel; 231 uno::Reference < XActiveDataSink > xSink ( xTunnel, UNO_QUERY ); 232 if ( xSink.is() ) 233 { 234 OUString sManifestReader ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestReader" ) ); 235 uno::Reference < XManifestReader > xReader ( m_xFactory->createInstance( sManifestReader ), UNO_QUERY ); 236 if ( xReader.is() ) 237 { 238 const OUString sPropFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); 239 const OUString sPropVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); 240 const OUString sPropMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); 241 const OUString sPropInitialisationVector ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ); 242 const OUString sPropSalt ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ); 243 const OUString sPropIterationCount ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); 244 const OUString sPropSize ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); 245 const OUString sPropDigest ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); 246 const OUString sPropDerivedKeySize ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ); 247 const OUString sPropDigestAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ); 248 const OUString sPropEncryptionAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ); 249 const OUString sPropStartKeyAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ); 250 251 uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence = xReader->readManifestSequence ( xSink->getInputStream() ); 252 sal_Int32 nLength = aManifestSequence.getLength(); 253 const uno::Sequence < PropertyValue > *pSequence = aManifestSequence.getConstArray(); 254 ZipPackageStream *pStream = NULL; 255 ZipPackageFolder *pFolder = NULL; 256 257 for ( sal_Int32 i = 0; i < nLength ; i++, pSequence++ ) 258 { 259 OUString sPath, sMediaType, sVersion; 260 const PropertyValue *pValue = pSequence->getConstArray(); 261 const Any *pSalt = NULL, *pVector = NULL, *pCount = NULL, *pSize = NULL, *pDigest = NULL, *pDigestAlg = NULL, *pEncryptionAlg = NULL, *pStartKeyAlg = NULL, *pDerivedKeySize = NULL; 262 for ( sal_Int32 j = 0, nNum = pSequence->getLength(); j < nNum; j++ ) 263 { 264 if ( pValue[j].Name.equals( sPropFullPath ) ) 265 pValue[j].Value >>= sPath; 266 else if ( pValue[j].Name.equals( sPropVersion ) ) 267 pValue[j].Value >>= sVersion; 268 else if ( pValue[j].Name.equals( sPropMediaType ) ) 269 pValue[j].Value >>= sMediaType; 270 else if ( pValue[j].Name.equals( sPropSalt ) ) 271 pSalt = &( pValue[j].Value ); 272 else if ( pValue[j].Name.equals( sPropInitialisationVector ) ) 273 pVector = &( pValue[j].Value ); 274 else if ( pValue[j].Name.equals( sPropIterationCount ) ) 275 pCount = &( pValue[j].Value ); 276 else if ( pValue[j].Name.equals( sPropSize ) ) 277 pSize = &( pValue[j].Value ); 278 else if ( pValue[j].Name.equals( sPropDigest ) ) 279 pDigest = &( pValue[j].Value ); 280 else if ( pValue[j].Name.equals( sPropDigestAlgorithm ) ) 281 pDigestAlg = &( pValue[j].Value ); 282 else if ( pValue[j].Name.equals( sPropEncryptionAlgorithm ) ) 283 pEncryptionAlg = &( pValue[j].Value ); 284 else if ( pValue[j].Name.equals( sPropStartKeyAlgorithm ) ) 285 pStartKeyAlg = &( pValue[j].Value ); 286 else if ( pValue[j].Name.equals( sPropDerivedKeySize ) ) 287 pDerivedKeySize = &( pValue[j].Value ); 288 } 289 290 if ( sPath.getLength() && hasByHierarchicalName ( sPath ) ) 291 { 292 aAny = getByHierarchicalName( sPath ); 293 uno::Reference < XUnoTunnel > xUnoTunnel; 294 aAny >>= xUnoTunnel; 295 sal_Int64 nTest=0; 296 if ( (nTest = xUnoTunnel->getSomething( ZipPackageFolder::static_getImplementationId() )) != 0 ) 297 { 298 pFolder = reinterpret_cast < ZipPackageFolder* > ( nTest ); 299 pFolder->SetMediaType ( sMediaType ); 300 pFolder->SetVersion ( sVersion ); 301 } 302 else 303 { 304 pStream = reinterpret_cast < ZipPackageStream* > ( xUnoTunnel->getSomething( ZipPackageStream::static_getImplementationId() )); 305 pStream->SetMediaType ( sMediaType ); 306 pStream->SetFromManifest( sal_True ); 307 308 if ( pSalt && pVector && pCount && pSize && pDigest && pDigestAlg && pEncryptionAlg ) 309 { 310 uno::Sequence < sal_Int8 > aSequence; 311 sal_Int32 nCount = 0, nSize = 0, nDigestAlg = 0, nEncryptionAlg = 0, nDerivedKeySize = 16, nStartKeyAlg = xml::crypto::DigestID::SHA1; 312 313 pStream->SetToBeEncrypted ( sal_True ); 314 315 *pSalt >>= aSequence; 316 pStream->setSalt ( aSequence ); 317 318 *pVector >>= aSequence; 319 pStream->setInitialisationVector ( aSequence ); 320 321 *pCount >>= nCount; 322 pStream->setIterationCount ( nCount ); 323 324 *pSize >>= nSize; 325 pStream->setSize ( nSize ); 326 327 *pDigest >>= aSequence; 328 pStream->setDigest ( aSequence ); 329 330 *pDigestAlg >>= nDigestAlg; 331 pStream->SetImportedChecksumAlgorithm( nDigestAlg ); 332 333 *pEncryptionAlg >>= nEncryptionAlg; 334 pStream->SetImportedEncryptionAlgorithm( nEncryptionAlg ); 335 336 if ( pDerivedKeySize ) 337 *pDerivedKeySize >>= nDerivedKeySize; 338 pStream->SetImportedDerivedKeySize( nDerivedKeySize ); 339 340 if ( pStartKeyAlg ) 341 *pStartKeyAlg >>= nStartKeyAlg; 342 pStream->SetImportedStartKeyAlgorithm( nStartKeyAlg ); 343 344 pStream->SetToBeCompressed ( sal_True ); 345 pStream->SetToBeEncrypted ( sal_True ); 346 pStream->SetIsEncrypted ( sal_True ); 347 if ( !m_bHasEncryptedEntries 348 && pStream->getName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) ) ) 349 { 350 m_bHasEncryptedEntries = sal_True; 351 m_nStartKeyGenerationID = nStartKeyAlg; 352 m_nChecksumDigestID = nDigestAlg; 353 m_nCommonEncryptionID = nEncryptionAlg; 354 } 355 } 356 else 357 m_bHasNonEncryptedEntries = sal_True; 358 } 359 } 360 } 361 362 bManifestParsed = sal_True; 363 } 364 else 365 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No manifes parser!" ) ), uno::Reference< uno::XInterface >() ); 366 } 367 368 // now hide the manifest.xml file from user 369 xMetaInfFolder->removeByName( sManifest ); 370 } 371 } 372 catch( Exception& ) 373 { 374 if ( !m_bForceRecovery ) 375 throw; 376 } 377 } 378 379 if ( !bManifestParsed && !m_bForceRecovery ) 380 throw ZipIOException( 381 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Could not parse manifest.xml\n" ) ), 382 uno::Reference< uno::XInterface >() ); 383 384 const OUString sMimetype ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) ); 385 if ( m_xRootFolder->hasByName( sMimetype ) ) 386 { 387 // get mediatype from the "mimetype" stream 388 ::rtl::OUString aPackageMediatype; 389 uno::Reference< lang::XUnoTunnel > xMimeTypeTunnel; 390 m_xRootFolder->getByName( sMimetype ) >>= xMimeTypeTunnel; 391 uno::Reference < io::XActiveDataSink > xMimeSink( xMimeTypeTunnel, UNO_QUERY ); 392 if ( xMimeSink.is() ) 393 { 394 uno::Reference< io::XInputStream > xMimeInStream = xMimeSink->getInputStream(); 395 if ( xMimeInStream.is() ) 396 { 397 // Mediatypes longer than 1024 symbols should not appear here 398 uno::Sequence< sal_Int8 > aData( 1024 ); 399 sal_Int32 nRead = xMimeInStream->readBytes( aData, 1024 ); 400 if ( nRead > aData.getLength() ) 401 nRead = aData.getLength(); 402 403 if ( nRead ) 404 aPackageMediatype = ::rtl::OUString( ( sal_Char* )aData.getConstArray(), nRead, RTL_TEXTENCODING_ASCII_US ); 405 } 406 } 407 408 409 if ( !bManifestParsed ) 410 { 411 // the manifest.xml could not be successfuly parsed, this is an inconsistent package 412 if ( aPackageMediatype.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "application/vnd." ) ) == 0 ) 413 { 414 // accept only types that look similar to own mediatypes 415 m_pRootFolder->SetMediaType( aPackageMediatype ); 416 m_bMediaTypeFallbackUsed = sal_True; 417 } 418 } 419 else if ( !m_bForceRecovery ) 420 { 421 // the mimetype stream should contain the information from manifest.xml 422 if ( !m_pRootFolder->GetMediaType().equals( aPackageMediatype ) ) 423 throw ZipIOException( 424 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "mimetype conflicts with manifest.xml\n" ) ), 425 uno::Reference< uno::XInterface >() ); 426 } 427 428 m_xRootFolder->removeByName( sMimetype ); 429 } 430 431 m_bInconsistent = m_pRootFolder->LookForUnexpectedODF12Streams( ::rtl::OUString() ); 432 433 sal_Bool bODF12AndNewer = ( m_pRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 ); 434 if ( !m_bForceRecovery && bODF12AndNewer ) 435 { 436 if ( m_bInconsistent ) 437 { 438 // this is an ODF1.2 document that contains streams not referred in the manifest.xml; 439 // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent 440 // should be checked later 441 throw ZipIOException( 442 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "there are streams not referred in manifest.xml\n" ) ), 443 uno::Reference< uno::XInterface >() ); 444 } 445 else if ( bDifferentStartKeyAlgorithm ) 446 { 447 // all the streams should be encrypted with the same StartKey in ODF1.2 448 // TODO/LATER: in future the exception should be thrown 449 OSL_ENSURE( false, "ODF1.2 contains different StartKey Algorithms" ); 450 // throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "More than one Start Key Generation algorithm is specified!" ) ), uno::Reference< uno::XInterface >() ); 451 } 452 } 453 454 // in case it is a correct ODF1.2 document, the version must be set 455 // and the META-INF folder is reserved for package format 456 if ( bODF12AndNewer ) 457 m_xRootFolder->removeByName( sMeta ); 458 } 459 } 460 461 //-------------------------------------------------------- 462 void ZipPackage::parseContentType() 463 { 464 if ( m_nFormat == embed::StorageFormats::OFOPXML ) 465 { 466 const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); 467 try { 468 // the content type must exist in OFOPXML format! 469 if ( !m_xRootFolder->hasByName( aContentTypes ) ) 470 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong format!" ) ), 471 uno::Reference< uno::XInterface >() ); 472 473 uno::Reference< lang::XUnoTunnel > xTunnel; 474 uno::Any aAny = m_xRootFolder->getByName( aContentTypes ); 475 aAny >>= xTunnel; 476 uno::Reference < io::XActiveDataSink > xSink( xTunnel, UNO_QUERY ); 477 if ( xSink.is() ) 478 { 479 uno::Reference< io::XInputStream > xInStream = xSink->getInputStream(); 480 if ( xInStream.is() ) 481 { 482 sal_Int32 nInd = 0; 483 // here aContentTypeInfo[0] - Defaults, and aContentTypeInfo[1] - Overrides 484 uno::Sequence< uno::Sequence< beans::StringPair > > aContentTypeInfo = 485 ::comphelper::OFOPXMLHelper::ReadContentTypeSequence( xInStream, m_xFactory ); 486 487 if ( aContentTypeInfo.getLength() != 2 ) 488 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 489 490 // set the implicit types fist 491 for ( nInd = 0; nInd < aContentTypeInfo[0].getLength(); nInd++ ) 492 m_pRootFolder->setChildStreamsTypeByExtension( aContentTypeInfo[0][nInd] ); 493 494 // now set the explicit types 495 for ( nInd = 0; nInd < aContentTypeInfo[1].getLength(); nInd++ ) 496 { 497 ::rtl::OUString aPath; 498 if ( aContentTypeInfo[1][nInd].First.toChar() == ( sal_Unicode )'/' ) 499 aPath = aContentTypeInfo[1][nInd].First.copy( 1 ); 500 else 501 aPath = aContentTypeInfo[1][nInd].First; 502 503 if ( aPath.getLength() && hasByHierarchicalName( aPath ) ) 504 { 505 uno::Any aIterAny = getByHierarchicalName( aPath ); 506 uno::Reference < lang::XUnoTunnel > xIterTunnel; 507 aIterAny >>= xIterTunnel; 508 sal_Int64 nTest = xIterTunnel->getSomething( ZipPackageStream::static_getImplementationId() ); 509 if ( nTest != 0 ) 510 { 511 // this is a package stream, in OFOPXML format only streams can have mediatype 512 ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream* > ( nTest ); 513 pStream->SetMediaType( aContentTypeInfo[1][nInd].Second ); 514 } 515 } 516 } 517 } 518 } 519 520 m_xRootFolder->removeByName( aContentTypes ); 521 } 522 catch( uno::Exception& ) 523 { 524 if ( !m_bForceRecovery ) 525 throw; 526 } 527 } 528 } 529 530 //-------------------------------------------------------- 531 void ZipPackage::getZipFileContents() 532 { 533 auto_ptr < ZipEnumeration > pEnum ( m_pZipFile->entries() ); 534 ZipPackageStream *pPkgStream; 535 ZipPackageFolder *pPkgFolder, *pCurrent; 536 OUString sTemp, sDirName; 537 sal_Int32 nOldIndex, nIndex, nStreamIndex; 538 FolderHash::iterator aIter; 539 540 while ( pEnum->hasMoreElements() ) 541 { 542 nIndex = nOldIndex = 0; 543 pCurrent = m_pRootFolder; 544 const ZipEntry & rEntry = *pEnum->nextElement(); 545 OUString rName = rEntry.sPath; 546 547 if ( m_bForceRecovery ) 548 { 549 // the PKZIP Application note version 6.2 does not allows to use '\' as separator 550 // unfortunately it is used by some implementations, so we have to support it in recovery mode 551 rName = rName.replace( '\\', '/' ); 552 } 553 554 nStreamIndex = rName.lastIndexOf ( '/' ); 555 if ( nStreamIndex != -1 ) 556 { 557 sDirName = rName.copy ( 0, nStreamIndex ); 558 aIter = m_aRecent.find ( sDirName ); 559 if ( aIter != m_aRecent.end() ) 560 pCurrent = ( *aIter ).second; 561 } 562 563 if ( pCurrent == m_pRootFolder ) 564 { 565 while ( ( nIndex = rName.indexOf( '/', nOldIndex ) ) != -1 ) 566 { 567 sTemp = rName.copy ( nOldIndex, nIndex - nOldIndex ); 568 if ( nIndex == nOldIndex ) 569 break; 570 if ( !pCurrent->hasByName( sTemp ) ) 571 { 572 pPkgFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); 573 pPkgFolder->setName( sTemp ); 574 pPkgFolder->doSetParent( pCurrent, sal_True ); 575 pCurrent = pPkgFolder; 576 } 577 else 578 pCurrent = pCurrent->doGetByName( sTemp ).pFolder; 579 nOldIndex = nIndex+1; 580 } 581 if ( nStreamIndex != -1 && sDirName.getLength() ) 582 m_aRecent [ sDirName ] = pCurrent; 583 } 584 if ( rName.getLength() -1 != nStreamIndex ) 585 { 586 nStreamIndex++; 587 sTemp = rName.copy( nStreamIndex, rName.getLength() - nStreamIndex ); 588 pPkgStream = new ZipPackageStream( *this, m_xFactory, m_bAllowRemoveOnInsert ); 589 pPkgStream->SetPackageMember( sal_True ); 590 pPkgStream->setZipEntryOnLoading( rEntry ); 591 pPkgStream->setName( sTemp ); 592 pPkgStream->doSetParent( pCurrent, sal_True ); 593 } 594 } 595 596 if ( m_nFormat == embed::StorageFormats::PACKAGE ) 597 parseManifest(); 598 else if ( m_nFormat == embed::StorageFormats::OFOPXML ) 599 parseContentType(); 600 } 601 602 //-------------------------------------------------------- 603 void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) 604 throw( Exception, RuntimeException ) 605 { 606 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::initialize" ); 607 sal_Bool bBadZipFile = sal_False, bHaveZipFile = sal_True; 608 uno::Reference< XProgressHandler > xProgressHandler; 609 beans::NamedValue aNamedValue; 610 611 if ( aArguments.getLength() ) 612 { 613 for( int ind = 0; ind < aArguments.getLength(); ind++ ) 614 { 615 OUString aParamUrl; 616 if ( ( aArguments[ind] >>= aParamUrl )) 617 { 618 m_eMode = e_IMode_URL; 619 try 620 { 621 sal_Int32 nParam = aParamUrl.indexOf( '?' ); 622 if ( nParam >= 0 ) 623 { 624 m_aURL = aParamUrl.copy( 0, nParam ); 625 OUString aParam = aParamUrl.copy( nParam + 1 ); 626 627 sal_Int32 nIndex = 0; 628 do 629 { 630 ::rtl::OUString aCommand = aParam.getToken( 0, '&', nIndex ); 631 if ( aCommand.equals( OUString::createFromAscii( "repairpackage" ) ) ) 632 { 633 m_bForceRecovery = sal_True; 634 break; 635 } 636 else if ( aCommand.equals( OUString::createFromAscii( "purezip" ) ) ) 637 { 638 m_nFormat = embed::StorageFormats::ZIP; 639 m_pRootFolder->setPackageFormat_Impl( m_nFormat ); 640 break; 641 } 642 else if ( aCommand.equals( OUString::createFromAscii( "ofopxml" ) ) ) 643 { 644 m_nFormat = embed::StorageFormats::OFOPXML; 645 m_pRootFolder->setPackageFormat_Impl( m_nFormat ); 646 break; 647 } 648 } 649 while ( nIndex >= 0 ); 650 } 651 else 652 m_aURL = aParamUrl; 653 654 Content aContent ( m_aURL, uno::Reference < XCommandEnvironment >() ); 655 Any aAny = aContent.getPropertyValue( OUString::createFromAscii( "Size" ) ); 656 sal_uInt64 aSize = 0; 657 // kind of optimisation: treat empty files as nonexistent files 658 // and write to such files directly. Note that "Size" property is optional. 659 bool bHasSizeProperty = aAny >>= aSize; 660 if( !bHasSizeProperty || ( bHasSizeProperty && aSize ) ) 661 { 662 uno::Reference < XActiveDataSink > xSink = new ZipPackageSink; 663 if ( aContent.openStream ( xSink ) ) 664 m_xContentStream = xSink->getInputStream(); 665 } 666 else 667 bHaveZipFile = sal_False; 668 } 669 catch ( com::sun::star::uno::Exception& ) 670 { 671 // Exception derived from uno::Exception thrown. This probably 672 // means the file doesn't exist...we'll create it at 673 // commitChanges time 674 bHaveZipFile = sal_False; 675 } 676 } 677 else if ( ( aArguments[ind] >>= m_xStream ) ) 678 { 679 // a writable stream can implement both XStream & XInputStream 680 m_eMode = e_IMode_XStream; 681 m_xContentStream = m_xStream->getInputStream(); 682 } 683 else if ( ( aArguments[ind] >>= m_xContentStream ) ) 684 { 685 m_eMode = e_IMode_XInputStream; 686 } 687 else if ( ( aArguments[ind] >>= aNamedValue ) ) 688 { 689 if ( aNamedValue.Name.equalsAscii( "RepairPackage" ) ) 690 aNamedValue.Value >>= m_bForceRecovery; 691 else if ( aNamedValue.Name.equalsAscii( "PackageFormat" ) ) 692 { 693 // setting this argument to true means Package format 694 // setting it to false means plain Zip format 695 696 sal_Bool bPackFormat = sal_True; 697 aNamedValue.Value >>= bPackFormat; 698 if ( !bPackFormat ) 699 m_nFormat = embed::StorageFormats::ZIP; 700 701 m_pRootFolder->setPackageFormat_Impl( m_nFormat ); 702 } 703 else if ( aNamedValue.Name.equalsAscii( "StorageFormat" ) ) 704 { 705 ::rtl::OUString aFormatName; 706 sal_Int32 nFormatID = 0; 707 if ( aNamedValue.Value >>= aFormatName ) 708 { 709 if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) ) 710 m_nFormat = embed::StorageFormats::PACKAGE; 711 else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) ) 712 m_nFormat = embed::StorageFormats::ZIP; 713 else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) ) 714 m_nFormat = embed::StorageFormats::OFOPXML; 715 else 716 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 717 } 718 else if ( aNamedValue.Value >>= nFormatID ) 719 { 720 if ( nFormatID != embed::StorageFormats::PACKAGE 721 && nFormatID != embed::StorageFormats::ZIP 722 && nFormatID != embed::StorageFormats::OFOPXML ) 723 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 724 725 m_nFormat = nFormatID; 726 } 727 else 728 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); 729 730 m_pRootFolder->setPackageFormat_Impl( m_nFormat ); 731 } 732 else if ( aNamedValue.Name.equalsAscii( "AllowRemoveOnInsert" ) ) 733 { 734 aNamedValue.Value >>= m_bAllowRemoveOnInsert; 735 m_pRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert ); 736 } 737 738 // for now the progress handler is not used, probably it will never be 739 // if ( aNamedValue.Name.equalsAscii( "ProgressHandler" ) 740 } 741 else 742 { 743 // The URL is not acceptable 744 throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad arguments." ) ), 745 static_cast < ::cppu::OWeakObject * > ( this ) ); 746 } 747 } 748 749 try 750 { 751 if ( m_xContentStream.is() ) 752 { 753 // the stream must be seekable, if it is not it will be wrapped 754 m_xContentStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xContentStream, m_xFactory ); 755 m_xContentSeek = uno::Reference < XSeekable > ( m_xContentStream, UNO_QUERY ); 756 if ( ! m_xContentSeek.is() ) 757 throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "The package component _requires_ an XSeekable interface!" ) ), 758 static_cast < ::cppu::OWeakObject * > ( this ) ); 759 760 if ( !m_xContentSeek->getLength() ) 761 bHaveZipFile = sal_False; 762 } 763 else 764 bHaveZipFile = sal_False; 765 } 766 catch ( com::sun::star::uno::Exception& ) 767 { 768 // Exception derived from uno::Exception thrown. This probably 769 // means the file doesn't exist...we'll create it at 770 // commitChanges time 771 bHaveZipFile = sal_False; 772 } 773 if ( bHaveZipFile ) 774 { 775 try 776 { 777 m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_True, m_bForceRecovery, xProgressHandler ); 778 getZipFileContents(); 779 } 780 catch ( IOException & ) 781 { 782 bBadZipFile = sal_True; 783 } 784 catch ( ZipException & ) 785 { 786 bBadZipFile = sal_True; 787 } 788 catch ( Exception & ) 789 { 790 if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; } 791 throw; 792 } 793 794 if ( bBadZipFile ) 795 { 796 // clean up the memory, and tell the UCB about the error 797 if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; } 798 799 throw com::sun::star::packages::zip::ZipIOException ( 800 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad Zip File." ) ), 801 static_cast < ::cppu::OWeakObject * > ( this ) ); 802 } 803 } 804 } 805 806 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::initialize" ); 807 } 808 809 //-------------------------------------------------------- 810 Any SAL_CALL ZipPackage::getByHierarchicalName( const OUString& aName ) 811 throw( NoSuchElementException, RuntimeException ) 812 { 813 OUString sTemp, sDirName; 814 sal_Int32 nOldIndex, nIndex, nStreamIndex; 815 FolderHash::iterator aIter; 816 817 if ( ( nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' ) 818 return makeAny ( uno::Reference < XUnoTunnel > ( m_pRootFolder ) ); 819 else 820 { 821 nStreamIndex = aName.lastIndexOf ( '/' ); 822 bool bFolder = nStreamIndex == nIndex-1; 823 if ( nStreamIndex != -1 ) 824 { 825 sDirName = aName.copy ( 0, nStreamIndex ); 826 aIter = m_aRecent.find ( sDirName ); 827 if ( aIter != m_aRecent.end() ) 828 { 829 if ( bFolder ) 830 { 831 sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex ); 832 sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 ); 833 if ( sTemp == ( *aIter ).second->getName() ) 834 return makeAny ( uno::Reference < XUnoTunnel > ( ( *aIter ).second ) ); 835 else 836 m_aRecent.erase ( aIter ); 837 } 838 else 839 { 840 sTemp = aName.copy ( nStreamIndex + 1 ); 841 if ( ( *aIter ).second->hasByName( sTemp ) ) 842 return ( *aIter ).second->getByName( sTemp ); 843 else 844 m_aRecent.erase( aIter ); 845 } 846 } 847 } 848 else 849 { 850 if ( m_pRootFolder->hasByName ( aName ) ) 851 return m_pRootFolder->getByName ( aName ); 852 } 853 nOldIndex = 0; 854 ZipPackageFolder * pCurrent = m_pRootFolder; 855 ZipPackageFolder * pPrevious = NULL; 856 while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 ) 857 { 858 sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex ); 859 if ( nIndex == nOldIndex ) 860 break; 861 if ( pCurrent->hasByName( sTemp ) ) 862 { 863 pPrevious = pCurrent; 864 pCurrent = pCurrent->doGetByName( sTemp ).pFolder; 865 } 866 else 867 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 868 nOldIndex = nIndex+1; 869 } 870 if ( bFolder ) 871 { 872 if ( nStreamIndex != -1 ) 873 m_aRecent[sDirName] = pPrevious; 874 return makeAny ( uno::Reference < XUnoTunnel > ( pCurrent ) ); 875 } 876 else 877 { 878 sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex ); 879 if ( pCurrent->hasByName ( sTemp ) ) 880 { 881 if ( nStreamIndex != -1 ) 882 m_aRecent[sDirName] = pCurrent; 883 return pCurrent->getByName( sTemp ); 884 } 885 else 886 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 887 } 888 } 889 } 890 891 //-------------------------------------------------------- 892 sal_Bool SAL_CALL ZipPackage::hasByHierarchicalName( const OUString& aName ) 893 throw( RuntimeException ) 894 { 895 OUString sTemp, sDirName; 896 sal_Int32 nOldIndex, nIndex, nStreamIndex; 897 FolderHash::iterator aIter; 898 899 if ( ( nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' ) 900 return sal_True; 901 else 902 { 903 nStreamIndex = aName.lastIndexOf ( '/' ); 904 bool bFolder = nStreamIndex == nIndex-1; 905 if ( nStreamIndex != -1 ) 906 { 907 sDirName = aName.copy ( 0, nStreamIndex ); 908 aIter = m_aRecent.find ( sDirName ); 909 if ( aIter != m_aRecent.end() ) 910 { 911 if ( bFolder ) 912 { 913 sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex ); 914 sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 ); 915 if ( sTemp == ( *aIter ).second->getName() ) 916 return sal_True; 917 else 918 m_aRecent.erase ( aIter ); 919 } 920 else 921 { 922 sTemp = aName.copy ( nStreamIndex + 1 ); 923 if ( ( *aIter ).second->hasByName( sTemp ) ) 924 return sal_True; 925 else 926 m_aRecent.erase( aIter ); 927 } 928 } 929 } 930 else 931 { 932 if ( m_pRootFolder->hasByName ( aName ) ) 933 return sal_True; 934 } 935 ZipPackageFolder * pCurrent = m_pRootFolder; 936 ZipPackageFolder * pPrevious = NULL; 937 nOldIndex = 0; 938 while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 ) 939 { 940 sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex ); 941 if ( nIndex == nOldIndex ) 942 break; 943 if ( pCurrent->hasByName( sTemp ) ) 944 { 945 pPrevious = pCurrent; 946 pCurrent = pCurrent->doGetByName( sTemp ).pFolder; 947 } 948 else 949 return sal_False; 950 nOldIndex = nIndex+1; 951 } 952 if ( bFolder ) 953 { 954 m_aRecent[sDirName] = pPrevious; 955 return sal_True; 956 } 957 else 958 { 959 sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex ); 960 961 if ( pCurrent->hasByName( sTemp ) ) 962 { 963 m_aRecent[sDirName] = pCurrent; 964 return sal_True; 965 } 966 } 967 return sal_False; 968 } 969 } 970 971 //-------------------------------------------------------- 972 uno::Reference< XInterface > SAL_CALL ZipPackage::createInstance() 973 throw( Exception, RuntimeException ) 974 { 975 uno::Reference < XInterface > xRef = *( new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert ) ); 976 return xRef; 977 } 978 //-------------------------------------------------------- 979 uno::Reference< XInterface > SAL_CALL ZipPackage::createInstanceWithArguments( const uno::Sequence< Any >& aArguments ) 980 throw( Exception, RuntimeException ) 981 { 982 sal_Bool bArg = sal_False; 983 uno::Reference < XInterface > xRef; 984 if ( aArguments.getLength() ) 985 aArguments[0] >>= bArg; 986 if ( bArg ) 987 xRef = *new ZipPackageFolder ( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); 988 else 989 xRef = *new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert ); 990 991 return xRef; 992 } 993 994 //-------------------------------------------------------- 995 void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut ) 996 { 997 const OUString sMime ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) ); 998 if ( m_xRootFolder->hasByName( sMime ) ) 999 m_xRootFolder->removeByName( sMime ); 1000 1001 ZipEntry * pEntry = new ZipEntry; 1002 sal_Int32 nBufferLength = m_pRootFolder->GetMediaType().getLength(); 1003 OString sMediaType = OUStringToOString( m_pRootFolder->GetMediaType(), RTL_TEXTENCODING_ASCII_US ); 1004 uno::Sequence< sal_Int8 > aType( ( sal_Int8* )sMediaType.getStr(), 1005 nBufferLength ); 1006 1007 1008 pEntry->sPath = sMime; 1009 pEntry->nMethod = STORED; 1010 pEntry->nSize = pEntry->nCompressedSize = nBufferLength; 1011 pEntry->nTime = ZipOutputStream::getCurrentDosTime(); 1012 1013 CRC32 aCRC32; 1014 aCRC32.update( aType ); 1015 pEntry->nCrc = aCRC32.getValue(); 1016 1017 try 1018 { 1019 aZipOut.putNextEntry( *pEntry, NULL ); 1020 aZipOut.write( aType, 0, nBufferLength ); 1021 aZipOut.closeEntry(); 1022 } 1023 catch ( ::com::sun::star::io::IOException & r ) 1024 { 1025 throw WrappedTargetException( 1026 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Error adding mimetype to the ZipOutputStream!" ) ), 1027 static_cast < OWeakObject * > ( this ), 1028 makeAny( r ) ); 1029 } 1030 } 1031 1032 //-------------------------------------------------------- 1033 void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList ) 1034 { 1035 // Write the manifest 1036 uno::Reference < XOutputStream > xManOutStream; 1037 OUString sManifestWriter( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestWriter" ) ); 1038 uno::Reference < XManifestWriter > xWriter ( m_xFactory->createInstance( sManifestWriter ), UNO_QUERY ); 1039 if ( xWriter.is() ) 1040 { 1041 ZipEntry * pEntry = new ZipEntry; 1042 ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize ); 1043 xManOutStream = uno::Reference < XOutputStream > ( *pBuffer, UNO_QUERY ); 1044 1045 pEntry->sPath = OUString( RTL_CONSTASCII_USTRINGPARAM ( "META-INF/manifest.xml" ) ); 1046 pEntry->nMethod = DEFLATED; 1047 pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1; 1048 pEntry->nTime = ZipOutputStream::getCurrentDosTime(); 1049 1050 // Convert vector into a uno::Sequence 1051 uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence ( aManList.size() ); 1052 sal_Int32 nInd = 0; 1053 for ( vector < uno::Sequence < PropertyValue > >::const_iterator aIter = aManList.begin(), aEnd = aManList.end(); 1054 aIter != aEnd; 1055 aIter++, nInd++ ) 1056 { 1057 aManifestSequence[nInd] = ( *aIter ); 1058 } 1059 xWriter->writeManifestSequence ( xManOutStream, aManifestSequence ); 1060 1061 sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() ); 1062 pBuffer->realloc( nBufferLength ); 1063 1064 // the manifest.xml is never encrypted - so pass an empty reference 1065 aZipOut.putNextEntry( *pEntry, NULL ); 1066 aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); 1067 aZipOut.closeEntry(); 1068 } 1069 else 1070 { 1071 VOS_ENSURE ( 0, "Couldn't get a ManifestWriter!" ); 1072 IOException aException; 1073 throw WrappedTargetException( 1074 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Couldn't get a ManifestWriter!" ) ), 1075 static_cast < OWeakObject * > ( this ), 1076 makeAny( aException ) ); 1077 } 1078 } 1079 1080 //-------------------------------------------------------- 1081 void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList ) 1082 { 1083 const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); 1084 const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); 1085 1086 ZipEntry* pEntry = new ZipEntry; 1087 ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize ); 1088 uno::Reference< io::XOutputStream > xConTypeOutStream( *pBuffer, UNO_QUERY ); 1089 1090 pEntry->sPath = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); 1091 pEntry->nMethod = DEFLATED; 1092 pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1; 1093 pEntry->nTime = ZipOutputStream::getCurrentDosTime(); 1094 1095 // Convert vector into a uno::Sequence 1096 // TODO/LATER: use Defaulst entries in future 1097 uno::Sequence< beans::StringPair > aDefaultsSequence; 1098 uno::Sequence< beans::StringPair > aOverridesSequence( aManList.size() ); 1099 sal_Int32 nSeqLength = 0; 1100 for ( vector< uno::Sequence< beans::PropertyValue > >::const_iterator aIter = aManList.begin(), 1101 aEnd = aManList.end(); 1102 aIter != aEnd; 1103 aIter++ ) 1104 { 1105 ::rtl::OUString aPath; 1106 ::rtl::OUString aType; 1107 OSL_ENSURE( ( *aIter )[PKG_MNFST_MEDIATYPE].Name.equals( sMediaType ) && ( *aIter )[PKG_MNFST_FULLPATH].Name.equals( sFullPath ), 1108 "The mediatype sequence format is wrong!\n" ); 1109 ( *aIter )[PKG_MNFST_MEDIATYPE].Value >>= aType; 1110 if ( aType.getLength() ) 1111 { 1112 // only nonempty type makes sence here 1113 nSeqLength++; 1114 ( *aIter )[PKG_MNFST_FULLPATH].Value >>= aPath; 1115 aOverridesSequence[nSeqLength-1].First = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + aPath; 1116 aOverridesSequence[nSeqLength-1].Second = aType; 1117 } 1118 } 1119 aOverridesSequence.realloc( nSeqLength ); 1120 1121 ::comphelper::OFOPXMLHelper::WriteContentSequence( 1122 xConTypeOutStream, aDefaultsSequence, aOverridesSequence, m_xFactory ); 1123 1124 sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() ); 1125 pBuffer->realloc( nBufferLength ); 1126 1127 // there is no encryption in this format currently 1128 aZipOut.putNextEntry( *pEntry, NULL ); 1129 aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); 1130 aZipOut.closeEntry(); 1131 } 1132 1133 //-------------------------------------------------------- 1134 void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream ) 1135 { 1136 m_xContentSeek.set( xInStream, uno::UNO_QUERY_THROW ); 1137 m_xContentStream = xInStream; 1138 1139 // seek back to the beginning of the temp file so we can read segments from it 1140 m_xContentSeek->seek( 0 ); 1141 if ( m_pZipFile ) 1142 m_pZipFile->setInputStream( m_xContentStream ); 1143 else 1144 m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_False ); 1145 } 1146 1147 //-------------------------------------------------------- 1148 uno::Reference< io::XInputStream > ZipPackage::writeTempFile() 1149 { 1150 // In case the target local file does not exist or empty 1151 // write directly to it otherwize create a temporary file to write to. 1152 // If a temporary file is created it is returned back by the method. 1153 // If the data written directly, xComponentStream will be switched here 1154 1155 sal_Bool bUseTemp = sal_True; 1156 uno::Reference < io::XInputStream > xResult; 1157 uno::Reference < io::XInputStream > xTempIn; 1158 1159 uno::Reference < io::XOutputStream > xTempOut; 1160 uno::Reference< io::XActiveDataStreamer > xSink; 1161 1162 if ( m_eMode == e_IMode_URL && !m_pZipFile && isLocalFile_Impl( m_aURL ) ) 1163 { 1164 xSink = openOriginalForOutput(); 1165 if( xSink.is() ) 1166 { 1167 uno::Reference< io::XStream > xStr = xSink->getStream(); 1168 if( xStr.is() ) 1169 { 1170 xTempOut = xStr->getOutputStream(); 1171 if( xTempOut.is() ) 1172 bUseTemp = sal_False; 1173 } 1174 } 1175 } 1176 else if ( m_eMode == e_IMode_XStream && !m_pZipFile ) 1177 { 1178 // write directly to an empty stream 1179 xTempOut = m_xStream->getOutputStream(); 1180 if( xTempOut.is() ) 1181 bUseTemp = sal_False; 1182 } 1183 1184 if( bUseTemp ) 1185 { 1186 // create temporary file 1187 const OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); 1188 uno::Reference < io::XStream > xTempFile( m_xFactory->createInstance ( sServiceName ), UNO_QUERY_THROW ); 1189 xTempOut.set( xTempFile->getOutputStream(), UNO_SET_THROW ); 1190 xTempIn.set( xTempFile->getInputStream(), UNO_SET_THROW ); 1191 } 1192 1193 // Hand it to the ZipOutputStream: 1194 ZipOutputStream aZipOut( m_xFactory, xTempOut ); 1195 aZipOut.setMethod( DEFLATED ); 1196 aZipOut.setLevel( DEFAULT_COMPRESSION ); 1197 1198 try 1199 { 1200 if ( m_nFormat == embed::StorageFormats::PACKAGE ) 1201 { 1202 // Remove the old manifest.xml file as the 1203 // manifest will be re-generated and the 1204 // META-INF directory implicitly created if does not exist 1205 const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) ); 1206 1207 if ( m_xRootFolder->hasByName( sMeta ) ) 1208 { 1209 const OUString sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ); 1210 1211 uno::Reference< XUnoTunnel > xTunnel; 1212 Any aAny = m_xRootFolder->getByName( sMeta ); 1213 aAny >>= xTunnel; 1214 uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY ); 1215 if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) ) 1216 xMetaInfFolder->removeByName( sManifest ); 1217 } 1218 1219 // Write a magic file with mimetype 1220 WriteMimetypeMagicFile( aZipOut ); 1221 } 1222 else if ( m_nFormat == embed::StorageFormats::OFOPXML ) 1223 { 1224 // Remove the old [Content_Types].xml file as the 1225 // file will be re-generated 1226 1227 const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); 1228 1229 if ( m_xRootFolder->hasByName( aContentTypes ) ) 1230 m_xRootFolder->removeByName( aContentTypes ); 1231 } 1232 1233 // Create a vector to store data for the manifest.xml file 1234 vector < uno::Sequence < PropertyValue > > aManList; 1235 1236 const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); 1237 const OUString sVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); 1238 const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); 1239 1240 if ( m_nFormat == embed::StorageFormats::PACKAGE ) 1241 { 1242 uno::Sequence < PropertyValue > aPropSeq( PKG_SIZE_NOENCR_MNFST ); 1243 aPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType; 1244 aPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_pRootFolder->GetMediaType(); 1245 aPropSeq [PKG_MNFST_VERSION].Name = sVersion; 1246 aPropSeq [PKG_MNFST_VERSION].Value <<= m_pRootFolder->GetVersion(); 1247 aPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath; 1248 aPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString ( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); 1249 1250 aManList.push_back( aPropSeq ); 1251 } 1252 1253 // Get a random number generator and seed it with current timestamp 1254 // This will be used to generate random salt and initialisation vectors 1255 // for encrypted streams 1256 TimeValue aTime; 1257 osl_getSystemTime( &aTime ); 1258 rtlRandomPool aRandomPool = rtl_random_createPool (); 1259 rtl_random_addBytes ( aRandomPool, &aTime, 8 ); 1260 1261 // call saveContents ( it will recursively save sub-directories 1262 OUString aEmptyString; 1263 m_pRootFolder->saveContents( aEmptyString, aManList, aZipOut, GetEncryptionKey(), aRandomPool ); 1264 1265 // Clean up random pool memory 1266 rtl_random_destroyPool ( aRandomPool ); 1267 1268 if( m_nFormat == embed::StorageFormats::PACKAGE ) 1269 { 1270 WriteManifest( aZipOut, aManList ); 1271 } 1272 else if( m_nFormat == embed::StorageFormats::OFOPXML ) 1273 { 1274 WriteContentTypes( aZipOut, aManList ); 1275 } 1276 1277 aZipOut.finish(); 1278 1279 if( bUseTemp ) 1280 xResult = xTempIn; 1281 1282 // Update our References to point to the new temp file 1283 if( !bUseTemp ) 1284 { 1285 // the case when the original contents were written directly 1286 xTempOut->flush(); 1287 1288 // in case the stream is based on a file it will implement the following interface 1289 // the call should be used to be sure that the contents are written to the file system 1290 uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( xTempOut, uno::UNO_QUERY ); 1291 if ( asyncOutputMonitor.is() ) 1292 asyncOutputMonitor->waitForCompletion(); 1293 1294 // no need to postpone switching to the new stream since the target was written directly 1295 uno::Reference< io::XInputStream > xNewStream; 1296 if ( m_eMode == e_IMode_URL ) 1297 xNewStream = xSink->getStream()->getInputStream(); 1298 else if ( m_eMode == e_IMode_XStream && m_xStream.is() ) 1299 xNewStream = m_xStream->getInputStream(); 1300 1301 if ( xNewStream.is() ) 1302 ConnectTo( xNewStream ); 1303 } 1304 } 1305 catch ( uno::Exception& ) 1306 { 1307 if( bUseTemp ) 1308 { 1309 // no information loss appeares, thus no special handling is required 1310 uno::Any aCaught( ::cppu::getCaughtException() ); 1311 1312 // it is allowed to throw WrappedTargetException 1313 WrappedTargetException aException; 1314 if ( aCaught >>= aException ) 1315 throw aException; 1316 1317 throw WrappedTargetException( 1318 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Problem writing the original content!" ) ), 1319 static_cast < OWeakObject * > ( this ), 1320 aCaught ); 1321 } 1322 else 1323 { 1324 // the document is written directly, although it was empty it is important to notify that the writing has failed 1325 // TODO/LATER: let the package be able to recover in this situation 1326 ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is unusable!" ) ); 1327 embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), ::rtl::OUString() ); 1328 throw WrappedTargetException( aErrTxt, 1329 static_cast < OWeakObject * > ( this ), 1330 makeAny ( aException ) ); 1331 } 1332 } 1333 1334 return xResult; 1335 } 1336 1337 //-------------------------------------------------------- 1338 uno::Reference< XActiveDataStreamer > ZipPackage::openOriginalForOutput() 1339 { 1340 // open and truncate the original file 1341 Content aOriginalContent ( m_aURL, uno::Reference < XCommandEnvironment >() ); 1342 uno::Reference< XActiveDataStreamer > xSink = new ActiveDataStreamer; 1343 1344 if ( m_eMode == e_IMode_URL ) 1345 { 1346 try 1347 { 1348 sal_Bool bTruncSuccess = sal_False; 1349 1350 try 1351 { 1352 Exception aDetect; 1353 sal_Int64 aSize = 0; 1354 Any aAny = aOriginalContent.setPropertyValue( OUString::createFromAscii( "Size" ), makeAny( aSize ) ); 1355 if( !( aAny >>= aDetect ) ) 1356 bTruncSuccess = sal_True; 1357 } 1358 catch( Exception& ) 1359 { 1360 } 1361 1362 if( !bTruncSuccess ) 1363 { 1364 // the file is not accessible 1365 // just try to write an empty stream to it 1366 1367 uno::Reference< XInputStream > xTempIn = new DummyInputStream; //uno::Reference< XInputStream >( xTempOut, UNO_QUERY ); 1368 aOriginalContent.writeStream( xTempIn , sal_True ); 1369 } 1370 1371 OpenCommandArgument2 aArg; 1372 aArg.Mode = OpenMode::DOCUMENT; 1373 aArg.Priority = 0; // unused 1374 aArg.Sink = xSink; 1375 aArg.Properties = uno::Sequence< Property >( 0 ); // unused 1376 1377 aOriginalContent.executeCommand( OUString::createFromAscii( "open" ), makeAny( aArg ) ); 1378 } 1379 catch( Exception& ) 1380 { 1381 // seems to be nonlocal file 1382 // temporary file mechanics should be used 1383 } 1384 } 1385 1386 return xSink; 1387 } 1388 1389 //-------------------------------------------------------- 1390 void SAL_CALL ZipPackage::commitChanges() 1391 throw( WrappedTargetException, RuntimeException ) 1392 { 1393 // lock the component for the time of commiting 1394 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() ); 1395 1396 if ( m_eMode == e_IMode_XInputStream ) 1397 { 1398 IOException aException; 1399 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ), 1400 static_cast < OWeakObject * > ( this ), makeAny ( aException ) ); 1401 } 1402 1403 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::commitChanges" ); 1404 1405 // first the writeTempFile is called, if it returns a stream the stream should be written to the target 1406 // if no stream was returned, the file was written directly, nothing should be done 1407 1408 uno::Reference< io::XInputStream > xTempInStream = writeTempFile(); 1409 if ( xTempInStream.is() ) 1410 { 1411 uno::Reference< io::XSeekable > xTempSeek( xTempInStream, uno::UNO_QUERY_THROW ); 1412 1413 try 1414 { 1415 xTempSeek->seek( 0 ); 1416 } 1417 catch( uno::Exception& r ) 1418 { 1419 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Temporary file should be seekable!" ) ), 1420 static_cast < OWeakObject * > ( this ), makeAny ( r ) ); 1421 } 1422 1423 // connect to the temporary stream 1424 ConnectTo( xTempInStream ); 1425 1426 if ( m_eMode == e_IMode_XStream ) 1427 { 1428 // First truncate our output stream 1429 uno::Reference < XOutputStream > xOutputStream; 1430 1431 // preparation for copy step 1432 try 1433 { 1434 xOutputStream = m_xStream->getOutputStream(); 1435 uno::Reference < XTruncate > xTruncate ( xOutputStream, UNO_QUERY ); 1436 if ( !xTruncate.is() ) 1437 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1438 1439 // after successful truncation the original file contents are already lost 1440 xTruncate->truncate(); 1441 } 1442 catch( uno::Exception& r ) 1443 { 1444 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ), 1445 static_cast < OWeakObject * > ( this ), makeAny ( r ) ); 1446 } 1447 1448 try 1449 { 1450 // then copy the contents of the tempfile to our output stream 1451 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutputStream ); 1452 xOutputStream->flush(); 1453 uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( 1454 xOutputStream, uno::UNO_QUERY ); 1455 if ( asyncOutputMonitor.is() ) { 1456 asyncOutputMonitor->waitForCompletion(); 1457 } 1458 } 1459 catch( uno::Exception& ) 1460 { 1461 // if anything goes wrong in this block the target file becomes corrupted 1462 // so an exception should be thrown as a notification about it 1463 // and the package must disconnect from the stream 1464 DisconnectFromTargetAndThrowException_Impl( xTempInStream ); 1465 } 1466 } 1467 else if ( m_eMode == e_IMode_URL ) 1468 { 1469 uno::Reference< XOutputStream > aOrigFileStream; 1470 sal_Bool bCanBeCorrupted = sal_False; 1471 1472 if( isLocalFile_Impl( m_aURL ) ) 1473 { 1474 // write directly in case of local file 1475 uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleAccess( 1476 m_xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), 1477 uno::UNO_QUERY ); 1478 OSL_ENSURE( xSimpleAccess.is(), "Can't instatiate SimpleFileAccess service!\n" ); 1479 uno::Reference< io::XTruncate > xOrigTruncate; 1480 if ( xSimpleAccess.is() ) 1481 { 1482 try 1483 { 1484 aOrigFileStream = xSimpleAccess->openFileWrite( m_aURL ); 1485 xOrigTruncate = uno::Reference< io::XTruncate >( aOrigFileStream, uno::UNO_QUERY_THROW ); 1486 // after successful truncation the file is already corrupted 1487 xOrigTruncate->truncate(); 1488 } 1489 catch( uno::Exception& ) 1490 {} 1491 } 1492 1493 if( xOrigTruncate.is() ) 1494 { 1495 try 1496 { 1497 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, aOrigFileStream ); 1498 aOrigFileStream->closeOutput(); 1499 } 1500 catch( uno::Exception& ) 1501 { 1502 try { 1503 aOrigFileStream->closeOutput(); 1504 } catch ( uno::Exception& ) {} 1505 1506 aOrigFileStream = uno::Reference< XOutputStream >(); 1507 // the original file can already be corrupted 1508 bCanBeCorrupted = sal_True; 1509 } 1510 } 1511 } 1512 1513 if( !aOrigFileStream.is() ) 1514 { 1515 try 1516 { 1517 uno::Reference < XPropertySet > xPropSet ( xTempInStream, UNO_QUERY ); 1518 OSL_ENSURE( xPropSet.is(), "This is a temporary file that must implement XPropertySet!\n" ); 1519 if ( !xPropSet.is() ) 1520 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1521 1522 OUString sTargetFolder = m_aURL.copy ( 0, m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) ); 1523 Content aContent ( sTargetFolder, uno::Reference < XCommandEnvironment > () ); 1524 1525 OUString sTempURL; 1526 Any aAny = xPropSet->getPropertyValue ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Uri" ) ) ); 1527 aAny >>= sTempURL; 1528 1529 TransferInfo aInfo; 1530 aInfo.NameClash = NameClash::OVERWRITE; 1531 aInfo.MoveData = sal_False; 1532 aInfo.SourceURL = sTempURL; 1533 aInfo.NewTitle = rtl::Uri::decode ( m_aURL.copy ( 1 + m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) ), 1534 rtl_UriDecodeWithCharset, 1535 RTL_TEXTENCODING_UTF8 ); 1536 aAny <<= aInfo; 1537 1538 // if the file is still not corrupted, it can become after the next step 1539 aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "transfer" ) ), aAny ); 1540 } 1541 catch ( ::com::sun::star::uno::Exception& r ) 1542 { 1543 if ( bCanBeCorrupted ) 1544 DisconnectFromTargetAndThrowException_Impl( xTempInStream ); 1545 1546 throw WrappedTargetException( 1547 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package may be read only!" ) ), 1548 static_cast < OWeakObject * > ( this ), 1549 makeAny ( r ) ); 1550 } 1551 } 1552 } 1553 } 1554 1555 // after successful storing it can be set to false 1556 m_bMediaTypeFallbackUsed = sal_False; 1557 1558 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::commitChanges" ); 1559 } 1560 1561 //-------------------------------------------------------- 1562 void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Reference< io::XInputStream >& xTempStream ) 1563 { 1564 m_xStream = uno::Reference< io::XStream >( xTempStream, uno::UNO_QUERY ); 1565 if ( m_xStream.is() ) 1566 m_eMode = e_IMode_XStream; 1567 else 1568 m_eMode = e_IMode_XInputStream; 1569 1570 ::rtl::OUString aTempURL; 1571 try { 1572 uno::Reference< beans::XPropertySet > xTempFile( xTempStream, uno::UNO_QUERY_THROW ); 1573 uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) ); 1574 aUrl >>= aTempURL; 1575 xTempFile->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ), 1576 uno::makeAny( sal_False ) ); 1577 } 1578 catch ( uno::Exception& ) 1579 { 1580 OSL_ENSURE( sal_False, "These calls are pretty simple, they should not fail!\n" ); 1581 } 1582 1583 ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ); 1584 embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL ); 1585 throw WrappedTargetException( aErrTxt, 1586 static_cast < OWeakObject * > ( this ), 1587 makeAny ( aException ) ); 1588 } 1589 1590 //-------------------------------------------------------- 1591 const uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey() 1592 { 1593 uno::Sequence< sal_Int8 > aResult; 1594 1595 if ( m_aStorageEncryptionKeys.getLength() ) 1596 { 1597 ::rtl::OUString aNameToFind; 1598 if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA256 ) 1599 aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; 1600 else if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA1 ) 1601 aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; 1602 else 1603 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); 1604 1605 for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ ) 1606 if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) ) 1607 m_aStorageEncryptionKeys[nInd].Value >>= aResult; 1608 1609 // empty keys are not allowed here 1610 // so it is not important whether there is no key, or the key is empty, it is an error 1611 if ( !aResult.getLength() ) 1612 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); 1613 } 1614 else 1615 aResult = m_aEncryptionKey; 1616 1617 return aResult; 1618 } 1619 1620 //-------------------------------------------------------- 1621 sal_Bool SAL_CALL ZipPackage::hasPendingChanges() 1622 throw( RuntimeException ) 1623 { 1624 return sal_False; 1625 } 1626 //-------------------------------------------------------- 1627 Sequence< ElementChange > SAL_CALL ZipPackage::getPendingChanges() 1628 throw( RuntimeException ) 1629 { 1630 return uno::Sequence < ElementChange > (); 1631 } 1632 1633 /** 1634 * Function to create a new component instance; is needed by factory helper implementation. 1635 * @param xMgr service manager to if the components needs other component instances 1636 */ 1637 uno::Reference < XInterface >SAL_CALL ZipPackage_createInstance( 1638 const uno::Reference< XMultiServiceFactory > & xMgr ) 1639 { 1640 return uno::Reference< XInterface >( *new ZipPackage( xMgr ) ); 1641 } 1642 1643 //-------------------------------------------------------- 1644 OUString ZipPackage::static_getImplementationName() 1645 { 1646 return OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.comp.ZipPackage" ) ); 1647 } 1648 1649 //-------------------------------------------------------- 1650 Sequence< OUString > ZipPackage::static_getSupportedServiceNames() 1651 { 1652 uno::Sequence< OUString > aNames( 1 ); 1653 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.Package" ) ); 1654 return aNames; 1655 } 1656 //-------------------------------------------------------- 1657 sal_Bool SAL_CALL ZipPackage::static_supportsService( OUString const & rServiceName ) 1658 { 1659 return rServiceName == getSupportedServiceNames()[0]; 1660 } 1661 1662 //-------------------------------------------------------- 1663 OUString ZipPackage::getImplementationName() 1664 throw ( RuntimeException ) 1665 { 1666 return static_getImplementationName(); 1667 } 1668 1669 //-------------------------------------------------------- 1670 Sequence< OUString > ZipPackage::getSupportedServiceNames() 1671 throw ( RuntimeException ) 1672 { 1673 return static_getSupportedServiceNames(); 1674 } 1675 //-------------------------------------------------------- 1676 sal_Bool SAL_CALL ZipPackage::supportsService( OUString const & rServiceName ) 1677 throw ( RuntimeException ) 1678 { 1679 return static_supportsService ( rServiceName ); 1680 } 1681 //-------------------------------------------------------- 1682 uno::Reference < XSingleServiceFactory > ZipPackage::createServiceFactory( uno::Reference < XMultiServiceFactory > const & rServiceFactory ) 1683 { 1684 return cppu::createSingleFactory ( rServiceFactory, 1685 static_getImplementationName(), 1686 ZipPackage_createInstance, 1687 static_getSupportedServiceNames() ); 1688 } 1689 1690 namespace { struct lcl_ImplId : public rtl::Static< ::cppu::OImplementationId, lcl_ImplId > {}; } 1691 1692 //-------------------------------------------------------- 1693 Sequence< sal_Int8 > ZipPackage::getUnoTunnelImplementationId( void ) 1694 throw ( RuntimeException ) 1695 { 1696 ::cppu::OImplementationId &rId = lcl_ImplId::get(); 1697 return rId.getImplementationId(); 1698 } 1699 1700 //-------------------------------------------------------- 1701 sal_Int64 SAL_CALL ZipPackage::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier ) 1702 throw( RuntimeException ) 1703 { 1704 if ( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) 1705 return reinterpret_cast < sal_Int64 > ( this ); 1706 return 0; 1707 } 1708 1709 //-------------------------------------------------------- 1710 uno::Reference< XPropertySetInfo > SAL_CALL ZipPackage::getPropertySetInfo() 1711 throw( RuntimeException ) 1712 { 1713 return uno::Reference < XPropertySetInfo > (); 1714 } 1715 1716 //-------------------------------------------------------- 1717 void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) 1718 throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) 1719 { 1720 if ( m_nFormat != embed::StorageFormats::PACKAGE ) 1721 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1722 1723 if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) 1724 ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) 1725 ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( IS_INCONSISTENT_PROPERTY ) ) 1726 ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) 1727 throw PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1728 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) ) 1729 { 1730 if ( !( aValue >>= m_aEncryptionKey ) ) 1731 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); 1732 1733 m_aStorageEncryptionKeys.realloc( 0 ); 1734 } 1735 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) 1736 { 1737 // this property is only necessary to support raw passwords in storage API; 1738 // because of this support the storage has to operate with more than one key dependent on storage generation algorithm; 1739 // when this support is removed, the storage will get only one key from outside 1740 // TODO/LATER: Get rid of this property as well as of support of raw passwords in storages 1741 uno::Sequence< beans::NamedValue > aKeys; 1742 if ( !( aValue >>= aKeys ) || ( aKeys.getLength() && aKeys.getLength() < 2 ) ) 1743 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); 1744 1745 if ( aKeys.getLength() ) 1746 { 1747 bool bHasSHA256 = false; 1748 bool bHasSHA1 = false; 1749 for ( sal_Int32 nInd = 0; nInd < aKeys.getLength(); nInd++ ) 1750 { 1751 if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA256UTF8 ) ) 1752 bHasSHA256 = true; 1753 if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA1UTF8 ) ) 1754 bHasSHA1 = true; 1755 } 1756 1757 if ( !bHasSHA256 || !bHasSHA1 ) 1758 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Expected keys are not provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); 1759 } 1760 1761 m_aStorageEncryptionKeys = aKeys; 1762 m_aEncryptionKey.realloc( 0 ); 1763 } 1764 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) 1765 { 1766 uno::Sequence< beans::NamedValue > aAlgorithms; 1767 if ( m_pZipFile || !( aValue >>= aAlgorithms ) || aAlgorithms.getLength() == 0 ) 1768 { 1769 // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile ) 1770 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); 1771 } 1772 1773 for ( sal_Int32 nInd = 0; nInd < aAlgorithms.getLength(); nInd++ ) 1774 { 1775 if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ) 1776 { 1777 sal_Int32 nID = 0; 1778 if ( !( aAlgorithms[nInd].Value >>= nID ) 1779 || ( nID != xml::crypto::DigestID::SHA256 && nID != xml::crypto::DigestID::SHA1 ) ) 1780 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); 1781 1782 m_nStartKeyGenerationID = nID; 1783 } 1784 else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionAlgorithm" ) ) ) 1785 { 1786 sal_Int32 nID = 0; 1787 if ( !( aAlgorithms[nInd].Value >>= nID ) 1788 || ( nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING && nID != xml::crypto::CipherID::BLOWFISH_CFB_8 ) ) 1789 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); 1790 1791 m_nCommonEncryptionID = nID; 1792 } 1793 else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ChecksumAlgorithm" ) ) ) 1794 { 1795 sal_Int32 nID = 0; 1796 if ( !( aAlgorithms[nInd].Value >>= nID ) 1797 || ( nID != xml::crypto::DigestID::SHA1_1K && nID != xml::crypto::DigestID::SHA256_1K ) ) 1798 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); 1799 1800 m_nChecksumDigestID = nID; 1801 } 1802 else 1803 { 1804 OSL_ENSURE( sal_False, "Unexpected encryption algorithm is provided!" ); 1805 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); 1806 } 1807 } 1808 } 1809 else 1810 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1811 } 1812 1813 //-------------------------------------------------------- 1814 Any SAL_CALL ZipPackage::getPropertyValue( const OUString& PropertyName ) 1815 throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) 1816 { 1817 // TODO/LATER: Activate the check when zip-ucp is ready 1818 // if ( m_nFormat != embed::StorageFormats::PACKAGE ) 1819 // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1820 1821 Any aAny; 1822 if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( ENCRYPTION_KEY_PROPERTY ) ) ) 1823 { 1824 aAny <<= m_aEncryptionKey; 1825 return aAny; 1826 } 1827 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) 1828 { 1829 ::comphelper::SequenceAsHashMap aAlgorithms; 1830 aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ] <<= m_nStartKeyGenerationID; 1831 aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionAlgorithm" ) ) ] <<= m_nCommonEncryptionID; 1832 aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChecksumAlgorithm" ) ) ] <<= m_nChecksumDigestID; 1833 aAny <<= aAlgorithms.getAsConstNamedValueList(); 1834 return aAny; 1835 } 1836 if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) 1837 { 1838 aAny <<= m_aStorageEncryptionKeys; 1839 return aAny; 1840 } 1841 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) ) 1842 { 1843 aAny <<= m_bHasEncryptedEntries; 1844 return aAny; 1845 } 1846 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) ) 1847 { 1848 aAny <<= m_bHasNonEncryptedEntries; 1849 return aAny; 1850 } 1851 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( IS_INCONSISTENT_PROPERTY ) ) ) 1852 { 1853 aAny <<= m_bInconsistent; 1854 return aAny; 1855 } 1856 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) 1857 { 1858 aAny <<= m_bMediaTypeFallbackUsed; 1859 return aAny; 1860 } 1861 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 1862 } 1863 //-------------------------------------------------------- 1864 void SAL_CALL ZipPackage::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ ) 1865 throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) 1866 { 1867 } 1868 //-------------------------------------------------------- 1869 void SAL_CALL ZipPackage::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ ) 1870 throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) 1871 { 1872 } 1873 //-------------------------------------------------------- 1874 void SAL_CALL ZipPackage::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) 1875 throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) 1876 { 1877 } 1878 //-------------------------------------------------------- 1879 void SAL_CALL ZipPackage::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) 1880 throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) 1881 { 1882 } 1883