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