1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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 ).
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.
26 ************************************************************************/
28 // MARKER( update_precomp.py ): autogen include statement, do not remove
29 #include "precompiled_package.hxx"
30 #include <ZipPackage.hxx>
31 #include <ZipPackageSink.hxx>
32 #include <ZipEnumeration.hxx>
33 #include <ZipPackageStream.hxx>
34 #include <ZipPackageFolder.hxx>
35 #include <ZipOutputStream.hxx>
36 #include <ZipPackageBuffer.hxx>
37 #include <ZipFile.hxx>
38 #include <PackageConstants.hxx>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/NamedValue.hpp>
41 #include <com/sun/star/packages/zip/ZipConstants.hpp>
42 #include <com/sun/star/packages/manifest/XManifestReader.hpp>
43 #include <com/sun/star/packages/manifest/XManifestWriter.hpp>
44 #include <com/sun/star/io/XStream.hpp>
45 #include <com/sun/star/io/XInputStream.hpp>
46 #include <com/sun/star/io/XOutputStream.hpp>
47 #include <com/sun/star/io/XTruncate.hpp>
48 #include <com/sun/star/io/XSeekable.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <com/sun/star/ucb/IOErrorCode.hpp>
52 #include <ucbhelper/content.hxx>
53 #include <cppuhelper/factory.hxx>
54 #include <cppuhelper/exc_hlp.hxx>
55 #include <com/sun/star/ucb/TransferInfo.hpp>
56 #include <com/sun/star/ucb/NameClash.hpp>
57 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
58 #include <com/sun/star/ucb/OpenMode.hpp>
59 #include <com/sun/star/ucb/XProgressHandler.hpp>
60 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
61 #include <com/sun/star/io/XActiveDataStreamer.hpp>
62 #include <com/sun/star/embed/XTransactedObject.hpp>
63 #include <com/sun/star/embed/UseBackupException.hpp>
64 #include <com/sun/star/embed/StorageFormats.hpp>
65 #include <com/sun/star/beans/NamedValue.hpp>
66 #include <com/sun/star/xml/crypto/DigestID.hpp>
67 #include <com/sun/star/xml/crypto/CipherID.hpp>
68 #include <cppuhelper/implbase1.hxx>
69 #include <ContentInfo.hxx>
70 #include <cppuhelper/typeprovider.hxx>
71 #include <rtl/uri.hxx>
72 #include <rtl/random.h>
73 #include <rtl/logfile.hxx>
74 #include <rtl/instance.hxx>
76 #include <osl/file.hxx>
77 #include "com/sun/star/io/XAsyncOutputMonitor.hpp"
82 #include <ucbhelper/contentbroker.hxx>
83 #include <ucbhelper/fileidentifierconverter.hxx>
84 #include <comphelper/seekableinput.hxx>
85 #include <comphelper/storagehelper.hxx>
86 #include <comphelper/ofopxmlhelper.hxx>
87 #include <comphelper/documentconstants.hxx>
88 #include <comphelper/sequenceashashmap.hxx>
94 using namespace ucbhelper
;
95 using namespace com::sun::star
;
96 using namespace com::sun::star::io
;
97 using namespace com::sun::star::uno
;
98 using namespace com::sun::star::ucb
;
99 using namespace com::sun::star::util
;
100 using namespace com::sun::star::lang
;
101 using namespace com::sun::star::task
;
102 using namespace com::sun::star::beans
;
103 using namespace com::sun::star::packages
;
104 using namespace com::sun::star::container
;
105 using namespace com::sun::star::packages::zip
;
106 using namespace com::sun::star::packages::manifest
;
107 using namespace com::sun::star::packages::zip::ZipConstants
;
109 #define LOGFILE_AUTHOR "mg115289"
114 sal_Bool
isLocalFile_Impl( ::rtl::OUString aURL
)
116 ::rtl::OUString aSystemPath
;
117 ContentBroker
* pBroker
= ContentBroker::get();
120 ::rtl::OUString aRet
;
121 if ( FileBase::getSystemPathFromFileURL( aURL
, aRet
) == FileBase::E_None
)
126 uno::Reference
< XContentProviderManager
> xManager
=
127 pBroker
->getContentProviderManagerInterface();
130 aSystemPath
= getSystemPathFromFileURL( xManager
, aURL
);
137 return ( aSystemPath
.getLength() != 0 );
142 //===========================================================================
144 class ActiveDataStreamer
: public ::cppu::WeakImplHelper1
< XActiveDataStreamer
>
146 uno::Reference
< XStream
> mStream
;
149 virtual uno::Reference
< XStream
> SAL_CALL
getStream()
150 throw( RuntimeException
)
153 virtual void SAL_CALL
setStream( const uno::Reference
< XStream
>& stream
)
154 throw( RuntimeException
)
155 { mStream
= stream
; }
158 class DummyInputStream
: public ::cppu::WeakImplHelper1
< XInputStream
>
160 virtual sal_Int32 SAL_CALL
readBytes( uno::Sequence
< sal_Int8
>&, sal_Int32
)
161 throw ( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
164 virtual sal_Int32 SAL_CALL
readSomeBytes( uno::Sequence
< sal_Int8
>&, sal_Int32
)
165 throw ( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
168 virtual void SAL_CALL
skipBytes( sal_Int32
)
169 throw ( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
172 virtual sal_Int32 SAL_CALL
available()
173 throw ( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
176 virtual void SAL_CALL
closeInput()
177 throw ( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
181 //===========================================================================
183 ZipPackage::ZipPackage ( const uno::Reference
< XMultiServiceFactory
> &xNewFactory
)
184 : m_aMutexHolder( new SotMutexHolder
)
185 , m_nStartKeyGenerationID( xml::crypto::DigestID::SHA1
)
186 , m_nChecksumDigestID( xml::crypto::DigestID::SHA1_1K
)
187 , m_nCommonEncryptionID( xml::crypto::CipherID::BLOWFISH_CFB_8
)
188 , m_bHasEncryptedEntries ( sal_False
)
189 , m_bHasNonEncryptedEntries ( sal_False
)
190 , m_bInconsistent ( sal_False
)
191 , m_bForceRecovery ( sal_False
)
192 , m_bMediaTypeFallbackUsed ( sal_False
)
193 , m_nFormat( embed::StorageFormats::PACKAGE
) // package is the default format
194 , m_bAllowRemoveOnInsert( sal_True
)
195 , m_eMode ( e_IMode_None
)
196 , m_xFactory( xNewFactory
)
197 , m_pRootFolder( NULL
)
200 m_xRootFolder
= m_pRootFolder
= new ZipPackageFolder( m_xFactory
, m_nFormat
, m_bAllowRemoveOnInsert
);
203 ZipPackage::~ZipPackage( void )
207 // All folders and streams contain pointers to their parents, when a parent diappeares
208 // it should disconnect all the children from itself during destruction automatically.
209 // So there is no need in explicit m_pRootFolder->releaseUpwardRef() call here any more
210 // since m_pRootFolder has no parent and cleaning of it's children will be done automatically
211 // during m_pRootFolder dieing by refcount.
214 //--------------------------------------------------------
215 void ZipPackage::parseManifest()
217 if ( m_nFormat
== embed::StorageFormats::PACKAGE
)
219 sal_Bool bManifestParsed
= sal_False
;
220 bool bDifferentStartKeyAlgorithm
= false;
221 const OUString
sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) );
222 if ( m_xRootFolder
->hasByName( sMeta
) )
224 const OUString
sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) );
227 uno::Reference
< XUnoTunnel
> xTunnel
;
228 Any aAny
= m_xRootFolder
->getByName( sMeta
);
230 uno::Reference
< XNameContainer
> xMetaInfFolder( xTunnel
, UNO_QUERY
);
231 if ( xMetaInfFolder
.is() && xMetaInfFolder
->hasByName( sManifest
) )
233 aAny
= xMetaInfFolder
->getByName( sManifest
);
235 uno::Reference
< XActiveDataSink
> xSink ( xTunnel
, UNO_QUERY
);
238 OUString
sManifestReader ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestReader" ) );
239 uno::Reference
< XManifestReader
> xReader ( m_xFactory
->createInstance( sManifestReader
), UNO_QUERY
);
242 const OUString
sPropFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
243 const OUString
sPropVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) );
244 const OUString
sPropMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
245 const OUString
sPropInitialisationVector ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) );
246 const OUString
sPropSalt ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) );
247 const OUString
sPropIterationCount ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) );
248 const OUString
sPropSize ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) );
249 const OUString
sPropDigest ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) );
250 const OUString
sPropDerivedKeySize ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) );
251 const OUString
sPropDigestAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) );
252 const OUString
sPropEncryptionAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) );
253 const OUString
sPropStartKeyAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) );
255 uno::Sequence
< uno::Sequence
< PropertyValue
> > aManifestSequence
= xReader
->readManifestSequence ( xSink
->getInputStream() );
256 sal_Int32 nLength
= aManifestSequence
.getLength();
257 const uno::Sequence
< PropertyValue
> *pSequence
= aManifestSequence
.getConstArray();
258 ZipPackageStream
*pStream
= NULL
;
259 ZipPackageFolder
*pFolder
= NULL
;
261 for ( sal_Int32 i
= 0; i
< nLength
; i
++, pSequence
++ )
263 OUString sPath
, sMediaType
, sVersion
;
264 const PropertyValue
*pValue
= pSequence
->getConstArray();
265 const Any
*pSalt
= NULL
, *pVector
= NULL
, *pCount
= NULL
, *pSize
= NULL
, *pDigest
= NULL
, *pDigestAlg
= NULL
, *pEncryptionAlg
= NULL
, *pStartKeyAlg
= NULL
, *pDerivedKeySize
= NULL
;
266 for ( sal_Int32 j
= 0, nNum
= pSequence
->getLength(); j
< nNum
; j
++ )
268 if ( pValue
[j
].Name
.equals( sPropFullPath
) )
269 pValue
[j
].Value
>>= sPath
;
270 else if ( pValue
[j
].Name
.equals( sPropVersion
) )
271 pValue
[j
].Value
>>= sVersion
;
272 else if ( pValue
[j
].Name
.equals( sPropMediaType
) )
273 pValue
[j
].Value
>>= sMediaType
;
274 else if ( pValue
[j
].Name
.equals( sPropSalt
) )
275 pSalt
= &( pValue
[j
].Value
);
276 else if ( pValue
[j
].Name
.equals( sPropInitialisationVector
) )
277 pVector
= &( pValue
[j
].Value
);
278 else if ( pValue
[j
].Name
.equals( sPropIterationCount
) )
279 pCount
= &( pValue
[j
].Value
);
280 else if ( pValue
[j
].Name
.equals( sPropSize
) )
281 pSize
= &( pValue
[j
].Value
);
282 else if ( pValue
[j
].Name
.equals( sPropDigest
) )
283 pDigest
= &( pValue
[j
].Value
);
284 else if ( pValue
[j
].Name
.equals( sPropDigestAlgorithm
) )
285 pDigestAlg
= &( pValue
[j
].Value
);
286 else if ( pValue
[j
].Name
.equals( sPropEncryptionAlgorithm
) )
287 pEncryptionAlg
= &( pValue
[j
].Value
);
288 else if ( pValue
[j
].Name
.equals( sPropStartKeyAlgorithm
) )
289 pStartKeyAlg
= &( pValue
[j
].Value
);
290 else if ( pValue
[j
].Name
.equals( sPropDerivedKeySize
) )
291 pDerivedKeySize
= &( pValue
[j
].Value
);
294 if ( sPath
.getLength() && hasByHierarchicalName ( sPath
) )
296 aAny
= getByHierarchicalName( sPath
);
297 uno::Reference
< XUnoTunnel
> xUnoTunnel
;
300 if ( (nTest
= xUnoTunnel
->getSomething( ZipPackageFolder::static_getImplementationId() )) != 0 )
302 pFolder
= reinterpret_cast < ZipPackageFolder
* > ( nTest
);
303 pFolder
->SetMediaType ( sMediaType
);
304 pFolder
->SetVersion ( sVersion
);
308 pStream
= reinterpret_cast < ZipPackageStream
* > ( xUnoTunnel
->getSomething( ZipPackageStream::static_getImplementationId() ));
309 pStream
->SetMediaType ( sMediaType
);
310 pStream
->SetFromManifest( sal_True
);
312 if ( pSalt
&& pVector
&& pCount
&& pSize
&& pDigest
&& pDigestAlg
&& pEncryptionAlg
)
314 uno::Sequence
< sal_Int8
> aSequence
;
315 sal_Int32 nCount
= 0, nSize
= 0, nDigestAlg
= 0, nEncryptionAlg
= 0, nDerivedKeySize
= 16, nStartKeyAlg
= xml::crypto::DigestID::SHA1
;
317 pStream
->SetToBeEncrypted ( sal_True
);
319 *pSalt
>>= aSequence
;
320 pStream
->setSalt ( aSequence
);
322 *pVector
>>= aSequence
;
323 pStream
->setInitialisationVector ( aSequence
);
326 pStream
->setIterationCount ( nCount
);
329 pStream
->setSize ( nSize
);
331 *pDigest
>>= aSequence
;
332 pStream
->setDigest ( aSequence
);
334 *pDigestAlg
>>= nDigestAlg
;
335 pStream
->SetImportedChecksumAlgorithm( nDigestAlg
);
337 *pEncryptionAlg
>>= nEncryptionAlg
;
338 pStream
->SetImportedEncryptionAlgorithm( nEncryptionAlg
);
340 if ( pDerivedKeySize
)
341 *pDerivedKeySize
>>= nDerivedKeySize
;
342 pStream
->SetImportedDerivedKeySize( nDerivedKeySize
);
345 *pStartKeyAlg
>>= nStartKeyAlg
;
346 pStream
->SetImportedStartKeyAlgorithm( nStartKeyAlg
);
348 pStream
->SetToBeCompressed ( sal_True
);
349 pStream
->SetToBeEncrypted ( sal_True
);
350 pStream
->SetIsEncrypted ( sal_True
);
351 if ( !m_bHasEncryptedEntries
352 && pStream
->getName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) ) )
354 m_bHasEncryptedEntries
= sal_True
;
355 m_nStartKeyGenerationID
= nStartKeyAlg
;
356 m_nChecksumDigestID
= nDigestAlg
;
357 m_nCommonEncryptionID
= nEncryptionAlg
;
361 m_bHasNonEncryptedEntries
= sal_True
;
366 bManifestParsed
= sal_True
;
369 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"No manifes parser!" ) ), uno::Reference
< uno::XInterface
>() );
372 // now hide the manifest.xml file from user
373 xMetaInfFolder
->removeByName( sManifest
);
378 if ( !m_bForceRecovery
)
383 if ( !bManifestParsed
&& !m_bForceRecovery
)
384 throw ZipIOException(
385 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Could not parse manifest.xml\n" ) ),
386 uno::Reference
< uno::XInterface
>() );
388 const OUString
sMimetype ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) );
389 if ( m_xRootFolder
->hasByName( sMimetype
) )
391 // get mediatype from the "mimetype" stream
392 ::rtl::OUString aPackageMediatype
;
393 uno::Reference
< lang::XUnoTunnel
> xMimeTypeTunnel
;
394 m_xRootFolder
->getByName( sMimetype
) >>= xMimeTypeTunnel
;
395 uno::Reference
< io::XActiveDataSink
> xMimeSink( xMimeTypeTunnel
, UNO_QUERY
);
396 if ( xMimeSink
.is() )
398 uno::Reference
< io::XInputStream
> xMimeInStream
= xMimeSink
->getInputStream();
399 if ( xMimeInStream
.is() )
401 // Mediatypes longer than 1024 symbols should not appear here
402 uno::Sequence
< sal_Int8
> aData( 1024 );
403 sal_Int32 nRead
= xMimeInStream
->readBytes( aData
, 1024 );
404 if ( nRead
> aData
.getLength() )
405 nRead
= aData
.getLength();
408 aPackageMediatype
= ::rtl::OUString( ( sal_Char
* )aData
.getConstArray(), nRead
, RTL_TEXTENCODING_ASCII_US
);
413 if ( !bManifestParsed
)
415 // the manifest.xml could not be successfuly parsed, this is an inconsistent package
416 if ( aPackageMediatype
.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "application/vnd." ) ) == 0 )
418 // accept only types that look similar to own mediatypes
419 m_pRootFolder
->SetMediaType( aPackageMediatype
);
420 m_bMediaTypeFallbackUsed
= sal_True
;
423 else if ( !m_bForceRecovery
)
425 // the mimetype stream should contain the information from manifest.xml
426 if ( !m_pRootFolder
->GetMediaType().equals( aPackageMediatype
) )
427 throw ZipIOException(
428 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"mimetype conflicts with manifest.xml\n" ) ),
429 uno::Reference
< uno::XInterface
>() );
432 m_xRootFolder
->removeByName( sMimetype
);
435 m_bInconsistent
= m_pRootFolder
->LookForUnexpectedODF12Streams( ::rtl::OUString() );
437 sal_Bool bODF12AndNewer
= ( m_pRootFolder
->GetVersion().compareTo( ODFVER_012_TEXT
) >= 0 );
438 if ( !m_bForceRecovery
&& bODF12AndNewer
)
440 if ( m_bInconsistent
)
442 // this is an ODF1.2 document that contains streams not referred in the manifest.xml;
443 // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent
444 // should be checked later
445 throw ZipIOException(
446 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"there are streams not referred in manifest.xml\n" ) ),
447 uno::Reference
< uno::XInterface
>() );
449 else if ( bDifferentStartKeyAlgorithm
)
451 // all the streams should be encrypted with the same StartKey in ODF1.2
452 // TODO/LATER: in future the exception should be thrown
453 OSL_ENSURE( false, "ODF1.2 contains different StartKey Algorithms" );
454 // throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "More than one Start Key Generation algorithm is specified!" ) ), uno::Reference< uno::XInterface >() );
458 // in case it is a correct ODF1.2 document, the version must be set
459 // and the META-INF folder is reserved for package format
460 if ( bODF12AndNewer
)
461 m_xRootFolder
->removeByName( sMeta
);
465 //--------------------------------------------------------
466 void ZipPackage::parseContentType()
468 if ( m_nFormat
== embed::StorageFormats::OFOPXML
)
470 const ::rtl::OUString
aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) );
472 // the content type must exist in OFOPXML format!
473 if ( !m_xRootFolder
->hasByName( aContentTypes
) )
474 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Wrong format!" ) ),
475 uno::Reference
< uno::XInterface
>() );
477 uno::Reference
< lang::XUnoTunnel
> xTunnel
;
478 uno::Any aAny
= m_xRootFolder
->getByName( aContentTypes
);
480 uno::Reference
< io::XActiveDataSink
> xSink( xTunnel
, UNO_QUERY
);
483 uno::Reference
< io::XInputStream
> xInStream
= xSink
->getInputStream();
484 if ( xInStream
.is() )
487 // here aContentTypeInfo[0] - Defaults, and aContentTypeInfo[1] - Overrides
488 uno::Sequence
< uno::Sequence
< beans::StringPair
> > aContentTypeInfo
=
489 ::comphelper::OFOPXMLHelper::ReadContentTypeSequence( xInStream
, m_xFactory
);
491 if ( aContentTypeInfo
.getLength() != 2 )
492 throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
494 // set the implicit types fist
495 for ( nInd
= 0; nInd
< aContentTypeInfo
[0].getLength(); nInd
++ )
496 m_pRootFolder
->setChildStreamsTypeByExtension( aContentTypeInfo
[0][nInd
] );
498 // now set the explicit types
499 for ( nInd
= 0; nInd
< aContentTypeInfo
[1].getLength(); nInd
++ )
501 ::rtl::OUString aPath
;
502 if ( aContentTypeInfo
[1][nInd
].First
.toChar() == ( sal_Unicode
)'/' )
503 aPath
= aContentTypeInfo
[1][nInd
].First
.copy( 1 );
505 aPath
= aContentTypeInfo
[1][nInd
].First
;
507 if ( aPath
.getLength() && hasByHierarchicalName( aPath
) )
509 uno::Any aIterAny
= getByHierarchicalName( aPath
);
510 uno::Reference
< lang::XUnoTunnel
> xIterTunnel
;
511 aIterAny
>>= xIterTunnel
;
512 sal_Int64 nTest
= xIterTunnel
->getSomething( ZipPackageStream::static_getImplementationId() );
515 // this is a package stream, in OFOPXML format only streams can have mediatype
516 ZipPackageStream
*pStream
= reinterpret_cast < ZipPackageStream
* > ( nTest
);
517 pStream
->SetMediaType( aContentTypeInfo
[1][nInd
].Second
);
524 m_xRootFolder
->removeByName( aContentTypes
);
526 catch( uno::Exception
& )
528 if ( !m_bForceRecovery
)
534 //--------------------------------------------------------
535 void ZipPackage::getZipFileContents()
537 auto_ptr
< ZipEnumeration
> pEnum ( m_pZipFile
->entries() );
538 ZipPackageStream
*pPkgStream
;
539 ZipPackageFolder
*pPkgFolder
, *pCurrent
;
540 OUString sTemp
, sDirName
;
541 sal_Int32 nOldIndex
, nIndex
, nStreamIndex
;
542 FolderHash::iterator aIter
;
544 while ( pEnum
->hasMoreElements() )
546 nIndex
= nOldIndex
= 0;
547 pCurrent
= m_pRootFolder
;
548 const ZipEntry
& rEntry
= *pEnum
->nextElement();
549 OUString rName
= rEntry
.sPath
;
551 if ( m_bForceRecovery
)
553 // the PKZIP Application note version 6.2 does not allows to use '\' as separator
554 // unfortunately it is used by some implementations, so we have to support it in recovery mode
555 rName
= rName
.replace( '\\', '/' );
558 nStreamIndex
= rName
.lastIndexOf ( '/' );
559 if ( nStreamIndex
!= -1 )
561 sDirName
= rName
.copy ( 0, nStreamIndex
);
562 aIter
= m_aRecent
.find ( sDirName
);
563 if ( aIter
!= m_aRecent
.end() )
564 pCurrent
= ( *aIter
).second
;
567 if ( pCurrent
== m_pRootFolder
)
569 while ( ( nIndex
= rName
.indexOf( '/', nOldIndex
) ) != -1 )
571 sTemp
= rName
.copy ( nOldIndex
, nIndex
- nOldIndex
);
572 if ( nIndex
== nOldIndex
)
574 if ( !pCurrent
->hasByName( sTemp
) )
576 pPkgFolder
= new ZipPackageFolder( m_xFactory
, m_nFormat
, m_bAllowRemoveOnInsert
);
577 pPkgFolder
->setName( sTemp
);
578 pPkgFolder
->doSetParent( pCurrent
, sal_True
);
579 pCurrent
= pPkgFolder
;
582 pCurrent
= pCurrent
->doGetByName( sTemp
).pFolder
;
583 nOldIndex
= nIndex
+1;
585 if ( nStreamIndex
!= -1 && sDirName
.getLength() )
586 m_aRecent
[ sDirName
] = pCurrent
;
588 if ( rName
.getLength() -1 != nStreamIndex
)
591 sTemp
= rName
.copy( nStreamIndex
, rName
.getLength() - nStreamIndex
);
592 pPkgStream
= new ZipPackageStream( *this, m_xFactory
, m_bAllowRemoveOnInsert
);
593 pPkgStream
->SetPackageMember( sal_True
);
594 pPkgStream
->setZipEntryOnLoading( rEntry
);
595 pPkgStream
->setName( sTemp
);
596 pPkgStream
->doSetParent( pCurrent
, sal_True
);
600 if ( m_nFormat
== embed::StorageFormats::PACKAGE
)
602 else if ( m_nFormat
== embed::StorageFormats::OFOPXML
)
606 //--------------------------------------------------------
607 void SAL_CALL
ZipPackage::initialize( const uno::Sequence
< Any
>& aArguments
)
608 throw( Exception
, RuntimeException
)
610 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR
, "{ ZipPackage::initialize" );
611 sal_Bool bBadZipFile
= sal_False
, bHaveZipFile
= sal_True
;
612 uno::Reference
< XProgressHandler
> xProgressHandler
;
613 beans::NamedValue aNamedValue
;
615 if ( aArguments
.getLength() )
617 for( int ind
= 0; ind
< aArguments
.getLength(); ind
++ )
620 if ( ( aArguments
[ind
] >>= aParamUrl
))
622 m_eMode
= e_IMode_URL
;
625 sal_Int32 nParam
= aParamUrl
.indexOf( '?' );
628 m_aURL
= aParamUrl
.copy( 0, nParam
);
629 OUString aParam
= aParamUrl
.copy( nParam
+ 1 );
631 sal_Int32 nIndex
= 0;
634 ::rtl::OUString aCommand
= aParam
.getToken( 0, '&', nIndex
);
635 if ( aCommand
.equals( OUString::createFromAscii( "repairpackage" ) ) )
637 m_bForceRecovery
= sal_True
;
640 else if ( aCommand
.equals( OUString::createFromAscii( "purezip" ) ) )
642 m_nFormat
= embed::StorageFormats::ZIP
;
643 m_pRootFolder
->setPackageFormat_Impl( m_nFormat
);
646 else if ( aCommand
.equals( OUString::createFromAscii( "ofopxml" ) ) )
648 m_nFormat
= embed::StorageFormats::OFOPXML
;
649 m_pRootFolder
->setPackageFormat_Impl( m_nFormat
);
653 while ( nIndex
>= 0 );
658 Content
aContent ( m_aURL
, uno::Reference
< XCommandEnvironment
>() );
659 Any aAny
= aContent
.getPropertyValue( OUString::createFromAscii( "Size" ) );
660 sal_uInt64 aSize
= 0;
661 // kind of optimisation: treat empty files as nonexistent files
662 // and write to such files directly. Note that "Size" property is optional.
663 bool bHasSizeProperty
= aAny
>>= aSize
;
664 if( !bHasSizeProperty
|| ( bHasSizeProperty
&& aSize
) )
666 uno::Reference
< XActiveDataSink
> xSink
= new ZipPackageSink
;
667 if ( aContent
.openStream ( xSink
) )
668 m_xContentStream
= xSink
->getInputStream();
671 bHaveZipFile
= sal_False
;
673 catch ( com::sun::star::uno::Exception
& )
675 // Exception derived from uno::Exception thrown. This probably
676 // means the file doesn't exist...we'll create it at
677 // commitChanges time
678 bHaveZipFile
= sal_False
;
681 else if ( ( aArguments
[ind
] >>= m_xStream
) )
683 // a writable stream can implement both XStream & XInputStream
684 m_eMode
= e_IMode_XStream
;
685 m_xContentStream
= m_xStream
->getInputStream();
687 else if ( ( aArguments
[ind
] >>= m_xContentStream
) )
689 m_eMode
= e_IMode_XInputStream
;
691 else if ( ( aArguments
[ind
] >>= aNamedValue
) )
693 if ( aNamedValue
.Name
.equalsAscii( "RepairPackage" ) )
694 aNamedValue
.Value
>>= m_bForceRecovery
;
695 else if ( aNamedValue
.Name
.equalsAscii( "PackageFormat" ) )
697 // setting this argument to true means Package format
698 // setting it to false means plain Zip format
700 sal_Bool bPackFormat
= sal_True
;
701 aNamedValue
.Value
>>= bPackFormat
;
703 m_nFormat
= embed::StorageFormats::ZIP
;
705 m_pRootFolder
->setPackageFormat_Impl( m_nFormat
);
707 else if ( aNamedValue
.Name
.equalsAscii( "StorageFormat" ) )
709 ::rtl::OUString aFormatName
;
710 sal_Int32 nFormatID
= 0;
711 if ( aNamedValue
.Value
>>= aFormatName
)
713 if ( aFormatName
.equals( PACKAGE_STORAGE_FORMAT_STRING
) )
714 m_nFormat
= embed::StorageFormats::PACKAGE
;
715 else if ( aFormatName
.equals( ZIP_STORAGE_FORMAT_STRING
) )
716 m_nFormat
= embed::StorageFormats::ZIP
;
717 else if ( aFormatName
.equals( OFOPXML_STORAGE_FORMAT_STRING
) )
718 m_nFormat
= embed::StorageFormats::OFOPXML
;
720 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 1 );
722 else if ( aNamedValue
.Value
>>= nFormatID
)
724 if ( nFormatID
!= embed::StorageFormats::PACKAGE
725 && nFormatID
!= embed::StorageFormats::ZIP
726 && nFormatID
!= embed::StorageFormats::OFOPXML
)
727 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 1 );
729 m_nFormat
= nFormatID
;
732 throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 1 );
734 m_pRootFolder
->setPackageFormat_Impl( m_nFormat
);
736 else if ( aNamedValue
.Name
.equalsAscii( "AllowRemoveOnInsert" ) )
738 aNamedValue
.Value
>>= m_bAllowRemoveOnInsert
;
739 m_pRootFolder
->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert
);
742 // for now the progress handler is not used, probably it will never be
743 // if ( aNamedValue.Name.equalsAscii( "ProgressHandler" )
747 // The URL is not acceptable
748 throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Bad arguments." ) ),
749 static_cast < ::cppu::OWeakObject
* > ( this ) );
755 if ( m_xContentStream
.is() )
757 // the stream must be seekable, if it is not it will be wrapped
758 m_xContentStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xContentStream
, m_xFactory
);
759 m_xContentSeek
= uno::Reference
< XSeekable
> ( m_xContentStream
, UNO_QUERY
);
760 if ( ! m_xContentSeek
.is() )
761 throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"The package component _requires_ an XSeekable interface!" ) ),
762 static_cast < ::cppu::OWeakObject
* > ( this ) );
764 if ( !m_xContentSeek
->getLength() )
765 bHaveZipFile
= sal_False
;
768 bHaveZipFile
= sal_False
;
770 catch ( com::sun::star::uno::Exception
& )
772 // Exception derived from uno::Exception thrown. This probably
773 // means the file doesn't exist...we'll create it at
774 // commitChanges time
775 bHaveZipFile
= sal_False
;
781 m_pZipFile
= new ZipFile ( m_xContentStream
, m_xFactory
, sal_True
, m_bForceRecovery
, xProgressHandler
);
782 getZipFileContents();
784 catch ( IOException
& )
786 bBadZipFile
= sal_True
;
788 catch ( ZipException
& )
790 bBadZipFile
= sal_True
;
792 catch ( Exception
& )
794 if( m_pZipFile
) { delete m_pZipFile
; m_pZipFile
= NULL
; }
800 // clean up the memory, and tell the UCB about the error
801 if( m_pZipFile
) { delete m_pZipFile
; m_pZipFile
= NULL
; }
803 throw com::sun::star::packages::zip::ZipIOException (
804 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Bad Zip File." ) ),
805 static_cast < ::cppu::OWeakObject
* > ( this ) );
810 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR
, "} ZipPackage::initialize" );
813 //--------------------------------------------------------
814 Any SAL_CALL
ZipPackage::getByHierarchicalName( const OUString
& aName
)
815 throw( NoSuchElementException
, RuntimeException
)
817 OUString sTemp
, sDirName
;
818 sal_Int32 nOldIndex
, nIndex
, nStreamIndex
;
819 FolderHash::iterator aIter
;
821 if ( ( nIndex
= aName
.getLength() ) == 1 && *aName
.getStr() == '/' )
822 return makeAny ( uno::Reference
< XUnoTunnel
> ( m_pRootFolder
) );
825 nStreamIndex
= aName
.lastIndexOf ( '/' );
826 bool bFolder
= nStreamIndex
== nIndex
-1;
827 if ( nStreamIndex
!= -1 )
829 sDirName
= aName
.copy ( 0, nStreamIndex
);
830 aIter
= m_aRecent
.find ( sDirName
);
831 if ( aIter
!= m_aRecent
.end() )
835 sal_Int32 nDirIndex
= aName
.lastIndexOf ( '/', nStreamIndex
);
836 sTemp
= aName
.copy ( nDirIndex
== -1 ? 0 : nDirIndex
+1, nStreamIndex
-nDirIndex
-1 );
837 if ( sTemp
== ( *aIter
).second
->getName() )
838 return makeAny ( uno::Reference
< XUnoTunnel
> ( ( *aIter
).second
) );
840 m_aRecent
.erase ( aIter
);
844 sTemp
= aName
.copy ( nStreamIndex
+ 1 );
845 if ( ( *aIter
).second
->hasByName( sTemp
) )
846 return ( *aIter
).second
->getByName( sTemp
);
848 m_aRecent
.erase( aIter
);
854 if ( m_pRootFolder
->hasByName ( aName
) )
855 return m_pRootFolder
->getByName ( aName
);
858 ZipPackageFolder
* pCurrent
= m_pRootFolder
;
859 ZipPackageFolder
* pPrevious
= NULL
;
860 while ( ( nIndex
= aName
.indexOf( '/', nOldIndex
)) != -1 )
862 sTemp
= aName
.copy ( nOldIndex
, nIndex
- nOldIndex
);
863 if ( nIndex
== nOldIndex
)
865 if ( pCurrent
->hasByName( sTemp
) )
867 pPrevious
= pCurrent
;
868 pCurrent
= pCurrent
->doGetByName( sTemp
).pFolder
;
871 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
872 nOldIndex
= nIndex
+1;
876 if ( nStreamIndex
!= -1 )
877 m_aRecent
[sDirName
] = pPrevious
;
878 return makeAny ( uno::Reference
< XUnoTunnel
> ( pCurrent
) );
882 sTemp
= aName
.copy( nOldIndex
, aName
.getLength() - nOldIndex
);
883 if ( pCurrent
->hasByName ( sTemp
) )
885 if ( nStreamIndex
!= -1 )
886 m_aRecent
[sDirName
] = pCurrent
;
887 return pCurrent
->getByName( sTemp
);
890 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
895 //--------------------------------------------------------
896 sal_Bool SAL_CALL
ZipPackage::hasByHierarchicalName( const OUString
& aName
)
897 throw( RuntimeException
)
899 OUString sTemp
, sDirName
;
900 sal_Int32 nOldIndex
, nIndex
, nStreamIndex
;
901 FolderHash::iterator aIter
;
903 if ( ( nIndex
= aName
.getLength() ) == 1 && *aName
.getStr() == '/' )
907 nStreamIndex
= aName
.lastIndexOf ( '/' );
908 bool bFolder
= nStreamIndex
== nIndex
-1;
909 if ( nStreamIndex
!= -1 )
911 sDirName
= aName
.copy ( 0, nStreamIndex
);
912 aIter
= m_aRecent
.find ( sDirName
);
913 if ( aIter
!= m_aRecent
.end() )
917 sal_Int32 nDirIndex
= aName
.lastIndexOf ( '/', nStreamIndex
);
918 sTemp
= aName
.copy ( nDirIndex
== -1 ? 0 : nDirIndex
+1, nStreamIndex
-nDirIndex
-1 );
919 if ( sTemp
== ( *aIter
).second
->getName() )
922 m_aRecent
.erase ( aIter
);
926 sTemp
= aName
.copy ( nStreamIndex
+ 1 );
927 if ( ( *aIter
).second
->hasByName( sTemp
) )
930 m_aRecent
.erase( aIter
);
936 if ( m_pRootFolder
->hasByName ( aName
) )
939 ZipPackageFolder
* pCurrent
= m_pRootFolder
;
940 ZipPackageFolder
* pPrevious
= NULL
;
942 while ( ( nIndex
= aName
.indexOf( '/', nOldIndex
)) != -1 )
944 sTemp
= aName
.copy ( nOldIndex
, nIndex
- nOldIndex
);
945 if ( nIndex
== nOldIndex
)
947 if ( pCurrent
->hasByName( sTemp
) )
949 pPrevious
= pCurrent
;
950 pCurrent
= pCurrent
->doGetByName( sTemp
).pFolder
;
954 nOldIndex
= nIndex
+1;
958 m_aRecent
[sDirName
] = pPrevious
;
963 sTemp
= aName
.copy( nOldIndex
, aName
.getLength() - nOldIndex
);
965 if ( pCurrent
->hasByName( sTemp
) )
967 m_aRecent
[sDirName
] = pCurrent
;
975 //--------------------------------------------------------
976 uno::Reference
< XInterface
> SAL_CALL
ZipPackage::createInstance()
977 throw( Exception
, RuntimeException
)
979 uno::Reference
< XInterface
> xRef
= *( new ZipPackageStream ( *this, m_xFactory
, m_bAllowRemoveOnInsert
) );
982 //--------------------------------------------------------
983 uno::Reference
< XInterface
> SAL_CALL
ZipPackage::createInstanceWithArguments( const uno::Sequence
< Any
>& aArguments
)
984 throw( Exception
, RuntimeException
)
986 sal_Bool bArg
= sal_False
;
987 uno::Reference
< XInterface
> xRef
;
988 if ( aArguments
.getLength() )
989 aArguments
[0] >>= bArg
;
991 xRef
= *new ZipPackageFolder ( m_xFactory
, m_nFormat
, m_bAllowRemoveOnInsert
);
993 xRef
= *new ZipPackageStream ( *this, m_xFactory
, m_bAllowRemoveOnInsert
);
998 //--------------------------------------------------------
999 void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream
& aZipOut
)
1001 const OUString
sMime ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) );
1002 if ( m_xRootFolder
->hasByName( sMime
) )
1003 m_xRootFolder
->removeByName( sMime
);
1005 ZipEntry
* pEntry
= new ZipEntry
;
1006 sal_Int32 nBufferLength
= m_pRootFolder
->GetMediaType().getLength();
1007 OString sMediaType
= OUStringToOString( m_pRootFolder
->GetMediaType(), RTL_TEXTENCODING_ASCII_US
);
1008 uno::Sequence
< sal_Int8
> aType( ( sal_Int8
* )sMediaType
.getStr(),
1012 pEntry
->sPath
= sMime
;
1013 pEntry
->nMethod
= STORED
;
1014 pEntry
->nSize
= pEntry
->nCompressedSize
= nBufferLength
;
1015 pEntry
->nTime
= ZipOutputStream::getCurrentDosTime();
1018 aCRC32
.update( aType
);
1019 pEntry
->nCrc
= aCRC32
.getValue();
1023 aZipOut
.putNextEntry( *pEntry
, NULL
);
1024 aZipOut
.write( aType
, 0, nBufferLength
);
1025 aZipOut
.closeEntry();
1027 catch ( ::com::sun::star::io::IOException
& r
)
1029 throw WrappedTargetException(
1030 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Error adding mimetype to the ZipOutputStream!" ) ),
1031 static_cast < OWeakObject
* > ( this ),
1036 //--------------------------------------------------------
1037 void ZipPackage::WriteManifest( ZipOutputStream
& aZipOut
, const vector
< uno::Sequence
< PropertyValue
> >& aManList
)
1039 // Write the manifest
1040 uno::Reference
< XOutputStream
> xManOutStream
;
1041 OUString
sManifestWriter( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestWriter" ) );
1042 uno::Reference
< XManifestWriter
> xWriter ( m_xFactory
->createInstance( sManifestWriter
), UNO_QUERY
);
1045 ZipEntry
* pEntry
= new ZipEntry
;
1046 ZipPackageBuffer
*pBuffer
= new ZipPackageBuffer( n_ConstBufferSize
);
1047 xManOutStream
= uno::Reference
< XOutputStream
> ( *pBuffer
, UNO_QUERY
);
1049 pEntry
->sPath
= OUString( RTL_CONSTASCII_USTRINGPARAM ( "META-INF/manifest.xml" ) );
1050 pEntry
->nMethod
= DEFLATED
;
1051 pEntry
->nCrc
= pEntry
->nSize
= pEntry
->nCompressedSize
= -1;
1052 pEntry
->nTime
= ZipOutputStream::getCurrentDosTime();
1054 // Convert vector into a uno::Sequence
1055 uno::Sequence
< uno::Sequence
< PropertyValue
> > aManifestSequence ( aManList
.size() );
1057 for ( vector
< uno::Sequence
< PropertyValue
> >::const_iterator aIter
= aManList
.begin(), aEnd
= aManList
.end();
1061 aManifestSequence
[nInd
] = ( *aIter
);
1063 xWriter
->writeManifestSequence ( xManOutStream
, aManifestSequence
);
1065 sal_Int32 nBufferLength
= static_cast < sal_Int32
> ( pBuffer
->getPosition() );
1066 pBuffer
->realloc( nBufferLength
);
1068 // the manifest.xml is never encrypted - so pass an empty reference
1069 aZipOut
.putNextEntry( *pEntry
, NULL
);
1070 aZipOut
.write( pBuffer
->getSequence(), 0, nBufferLength
);
1071 aZipOut
.closeEntry();
1075 VOS_ENSURE ( 0, "Couldn't get a ManifestWriter!" );
1076 IOException aException
;
1077 throw WrappedTargetException(
1078 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Couldn't get a ManifestWriter!" ) ),
1079 static_cast < OWeakObject
* > ( this ),
1080 makeAny( aException
) );
1084 //--------------------------------------------------------
1085 void ZipPackage::WriteContentTypes( ZipOutputStream
& aZipOut
, const vector
< uno::Sequence
< PropertyValue
> >& aManList
)
1087 const OUString
sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
1088 const OUString
sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
1090 ZipEntry
* pEntry
= new ZipEntry
;
1091 ZipPackageBuffer
*pBuffer
= new ZipPackageBuffer( n_ConstBufferSize
);
1092 uno::Reference
< io::XOutputStream
> xConTypeOutStream( *pBuffer
, UNO_QUERY
);
1094 pEntry
->sPath
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) );
1095 pEntry
->nMethod
= DEFLATED
;
1096 pEntry
->nCrc
= pEntry
->nSize
= pEntry
->nCompressedSize
= -1;
1097 pEntry
->nTime
= ZipOutputStream::getCurrentDosTime();
1099 // Convert vector into a uno::Sequence
1100 // TODO/LATER: use Defaulst entries in future
1101 uno::Sequence
< beans::StringPair
> aDefaultsSequence
;
1102 uno::Sequence
< beans::StringPair
> aOverridesSequence( aManList
.size() );
1103 sal_Int32 nSeqLength
= 0;
1104 for ( vector
< uno::Sequence
< beans::PropertyValue
> >::const_iterator aIter
= aManList
.begin(),
1105 aEnd
= aManList
.end();
1109 ::rtl::OUString aPath
;
1110 ::rtl::OUString aType
;
1111 OSL_ENSURE( ( *aIter
)[PKG_MNFST_MEDIATYPE
].Name
.equals( sMediaType
) && ( *aIter
)[PKG_MNFST_FULLPATH
].Name
.equals( sFullPath
),
1112 "The mediatype sequence format is wrong!\n" );
1113 ( *aIter
)[PKG_MNFST_MEDIATYPE
].Value
>>= aType
;
1114 if ( aType
.getLength() )
1116 // only nonempty type makes sence here
1118 ( *aIter
)[PKG_MNFST_FULLPATH
].Value
>>= aPath
;
1119 aOverridesSequence
[nSeqLength
-1].First
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + aPath
;
1120 aOverridesSequence
[nSeqLength
-1].Second
= aType
;
1123 aOverridesSequence
.realloc( nSeqLength
);
1125 ::comphelper::OFOPXMLHelper::WriteContentSequence(
1126 xConTypeOutStream
, aDefaultsSequence
, aOverridesSequence
, m_xFactory
);
1128 sal_Int32 nBufferLength
= static_cast < sal_Int32
> ( pBuffer
->getPosition() );
1129 pBuffer
->realloc( nBufferLength
);
1131 // there is no encryption in this format currently
1132 aZipOut
.putNextEntry( *pEntry
, NULL
);
1133 aZipOut
.write( pBuffer
->getSequence(), 0, nBufferLength
);
1134 aZipOut
.closeEntry();
1137 //--------------------------------------------------------
1138 void ZipPackage::ConnectTo( const uno::Reference
< io::XInputStream
>& xInStream
)
1140 m_xContentSeek
.set( xInStream
, uno::UNO_QUERY_THROW
);
1141 m_xContentStream
= xInStream
;
1143 // seek back to the beginning of the temp file so we can read segments from it
1144 m_xContentSeek
->seek( 0 );
1146 m_pZipFile
->setInputStream( m_xContentStream
);
1148 m_pZipFile
= new ZipFile ( m_xContentStream
, m_xFactory
, sal_False
);
1151 //--------------------------------------------------------
1152 uno::Reference
< io::XInputStream
> ZipPackage::writeTempFile()
1154 // In case the target local file does not exist or empty
1155 // write directly to it otherwize create a temporary file to write to.
1156 // If a temporary file is created it is returned back by the method.
1157 // If the data written directly, xComponentStream will be switched here
1159 sal_Bool bUseTemp
= sal_True
;
1160 uno::Reference
< io::XInputStream
> xResult
;
1161 uno::Reference
< io::XInputStream
> xTempIn
;
1163 uno::Reference
< io::XOutputStream
> xTempOut
;
1164 uno::Reference
< io::XActiveDataStreamer
> xSink
;
1166 if ( m_eMode
== e_IMode_URL
&& !m_pZipFile
&& isLocalFile_Impl( m_aURL
) )
1168 xSink
= openOriginalForOutput();
1171 uno::Reference
< io::XStream
> xStr
= xSink
->getStream();
1174 xTempOut
= xStr
->getOutputStream();
1176 bUseTemp
= sal_False
;
1180 else if ( m_eMode
== e_IMode_XStream
&& !m_pZipFile
)
1182 // write directly to an empty stream
1183 xTempOut
= m_xStream
->getOutputStream();
1185 bUseTemp
= sal_False
;
1190 // create temporary file
1191 const OUString
sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
1192 uno::Reference
< io::XStream
> xTempFile( m_xFactory
->createInstance ( sServiceName
), UNO_QUERY_THROW
);
1193 xTempOut
.set( xTempFile
->getOutputStream(), UNO_SET_THROW
);
1194 xTempIn
.set( xTempFile
->getInputStream(), UNO_SET_THROW
);
1197 // Hand it to the ZipOutputStream:
1198 ZipOutputStream
aZipOut( m_xFactory
, xTempOut
);
1199 aZipOut
.setMethod( DEFLATED
);
1200 aZipOut
.setLevel( DEFAULT_COMPRESSION
);
1204 if ( m_nFormat
== embed::StorageFormats::PACKAGE
)
1206 // Remove the old manifest.xml file as the
1207 // manifest will be re-generated and the
1208 // META-INF directory implicitly created if does not exist
1209 const OUString
sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) );
1211 if ( m_xRootFolder
->hasByName( sMeta
) )
1213 const OUString
sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) );
1215 uno::Reference
< XUnoTunnel
> xTunnel
;
1216 Any aAny
= m_xRootFolder
->getByName( sMeta
);
1218 uno::Reference
< XNameContainer
> xMetaInfFolder( xTunnel
, UNO_QUERY
);
1219 if ( xMetaInfFolder
.is() && xMetaInfFolder
->hasByName( sManifest
) )
1220 xMetaInfFolder
->removeByName( sManifest
);
1223 // Write a magic file with mimetype
1224 WriteMimetypeMagicFile( aZipOut
);
1226 else if ( m_nFormat
== embed::StorageFormats::OFOPXML
)
1228 // Remove the old [Content_Types].xml file as the
1229 // file will be re-generated
1231 const ::rtl::OUString
aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) );
1233 if ( m_xRootFolder
->hasByName( aContentTypes
) )
1234 m_xRootFolder
->removeByName( aContentTypes
);
1237 // Create a vector to store data for the manifest.xml file
1238 vector
< uno::Sequence
< PropertyValue
> > aManList
;
1240 const OUString
sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
1241 const OUString
sVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) );
1242 const OUString
sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
1244 if ( m_nFormat
== embed::StorageFormats::PACKAGE
)
1246 uno::Sequence
< PropertyValue
> aPropSeq( PKG_SIZE_NOENCR_MNFST
);
1247 aPropSeq
[PKG_MNFST_MEDIATYPE
].Name
= sMediaType
;
1248 aPropSeq
[PKG_MNFST_MEDIATYPE
].Value
<<= m_pRootFolder
->GetMediaType();
1249 aPropSeq
[PKG_MNFST_VERSION
].Name
= sVersion
;
1250 aPropSeq
[PKG_MNFST_VERSION
].Value
<<= m_pRootFolder
->GetVersion();
1251 aPropSeq
[PKG_MNFST_FULLPATH
].Name
= sFullPath
;
1252 aPropSeq
[PKG_MNFST_FULLPATH
].Value
<<= OUString ( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
1254 aManList
.push_back( aPropSeq
);
1257 // Get a random number generator and seed it with current timestamp
1258 // This will be used to generate random salt and initialisation vectors
1259 // for encrypted streams
1261 osl_getSystemTime( &aTime
);
1262 rtlRandomPool aRandomPool
= rtl_random_createPool ();
1263 rtl_random_addBytes ( aRandomPool
, &aTime
, 8 );
1265 // call saveContents ( it will recursively save sub-directories
1266 OUString aEmptyString
;
1267 m_pRootFolder
->saveContents( aEmptyString
, aManList
, aZipOut
, GetEncryptionKey(), aRandomPool
);
1269 // Clean up random pool memory
1270 rtl_random_destroyPool ( aRandomPool
);
1272 if( m_nFormat
== embed::StorageFormats::PACKAGE
)
1274 WriteManifest( aZipOut
, aManList
);
1276 else if( m_nFormat
== embed::StorageFormats::OFOPXML
)
1278 WriteContentTypes( aZipOut
, aManList
);
1286 // Update our References to point to the new temp file
1289 // the case when the original contents were written directly
1292 // in case the stream is based on a file it will implement the following interface
1293 // the call should be used to be sure that the contents are written to the file system
1294 uno::Reference
< io::XAsyncOutputMonitor
> asyncOutputMonitor( xTempOut
, uno::UNO_QUERY
);
1295 if ( asyncOutputMonitor
.is() )
1296 asyncOutputMonitor
->waitForCompletion();
1298 // no need to postpone switching to the new stream since the target was written directly
1299 uno::Reference
< io::XInputStream
> xNewStream
;
1300 if ( m_eMode
== e_IMode_URL
)
1301 xNewStream
= xSink
->getStream()->getInputStream();
1302 else if ( m_eMode
== e_IMode_XStream
&& m_xStream
.is() )
1303 xNewStream
= m_xStream
->getInputStream();
1305 if ( xNewStream
.is() )
1306 ConnectTo( xNewStream
);
1309 catch ( uno::Exception
& )
1313 // no information loss appeares, thus no special handling is required
1314 uno::Any
aCaught( ::cppu::getCaughtException() );
1316 // it is allowed to throw WrappedTargetException
1317 WrappedTargetException aException
;
1318 if ( aCaught
>>= aException
)
1321 throw WrappedTargetException(
1322 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Problem writing the original content!" ) ),
1323 static_cast < OWeakObject
* > ( this ),
1328 // the document is written directly, although it was empty it is important to notify that the writing has failed
1329 // TODO/LATER: let the package be able to recover in this situation
1330 ::rtl::OUString
aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"This package is unusable!" ) );
1331 embed::UseBackupException
aException( aErrTxt
, uno::Reference
< uno::XInterface
>(), ::rtl::OUString() );
1332 throw WrappedTargetException( aErrTxt
,
1333 static_cast < OWeakObject
* > ( this ),
1334 makeAny ( aException
) );
1341 //--------------------------------------------------------
1342 uno::Reference
< XActiveDataStreamer
> ZipPackage::openOriginalForOutput()
1344 // open and truncate the original file
1345 Content
aOriginalContent ( m_aURL
, uno::Reference
< XCommandEnvironment
>() );
1346 uno::Reference
< XActiveDataStreamer
> xSink
= new ActiveDataStreamer
;
1348 if ( m_eMode
== e_IMode_URL
)
1352 sal_Bool bTruncSuccess
= sal_False
;
1357 sal_Int64 aSize
= 0;
1358 Any aAny
= aOriginalContent
.setPropertyValue( OUString::createFromAscii( "Size" ), makeAny( aSize
) );
1359 if( !( aAny
>>= aDetect
) )
1360 bTruncSuccess
= sal_True
;
1366 if( !bTruncSuccess
)
1368 // the file is not accessible
1369 // just try to write an empty stream to it
1371 uno::Reference
< XInputStream
> xTempIn
= new DummyInputStream
; //uno::Reference< XInputStream >( xTempOut, UNO_QUERY );
1372 aOriginalContent
.writeStream( xTempIn
, sal_True
);
1375 OpenCommandArgument2 aArg
;
1376 aArg
.Mode
= OpenMode::DOCUMENT
;
1377 aArg
.Priority
= 0; // unused
1379 aArg
.Properties
= uno::Sequence
< Property
>( 0 ); // unused
1381 aOriginalContent
.executeCommand( OUString::createFromAscii( "open" ), makeAny( aArg
) );
1385 // seems to be nonlocal file
1386 // temporary file mechanics should be used
1393 //--------------------------------------------------------
1394 void SAL_CALL
ZipPackage::commitChanges()
1395 throw( WrappedTargetException
, RuntimeException
)
1397 // lock the component for the time of commiting
1398 ::osl::MutexGuard
aGuard( m_aMutexHolder
->GetMutex() );
1400 if ( m_eMode
== e_IMode_XInputStream
)
1402 IOException aException
;
1403 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"This package is read only!" ) ),
1404 static_cast < OWeakObject
* > ( this ), makeAny ( aException
) );
1407 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR
, "{ ZipPackage::commitChanges" );
1409 // first the writeTempFile is called, if it returns a stream the stream should be written to the target
1410 // if no stream was returned, the file was written directly, nothing should be done
1412 uno::Reference
< io::XInputStream
> xTempInStream
= writeTempFile();
1413 if ( xTempInStream
.is() )
1415 uno::Reference
< io::XSeekable
> xTempSeek( xTempInStream
, uno::UNO_QUERY_THROW
);
1419 xTempSeek
->seek( 0 );
1421 catch( uno::Exception
& r
)
1423 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"Temporary file should be seekable!" ) ),
1424 static_cast < OWeakObject
* > ( this ), makeAny ( r
) );
1427 // connect to the temporary stream
1428 ConnectTo( xTempInStream
);
1430 if ( m_eMode
== e_IMode_XStream
)
1432 // First truncate our output stream
1433 uno::Reference
< XOutputStream
> xOutputStream
;
1435 // preparation for copy step
1438 xOutputStream
= m_xStream
->getOutputStream();
1439 uno::Reference
< XTruncate
> xTruncate ( xOutputStream
, UNO_QUERY
);
1440 if ( !xTruncate
.is() )
1441 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1443 // after successful truncation the original file contents are already lost
1444 xTruncate
->truncate();
1446 catch( uno::Exception
& r
)
1448 throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"This package is read only!" ) ),
1449 static_cast < OWeakObject
* > ( this ), makeAny ( r
) );
1454 // then copy the contents of the tempfile to our output stream
1455 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream
, xOutputStream
);
1456 xOutputStream
->flush();
1457 uno::Reference
< io::XAsyncOutputMonitor
> asyncOutputMonitor(
1458 xOutputStream
, uno::UNO_QUERY
);
1459 if ( asyncOutputMonitor
.is() ) {
1460 asyncOutputMonitor
->waitForCompletion();
1463 catch( uno::Exception
& )
1465 // if anything goes wrong in this block the target file becomes corrupted
1466 // so an exception should be thrown as a notification about it
1467 // and the package must disconnect from the stream
1468 DisconnectFromTargetAndThrowException_Impl( xTempInStream
);
1471 else if ( m_eMode
== e_IMode_URL
)
1473 uno::Reference
< XOutputStream
> aOrigFileStream
;
1474 sal_Bool bCanBeCorrupted
= sal_False
;
1476 if( isLocalFile_Impl( m_aURL
) )
1478 // write directly in case of local file
1479 uno::Reference
< ::com::sun::star::ucb::XSimpleFileAccess
> xSimpleAccess(
1480 m_xFactory
->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ),
1482 OSL_ENSURE( xSimpleAccess
.is(), "Can't instatiate SimpleFileAccess service!\n" );
1483 uno::Reference
< io::XTruncate
> xOrigTruncate
;
1484 if ( xSimpleAccess
.is() )
1488 aOrigFileStream
= xSimpleAccess
->openFileWrite( m_aURL
);
1489 xOrigTruncate
= uno::Reference
< io::XTruncate
>( aOrigFileStream
, uno::UNO_QUERY_THROW
);
1490 // after successful truncation the file is already corrupted
1491 xOrigTruncate
->truncate();
1493 catch( uno::Exception
& )
1497 if( xOrigTruncate
.is() )
1501 ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream
, aOrigFileStream
);
1502 aOrigFileStream
->closeOutput();
1504 catch( uno::Exception
& )
1507 aOrigFileStream
->closeOutput();
1508 } catch ( uno::Exception
& ) {}
1510 aOrigFileStream
= uno::Reference
< XOutputStream
>();
1511 // the original file can already be corrupted
1512 bCanBeCorrupted
= sal_True
;
1517 if( !aOrigFileStream
.is() )
1521 uno::Reference
< XPropertySet
> xPropSet ( xTempInStream
, UNO_QUERY
);
1522 OSL_ENSURE( xPropSet
.is(), "This is a temporary file that must implement XPropertySet!\n" );
1523 if ( !xPropSet
.is() )
1524 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1526 OUString sTargetFolder
= m_aURL
.copy ( 0, m_aURL
.lastIndexOf ( static_cast < sal_Unicode
> ( '/' ) ) );
1527 Content
aContent ( sTargetFolder
, uno::Reference
< XCommandEnvironment
> () );
1530 Any aAny
= xPropSet
->getPropertyValue ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Uri" ) ) );
1534 aInfo
.NameClash
= NameClash::OVERWRITE
;
1535 aInfo
.MoveData
= sal_False
;
1536 aInfo
.SourceURL
= sTempURL
;
1537 aInfo
.NewTitle
= rtl::Uri::decode ( m_aURL
.copy ( 1 + m_aURL
.lastIndexOf ( static_cast < sal_Unicode
> ( '/' ) ) ),
1538 rtl_UriDecodeWithCharset
,
1539 RTL_TEXTENCODING_UTF8
);
1542 // if the file is still not corrupted, it can become after the next step
1543 aContent
.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "transfer" ) ), aAny
);
1545 catch ( ::com::sun::star::uno::Exception
& r
)
1547 if ( bCanBeCorrupted
)
1548 DisconnectFromTargetAndThrowException_Impl( xTempInStream
);
1550 throw WrappedTargetException(
1551 OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"This package may be read only!" ) ),
1552 static_cast < OWeakObject
* > ( this ),
1559 // after successful storing it can be set to false
1560 m_bMediaTypeFallbackUsed
= sal_False
;
1562 RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR
, "} ZipPackage::commitChanges" );
1565 //--------------------------------------------------------
1566 void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Reference
< io::XInputStream
>& xTempStream
)
1568 m_xStream
= uno::Reference
< io::XStream
>( xTempStream
, uno::UNO_QUERY
);
1569 if ( m_xStream
.is() )
1570 m_eMode
= e_IMode_XStream
;
1572 m_eMode
= e_IMode_XInputStream
;
1574 ::rtl::OUString aTempURL
;
1576 uno::Reference
< beans::XPropertySet
> xTempFile( xTempStream
, uno::UNO_QUERY_THROW
);
1577 uno::Any aUrl
= xTempFile
->getPropertyValue( ::rtl::OUString::createFromAscii( "Uri" ) );
1579 xTempFile
->setPropertyValue( ::rtl::OUString::createFromAscii( "RemoveFile" ),
1580 uno::makeAny( sal_False
) );
1582 catch ( uno::Exception
& )
1584 OSL_ENSURE( sal_False
, "These calls are pretty simple, they should not fail!\n" );
1587 ::rtl::OUString
aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX
"This package is read only!" ) );
1588 embed::UseBackupException
aException( aErrTxt
, uno::Reference
< uno::XInterface
>(), aTempURL
);
1589 throw WrappedTargetException( aErrTxt
,
1590 static_cast < OWeakObject
* > ( this ),
1591 makeAny ( aException
) );
1594 //--------------------------------------------------------
1595 const uno::Sequence
< sal_Int8
> ZipPackage::GetEncryptionKey()
1597 uno::Sequence
< sal_Int8
> aResult
;
1599 if ( m_aStorageEncryptionKeys
.getLength() )
1601 ::rtl::OUString aNameToFind
;
1602 if ( m_nStartKeyGenerationID
== xml::crypto::DigestID::SHA256
)
1603 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA256UTF8
;
1604 else if ( m_nStartKeyGenerationID
== xml::crypto::DigestID::SHA1
)
1605 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA1UTF8
;
1607 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"No expected key is provided!" ) ), uno::Reference
< uno::XInterface
>() );
1609 for ( sal_Int32 nInd
= 0; nInd
< m_aStorageEncryptionKeys
.getLength(); nInd
++ )
1610 if ( m_aStorageEncryptionKeys
[nInd
].Name
.equals( aNameToFind
) )
1611 m_aStorageEncryptionKeys
[nInd
].Value
>>= aResult
;
1613 // empty keys are not allowed here
1614 // so it is not important whether there is no key, or the key is empty, it is an error
1615 if ( !aResult
.getLength() )
1616 throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"No expected key is provided!" ) ), uno::Reference
< uno::XInterface
>() );
1619 aResult
= m_aEncryptionKey
;
1624 //--------------------------------------------------------
1625 sal_Bool SAL_CALL
ZipPackage::hasPendingChanges()
1626 throw( RuntimeException
)
1630 //--------------------------------------------------------
1631 Sequence
< ElementChange
> SAL_CALL
ZipPackage::getPendingChanges()
1632 throw( RuntimeException
)
1634 return uno::Sequence
< ElementChange
> ();
1638 * Function to create a new component instance; is needed by factory helper implementation.
1639 * @param xMgr service manager to if the components needs other component instances
1641 uno::Reference
< XInterface
>SAL_CALL
ZipPackage_createInstance(
1642 const uno::Reference
< XMultiServiceFactory
> & xMgr
)
1644 return uno::Reference
< XInterface
>( *new ZipPackage( xMgr
) );
1647 //--------------------------------------------------------
1648 OUString
ZipPackage::static_getImplementationName()
1650 return OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.comp.ZipPackage" ) );
1653 //--------------------------------------------------------
1654 Sequence
< OUString
> ZipPackage::static_getSupportedServiceNames()
1656 uno::Sequence
< OUString
> aNames( 1 );
1657 aNames
[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.Package" ) );
1660 //--------------------------------------------------------
1661 sal_Bool SAL_CALL
ZipPackage::static_supportsService( OUString
const & rServiceName
)
1663 return rServiceName
== getSupportedServiceNames()[0];
1666 //--------------------------------------------------------
1667 OUString
ZipPackage::getImplementationName()
1668 throw ( RuntimeException
)
1670 return static_getImplementationName();
1673 //--------------------------------------------------------
1674 Sequence
< OUString
> ZipPackage::getSupportedServiceNames()
1675 throw ( RuntimeException
)
1677 return static_getSupportedServiceNames();
1679 //--------------------------------------------------------
1680 sal_Bool SAL_CALL
ZipPackage::supportsService( OUString
const & rServiceName
)
1681 throw ( RuntimeException
)
1683 return static_supportsService ( rServiceName
);
1685 //--------------------------------------------------------
1686 uno::Reference
< XSingleServiceFactory
> ZipPackage::createServiceFactory( uno::Reference
< XMultiServiceFactory
> const & rServiceFactory
)
1688 return cppu::createSingleFactory ( rServiceFactory
,
1689 static_getImplementationName(),
1690 ZipPackage_createInstance
,
1691 static_getSupportedServiceNames() );
1694 namespace { struct lcl_ImplId
: public rtl::Static
< ::cppu::OImplementationId
, lcl_ImplId
> {}; }
1696 //--------------------------------------------------------
1697 Sequence
< sal_Int8
> ZipPackage::getUnoTunnelImplementationId( void )
1698 throw ( RuntimeException
)
1700 ::cppu::OImplementationId
&rId
= lcl_ImplId::get();
1701 return rId
.getImplementationId();
1704 //--------------------------------------------------------
1705 sal_Int64 SAL_CALL
ZipPackage::getSomething( const uno::Sequence
< sal_Int8
>& aIdentifier
)
1706 throw( RuntimeException
)
1708 if ( aIdentifier
.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), aIdentifier
.getConstArray(), 16 ) )
1709 return reinterpret_cast < sal_Int64
> ( this );
1713 //--------------------------------------------------------
1714 uno::Reference
< XPropertySetInfo
> SAL_CALL
ZipPackage::getPropertySetInfo()
1715 throw( RuntimeException
)
1717 return uno::Reference
< XPropertySetInfo
> ();
1720 //--------------------------------------------------------
1721 void SAL_CALL
ZipPackage::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
1722 throw( UnknownPropertyException
, PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
1724 if ( m_nFormat
!= embed::StorageFormats::PACKAGE
)
1725 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1727 if ( aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_ENCRYPTED_ENTRIES_PROPERTY
) )
1728 ||aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_NONENCRYPTED_ENTRIES_PROPERTY
) )
1729 ||aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( IS_INCONSISTENT_PROPERTY
) )
1730 ||aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MEDIATYPE_FALLBACK_USED_PROPERTY
) ) )
1731 throw PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1732 else if ( aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY
) ) )
1734 if ( !( aValue
>>= m_aEncryptionKey
) )
1735 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 2 );
1737 m_aStorageEncryptionKeys
.realloc( 0 );
1739 else if ( aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY
) ) )
1741 // this property is only necessary to support raw passwords in storage API;
1742 // because of this support the storage has to operate with more than one key dependent on storage generation algorithm;
1743 // when this support is removed, the storage will get only one key from outside
1744 // TODO/LATER: Get rid of this property as well as of support of raw passwords in storages
1745 uno::Sequence
< beans::NamedValue
> aKeys
;
1746 if ( !( aValue
>>= aKeys
) || ( aKeys
.getLength() && aKeys
.getLength() < 2 ) )
1747 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 2 );
1749 if ( aKeys
.getLength() )
1751 bool bHasSHA256
= false;
1752 bool bHasSHA1
= false;
1753 for ( sal_Int32 nInd
= 0; nInd
< aKeys
.getLength(); nInd
++ )
1755 if ( aKeys
[nInd
].Name
.equals( PACKAGE_ENCRYPTIONDATA_SHA256UTF8
) )
1757 if ( aKeys
[nInd
].Name
.equals( PACKAGE_ENCRYPTIONDATA_SHA1UTF8
) )
1761 if ( !bHasSHA256
|| !bHasSHA1
)
1762 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Expected keys are not provided!" ) ), uno::Reference
< uno::XInterface
>(), 2 );
1765 m_aStorageEncryptionKeys
= aKeys
;
1766 m_aEncryptionKey
.realloc( 0 );
1768 else if ( aPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY
) ) )
1770 uno::Sequence
< beans::NamedValue
> aAlgorithms
;
1771 if ( m_pZipFile
|| !( aValue
>>= aAlgorithms
) || aAlgorithms
.getLength() == 0 )
1773 // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile )
1774 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"unexpected algorithms list is provided." ) ), uno::Reference
< uno::XInterface
>(), 2 );
1777 for ( sal_Int32 nInd
= 0; nInd
< aAlgorithms
.getLength(); nInd
++ )
1779 if ( aAlgorithms
[nInd
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StartKeyGenerationAlgorithm" ) ) )
1782 if ( !( aAlgorithms
[nInd
].Value
>>= nID
)
1783 || ( nID
!= xml::crypto::DigestID::SHA256
&& nID
!= xml::crypto::DigestID::SHA1
) )
1784 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Unexpected start key generation algorithm is provided!" ) ), uno::Reference
< uno::XInterface
>(), 2 );
1786 m_nStartKeyGenerationID
= nID
;
1788 else if ( aAlgorithms
[nInd
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionAlgorithm" ) ) )
1791 if ( !( aAlgorithms
[nInd
].Value
>>= nID
)
1792 || ( nID
!= xml::crypto::CipherID::AES_CBC_W3C_PADDING
&& nID
!= xml::crypto::CipherID::BLOWFISH_CFB_8
) )
1793 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Unexpected start key generation algorithm is provided!" ) ), uno::Reference
< uno::XInterface
>(), 2 );
1795 m_nCommonEncryptionID
= nID
;
1797 else if ( aAlgorithms
[nInd
].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ChecksumAlgorithm" ) ) )
1800 if ( !( aAlgorithms
[nInd
].Value
>>= nID
)
1801 || ( nID
!= xml::crypto::DigestID::SHA1_1K
&& nID
!= xml::crypto::DigestID::SHA256_1K
) )
1802 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"Unexpected start key generation algorithm is provided!" ) ), uno::Reference
< uno::XInterface
>(), 2 );
1804 m_nChecksumDigestID
= nID
;
1808 OSL_ENSURE( sal_False
, "Unexpected encryption algorithm is provided!" );
1809 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
"unexpected algorithms list is provided." ) ), uno::Reference
< uno::XInterface
>(), 2 );
1814 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1817 //--------------------------------------------------------
1818 Any SAL_CALL
ZipPackage::getPropertyValue( const OUString
& PropertyName
)
1819 throw( UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1821 // TODO/LATER: Activate the check when zip-ucp is ready
1822 // if ( m_nFormat != embed::StorageFormats::PACKAGE )
1823 // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
1826 if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( ENCRYPTION_KEY_PROPERTY
) ) )
1828 aAny
<<= m_aEncryptionKey
;
1831 else if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY
) ) )
1833 ::comphelper::SequenceAsHashMap aAlgorithms
;
1834 aAlgorithms
[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ] <<= m_nStartKeyGenerationID
;
1835 aAlgorithms
[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionAlgorithm" ) ) ] <<= m_nCommonEncryptionID
;
1836 aAlgorithms
[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChecksumAlgorithm" ) ) ] <<= m_nChecksumDigestID
;
1837 aAny
<<= aAlgorithms
.getAsConstNamedValueList();
1840 if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( STORAGE_ENCRYPTION_KEYS_PROPERTY
) ) )
1842 aAny
<<= m_aStorageEncryptionKeys
;
1845 else if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_ENCRYPTED_ENTRIES_PROPERTY
) ) )
1847 aAny
<<= m_bHasEncryptedEntries
;
1850 else if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_NONENCRYPTED_ENTRIES_PROPERTY
) ) )
1852 aAny
<<= m_bHasNonEncryptedEntries
;
1855 else if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( IS_INCONSISTENT_PROPERTY
) ) )
1857 aAny
<<= m_bInconsistent
;
1860 else if ( PropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( MEDIATYPE_FALLBACK_USED_PROPERTY
) ) )
1862 aAny
<<= m_bMediaTypeFallbackUsed
;
1865 throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
1867 //--------------------------------------------------------
1868 void SAL_CALL
ZipPackage::addPropertyChangeListener( const OUString
& /*aPropertyName*/, const uno::Reference
< XPropertyChangeListener
>& /*xListener*/ )
1869 throw( UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1872 //--------------------------------------------------------
1873 void SAL_CALL
ZipPackage::removePropertyChangeListener( const OUString
& /*aPropertyName*/, const uno::Reference
< XPropertyChangeListener
>& /*aListener*/ )
1874 throw( UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1877 //--------------------------------------------------------
1878 void SAL_CALL
ZipPackage::addVetoableChangeListener( const OUString
& /*PropertyName*/, const uno::Reference
< XVetoableChangeListener
>& /*aListener*/ )
1879 throw( UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
1882 //--------------------------------------------------------
1883 void SAL_CALL
ZipPackage::removeVetoableChangeListener( const OUString
& /*PropertyName*/, const uno::Reference
< XVetoableChangeListener
>& /*aListener*/ )
1884 throw( UnknownPropertyException
, WrappedTargetException
, RuntimeException
)