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