Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : // MARKER( update_precomp.py ): autogen include statement, do not remove
21 : #include <com/sun/star/packages/zip/ZipConstants.hpp>
22 : #include <com/sun/star/embed/StorageFormats.hpp>
23 : #include <com/sun/star/packages/zip/ZipIOException.hpp>
24 : #include <com/sun/star/io/TempFile.hpp>
25 : #include <com/sun/star/io/XInputStream.hpp>
26 : #include <com/sun/star/io/XOutputStream.hpp>
27 : #include <com/sun/star/io/XStream.hpp>
28 : #include <com/sun/star/io/XSeekable.hpp>
29 : #include <com/sun/star/xml/crypto/DigestID.hpp>
30 : #include <com/sun/star/xml/crypto/CipherID.hpp>
31 :
32 : #include <string.h>
33 :
34 : #include <ZipPackageStream.hxx>
35 : #include <ZipPackage.hxx>
36 : #include <ZipFile.hxx>
37 : #include <EncryptedDataHeader.hxx>
38 : #include <osl/diagnose.h>
39 : #include "wrapstreamforshare.hxx"
40 :
41 : #include <comphelper/processfactory.hxx>
42 : #include <comphelper/seekableinput.hxx>
43 : #include <comphelper/storagehelper.hxx>
44 :
45 : #include <rtl/instance.hxx>
46 :
47 : #include <PackageConstants.hxx>
48 :
49 : using namespace com::sun::star::packages::zip::ZipConstants;
50 : using namespace com::sun::star::packages::zip;
51 : using namespace com::sun::star::uno;
52 : using namespace com::sun::star::lang;
53 : using namespace com::sun::star;
54 : using namespace cppu;
55 :
56 : namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
57 :
58 7646 : const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageStream::static_getImplementationId()
59 : {
60 7646 : return lcl_CachedImplId::get();
61 : }
62 :
63 6826 : ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
64 : const uno::Reference< XMultiServiceFactory >& xFactory,
65 : sal_Bool bAllowRemoveOnInsert )
66 : : m_xFactory( xFactory )
67 : , rZipPackage( rNewPackage )
68 : , bToBeCompressed ( sal_True )
69 : , bToBeEncrypted ( sal_False )
70 : , bHaveOwnKey ( sal_False )
71 : , bIsEncrypted ( sal_False )
72 : , m_nImportedStartKeyAlgorithm( 0 )
73 : , m_nImportedEncryptionAlgorithm( 0 )
74 : , m_nImportedChecksumAlgorithm( 0 )
75 : , m_nImportedDerivedKeySize( 0 )
76 : , m_nStreamMode( PACKAGE_STREAM_NOTSET )
77 : , m_nMagicalHackPos( 0 )
78 : , m_nMagicalHackSize( 0 )
79 : , m_bHasSeekable( sal_False )
80 : , m_bCompressedIsSetFromOutside( sal_False )
81 : , m_bFromManifest( sal_False )
82 6826 : , m_bUseWinEncoding( false )
83 : {
84 : OSL_ENSURE( m_xFactory.is(), "No factory is provided to ZipPackageStream!\n" );
85 :
86 6826 : this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
87 :
88 6826 : SetFolder ( sal_False );
89 6826 : aEntry.nVersion = -1;
90 6826 : aEntry.nFlag = 0;
91 6826 : aEntry.nMethod = -1;
92 6826 : aEntry.nTime = -1;
93 6826 : aEntry.nCrc = -1;
94 6826 : aEntry.nCompressedSize = -1;
95 6826 : aEntry.nSize = -1;
96 6826 : aEntry.nOffset = -1;
97 6826 : aEntry.nPathLen = -1;
98 6826 : aEntry.nExtraLen = -1;
99 :
100 6826 : Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
101 6826 : if ( !rCachedImplId.getLength() )
102 14 : rCachedImplId = getImplementationId();
103 6826 : }
104 :
105 12798 : ZipPackageStream::~ZipPackageStream( void )
106 : {
107 12798 : }
108 :
109 4859 : void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
110 : {
111 4859 : aEntry.nVersion = rInEntry.nVersion;
112 4859 : aEntry.nFlag = rInEntry.nFlag;
113 4859 : aEntry.nMethod = rInEntry.nMethod;
114 4859 : aEntry.nTime = rInEntry.nTime;
115 4859 : aEntry.nCrc = rInEntry.nCrc;
116 4859 : aEntry.nCompressedSize = rInEntry.nCompressedSize;
117 4859 : aEntry.nSize = rInEntry.nSize;
118 4859 : aEntry.nOffset = rInEntry.nOffset;
119 4859 : aEntry.sPath = rInEntry.sPath;
120 4859 : aEntry.nPathLen = rInEntry.nPathLen;
121 4859 : aEntry.nExtraLen = rInEntry.nExtraLen;
122 :
123 4859 : if ( aEntry.nMethod == STORED )
124 305 : bToBeCompressed = sal_False;
125 4859 : }
126 :
127 : //--------------------------------------------------------------------------
128 235 : void ZipPackageStream::CloseOwnStreamIfAny()
129 : {
130 235 : if ( xStream.is() )
131 : {
132 235 : xStream->closeInput();
133 235 : xStream = uno::Reference< io::XInputStream >();
134 235 : m_bHasSeekable = sal_False;
135 : }
136 235 : }
137 :
138 : //--------------------------------------------------------------------------
139 520 : uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
140 : {
141 520 : if ( !m_bHasSeekable && xStream.is() )
142 : {
143 : // The package component requires that every stream either be FROM a package or it must support XSeekable!
144 : // The only exception is a nonseekable stream that is provided only for storing, if such a stream
145 : // is accessed before commit it MUST be wrapped.
146 : // Wrap the stream in case it is not seekable
147 260 : xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream, comphelper::getComponentContext( m_xFactory ) );
148 260 : uno::Reference< io::XSeekable > xSeek( xStream, UNO_QUERY );
149 260 : if ( !xSeek.is() )
150 : throw RuntimeException( OSL_LOG_PREFIX "The stream must support XSeekable!",
151 0 : uno::Reference< XInterface >() );
152 :
153 260 : m_bHasSeekable = sal_True;
154 : }
155 :
156 520 : return xStream;
157 : }
158 :
159 : //--------------------------------------------------------------------------
160 0 : uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
161 : {
162 0 : if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
163 0 : throw io::IOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
164 :
165 0 : if ( m_xBaseEncryptionData.is() )
166 : throw ZipIOException(OSL_LOG_PREFIX "Encrypted stream without encryption data!\n",
167 0 : uno::Reference< XInterface >() );
168 :
169 0 : uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
170 0 : if ( !xSeek.is() )
171 : throw ZipIOException(OSL_LOG_PREFIX "The stream must be seekable!\n",
172 0 : uno::Reference< XInterface >() );
173 :
174 : // skip header
175 0 : xSeek->seek( n_ConstHeaderSize + getInitialisationVector().getLength() +
176 0 : getSalt().getLength() + getDigest().getLength() );
177 :
178 : // create temporary stream
179 : uno::Reference < io::XOutputStream > xTempOut(
180 : io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
181 0 : uno::UNO_QUERY_THROW );
182 0 : uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW );
183 0 : uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
184 :
185 : // copy the raw stream to the temporary file starting from the current position
186 0 : ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
187 0 : xTempOut->closeOutput();
188 0 : xTempSeek->seek( 0 );
189 :
190 0 : return xTempIn;
191 : }
192 :
193 : //--------------------------------------------------------------------------
194 28 : sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
195 : {
196 28 : return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID();
197 : }
198 :
199 : //--------------------------------------------------------------------------
200 4 : sal_Int32 ZipPackageStream::GetBlockSize() const
201 : {
202 4 : return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
203 : }
204 :
205 : //--------------------------------------------------------------------------
206 2308 : ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
207 : {
208 2308 : ::rtl::Reference< EncryptionData > xResult;
209 2308 : if ( m_xBaseEncryptionData.is() )
210 : xResult = new EncryptionData(
211 24 : *m_xBaseEncryptionData,
212 : GetEncryptionKey( bUseWinEncoding ),
213 : GetEncryptionAlgorithm(),
214 12 : m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : rZipPackage.GetChecksumAlgID(),
215 12 : m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : rZipPackage.GetDefaultDerivedKeySize(),
216 48 : GetStartKeyGenID() );
217 :
218 2308 : return xResult;
219 : }
220 :
221 : //--------------------------------------------------------------------------
222 24 : uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
223 : {
224 24 : uno::Sequence< sal_Int8 > aResult;
225 24 : sal_Int32 nKeyGenID = GetStartKeyGenID();
226 24 : bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
227 :
228 24 : if ( bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
229 : {
230 12 : OUString aNameToFind;
231 12 : if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
232 8 : aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
233 4 : else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
234 : {
235 4 : aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
236 : }
237 : else
238 0 : throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
239 :
240 48 : for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
241 36 : if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
242 12 : m_aStorageEncryptionKeys[nInd].Value >>= aResult;
243 :
244 : // empty keys are not allowed here
245 : // so it is not important whether there is no key, or the key is empty, it is an error
246 12 : if ( !aResult.getLength() )
247 0 : throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
248 : }
249 : else
250 12 : aResult = m_aEncryptionKey;
251 :
252 24 : if ( !aResult.getLength() || !bHaveOwnKey )
253 12 : aResult = rZipPackage.GetEncryptionKey();
254 :
255 24 : return aResult;
256 : }
257 :
258 : //--------------------------------------------------------------------------
259 48 : 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 48 : return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : rZipPackage.GetStartKeyGenID();
264 : }
265 :
266 : //--------------------------------------------------------------------------
267 0 : uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr )
268 : {
269 0 : if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !bToBeEncrypted ) )
270 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
271 :
272 0 : Sequence< sal_Int8 > aKey;
273 :
274 0 : if ( bToBeEncrypted )
275 : {
276 0 : aKey = GetEncryptionKey();
277 0 : if ( !aKey.getLength() )
278 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
279 : }
280 :
281 : try
282 : {
283 : // create temporary file
284 : uno::Reference < io::XStream > xTempStream(
285 : io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
286 0 : uno::UNO_QUERY_THROW );
287 :
288 : // create a package based on it
289 0 : ZipPackage* pPackage = new ZipPackage( m_xFactory );
290 0 : uno::Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
291 0 : if ( !xPackageAsFactory.is() )
292 0 : throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
293 :
294 0 : Sequence< Any > aArgs( 1 );
295 0 : aArgs[0] <<= xTempStream;
296 0 : pPackage->initialize( aArgs );
297 :
298 : // create a new package stream
299 0 : uno::Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
300 0 : if ( !xNewPackStream.is() )
301 0 : throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
302 :
303 0 : xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
304 0 : new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ) ) );
305 :
306 0 : uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
307 0 : if ( !xNewPSProps.is() )
308 0 : throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
309 :
310 : // copy all the properties of this stream to the new stream
311 0 : xNewPSProps->setPropertyValue("MediaType", makeAny( sMediaType ) );
312 0 : xNewPSProps->setPropertyValue("Compressed", makeAny( bToBeCompressed ) );
313 0 : if ( bToBeEncrypted )
314 : {
315 0 : xNewPSProps->setPropertyValue(ENCRYPTION_KEY_PROPERTY, makeAny( aKey ) );
316 0 : xNewPSProps->setPropertyValue("Encrypted", makeAny( sal_True ) );
317 : }
318 :
319 : // insert a new stream in the package
320 0 : uno::Reference< XUnoTunnel > xTunnel;
321 0 : Any aRoot = pPackage->getByHierarchicalName("/");
322 0 : aRoot >>= xTunnel;
323 0 : uno::Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
324 0 : if ( !xRootNameContainer.is() )
325 0 : throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
326 :
327 0 : uno::Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
328 0 : xRootNameContainer->insertByName("dummy", makeAny( xNPSTunnel ) );
329 :
330 : // commit the temporary package
331 0 : pPackage->commitChanges();
332 :
333 : // get raw stream from the temporary package
334 0 : uno::Reference< io::XInputStream > xInRaw;
335 0 : if ( bAddHeaderForEncr )
336 0 : xInRaw = xNewPackStream->getRawStream();
337 : else
338 0 : xInRaw = xNewPackStream->getPlainRawStream();
339 :
340 : // create another temporary file
341 : uno::Reference < io::XOutputStream > xTempOut(
342 : io::TempFile::create(comphelper::getComponentContext(m_xFactory)),
343 0 : uno::UNO_QUERY_THROW );
344 0 : uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW );
345 0 : uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
346 :
347 : // copy the raw stream to the temporary file
348 0 : ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
349 0 : xTempOut->closeOutput();
350 0 : xTempSeek->seek( 0 );
351 :
352 : // close raw stream, package stream and folder
353 0 : xInRaw = uno::Reference< io::XInputStream >();
354 0 : xNewPSProps = uno::Reference< XPropertySet >();
355 0 : xNPSTunnel = uno::Reference< XUnoTunnel >();
356 0 : xNewPackStream = uno::Reference< XDataSinkEncrSupport >();
357 0 : xTunnel = uno::Reference< XUnoTunnel >();
358 0 : xRootNameContainer = uno::Reference< container::XNameContainer >();
359 :
360 : // return the stream representing the first temporary file
361 0 : return xTempIn;
362 : }
363 0 : catch ( RuntimeException& )
364 : {
365 0 : throw;
366 : }
367 0 : catch ( Exception& )
368 : {
369 : }
370 :
371 0 : throw io::IOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
372 : }
373 :
374 : //--------------------------------------------------------------------------
375 0 : sal_Bool ZipPackageStream::ParsePackageRawStream()
376 : {
377 : OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
378 :
379 0 : if ( !GetOwnSeekStream().is() )
380 0 : return sal_False;
381 :
382 0 : sal_Bool bOk = sal_False;
383 :
384 0 : ::rtl::Reference< BaseEncryptionData > xTempEncrData;
385 0 : sal_Int32 nMagHackSize = 0;
386 0 : Sequence < sal_Int8 > aHeader ( 4 );
387 :
388 : try
389 : {
390 0 : if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
391 : {
392 0 : const sal_Int8 *pHeader = aHeader.getConstArray();
393 0 : sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
394 0 : ( pHeader [1] & 0xFF ) << 8 |
395 0 : ( pHeader [2] & 0xFF ) << 16 |
396 0 : ( pHeader [3] & 0xFF ) << 24;
397 0 : if ( nHeader == n_ConstHeader )
398 : {
399 : // this is one of our god-awful, but extremely devious hacks, everyone cheer
400 0 : xTempEncrData = new BaseEncryptionData;
401 :
402 0 : OUString aMediaType;
403 0 : sal_Int32 nEncAlgorithm = 0;
404 0 : sal_Int32 nChecksumAlgorithm = 0;
405 0 : sal_Int32 nDerivedKeySize = 0;
406 0 : sal_Int32 nStartKeyGenID = 0;
407 0 : if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
408 : {
409 : // We'll want to skip the data we've just read, so calculate how much we just read
410 : // and remember it
411 0 : m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
412 0 : + xTempEncrData->m_aInitVector.getLength()
413 0 : + xTempEncrData->m_aDigest.getLength()
414 0 : + aMediaType.getLength() * sizeof( sal_Unicode );
415 0 : m_nImportedEncryptionAlgorithm = nEncAlgorithm;
416 0 : m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
417 0 : m_nImportedDerivedKeySize = nDerivedKeySize;
418 0 : m_nImportedStartKeyAlgorithm = nStartKeyGenID;
419 0 : m_nMagicalHackSize = nMagHackSize;
420 0 : sMediaType = aMediaType;
421 :
422 0 : bOk = sal_True;
423 0 : }
424 : }
425 : }
426 : }
427 0 : catch( Exception& )
428 : {
429 : }
430 :
431 0 : if ( !bOk )
432 : {
433 : // the provided stream is not a raw stream
434 0 : return sal_False;
435 : }
436 :
437 0 : m_xBaseEncryptionData = xTempEncrData;
438 0 : SetIsEncrypted ( sal_True );
439 : // it's already compressed and encrypted
440 0 : bToBeEncrypted = bToBeCompressed = sal_False;
441 :
442 0 : return sal_True;
443 : }
444 :
445 6087 : void ZipPackageStream::SetPackageMember( sal_Bool bNewValue )
446 : {
447 6087 : if ( bNewValue )
448 : {
449 5094 : m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
450 5094 : m_nMagicalHackPos = 0;
451 5094 : m_nMagicalHackSize = 0;
452 : }
453 993 : else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
454 0 : m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
455 6087 : }
456 :
457 : // XActiveDataSink
458 : //--------------------------------------------------------------------------
459 993 : void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
460 : throw( RuntimeException )
461 : {
462 : // if seekable access is required the wrapping will be done on demand
463 993 : xStream = aStream;
464 993 : m_nImportedEncryptionAlgorithm = 0;
465 993 : m_bHasSeekable = sal_False;
466 993 : SetPackageMember ( sal_False );
467 993 : aEntry.nTime = -1;
468 993 : m_nStreamMode = PACKAGE_STREAM_DETECT;
469 993 : }
470 :
471 : //--------------------------------------------------------------------------
472 235 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
473 : throw( RuntimeException )
474 : {
475 : try
476 : {
477 235 : if ( IsPackageMember() )
478 : {
479 0 : return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
480 : }
481 235 : else if ( GetOwnSeekStream().is() )
482 : {
483 235 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
484 : }
485 : else
486 0 : return uno::Reference < io::XInputStream > ();
487 : }
488 0 : catch ( ZipException & )//rException )
489 : {
490 : OSL_FAIL( "ZipException thrown" );//rException.Message);
491 0 : return uno::Reference < io::XInputStream > ();
492 : }
493 0 : catch ( Exception & )
494 : {
495 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
496 0 : return uno::Reference < io::XInputStream > ();
497 : }
498 : }
499 :
500 : //--------------------------------------------------------------------------
501 325 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
502 : throw( RuntimeException )
503 : {
504 : try
505 : {
506 325 : if ( IsPackageMember() )
507 : {
508 325 : return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
509 : }
510 0 : else if ( GetOwnSeekStream().is() )
511 : {
512 0 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
513 : }
514 : else
515 0 : return uno::Reference < io::XInputStream > ();
516 : }
517 0 : catch ( ZipException & )//rException )
518 : {
519 : OSL_FAIL( "ZipException thrown" );//rException.Message);
520 0 : return uno::Reference < io::XInputStream > ();
521 : }
522 0 : catch ( Exception &ex )
523 : {
524 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
525 : OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
526 : (void)ex;
527 0 : return uno::Reference < io::XInputStream > ();
528 : }
529 : }
530 :
531 : // XDataSinkEncrSupport
532 : //--------------------------------------------------------------------------
533 2322 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
534 : throw ( packages::WrongPasswordException,
535 : io::IOException,
536 : RuntimeException )
537 : {
538 : // There is no stream attached to this object
539 2322 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
540 326 : return uno::Reference< io::XInputStream >();
541 :
542 : // this method can not be used together with old approach
543 1996 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
544 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
545 :
546 1996 : if ( IsPackageMember() )
547 : {
548 1971 : uno::Reference< io::XInputStream > xResult;
549 : try
550 : {
551 1971 : xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
552 : }
553 0 : catch( packages::WrongPasswordException& )
554 : {
555 : // workaround for the encrypted documents generated with the old OOo1.x bug.
556 0 : if ( rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 && !m_bUseWinEncoding )
557 : {
558 0 : xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
559 0 : m_bUseWinEncoding = true;
560 : }
561 : else
562 0 : throw;
563 : }
564 1971 : return xResult;
565 : }
566 25 : else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
567 0 : return ZipFile::StaticGetDataFromRawStream( comphelper::getComponentContext(m_xFactory), GetOwnSeekStream(), GetEncryptionData() );
568 25 : else if ( GetOwnSeekStream().is() )
569 : {
570 25 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
571 : }
572 : else
573 0 : return uno::Reference< io::XInputStream >();
574 : }
575 :
576 : //--------------------------------------------------------------------------
577 0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
578 : throw ( packages::NoEncryptionException,
579 : io::IOException,
580 : uno::RuntimeException )
581 : {
582 : // There is no stream attached to this object
583 0 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
584 0 : return uno::Reference< io::XInputStream >();
585 :
586 : // this method can not be used together with old approach
587 0 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
588 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
589 :
590 0 : if ( IsPackageMember() )
591 : {
592 0 : if ( !bIsEncrypted || !GetEncryptionData().is() )
593 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
594 :
595 0 : return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() );
596 : }
597 0 : else if ( GetOwnSeekStream().is() )
598 : {
599 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
600 : {
601 0 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
602 : }
603 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
604 0 : return TryToGetRawFromDataStream( sal_True );
605 : }
606 :
607 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
608 : }
609 :
610 :
611 : //--------------------------------------------------------------------------
612 993 : void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
613 : throw ( io::IOException,
614 : RuntimeException )
615 : {
616 993 : setInputStream( aStream );
617 993 : m_nStreamMode = PACKAGE_STREAM_DATA;
618 993 : }
619 :
620 : //--------------------------------------------------------------------------
621 0 : void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
622 : throw ( packages::EncryptionNotAllowedException,
623 : packages::NoRawFormatException,
624 : io::IOException,
625 : RuntimeException )
626 : {
627 : // wrap the stream in case it is not seekable
628 0 : uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, comphelper::getComponentContext( m_xFactory ) );
629 0 : uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
630 0 : if ( !xSeek.is() )
631 : throw RuntimeException(OSL_LOG_PREFIX "The stream must support XSeekable!",
632 0 : uno::Reference< XInterface >() );
633 :
634 0 : xSeek->seek( 0 );
635 0 : uno::Reference< io::XInputStream > xOldStream = xStream;
636 0 : xStream = xNewStream;
637 0 : if ( !ParsePackageRawStream() )
638 : {
639 0 : xStream = xOldStream;
640 0 : throw packages::NoRawFormatException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
641 : }
642 :
643 : // the raw stream MUST have seekable access
644 0 : m_bHasSeekable = sal_True;
645 :
646 0 : SetPackageMember ( sal_False );
647 0 : aEntry.nTime = -1;
648 0 : m_nStreamMode = PACKAGE_STREAM_RAW;
649 0 : }
650 :
651 : //--------------------------------------------------------------------------
652 0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
653 : throw ( io::IOException,
654 : uno::RuntimeException )
655 : {
656 : // There is no stream attached to this object
657 0 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
658 0 : return uno::Reference< io::XInputStream >();
659 :
660 : // this method can not be used together with old approach
661 0 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
662 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
663 :
664 0 : if ( IsPackageMember() )
665 : {
666 0 : return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
667 : }
668 0 : else if ( GetOwnSeekStream().is() )
669 : {
670 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
671 : {
672 : // the header should not be returned here
673 0 : return GetRawEncrStreamNoHeaderCopy();
674 : }
675 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
676 0 : return TryToGetRawFromDataStream( sal_False );
677 : }
678 :
679 0 : return uno::Reference< io::XInputStream >();
680 : }
681 :
682 : // XUnoTunnel
683 :
684 : //--------------------------------------------------------------------------
685 4502 : sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
686 : throw( RuntimeException )
687 : {
688 4502 : sal_Int64 nMe = 0;
689 9004 : if ( aIdentifier.getLength() == 16 &&
690 4502 : 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
691 3144 : nMe = reinterpret_cast < sal_Int64 > ( this );
692 4502 : return nMe;
693 : }
694 :
695 : // XPropertySet
696 : //--------------------------------------------------------------------------
697 4741 : void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
698 : throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
699 : {
700 4741 : if ( aPropertyName == "MediaType" )
701 : {
702 1067 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
703 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
704 :
705 1067 : if ( aValue >>= sMediaType )
706 : {
707 1067 : if ( !sMediaType.isEmpty() )
708 : {
709 1045 : if ( sMediaType.indexOf ( "text" ) != -1
710 222 : || sMediaType == "application/vnd.sun.star.oleobject" )
711 614 : bToBeCompressed = sal_True;
712 209 : else if ( !m_bCompressedIsSetFromOutside )
713 209 : bToBeCompressed = sal_False;
714 : }
715 : }
716 : else
717 : throw IllegalArgumentException(OSL_LOG_PREFIX "MediaType must be a string!\n",
718 : uno::Reference< XInterface >(),
719 0 : 2 );
720 :
721 : }
722 3674 : else if ( aPropertyName == "Size" )
723 : {
724 0 : if ( !( aValue >>= aEntry.nSize ) )
725 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Size property!\n",
726 : uno::Reference< XInterface >(),
727 0 : 2 );
728 : }
729 3674 : else if ( aPropertyName == "Encrypted" )
730 : {
731 1730 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
732 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
733 :
734 1730 : sal_Bool bEnc = sal_False;
735 1730 : if ( aValue >>= bEnc )
736 : {
737 : // In case of new raw stream, the stream must not be encrypted on storing
738 1730 : if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
739 : throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
740 : uno::Reference< XInterface >(),
741 0 : 2 );
742 :
743 1730 : bToBeEncrypted = bEnc;
744 1730 : if ( bToBeEncrypted && !m_xBaseEncryptionData.is() )
745 791 : m_xBaseEncryptionData = new BaseEncryptionData;
746 : }
747 : else
748 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Encrypted property!\n",
749 : uno::Reference< XInterface >(),
750 0 : 2 );
751 :
752 : }
753 1944 : else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
754 : {
755 0 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
756 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
757 :
758 0 : uno::Sequence< sal_Int8 > aNewKey;
759 :
760 0 : if ( !( aValue >>= aNewKey ) )
761 : {
762 0 : OUString sTempString;
763 0 : if ( ( aValue >>= sTempString ) )
764 : {
765 0 : sal_Int32 nPathLength = sTempString.getLength();
766 0 : Sequence < sal_Int8 > aSequence ( nPathLength );
767 0 : sal_Int8 *pArray = aSequence.getArray();
768 0 : const sal_Unicode *pChar = sTempString.getStr();
769 0 : for ( sal_Int16 i = 0; i < nPathLength; i++ )
770 0 : pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
771 0 : aNewKey = aSequence;
772 : }
773 : else
774 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n",
775 : uno::Reference< XInterface >(),
776 0 : 2 );
777 : }
778 :
779 0 : if ( aNewKey.getLength() )
780 : {
781 0 : if ( !m_xBaseEncryptionData.is() )
782 0 : m_xBaseEncryptionData = new BaseEncryptionData;
783 :
784 0 : m_aEncryptionKey = aNewKey;
785 : // In case of new raw stream, the stream must not be encrypted on storing
786 0 : bHaveOwnKey = sal_True;
787 0 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
788 0 : bToBeEncrypted = sal_True;
789 : }
790 : else
791 : {
792 0 : bHaveOwnKey = sal_False;
793 0 : m_aEncryptionKey.realloc( 0 );
794 : }
795 :
796 0 : m_aStorageEncryptionKeys.realloc( 0 );
797 : }
798 1944 : else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
799 : {
800 877 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
801 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
802 :
803 877 : uno::Sequence< beans::NamedValue > aKeys;
804 877 : if ( !( aValue >>= aKeys ) )
805 : {
806 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n",
807 : uno::Reference< XInterface >(),
808 0 : 2 );
809 : }
810 :
811 877 : if ( aKeys.getLength() )
812 : {
813 12 : if ( !m_xBaseEncryptionData.is() )
814 0 : m_xBaseEncryptionData = new BaseEncryptionData;
815 :
816 12 : m_aStorageEncryptionKeys = aKeys;
817 :
818 : // In case of new raw stream, the stream must not be encrypted on storing
819 12 : bHaveOwnKey = sal_True;
820 12 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
821 12 : bToBeEncrypted = sal_True;
822 : }
823 : else
824 : {
825 865 : bHaveOwnKey = sal_False;
826 865 : m_aStorageEncryptionKeys.realloc( 0 );
827 : }
828 :
829 877 : m_aEncryptionKey.realloc( 0 );
830 : }
831 1067 : else if ( aPropertyName == "Compressed" )
832 : {
833 1067 : sal_Bool bCompr = sal_False;
834 :
835 1067 : if ( aValue >>= bCompr )
836 : {
837 : // In case of new raw stream, the stream must not be encrypted on storing
838 1067 : if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
839 : throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
840 : uno::Reference< XInterface >(),
841 0 : 2 );
842 :
843 1067 : bToBeCompressed = bCompr;
844 1067 : m_bCompressedIsSetFromOutside = sal_True;
845 : }
846 : else
847 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Compressed property!\n",
848 : uno::Reference< XInterface >(),
849 0 : 2 );
850 : }
851 : else
852 0 : throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
853 4741 : }
854 :
855 : //--------------------------------------------------------------------------
856 9118 : Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
857 : throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException )
858 : {
859 9118 : Any aAny;
860 9118 : if ( PropertyName == "MediaType" )
861 : {
862 2130 : aAny <<= sMediaType;
863 2130 : return aAny;
864 : }
865 6988 : else if ( PropertyName == "Size" )
866 : {
867 2491 : aAny <<= aEntry.nSize;
868 2491 : return aAny;
869 : }
870 4497 : else if ( PropertyName == "Encrypted" )
871 : {
872 969 : aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) ? sal_True : bToBeEncrypted);
873 969 : return aAny;
874 : }
875 3528 : else if ( PropertyName == "WasEncrypted" )
876 : {
877 1013 : aAny <<= bIsEncrypted;
878 1013 : return aAny;
879 : }
880 2515 : else if ( PropertyName == "Compressed" )
881 : {
882 2491 : aAny <<= bToBeCompressed;
883 2491 : return aAny;
884 : }
885 24 : else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
886 : {
887 0 : aAny <<= m_aEncryptionKey;
888 0 : return aAny;
889 : }
890 24 : else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
891 : {
892 24 : aAny <<= m_aStorageEncryptionKeys;
893 24 : return aAny;
894 : }
895 : else
896 0 : throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
897 : }
898 :
899 : //--------------------------------------------------------------------------
900 18 : void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
901 : {
902 18 : if ( aEntry.nCompressedSize != nNewSize )
903 18 : aEntry.nMethod = DEFLATED;
904 18 : aEntry.nSize = nNewSize;
905 18 : }
906 : //--------------------------------------------------------------------------
907 0 : OUString ZipPackageStream::getImplementationName()
908 : throw ( RuntimeException )
909 : {
910 0 : return OUString ("ZipPackageStream");
911 : }
912 :
913 : //--------------------------------------------------------------------------
914 0 : Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
915 : throw ( RuntimeException )
916 : {
917 0 : Sequence< OUString > aNames( 1 );
918 0 : aNames[0] = "com.sun.star.packages.PackageStream";
919 0 : return aNames;
920 : }
921 : //--------------------------------------------------------------------------
922 0 : sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
923 : throw ( RuntimeException )
924 : {
925 0 : return rServiceName == getSupportedServiceNames()[0];
926 : }
927 :
928 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|