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 : #include <ZipPackageStream.hxx>
21 :
22 : #include <com/sun/star/beans/PropertyValue.hpp>
23 : #include <com/sun/star/packages/zip/ZipConstants.hpp>
24 : #include <com/sun/star/embed/StorageFormats.hpp>
25 : #include <com/sun/star/packages/zip/ZipIOException.hpp>
26 : #include <com/sun/star/io/TempFile.hpp>
27 : #include <com/sun/star/io/XInputStream.hpp>
28 : #include <com/sun/star/io/XOutputStream.hpp>
29 : #include <com/sun/star/io/XStream.hpp>
30 : #include <com/sun/star/io/XSeekable.hpp>
31 : #include <com/sun/star/xml/crypto/DigestID.hpp>
32 : #include <com/sun/star/xml/crypto/CipherID.hpp>
33 :
34 : #include <string.h>
35 :
36 : #include <CRC32.hxx>
37 : #include <ZipOutputEntry.hxx>
38 : #include <ZipOutputStream.hxx>
39 : #include <ZipPackage.hxx>
40 : #include <ZipPackageFolder.hxx>
41 : #include <ZipFile.hxx>
42 : #include <EncryptedDataHeader.hxx>
43 : #include <osl/diagnose.h>
44 : #include "wrapstreamforshare.hxx"
45 :
46 : #include <comphelper/processfactory.hxx>
47 : #include <comphelper/seekableinput.hxx>
48 : #include <comphelper/storagehelper.hxx>
49 : #include <cppuhelper/exc_hlp.hxx>
50 : #include <cppuhelper/supportsservice.hxx>
51 : #include <cppuhelper/typeprovider.hxx>
52 :
53 : #include <rtl/instance.hxx>
54 : #include <rtl/random.h>
55 :
56 : #include <PackageConstants.hxx>
57 :
58 : using namespace com::sun::star::packages::zip::ZipConstants;
59 : using namespace com::sun::star::packages::zip;
60 : using namespace com::sun::star::uno;
61 : using namespace com::sun::star::lang;
62 : using namespace com::sun::star;
63 : using namespace cppu;
64 :
65 : #if OSL_DEBUG_LEVEL > 0
66 : #define THROW_WHERE SAL_WHERE
67 : #else
68 : #define THROW_WHERE ""
69 : #endif
70 :
71 : namespace { struct lcl_CachedImplId : public rtl::Static< cppu::OImplementationId, lcl_CachedImplId > {}; }
72 :
73 189082 : ::com::sun::star::uno::Sequence < sal_Int8 > ZipPackageStream::static_getImplementationId()
74 : {
75 189082 : return lcl_CachedImplId::get().getImplementationId();
76 : }
77 :
78 239013 : ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
79 : const uno::Reference< XComponentContext >& xContext,
80 : sal_Int32 nFormat,
81 : bool bAllowRemoveOnInsert )
82 : : m_rZipPackage( rNewPackage )
83 : , m_bToBeCompressed ( true )
84 : , m_bToBeEncrypted ( false )
85 : , m_bHaveOwnKey ( false )
86 : , m_bIsEncrypted ( false )
87 : , m_nImportedStartKeyAlgorithm( 0 )
88 : , m_nImportedEncryptionAlgorithm( 0 )
89 : , m_nImportedChecksumAlgorithm( 0 )
90 : , m_nImportedDerivedKeySize( 0 )
91 : , m_nStreamMode( PACKAGE_STREAM_NOTSET )
92 : , m_nMagicalHackPos( 0 )
93 : , m_nMagicalHackSize( 0 )
94 : , m_nOwnStreamOrigSize( 0 )
95 : , m_bHasSeekable( false )
96 : , m_bCompressedIsSetFromOutside( false )
97 : , m_bFromManifest( false )
98 : , m_bUseWinEncoding( false )
99 239013 : , m_bRawStream( false )
100 : {
101 239013 : m_xContext = xContext;
102 239013 : m_nFormat = nFormat;
103 239013 : mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
104 239013 : SetFolder ( false );
105 239013 : aEntry.nVersion = -1;
106 239013 : aEntry.nFlag = 0;
107 239013 : aEntry.nMethod = -1;
108 239013 : aEntry.nTime = -1;
109 239013 : aEntry.nCrc = -1;
110 239013 : aEntry.nCompressedSize = -1;
111 239013 : aEntry.nSize = -1;
112 239013 : aEntry.nOffset = -1;
113 239013 : aEntry.nPathLen = -1;
114 239013 : aEntry.nExtraLen = -1;
115 239013 : }
116 :
117 477850 : ZipPackageStream::~ZipPackageStream()
118 : {
119 477850 : }
120 :
121 211545 : void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
122 : {
123 211545 : aEntry.nVersion = rInEntry.nVersion;
124 211545 : aEntry.nFlag = rInEntry.nFlag;
125 211545 : aEntry.nMethod = rInEntry.nMethod;
126 211545 : aEntry.nTime = rInEntry.nTime;
127 211545 : aEntry.nCrc = rInEntry.nCrc;
128 211545 : aEntry.nCompressedSize = rInEntry.nCompressedSize;
129 211545 : aEntry.nSize = rInEntry.nSize;
130 211545 : aEntry.nOffset = rInEntry.nOffset;
131 211545 : aEntry.sPath = rInEntry.sPath;
132 211545 : aEntry.nPathLen = rInEntry.nPathLen;
133 211545 : aEntry.nExtraLen = rInEntry.nExtraLen;
134 :
135 211545 : if ( aEntry.nMethod == STORED )
136 6947 : m_bToBeCompressed = false;
137 211545 : }
138 :
139 10065 : void ZipPackageStream::CloseOwnStreamIfAny()
140 : {
141 10065 : if ( m_xStream.is() )
142 : {
143 10065 : m_xStream->closeInput();
144 10065 : m_xStream = uno::Reference< io::XInputStream >();
145 10065 : m_bHasSeekable = false;
146 : }
147 10065 : }
148 :
149 23721 : uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
150 : {
151 23721 : if ( !m_bHasSeekable && m_xStream.is() )
152 : {
153 : // The package component requires that every stream either be FROM a package or it must support XSeekable!
154 : // The only exception is a nonseekable stream that is provided only for storing, if such a stream
155 : // is accessed before commit it MUST be wrapped.
156 : // Wrap the stream in case it is not seekable
157 10616 : m_xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xStream, m_xContext );
158 10616 : uno::Reference< io::XSeekable > xSeek( m_xStream, UNO_QUERY );
159 10616 : if ( !xSeek.is() )
160 0 : throw RuntimeException( THROW_WHERE "The stream must support XSeekable!" );
161 :
162 10616 : m_bHasSeekable = true;
163 : }
164 :
165 23721 : return m_xStream;
166 : }
167 :
168 0 : uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
169 : {
170 0 : if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
171 0 : throw io::IOException(THROW_WHERE );
172 :
173 0 : if ( m_xBaseEncryptionData.is() )
174 0 : throw ZipIOException(THROW_WHERE "Encrypted stream without encryption data!" );
175 :
176 0 : uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
177 0 : if ( !xSeek.is() )
178 0 : throw ZipIOException(THROW_WHERE "The stream must be seekable!" );
179 :
180 : // skip header
181 0 : xSeek->seek( n_ConstHeaderSize + m_xBaseEncryptionData->m_aInitVector.getLength() +
182 0 : m_xBaseEncryptionData->m_aSalt.getLength() + m_xBaseEncryptionData->m_aDigest.getLength() );
183 :
184 : // create temporary stream
185 0 : uno::Reference < io::XTempFile > xTempFile = io::TempFile::create(m_xContext);
186 0 : uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
187 0 : uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();;
188 0 : uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
189 :
190 : // copy the raw stream to the temporary file starting from the current position
191 0 : ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
192 0 : xTempOut->closeOutput();
193 0 : xTempSeek->seek( 0 );
194 :
195 0 : return xTempIn;
196 : }
197 :
198 114 : sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
199 : {
200 114 : return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : m_rZipPackage.GetEncAlgID();
201 : }
202 :
203 4 : sal_Int32 ZipPackageStream::GetBlockSize() const
204 : {
205 4 : return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
206 : }
207 :
208 59024 : ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
209 : {
210 59024 : ::rtl::Reference< EncryptionData > xResult;
211 59024 : if ( m_xBaseEncryptionData.is() )
212 390 : xResult = new EncryptionData(
213 110 : *m_xBaseEncryptionData,
214 : GetEncryptionKey( bUseWinEncoding ),
215 : GetEncryptionAlgorithm(),
216 85 : m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : m_rZipPackage.GetChecksumAlgID(),
217 85 : m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : m_rZipPackage.GetDefaultDerivedKeySize(),
218 110 : GetStartKeyGenID() );
219 :
220 59024 : return xResult;
221 : }
222 :
223 110 : uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
224 : {
225 110 : uno::Sequence< sal_Int8 > aResult;
226 110 : sal_Int32 nKeyGenID = GetStartKeyGenID();
227 110 : bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
228 :
229 110 : if ( m_bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
230 : {
231 22 : OUString aNameToFind;
232 22 : if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
233 14 : aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
234 8 : else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
235 : {
236 8 : aNameToFind = bUseWinEncoding ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252) : OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8);
237 : }
238 : else
239 0 : throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
240 :
241 88 : for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
242 66 : if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
243 22 : m_aStorageEncryptionKeys[nInd].Value >>= aResult;
244 :
245 : // empty keys are not allowed here
246 : // so it is not important whether there is no key, or the key is empty, it is an error
247 22 : if ( !aResult.getLength() )
248 0 : throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
249 : }
250 : else
251 88 : aResult = m_aEncryptionKey;
252 :
253 110 : if ( !aResult.getLength() || !m_bHaveOwnKey )
254 88 : aResult = m_rZipPackage.GetEncryptionKey();
255 :
256 110 : return aResult;
257 : }
258 :
259 220 : sal_Int32 ZipPackageStream::GetStartKeyGenID()
260 : {
261 : // generally should all the streams use the same Start Key
262 : // but if raw copy without password takes place, we should preserve the imported algorithm
263 220 : return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : m_rZipPackage.GetStartKeyGenID();
264 : }
265 :
266 0 : uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( bool bAddHeaderForEncr )
267 : {
268 0 : if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !m_bToBeEncrypted ) )
269 0 : throw packages::NoEncryptionException(THROW_WHERE );
270 :
271 0 : Sequence< sal_Int8 > aKey;
272 :
273 0 : if ( m_bToBeEncrypted )
274 : {
275 0 : aKey = GetEncryptionKey();
276 0 : if ( !aKey.getLength() )
277 0 : throw packages::NoEncryptionException(THROW_WHERE );
278 : }
279 :
280 : try
281 : {
282 : // create temporary file
283 : uno::Reference < io::XStream > xTempStream(
284 : io::TempFile::create(m_xContext),
285 0 : uno::UNO_QUERY_THROW );
286 :
287 : // create a package based on it
288 0 : ZipPackage* pPackage = new ZipPackage( m_xContext );
289 0 : uno::Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
290 0 : if ( !xPackageAsFactory.is() )
291 0 : throw RuntimeException(THROW_WHERE );
292 :
293 0 : Sequence< Any > aArgs( 1 );
294 0 : aArgs[0] <<= xTempStream;
295 0 : pPackage->initialize( aArgs );
296 :
297 : // create a new package stream
298 0 : uno::Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
299 0 : if ( !xNewPackStream.is() )
300 0 : throw RuntimeException(THROW_WHERE );
301 :
302 0 : xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
303 0 : new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() ) ) );
304 :
305 0 : uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
306 0 : if ( !xNewPSProps.is() )
307 0 : throw RuntimeException(THROW_WHERE );
308 :
309 : // copy all the properties of this stream to the new stream
310 0 : xNewPSProps->setPropertyValue("MediaType", makeAny( msMediaType ) );
311 0 : xNewPSProps->setPropertyValue("Compressed", makeAny( m_bToBeCompressed ) );
312 0 : if ( m_bToBeEncrypted )
313 : {
314 0 : xNewPSProps->setPropertyValue(ENCRYPTION_KEY_PROPERTY, makeAny( aKey ) );
315 0 : xNewPSProps->setPropertyValue("Encrypted", makeAny( true ) );
316 : }
317 :
318 : // insert a new stream in the package
319 0 : uno::Reference< XUnoTunnel > xTunnel;
320 0 : Any aRoot = pPackage->getByHierarchicalName("/");
321 0 : aRoot >>= xTunnel;
322 0 : uno::Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
323 0 : if ( !xRootNameContainer.is() )
324 0 : throw RuntimeException(THROW_WHERE );
325 :
326 0 : uno::Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
327 0 : xRootNameContainer->insertByName("dummy", makeAny( xNPSTunnel ) );
328 :
329 : // commit the temporary package
330 0 : pPackage->commitChanges();
331 :
332 : // get raw stream from the temporary package
333 0 : uno::Reference< io::XInputStream > xInRaw;
334 0 : if ( bAddHeaderForEncr )
335 0 : xInRaw = xNewPackStream->getRawStream();
336 : else
337 0 : xInRaw = xNewPackStream->getPlainRawStream();
338 :
339 : // create another temporary file
340 : uno::Reference < io::XOutputStream > xTempOut(
341 : io::TempFile::create(m_xContext),
342 0 : uno::UNO_QUERY_THROW );
343 0 : uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW );
344 0 : uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
345 :
346 : // copy the raw stream to the temporary file
347 0 : ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
348 0 : xTempOut->closeOutput();
349 0 : xTempSeek->seek( 0 );
350 :
351 : // close raw stream, package stream and folder
352 0 : xInRaw = uno::Reference< io::XInputStream >();
353 0 : xNewPSProps = uno::Reference< XPropertySet >();
354 0 : xNPSTunnel = uno::Reference< XUnoTunnel >();
355 0 : xNewPackStream = uno::Reference< XDataSinkEncrSupport >();
356 0 : xTunnel = uno::Reference< XUnoTunnel >();
357 0 : xRootNameContainer = uno::Reference< container::XNameContainer >();
358 :
359 : // return the stream representing the first temporary file
360 0 : return xTempIn;
361 : }
362 0 : catch ( RuntimeException& )
363 : {
364 0 : throw;
365 : }
366 0 : catch ( Exception& )
367 : {
368 : }
369 :
370 0 : throw io::IOException(THROW_WHERE );
371 : }
372 :
373 1 : bool ZipPackageStream::ParsePackageRawStream()
374 : {
375 : OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
376 :
377 1 : if ( !GetOwnSeekStream().is() )
378 0 : return false;
379 :
380 1 : bool bOk = false;
381 :
382 1 : ::rtl::Reference< BaseEncryptionData > xTempEncrData;
383 1 : sal_Int32 nMagHackSize = 0;
384 2 : Sequence < sal_Int8 > aHeader ( 4 );
385 :
386 : try
387 : {
388 1 : if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
389 : {
390 1 : const sal_Int8 *pHeader = aHeader.getConstArray();
391 2 : sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
392 2 : ( pHeader [1] & 0xFF ) << 8 |
393 2 : ( pHeader [2] & 0xFF ) << 16 |
394 2 : ( pHeader [3] & 0xFF ) << 24;
395 1 : if ( nHeader == n_ConstHeader )
396 : {
397 : // this is one of our god-awful, but extremely devious hacks, everyone cheer
398 1 : xTempEncrData = new BaseEncryptionData;
399 :
400 1 : OUString aMediaType;
401 1 : sal_Int32 nEncAlgorithm = 0;
402 1 : sal_Int32 nChecksumAlgorithm = 0;
403 1 : sal_Int32 nDerivedKeySize = 0;
404 1 : sal_Int32 nStartKeyGenID = 0;
405 1 : if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
406 : {
407 : // We'll want to skip the data we've just read, so calculate how much we just read
408 : // and remember it
409 1 : m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
410 1 : + xTempEncrData->m_aInitVector.getLength()
411 1 : + xTempEncrData->m_aDigest.getLength()
412 1 : + aMediaType.getLength() * sizeof( sal_Unicode );
413 1 : m_nImportedEncryptionAlgorithm = nEncAlgorithm;
414 1 : m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
415 1 : m_nImportedDerivedKeySize = nDerivedKeySize;
416 1 : m_nImportedStartKeyAlgorithm = nStartKeyGenID;
417 1 : m_nMagicalHackSize = nMagHackSize;
418 1 : msMediaType = aMediaType;
419 :
420 1 : bOk = true;
421 1 : }
422 : }
423 : }
424 : }
425 0 : catch( Exception& )
426 : {
427 : }
428 :
429 1 : if ( !bOk )
430 : {
431 : // the provided stream is not a raw stream
432 0 : return false;
433 : }
434 :
435 1 : m_xBaseEncryptionData = xTempEncrData;
436 1 : SetIsEncrypted ( true );
437 : // it's already compressed and encrypted
438 1 : m_bToBeEncrypted = m_bToBeCompressed = false;
439 :
440 2 : return true;
441 : }
442 :
443 9885 : static void deflateZipEntry(ZipOutputEntry *pZipEntry,
444 : const uno::Reference< io::XInputStream >& xInStream)
445 : {
446 9885 : sal_Int32 nLength = 0;
447 9885 : uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
448 10221 : do
449 : {
450 10221 : nLength = xInStream->readBytes(aSeq, n_ConstBufferSize);
451 10221 : if (nLength != n_ConstBufferSize)
452 9885 : aSeq.realloc(nLength);
453 :
454 10221 : pZipEntry->write(aSeq);
455 : }
456 : while (nLength == n_ConstBufferSize);
457 9885 : pZipEntry->closeEntry();
458 9885 : }
459 :
460 88 : class DeflateThread: public comphelper::ThreadTask
461 : {
462 : ZipOutputEntry *mpEntry;
463 : uno::Reference< io::XInputStream > mxInStream;
464 :
465 : public:
466 44 : DeflateThread( ZipOutputEntry *pEntry,
467 : const uno::Reference< io::XInputStream >& xInStream )
468 : : mpEntry(pEntry)
469 44 : , mxInStream(xInStream)
470 44 : {}
471 :
472 : private:
473 44 : virtual void doWork() SAL_OVERRIDE
474 : {
475 : try
476 : {
477 44 : deflateZipEntry(mpEntry, mxInStream);
478 44 : mxInStream.clear();
479 : }
480 0 : catch (const uno::Exception&)
481 : {
482 0 : mpEntry->setParallelDeflateException(::cppu::getCaughtException());
483 : }
484 44 : }
485 : };
486 :
487 180 : static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< io::XInputStream> & rStream )
488 : {
489 : // It's very annoying that we have to do this, but lots of zip packages
490 : // don't allow data descriptors for STORED streams, meaning we have to
491 : // know the size and CRC32 of uncompressed streams before we actually
492 : // write them !
493 180 : CRC32 aCRC32;
494 180 : rEntry.nMethod = STORED;
495 180 : rEntry.nCompressedSize = rEntry.nSize = aCRC32.updateStream ( rStream );
496 180 : rEntry.nCrc = aCRC32.getValue();
497 180 : }
498 :
499 10167 : bool ZipPackageStream::saveChild(
500 : const OUString &rPath,
501 : std::vector < uno::Sequence < beans::PropertyValue > > &rManList,
502 : ZipOutputStream & rZipOut,
503 : const uno::Sequence < sal_Int8 >& rEncryptionKey,
504 : const rtlRandomPool &rRandomPool)
505 : {
506 10167 : bool bSuccess = true;
507 :
508 10167 : const OUString sMediaTypeProperty ("MediaType");
509 20334 : const OUString sVersionProperty ("Version");
510 20334 : const OUString sFullPathProperty ("FullPath");
511 20334 : const OUString sInitialisationVectorProperty ("InitialisationVector");
512 20334 : const OUString sSaltProperty ("Salt");
513 20334 : const OUString sIterationCountProperty ("IterationCount");
514 20334 : const OUString sSizeProperty ("Size");
515 20334 : const OUString sDigestProperty ("Digest");
516 20334 : const OUString sEncryptionAlgProperty ("EncryptionAlgorithm");
517 20334 : const OUString sStartKeyAlgProperty ("StartKeyAlgorithm");
518 20334 : const OUString sDigestAlgProperty ("DigestAlgorithm");
519 20334 : const OUString sDerivedKeySizeProperty ("DerivedKeySize");
520 :
521 20334 : uno::Sequence < beans::PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
522 :
523 : // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
524 : // and be deleted in the ZipOutputStream destructor
525 20334 : std::unique_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry );
526 10167 : ZipEntry* pTempEntry = pAutoTempEntry.get();
527 :
528 : // In case the entry we are reading is also the entry we are writing, we will
529 : // store the ZipEntry data in pTempEntry
530 :
531 10167 : ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry );
532 10167 : pTempEntry->sPath = rPath;
533 10167 : pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
534 :
535 10167 : const bool bToBeEncrypted = m_bToBeEncrypted && (rEncryptionKey.getLength() || m_bHaveOwnKey);
536 10167 : const bool bToBeCompressed = bToBeEncrypted || m_bToBeCompressed;
537 :
538 10167 : aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
539 10167 : aPropSet[PKG_MNFST_MEDIATYPE].Value <<= GetMediaType( );
540 10167 : aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
541 10167 : aPropSet[PKG_MNFST_VERSION].Value <<= OUString(); // no version is stored for streams currently
542 10167 : aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
543 10167 : aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
544 :
545 : OSL_ENSURE( m_nStreamMode != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
546 :
547 10167 : m_bRawStream = false;
548 10167 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
549 0 : m_bRawStream = ParsePackageRawStream();
550 10167 : else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
551 1 : m_bRawStream = true;
552 :
553 10167 : bool bParallelDeflate = false;
554 10167 : bool bTransportOwnEncrStreamAsRaw = false;
555 : // During the storing the original size of the stream can be changed
556 : // TODO/LATER: get rid of this hack
557 10167 : m_nOwnStreamOrigSize = m_bRawStream ? m_nMagicalHackSize : aEntry.nSize;
558 :
559 10167 : bool bUseNonSeekableAccess = false;
560 20334 : uno::Reference < io::XInputStream > xStream;
561 10167 : if ( !IsPackageMember() && !m_bRawStream && !bToBeEncrypted && bToBeCompressed )
562 : {
563 : // the stream is not a package member, not a raw stream,
564 : // it should not be encrypted and it should be compressed,
565 : // in this case nonseekable access can be used
566 :
567 9950 : xStream = m_xStream;
568 9950 : uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
569 :
570 9950 : bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
571 : }
572 :
573 10167 : if ( !bUseNonSeekableAccess )
574 : {
575 10155 : xStream = getRawData();
576 :
577 10155 : if ( !xStream.is() )
578 : {
579 : OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
580 0 : bSuccess = false;
581 0 : return bSuccess;
582 : }
583 :
584 10155 : uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
585 : try
586 : {
587 10155 : if ( xSeek.is() )
588 : {
589 : // If the stream is a raw one, then we should be positioned
590 : // at the beginning of the actual data
591 10053 : if ( !bToBeCompressed || m_bRawStream )
592 : {
593 : // The raw stream can neither be encrypted nor connected
594 : OSL_ENSURE( !m_bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
595 111 : xSeek->seek ( m_bRawStream ? m_nMagicalHackPos : 0 );
596 111 : ImplSetStoredData ( *pTempEntry, xStream );
597 :
598 : // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
599 : }
600 9942 : else if ( bToBeEncrypted )
601 : {
602 : // this is the correct original size
603 4 : pTempEntry->nSize = xSeek->getLength();
604 4 : m_nOwnStreamOrigSize = pTempEntry->nSize;
605 : }
606 :
607 10053 : xSeek->seek ( 0 );
608 : }
609 : else
610 : {
611 : // Okay, we don't have an xSeekable stream. This is possibly bad.
612 : // check if it's one of our own streams, if it is then we know that
613 : // each time we ask for it we'll get a new stream that will be
614 : // at position zero...otherwise, assert and skip this stream...
615 102 : if ( IsPackageMember() )
616 : {
617 : // if the password has been changed than the stream should not be package member any more
618 102 : if ( m_bIsEncrypted && m_bToBeEncrypted )
619 : {
620 : // Should be handled close to the raw stream handling
621 0 : bTransportOwnEncrStreamAsRaw = true;
622 0 : pTempEntry->nMethod = STORED;
623 :
624 : // TODO/LATER: get rid of this situation
625 : // this size should be different from the one that will be stored in manifest.xml
626 : // it is used in storing algorithms and after storing the correct size will be set
627 0 : pTempEntry->nSize = pTempEntry->nCompressedSize;
628 : }
629 : }
630 : else
631 : {
632 0 : bSuccess = false;
633 0 : return bSuccess;
634 : }
635 : }
636 : }
637 0 : catch ( uno::Exception& )
638 : {
639 0 : bSuccess = false;
640 0 : return bSuccess;
641 : }
642 :
643 10155 : if ( bToBeEncrypted || m_bRawStream || bTransportOwnEncrStreamAsRaw )
644 : {
645 5 : if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
646 : {
647 8 : uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( GetBlockSize() );
648 4 : rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
649 4 : rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
650 4 : sal_Int32 nIterationCount = 1024;
651 :
652 4 : if ( !m_bHaveOwnKey )
653 : {
654 4 : m_aEncryptionKey = rEncryptionKey;
655 4 : m_aStorageEncryptionKeys.realloc( 0 );
656 : }
657 :
658 4 : setInitialisationVector ( aVector );
659 4 : setSalt ( aSalt );
660 8 : setIterationCount ( nIterationCount );
661 : }
662 :
663 : // last property is digest, which is inserted later if we didn't have
664 : // a magic header
665 5 : aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
666 :
667 5 : aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
668 5 : aPropSet[PKG_MNFST_INIVECTOR].Value <<= m_xBaseEncryptionData->m_aInitVector;
669 5 : aPropSet[PKG_MNFST_SALT].Name = sSaltProperty;
670 5 : aPropSet[PKG_MNFST_SALT].Value <<= m_xBaseEncryptionData->m_aSalt;
671 5 : aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
672 5 : aPropSet[PKG_MNFST_ITERATION].Value <<= m_xBaseEncryptionData->m_nIterationCount;
673 :
674 : // Need to store the uncompressed size in the manifest
675 : OSL_ENSURE( m_nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
676 5 : aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
677 5 : aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= m_nOwnStreamOrigSize;
678 :
679 5 : if ( m_bRawStream || bTransportOwnEncrStreamAsRaw )
680 : {
681 1 : ::rtl::Reference< EncryptionData > xEncData = GetEncryptionData();
682 1 : if ( !xEncData.is() )
683 0 : throw uno::RuntimeException();
684 :
685 1 : aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
686 1 : aPropSet[PKG_MNFST_DIGEST].Value <<= m_xBaseEncryptionData->m_aDigest;
687 1 : aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
688 1 : aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
689 1 : aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
690 1 : aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
691 1 : aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
692 1 : aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
693 1 : aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
694 1 : aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
695 : }
696 10155 : }
697 : }
698 :
699 : // If the entry is already stored in the zip file in the format we
700 : // want for this write...copy it raw
701 20334 : if ( !bUseNonSeekableAccess
702 10270 : && ( m_bRawStream || bTransportOwnEncrStreamAsRaw
703 10154 : || ( IsPackageMember() && !bToBeEncrypted
704 102 : && ( ( aEntry.nMethod == DEFLATED && bToBeCompressed )
705 30 : || ( aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
706 : {
707 : // If it's a PackageMember, then it's an unbuffered stream and we need
708 : // to get a new version of it as we can't seek backwards.
709 103 : if ( IsPackageMember() )
710 : {
711 102 : xStream = getRawData();
712 102 : if ( !xStream.is() )
713 : {
714 : // Make sure that we actually _got_ a new one !
715 0 : bSuccess = false;
716 0 : return bSuccess;
717 : }
718 : }
719 :
720 : try
721 : {
722 103 : if ( m_bRawStream )
723 1 : xStream->skipBytes( m_nMagicalHackPos );
724 :
725 103 : ZipOutputStream::setEntry(pTempEntry);
726 103 : rZipOut.writeLOC(pTempEntry);
727 : // the entry is provided to the ZipOutputStream that will delete it
728 103 : pAutoTempEntry.release();
729 :
730 103 : uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
731 : sal_Int32 nLength;
732 :
733 107 : do
734 : {
735 107 : nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
736 107 : if (nLength != n_ConstBufferSize)
737 103 : aSeq.realloc(nLength);
738 :
739 107 : rZipOut.rawWrite(aSeq);
740 : }
741 : while ( nLength == n_ConstBufferSize );
742 :
743 103 : rZipOut.rawCloseEntry();
744 : }
745 0 : catch ( ZipException& )
746 : {
747 0 : bSuccess = false;
748 : }
749 0 : catch ( io::IOException& )
750 : {
751 0 : bSuccess = false;
752 : }
753 : }
754 : else
755 : {
756 : // This stream is defenitly not a raw stream
757 :
758 : // If nonseekable access is used the stream should be at the beginning and
759 : // is useless after the storing. Thus if the storing fails the package should
760 : // be thrown away ( as actually it is done currently )!
761 : // To allow to reuse the package after the error, the optimization must be removed!
762 :
763 : // If it's a PackageMember, then our previous reference held a 'raw' stream
764 : // so we need to re-get it, unencrypted, uncompressed and positioned at the
765 : // beginning of the stream
766 10064 : if ( IsPackageMember() )
767 : {
768 0 : xStream = getInputStream();
769 0 : if ( !xStream.is() )
770 : {
771 : // Make sure that we actually _got_ a new one !
772 0 : bSuccess = false;
773 0 : return bSuccess;
774 : }
775 : }
776 :
777 10064 : if ( bToBeCompressed )
778 : {
779 9954 : pTempEntry->nMethod = DEFLATED;
780 9954 : pTempEntry->nCrc = -1;
781 9954 : pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
782 : }
783 :
784 10064 : uno::Reference< io::XSeekable > xSeek(xStream, uno::UNO_QUERY);
785 : // It's not worth to deflate jpegs to save ~1% in a slow process
786 : // Unfortunately, does not work for streams protected by password
787 10064 : if (xSeek.is() && msMediaType.endsWith("/jpeg") && !m_bToBeEncrypted)
788 : {
789 69 : ImplSetStoredData(*pTempEntry, xStream);
790 69 : xSeek->seek(0);
791 : }
792 :
793 : try
794 : {
795 10064 : ZipOutputStream::setEntry(pTempEntry);
796 : // the entry is provided to the ZipOutputStream that will delete it
797 10064 : pAutoTempEntry.release();
798 :
799 10064 : if (pTempEntry->nMethod == STORED)
800 : {
801 : sal_Int32 nLength;
802 179 : uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
803 179 : rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
804 358 : do
805 : {
806 358 : nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
807 358 : if (nLength != n_ConstBufferSize)
808 179 : aSeq.realloc(nLength);
809 :
810 358 : rZipOut.rawWrite(aSeq);
811 : }
812 : while ( nLength == n_ConstBufferSize );
813 179 : rZipOut.rawCloseEntry(bToBeEncrypted);
814 : }
815 : else
816 : {
817 9885 : bParallelDeflate = true;
818 : // Do not deflate small streams in a thread
819 9885 : if (xSeek.is() && xSeek->getLength() < 100000)
820 9841 : bParallelDeflate = false;
821 :
822 9885 : if (bParallelDeflate)
823 : {
824 : // Start a new thread deflating this zip entry
825 : ZipOutputEntry *pZipEntry = new ZipOutputEntry(
826 : css::uno::Reference<css::io::XOutputStream>(),
827 44 : m_xContext, *pTempEntry, this, bToBeEncrypted);
828 44 : rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(pZipEntry, xStream) );
829 : }
830 : else
831 : {
832 9841 : rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
833 9841 : ZipOutputEntry aZipEntry(rZipOut.getStream(), m_xContext, *pTempEntry, this, bToBeEncrypted);
834 9841 : deflateZipEntry(&aZipEntry, xStream);
835 9841 : rZipOut.rawCloseEntry(bToBeEncrypted);
836 : }
837 : }
838 : }
839 0 : catch ( ZipException& )
840 : {
841 0 : bSuccess = false;
842 : }
843 0 : catch ( io::IOException& )
844 : {
845 0 : bSuccess = false;
846 : }
847 :
848 10064 : if ( bToBeEncrypted )
849 : {
850 4 : ::rtl::Reference< EncryptionData > xEncData = GetEncryptionData();
851 4 : if ( !xEncData.is() )
852 0 : throw uno::RuntimeException();
853 :
854 4 : aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
855 4 : aPropSet[PKG_MNFST_DIGEST].Value <<= m_xBaseEncryptionData->m_aDigest;
856 4 : aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
857 4 : aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
858 4 : aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
859 4 : aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
860 4 : aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
861 4 : aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
862 4 : aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
863 4 : aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
864 :
865 4 : SetIsEncrypted ( true );
866 10064 : }
867 : }
868 :
869 10167 : if (bSuccess && !bParallelDeflate)
870 10123 : successfullyWritten(pTempEntry);
871 :
872 20334 : if ( aPropSet.getLength()
873 10167 : && ( m_nFormat == embed::StorageFormats::PACKAGE || m_nFormat == embed::StorageFormats::OFOPXML ) )
874 10167 : rManList.push_back( aPropSet );
875 :
876 20334 : return bSuccess;
877 : }
878 :
879 10167 : void ZipPackageStream::successfullyWritten( ZipEntry *pEntry )
880 : {
881 10167 : if ( !IsPackageMember() )
882 : {
883 10065 : CloseOwnStreamIfAny();
884 10065 : SetPackageMember ( true );
885 : }
886 :
887 10167 : if ( m_bRawStream )
888 : {
889 : // the raw stream was integrated and now behaves
890 : // as usual encrypted stream
891 1 : SetToBeEncrypted( true );
892 : }
893 :
894 : // Then copy it back afterwards...
895 10167 : ZipPackageFolder::copyZipEntry( aEntry, *pEntry );
896 :
897 : // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
898 10167 : if ( IsEncrypted() )
899 5 : setSize( m_nOwnStreamOrigSize );
900 :
901 10167 : aEntry.nOffset *= -1;
902 10167 : }
903 :
904 235868 : void ZipPackageStream::SetPackageMember( bool bNewValue )
905 : {
906 235868 : if ( bNewValue )
907 : {
908 221610 : m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
909 221610 : m_nMagicalHackPos = 0;
910 221610 : m_nMagicalHackSize = 0;
911 : }
912 14258 : else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
913 0 : m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
914 235868 : }
915 :
916 : // XActiveDataSink
917 14257 : void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
918 : throw( RuntimeException, std::exception )
919 : {
920 : // if seekable access is required the wrapping will be done on demand
921 14257 : m_xStream = aStream;
922 14257 : m_nImportedEncryptionAlgorithm = 0;
923 14257 : m_bHasSeekable = false;
924 14257 : SetPackageMember ( false );
925 14257 : aEntry.nTime = -1;
926 14257 : m_nStreamMode = PACKAGE_STREAM_DETECT;
927 14257 : }
928 :
929 10257 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
930 : throw( RuntimeException )
931 : {
932 : try
933 : {
934 10257 : if ( IsPackageMember() )
935 : {
936 204 : return m_rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
937 : }
938 10053 : else if ( GetOwnSeekStream().is() )
939 : {
940 10053 : return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
941 : }
942 : else
943 0 : return uno::Reference < io::XInputStream > ();
944 : }
945 0 : catch ( ZipException & )//rException )
946 : {
947 : OSL_FAIL( "ZipException thrown" );//rException.Message);
948 0 : return uno::Reference < io::XInputStream > ();
949 : }
950 0 : catch ( Exception & )
951 : {
952 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
953 0 : return uno::Reference < io::XInputStream > ();
954 : }
955 : }
956 :
957 6907 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
958 : throw( RuntimeException, std::exception )
959 : {
960 : try
961 : {
962 6907 : if ( IsPackageMember() )
963 : {
964 6907 : return m_rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
965 : }
966 0 : else if ( GetOwnSeekStream().is() )
967 : {
968 0 : return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
969 : }
970 : else
971 0 : return uno::Reference < io::XInputStream > ();
972 : }
973 0 : catch ( ZipException & )//rException )
974 : {
975 : OSL_FAIL( "ZipException thrown" );//rException.Message);
976 0 : return uno::Reference < io::XInputStream > ();
977 : }
978 0 : catch ( Exception &ex )
979 : {
980 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
981 : OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
982 : (void)ex;
983 0 : return uno::Reference < io::XInputStream > ();
984 : }
985 : }
986 :
987 : // XDataSinkEncrSupport
988 68758 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
989 : throw ( packages::WrongPasswordException, ZipException,
990 : io::IOException,
991 : RuntimeException, std::exception )
992 : {
993 : // There is no stream attached to this object
994 68758 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
995 15058 : return uno::Reference< io::XInputStream >();
996 :
997 : // this method can not be used together with old approach
998 53700 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
999 0 : throw packages::zip::ZipIOException(THROW_WHERE );
1000 :
1001 53700 : if ( IsPackageMember() )
1002 : {
1003 51894 : uno::Reference< io::XInputStream > xResult;
1004 : try
1005 : {
1006 51894 : xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
1007 : }
1008 4 : catch( const packages::WrongPasswordException& )
1009 : {
1010 4 : if ( m_rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 )
1011 : {
1012 : try
1013 : {
1014 : // rhbz#1013844 / fdo#47482 workaround for the encrypted
1015 : // OpenOffice.org 1.0 documents generated by Libreoffice <=
1016 : // 3.6 with the new encryption format and using SHA256, but
1017 : // missing a specified startkey of SHA256
1018 :
1019 : // force SHA256 and see if that works
1020 4 : m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA256;
1021 4 : xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
1022 4 : return xResult;
1023 : }
1024 0 : catch (const packages::WrongPasswordException&)
1025 : {
1026 : // if that didn't work, restore to SHA1 and trundle through the *other* earlier
1027 : // bug fix
1028 0 : m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA1;
1029 : }
1030 :
1031 : // workaround for the encrypted documents generated with the old OOo1.x bug.
1032 0 : if ( !m_bUseWinEncoding )
1033 : {
1034 0 : xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
1035 0 : m_bUseWinEncoding = true;
1036 : }
1037 : else
1038 0 : throw;
1039 : }
1040 : else
1041 0 : throw;
1042 0 : }
1043 51890 : return xResult;
1044 : }
1045 1806 : else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
1046 0 : return ZipFile::StaticGetDataFromRawStream( m_xContext, GetOwnSeekStream(), GetEncryptionData() );
1047 1806 : else if ( GetOwnSeekStream().is() )
1048 : {
1049 1806 : return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
1050 : }
1051 : else
1052 0 : return uno::Reference< io::XInputStream >();
1053 : }
1054 :
1055 1 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
1056 : throw ( packages::NoEncryptionException,
1057 : io::IOException,
1058 : uno::RuntimeException, std::exception )
1059 : {
1060 : // There is no stream attached to this object
1061 1 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
1062 0 : return uno::Reference< io::XInputStream >();
1063 :
1064 : // this method can not be used together with old approach
1065 1 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
1066 0 : throw packages::zip::ZipIOException(THROW_WHERE );
1067 :
1068 1 : if ( IsPackageMember() )
1069 : {
1070 1 : if ( !m_bIsEncrypted || !GetEncryptionData().is() )
1071 0 : throw packages::NoEncryptionException(THROW_WHERE );
1072 :
1073 1 : return m_rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), msMediaType, m_rZipPackage.GetSharedMutexRef() );
1074 : }
1075 0 : else if ( GetOwnSeekStream().is() )
1076 : {
1077 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
1078 : {
1079 0 : return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
1080 : }
1081 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA && m_bToBeEncrypted )
1082 0 : return TryToGetRawFromDataStream( true );
1083 : }
1084 :
1085 0 : throw packages::NoEncryptionException(THROW_WHERE );
1086 : }
1087 :
1088 14257 : void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
1089 : throw ( io::IOException,
1090 : RuntimeException, std::exception )
1091 : {
1092 14257 : setInputStream( aStream );
1093 14257 : m_nStreamMode = PACKAGE_STREAM_DATA;
1094 14257 : }
1095 :
1096 1 : void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
1097 : throw ( packages::EncryptionNotAllowedException,
1098 : packages::NoRawFormatException,
1099 : io::IOException,
1100 : RuntimeException, std::exception )
1101 : {
1102 : // wrap the stream in case it is not seekable
1103 1 : uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xContext );
1104 2 : uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
1105 1 : if ( !xSeek.is() )
1106 0 : throw RuntimeException(THROW_WHERE "The stream must support XSeekable!" );
1107 :
1108 1 : xSeek->seek( 0 );
1109 2 : uno::Reference< io::XInputStream > xOldStream = m_xStream;
1110 1 : m_xStream = xNewStream;
1111 1 : if ( !ParsePackageRawStream() )
1112 : {
1113 0 : m_xStream = xOldStream;
1114 0 : throw packages::NoRawFormatException(THROW_WHERE );
1115 : }
1116 :
1117 : // the raw stream MUST have seekable access
1118 1 : m_bHasSeekable = true;
1119 :
1120 1 : SetPackageMember ( false );
1121 1 : aEntry.nTime = -1;
1122 2 : m_nStreamMode = PACKAGE_STREAM_RAW;
1123 1 : }
1124 :
1125 0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
1126 : throw ( io::IOException, packages::NoEncryptionException,
1127 : uno::RuntimeException, std::exception )
1128 : {
1129 : // There is no stream attached to this object
1130 0 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
1131 0 : return uno::Reference< io::XInputStream >();
1132 :
1133 : // this method can not be used together with old approach
1134 0 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
1135 0 : throw packages::zip::ZipIOException(THROW_WHERE );
1136 :
1137 0 : if ( IsPackageMember() )
1138 : {
1139 0 : return m_rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
1140 : }
1141 0 : else if ( GetOwnSeekStream().is() )
1142 : {
1143 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
1144 : {
1145 : // the header should not be returned here
1146 0 : return GetRawEncrStreamNoHeaderCopy();
1147 : }
1148 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
1149 0 : return TryToGetRawFromDataStream( false );
1150 : }
1151 :
1152 0 : return uno::Reference< io::XInputStream >();
1153 : }
1154 :
1155 : // XUnoTunnel
1156 :
1157 104562 : sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1158 : throw( RuntimeException, std::exception )
1159 : {
1160 104562 : sal_Int64 nMe = 0;
1161 418248 : if ( aIdentifier.getLength() == 16 &&
1162 418248 : 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
1163 84520 : nMe = reinterpret_cast < sal_Int64 > ( this );
1164 104562 : return nMe;
1165 : }
1166 :
1167 : // XPropertySet
1168 47198 : void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
1169 : throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception )
1170 : {
1171 47198 : if ( aPropertyName == "MediaType" )
1172 : {
1173 15248 : if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && m_rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
1174 0 : throw beans::PropertyVetoException(THROW_WHERE );
1175 :
1176 15248 : if ( aValue >>= msMediaType )
1177 : {
1178 15248 : if ( !msMediaType.isEmpty() )
1179 : {
1180 26854 : if ( msMediaType.indexOf ( "text" ) != -1
1181 13427 : || msMediaType == "application/vnd.sun.star.oleobject" )
1182 2741 : m_bToBeCompressed = true;
1183 10686 : else if ( !m_bCompressedIsSetFromOutside )
1184 9793 : m_bToBeCompressed = false;
1185 : }
1186 : }
1187 : else
1188 : throw IllegalArgumentException(THROW_WHERE "MediaType must be a string!",
1189 : uno::Reference< XInterface >(),
1190 0 : 2 );
1191 :
1192 : }
1193 31950 : else if ( aPropertyName == "Size" )
1194 : {
1195 0 : if ( !( aValue >>= aEntry.nSize ) )
1196 : throw IllegalArgumentException(THROW_WHERE "Wrong type for Size property!",
1197 : uno::Reference< XInterface >(),
1198 0 : 2 );
1199 : }
1200 31950 : else if ( aPropertyName == "Encrypted" )
1201 : {
1202 11119 : if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
1203 0 : throw beans::PropertyVetoException(THROW_WHERE );
1204 :
1205 11119 : bool bEnc = false;
1206 11119 : if ( aValue >>= bEnc )
1207 : {
1208 : // In case of new raw stream, the stream must not be encrypted on storing
1209 11119 : if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
1210 : throw IllegalArgumentException(THROW_WHERE "Raw stream can not be encrypted on storing",
1211 : uno::Reference< XInterface >(),
1212 0 : 2 );
1213 :
1214 11119 : m_bToBeEncrypted = bEnc;
1215 11119 : if ( m_bToBeEncrypted && !m_xBaseEncryptionData.is() )
1216 5195 : m_xBaseEncryptionData = new BaseEncryptionData;
1217 : }
1218 : else
1219 : throw IllegalArgumentException(THROW_WHERE "Wrong type for Encrypted property!",
1220 : uno::Reference< XInterface >(),
1221 0 : 2 );
1222 :
1223 : }
1224 20831 : else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
1225 : {
1226 0 : if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
1227 0 : throw beans::PropertyVetoException(THROW_WHERE );
1228 :
1229 0 : uno::Sequence< sal_Int8 > aNewKey;
1230 :
1231 0 : if ( !( aValue >>= aNewKey ) )
1232 : {
1233 0 : OUString sTempString;
1234 0 : if ( ( aValue >>= sTempString ) )
1235 : {
1236 0 : sal_Int32 nPathLength = sTempString.getLength();
1237 0 : Sequence < sal_Int8 > aSequence ( nPathLength );
1238 0 : sal_Int8 *pArray = aSequence.getArray();
1239 0 : const sal_Unicode *pChar = sTempString.getStr();
1240 0 : for ( sal_Int32 i = 0; i < nPathLength; i++ )
1241 0 : pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
1242 0 : aNewKey = aSequence;
1243 : }
1244 : else
1245 : throw IllegalArgumentException(THROW_WHERE "Wrong type for EncryptionKey property!",
1246 : uno::Reference< XInterface >(),
1247 0 : 2 );
1248 : }
1249 :
1250 0 : if ( aNewKey.getLength() )
1251 : {
1252 0 : if ( !m_xBaseEncryptionData.is() )
1253 0 : m_xBaseEncryptionData = new BaseEncryptionData;
1254 :
1255 0 : m_aEncryptionKey = aNewKey;
1256 : // In case of new raw stream, the stream must not be encrypted on storing
1257 0 : m_bHaveOwnKey = true;
1258 0 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
1259 0 : m_bToBeEncrypted = true;
1260 : }
1261 : else
1262 : {
1263 0 : m_bHaveOwnKey = false;
1264 0 : m_aEncryptionKey.realloc( 0 );
1265 : }
1266 :
1267 0 : m_aStorageEncryptionKeys.realloc( 0 );
1268 : }
1269 20831 : else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
1270 : {
1271 5583 : if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
1272 0 : throw beans::PropertyVetoException(THROW_WHERE );
1273 :
1274 5583 : uno::Sequence< beans::NamedValue > aKeys;
1275 5583 : if ( !( aValue >>= aKeys ) )
1276 : {
1277 : throw IllegalArgumentException(THROW_WHERE "Wrong type for StorageEncryptionKeys property!",
1278 : uno::Reference< XInterface >(),
1279 0 : 2 );
1280 : }
1281 :
1282 5583 : if ( aKeys.getLength() )
1283 : {
1284 17 : if ( !m_xBaseEncryptionData.is() )
1285 0 : m_xBaseEncryptionData = new BaseEncryptionData;
1286 :
1287 17 : m_aStorageEncryptionKeys = aKeys;
1288 :
1289 : // In case of new raw stream, the stream must not be encrypted on storing
1290 17 : m_bHaveOwnKey = true;
1291 17 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
1292 17 : m_bToBeEncrypted = true;
1293 : }
1294 : else
1295 : {
1296 5566 : m_bHaveOwnKey = false;
1297 5566 : m_aStorageEncryptionKeys.realloc( 0 );
1298 : }
1299 :
1300 5583 : m_aEncryptionKey.realloc( 0 );
1301 : }
1302 15248 : else if ( aPropertyName == "Compressed" )
1303 : {
1304 15248 : bool bCompr = false;
1305 :
1306 15248 : if ( aValue >>= bCompr )
1307 : {
1308 : // In case of new raw stream, the stream must not be encrypted on storing
1309 15248 : if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
1310 : throw IllegalArgumentException(THROW_WHERE "Raw stream can not be encrypted on storing",
1311 : uno::Reference< XInterface >(),
1312 0 : 2 );
1313 :
1314 15248 : m_bToBeCompressed = bCompr;
1315 15248 : m_bCompressedIsSetFromOutside = true;
1316 : }
1317 : else
1318 : throw IllegalArgumentException(THROW_WHERE "Wrong type for Compressed property!",
1319 : uno::Reference< XInterface >(),
1320 0 : 2 );
1321 : }
1322 : else
1323 0 : throw beans::UnknownPropertyException(THROW_WHERE );
1324 47198 : }
1325 :
1326 160929 : Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
1327 : throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
1328 : {
1329 160929 : Any aAny;
1330 160929 : if ( PropertyName == "MediaType" )
1331 : {
1332 42257 : aAny <<= msMediaType;
1333 42257 : return aAny;
1334 : }
1335 118672 : else if ( PropertyName == "Size" )
1336 : {
1337 51412 : aAny <<= aEntry.nSize;
1338 51412 : return aAny;
1339 : }
1340 67260 : else if ( PropertyName == "Encrypted" )
1341 : {
1342 7195 : aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) || m_bToBeEncrypted);
1343 7195 : return aAny;
1344 : }
1345 60065 : else if ( PropertyName == "WasEncrypted" )
1346 : {
1347 8598 : aAny <<= m_bIsEncrypted;
1348 8598 : return aAny;
1349 : }
1350 51467 : else if ( PropertyName == "Compressed" )
1351 : {
1352 51411 : aAny <<= m_bToBeCompressed;
1353 51411 : return aAny;
1354 : }
1355 56 : else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
1356 : {
1357 0 : aAny <<= m_aEncryptionKey;
1358 0 : return aAny;
1359 : }
1360 56 : else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
1361 : {
1362 56 : aAny <<= m_aStorageEncryptionKeys;
1363 56 : return aAny;
1364 : }
1365 : else
1366 0 : throw beans::UnknownPropertyException(THROW_WHERE );
1367 : }
1368 :
1369 29 : void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
1370 : {
1371 29 : if ( aEntry.nCompressedSize != nNewSize )
1372 29 : aEntry.nMethod = DEFLATED;
1373 29 : aEntry.nSize = nNewSize;
1374 29 : }
1375 0 : OUString ZipPackageStream::getImplementationName()
1376 : throw ( RuntimeException, std::exception )
1377 : {
1378 0 : return OUString ("ZipPackageStream");
1379 : }
1380 :
1381 0 : Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
1382 : throw ( RuntimeException, std::exception )
1383 : {
1384 0 : Sequence< OUString > aNames( 1 );
1385 0 : aNames[0] = "com.sun.star.packages.PackageStream";
1386 0 : return aNames;
1387 : }
1388 :
1389 0 : sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
1390 : throw ( RuntimeException, std::exception )
1391 : {
1392 0 : return cppu::supportsService(this, rServiceName);
1393 : }
1394 :
1395 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|