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 18116 : const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageStream::static_getImplementationId()
59 : {
60 18116 : return lcl_CachedImplId::get();
61 : }
62 :
63 18556 : ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
64 : const uno::Reference< XComponentContext >& xContext,
65 : sal_Bool bAllowRemoveOnInsert )
66 : : m_xContext( xContext )
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 18556 : , m_bUseWinEncoding( false )
83 : {
84 : OSL_ENSURE( m_xContext.is(), "No factory is provided to ZipPackageStream!\n" );
85 :
86 18556 : this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
87 :
88 18556 : SetFolder ( sal_False );
89 18556 : aEntry.nVersion = -1;
90 18556 : aEntry.nFlag = 0;
91 18556 : aEntry.nMethod = -1;
92 18556 : aEntry.nTime = -1;
93 18556 : aEntry.nCrc = -1;
94 18556 : aEntry.nCompressedSize = -1;
95 18556 : aEntry.nSize = -1;
96 18556 : aEntry.nOffset = -1;
97 18556 : aEntry.nPathLen = -1;
98 18556 : aEntry.nExtraLen = -1;
99 :
100 18556 : Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
101 18556 : if ( !rCachedImplId.getLength() )
102 64 : rCachedImplId = getImplementationId();
103 18556 : }
104 :
105 36928 : ZipPackageStream::~ZipPackageStream( void )
106 : {
107 36928 : }
108 :
109 13496 : void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
110 : {
111 13496 : aEntry.nVersion = rInEntry.nVersion;
112 13496 : aEntry.nFlag = rInEntry.nFlag;
113 13496 : aEntry.nMethod = rInEntry.nMethod;
114 13496 : aEntry.nTime = rInEntry.nTime;
115 13496 : aEntry.nCrc = rInEntry.nCrc;
116 13496 : aEntry.nCompressedSize = rInEntry.nCompressedSize;
117 13496 : aEntry.nSize = rInEntry.nSize;
118 13496 : aEntry.nOffset = rInEntry.nOffset;
119 13496 : aEntry.sPath = rInEntry.sPath;
120 13496 : aEntry.nPathLen = rInEntry.nPathLen;
121 13496 : aEntry.nExtraLen = rInEntry.nExtraLen;
122 :
123 13496 : if ( aEntry.nMethod == STORED )
124 1114 : bToBeCompressed = sal_False;
125 13496 : }
126 :
127 : //--------------------------------------------------------------------------
128 902 : void ZipPackageStream::CloseOwnStreamIfAny()
129 : {
130 902 : if ( xStream.is() )
131 : {
132 902 : xStream->closeInput();
133 902 : xStream = uno::Reference< io::XInputStream >();
134 902 : m_bHasSeekable = sal_False;
135 : }
136 902 : }
137 :
138 : //--------------------------------------------------------------------------
139 2114 : uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
140 : {
141 2114 : 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 1053 : xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream, m_xContext );
148 1053 : uno::Reference< io::XSeekable > xSeek( xStream, UNO_QUERY );
149 1053 : if ( !xSeek.is() )
150 : throw RuntimeException( OSL_LOG_PREFIX "The stream must support XSeekable!",
151 0 : uno::Reference< XInterface >() );
152 :
153 1053 : m_bHasSeekable = sal_True;
154 : }
155 :
156 2114 : 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 0 : uno::Reference < io::XTempFile > xTempFile = io::TempFile::create(m_xContext);
180 0 : uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
181 0 : uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();;
182 0 : uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
183 :
184 : // copy the raw stream to the temporary file starting from the current position
185 0 : ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
186 0 : xTempOut->closeOutput();
187 0 : xTempSeek->seek( 0 );
188 :
189 0 : return xTempIn;
190 : }
191 :
192 : //--------------------------------------------------------------------------
193 53 : sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
194 : {
195 53 : return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID();
196 : }
197 :
198 : //--------------------------------------------------------------------------
199 5 : sal_Int32 ZipPackageStream::GetBlockSize() const
200 : {
201 5 : return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
202 : }
203 :
204 : //--------------------------------------------------------------------------
205 5331 : ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
206 : {
207 5331 : ::rtl::Reference< EncryptionData > xResult;
208 5331 : if ( m_xBaseEncryptionData.is() )
209 166 : xResult = new EncryptionData(
210 48 : *m_xBaseEncryptionData,
211 : GetEncryptionKey( bUseWinEncoding ),
212 : GetEncryptionAlgorithm(),
213 35 : m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : rZipPackage.GetChecksumAlgID(),
214 35 : m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : rZipPackage.GetDefaultDerivedKeySize(),
215 48 : GetStartKeyGenID() );
216 :
217 5331 : return xResult;
218 : }
219 :
220 : //--------------------------------------------------------------------------
221 48 : uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
222 : {
223 48 : uno::Sequence< sal_Int8 > aResult;
224 48 : sal_Int32 nKeyGenID = GetStartKeyGenID();
225 48 : bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
226 :
227 48 : if ( bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
228 : {
229 13 : OUString aNameToFind;
230 13 : if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
231 9 : aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
232 4 : else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
233 : {
234 4 : aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
235 : }
236 : else
237 0 : throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
238 :
239 52 : for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
240 39 : if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
241 13 : m_aStorageEncryptionKeys[nInd].Value >>= aResult;
242 :
243 : // empty keys are not allowed here
244 : // so it is not important whether there is no key, or the key is empty, it is an error
245 13 : if ( !aResult.getLength() )
246 0 : throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
247 : }
248 : else
249 35 : aResult = m_aEncryptionKey;
250 :
251 48 : if ( !aResult.getLength() || !bHaveOwnKey )
252 35 : aResult = rZipPackage.GetEncryptionKey();
253 :
254 48 : return aResult;
255 : }
256 :
257 : //--------------------------------------------------------------------------
258 96 : sal_Int32 ZipPackageStream::GetStartKeyGenID()
259 : {
260 : // generally should all the streams use the same Start Key
261 : // but if raw copy without password takes place, we should preserve the imported algorithm
262 96 : return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : rZipPackage.GetStartKeyGenID();
263 : }
264 :
265 : //--------------------------------------------------------------------------
266 0 : uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr )
267 : {
268 0 : if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !bToBeEncrypted ) )
269 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
270 :
271 0 : Sequence< sal_Int8 > aKey;
272 :
273 0 : if ( bToBeEncrypted )
274 : {
275 0 : aKey = GetEncryptionKey();
276 0 : if ( !aKey.getLength() )
277 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
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(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
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(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
301 :
302 0 : xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
303 0 : new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ) ) );
304 :
305 0 : uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
306 0 : if ( !xNewPSProps.is() )
307 0 : throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
308 :
309 : // copy all the properties of this stream to the new stream
310 0 : xNewPSProps->setPropertyValue("MediaType", makeAny( sMediaType ) );
311 0 : xNewPSProps->setPropertyValue("Compressed", makeAny( bToBeCompressed ) );
312 0 : if ( bToBeEncrypted )
313 : {
314 0 : xNewPSProps->setPropertyValue(ENCRYPTION_KEY_PROPERTY, makeAny( aKey ) );
315 0 : xNewPSProps->setPropertyValue("Encrypted", makeAny( sal_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(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
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(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
371 : }
372 :
373 : //--------------------------------------------------------------------------
374 0 : sal_Bool ZipPackageStream::ParsePackageRawStream()
375 : {
376 : OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
377 :
378 0 : if ( !GetOwnSeekStream().is() )
379 0 : return sal_False;
380 :
381 0 : sal_Bool bOk = sal_False;
382 :
383 0 : ::rtl::Reference< BaseEncryptionData > xTempEncrData;
384 0 : sal_Int32 nMagHackSize = 0;
385 0 : Sequence < sal_Int8 > aHeader ( 4 );
386 :
387 : try
388 : {
389 0 : if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
390 : {
391 0 : const sal_Int8 *pHeader = aHeader.getConstArray();
392 0 : sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
393 0 : ( pHeader [1] & 0xFF ) << 8 |
394 0 : ( pHeader [2] & 0xFF ) << 16 |
395 0 : ( pHeader [3] & 0xFF ) << 24;
396 0 : if ( nHeader == n_ConstHeader )
397 : {
398 : // this is one of our god-awful, but extremely devious hacks, everyone cheer
399 0 : xTempEncrData = new BaseEncryptionData;
400 :
401 0 : OUString aMediaType;
402 0 : sal_Int32 nEncAlgorithm = 0;
403 0 : sal_Int32 nChecksumAlgorithm = 0;
404 0 : sal_Int32 nDerivedKeySize = 0;
405 0 : sal_Int32 nStartKeyGenID = 0;
406 0 : if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
407 : {
408 : // We'll want to skip the data we've just read, so calculate how much we just read
409 : // and remember it
410 0 : m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
411 0 : + xTempEncrData->m_aInitVector.getLength()
412 0 : + xTempEncrData->m_aDigest.getLength()
413 0 : + aMediaType.getLength() * sizeof( sal_Unicode );
414 0 : m_nImportedEncryptionAlgorithm = nEncAlgorithm;
415 0 : m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
416 0 : m_nImportedDerivedKeySize = nDerivedKeySize;
417 0 : m_nImportedStartKeyAlgorithm = nStartKeyGenID;
418 0 : m_nMagicalHackSize = nMagHackSize;
419 0 : sMediaType = aMediaType;
420 :
421 0 : bOk = sal_True;
422 0 : }
423 : }
424 : }
425 : }
426 0 : catch( Exception& )
427 : {
428 : }
429 :
430 0 : if ( !bOk )
431 : {
432 : // the provided stream is not a raw stream
433 0 : return sal_False;
434 : }
435 :
436 0 : m_xBaseEncryptionData = xTempEncrData;
437 0 : SetIsEncrypted ( sal_True );
438 : // it's already compressed and encrypted
439 0 : bToBeEncrypted = bToBeCompressed = sal_False;
440 :
441 0 : return sal_True;
442 : }
443 :
444 17161 : void ZipPackageStream::SetPackageMember( sal_Bool bNewValue )
445 : {
446 17161 : if ( bNewValue )
447 : {
448 14398 : m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
449 14398 : m_nMagicalHackPos = 0;
450 14398 : m_nMagicalHackSize = 0;
451 : }
452 2763 : else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
453 0 : m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
454 17161 : }
455 :
456 : // XActiveDataSink
457 : //--------------------------------------------------------------------------
458 2763 : void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
459 : throw( RuntimeException )
460 : {
461 : // if seekable access is required the wrapping will be done on demand
462 2763 : xStream = aStream;
463 2763 : m_nImportedEncryptionAlgorithm = 0;
464 2763 : m_bHasSeekable = sal_False;
465 2763 : SetPackageMember ( sal_False );
466 2763 : aEntry.nTime = -1;
467 2763 : m_nStreamMode = PACKAGE_STREAM_DETECT;
468 2763 : }
469 :
470 : //--------------------------------------------------------------------------
471 985 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
472 : throw( RuntimeException )
473 : {
474 : try
475 : {
476 985 : if ( IsPackageMember() )
477 : {
478 94 : return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
479 : }
480 891 : else if ( GetOwnSeekStream().is() )
481 : {
482 891 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
483 : }
484 : else
485 0 : return uno::Reference < io::XInputStream > ();
486 : }
487 0 : catch ( ZipException & )//rException )
488 : {
489 : OSL_FAIL( "ZipException thrown" );//rException.Message);
490 0 : return uno::Reference < io::XInputStream > ();
491 : }
492 0 : catch ( Exception & )
493 : {
494 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
495 0 : return uno::Reference < io::XInputStream > ();
496 : }
497 : }
498 :
499 : //--------------------------------------------------------------------------
500 1061 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
501 : throw( RuntimeException )
502 : {
503 : try
504 : {
505 1061 : if ( IsPackageMember() )
506 : {
507 1061 : return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
508 : }
509 0 : else if ( GetOwnSeekStream().is() )
510 : {
511 0 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
512 : }
513 : else
514 0 : return uno::Reference < io::XInputStream > ();
515 : }
516 0 : catch ( ZipException & )//rException )
517 : {
518 : OSL_FAIL( "ZipException thrown" );//rException.Message);
519 0 : return uno::Reference < io::XInputStream > ();
520 : }
521 0 : catch ( Exception &ex )
522 : {
523 : OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
524 : OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
525 : (void)ex;
526 0 : return uno::Reference < io::XInputStream > ();
527 : }
528 : }
529 :
530 : // XDataSinkEncrSupport
531 : //--------------------------------------------------------------------------
532 6353 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
533 : throw ( packages::WrongPasswordException,
534 : io::IOException,
535 : RuntimeException )
536 : {
537 : // There is no stream attached to this object
538 6353 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
539 2026 : return uno::Reference< io::XInputStream >();
540 :
541 : // this method can not be used together with old approach
542 4327 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
543 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
544 :
545 4327 : if ( IsPackageMember() )
546 : {
547 4161 : uno::Reference< io::XInputStream > xResult;
548 : try
549 : {
550 4161 : xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
551 : }
552 0 : catch( packages::WrongPasswordException& )
553 : {
554 : // workaround for the encrypted documents generated with the old OOo1.x bug.
555 0 : if ( rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 && !m_bUseWinEncoding )
556 : {
557 0 : xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
558 0 : m_bUseWinEncoding = true;
559 : }
560 : else
561 0 : throw;
562 : }
563 4161 : return xResult;
564 : }
565 166 : else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
566 0 : return ZipFile::StaticGetDataFromRawStream( m_xContext, GetOwnSeekStream(), GetEncryptionData() );
567 166 : else if ( GetOwnSeekStream().is() )
568 : {
569 166 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
570 : }
571 : else
572 0 : return uno::Reference< io::XInputStream >();
573 : }
574 :
575 : //--------------------------------------------------------------------------
576 0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
577 : throw ( packages::NoEncryptionException,
578 : io::IOException,
579 : uno::RuntimeException )
580 : {
581 : // There is no stream attached to this object
582 0 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
583 0 : return uno::Reference< io::XInputStream >();
584 :
585 : // this method can not be used together with old approach
586 0 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
587 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
588 :
589 0 : if ( IsPackageMember() )
590 : {
591 0 : if ( !bIsEncrypted || !GetEncryptionData().is() )
592 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
593 :
594 0 : return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() );
595 : }
596 0 : else if ( GetOwnSeekStream().is() )
597 : {
598 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
599 : {
600 0 : return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
601 : }
602 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
603 0 : return TryToGetRawFromDataStream( sal_True );
604 : }
605 :
606 0 : throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
607 : }
608 :
609 :
610 : //--------------------------------------------------------------------------
611 2763 : void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
612 : throw ( io::IOException,
613 : RuntimeException )
614 : {
615 2763 : setInputStream( aStream );
616 2763 : m_nStreamMode = PACKAGE_STREAM_DATA;
617 2763 : }
618 :
619 : //--------------------------------------------------------------------------
620 0 : void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
621 : throw ( packages::EncryptionNotAllowedException,
622 : packages::NoRawFormatException,
623 : io::IOException,
624 : RuntimeException )
625 : {
626 : // wrap the stream in case it is not seekable
627 0 : uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xContext );
628 0 : uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
629 0 : if ( !xSeek.is() )
630 : throw RuntimeException(OSL_LOG_PREFIX "The stream must support XSeekable!",
631 0 : uno::Reference< XInterface >() );
632 :
633 0 : xSeek->seek( 0 );
634 0 : uno::Reference< io::XInputStream > xOldStream = xStream;
635 0 : xStream = xNewStream;
636 0 : if ( !ParsePackageRawStream() )
637 : {
638 0 : xStream = xOldStream;
639 0 : throw packages::NoRawFormatException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
640 : }
641 :
642 : // the raw stream MUST have seekable access
643 0 : m_bHasSeekable = sal_True;
644 :
645 0 : SetPackageMember ( sal_False );
646 0 : aEntry.nTime = -1;
647 0 : m_nStreamMode = PACKAGE_STREAM_RAW;
648 0 : }
649 :
650 : //--------------------------------------------------------------------------
651 0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
652 : throw ( io::IOException,
653 : uno::RuntimeException )
654 : {
655 : // There is no stream attached to this object
656 0 : if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
657 0 : return uno::Reference< io::XInputStream >();
658 :
659 : // this method can not be used together with old approach
660 0 : if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
661 0 : throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
662 :
663 0 : if ( IsPackageMember() )
664 : {
665 0 : return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
666 : }
667 0 : else if ( GetOwnSeekStream().is() )
668 : {
669 0 : if ( m_nStreamMode == PACKAGE_STREAM_RAW )
670 : {
671 : // the header should not be returned here
672 0 : return GetRawEncrStreamNoHeaderCopy();
673 : }
674 0 : else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
675 0 : return TryToGetRawFromDataStream( sal_False );
676 : }
677 :
678 0 : return uno::Reference< io::XInputStream >();
679 : }
680 :
681 : // XUnoTunnel
682 :
683 : //--------------------------------------------------------------------------
684 10997 : sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
685 : throw( RuntimeException )
686 : {
687 10997 : sal_Int64 nMe = 0;
688 21994 : if ( aIdentifier.getLength() == 16 &&
689 10997 : 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
690 7119 : nMe = reinterpret_cast < sal_Int64 > ( this );
691 10997 : return nMe;
692 : }
693 :
694 : // XPropertySet
695 : //--------------------------------------------------------------------------
696 13217 : void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
697 : throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
698 : {
699 13217 : if ( aPropertyName == "MediaType" )
700 : {
701 2919 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
702 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
703 :
704 2919 : if ( aValue >>= sMediaType )
705 : {
706 2919 : if ( !sMediaType.isEmpty() )
707 : {
708 3656 : if ( sMediaType.indexOf ( "text" ) != -1
709 1828 : || sMediaType == "application/vnd.sun.star.oleobject" )
710 1021 : bToBeCompressed = sal_True;
711 807 : else if ( !m_bCompressedIsSetFromOutside )
712 659 : bToBeCompressed = sal_False;
713 : }
714 : }
715 : else
716 : throw IllegalArgumentException(OSL_LOG_PREFIX "MediaType must be a string!\n",
717 : uno::Reference< XInterface >(),
718 0 : 2 );
719 :
720 : }
721 10298 : else if ( aPropertyName == "Size" )
722 : {
723 0 : if ( !( aValue >>= aEntry.nSize ) )
724 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Size property!\n",
725 : uno::Reference< XInterface >(),
726 0 : 2 );
727 : }
728 10298 : else if ( aPropertyName == "Encrypted" )
729 : {
730 4908 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
731 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
732 :
733 4908 : sal_Bool bEnc = sal_False;
734 4908 : if ( aValue >>= bEnc )
735 : {
736 : // In case of new raw stream, the stream must not be encrypted on storing
737 4908 : if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
738 : throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
739 : uno::Reference< XInterface >(),
740 0 : 2 );
741 :
742 4908 : bToBeEncrypted = bEnc;
743 4908 : if ( bToBeEncrypted && !m_xBaseEncryptionData.is() )
744 2302 : m_xBaseEncryptionData = new BaseEncryptionData;
745 : }
746 : else
747 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Encrypted property!\n",
748 : uno::Reference< XInterface >(),
749 0 : 2 );
750 :
751 : }
752 5390 : else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
753 : {
754 0 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
755 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
756 :
757 0 : uno::Sequence< sal_Int8 > aNewKey;
758 :
759 0 : if ( !( aValue >>= aNewKey ) )
760 : {
761 0 : OUString sTempString;
762 0 : if ( ( aValue >>= sTempString ) )
763 : {
764 0 : sal_Int32 nPathLength = sTempString.getLength();
765 0 : Sequence < sal_Int8 > aSequence ( nPathLength );
766 0 : sal_Int8 *pArray = aSequence.getArray();
767 0 : const sal_Unicode *pChar = sTempString.getStr();
768 0 : for ( sal_Int16 i = 0; i < nPathLength; i++ )
769 0 : pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
770 0 : aNewKey = aSequence;
771 : }
772 : else
773 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n",
774 : uno::Reference< XInterface >(),
775 0 : 2 );
776 : }
777 :
778 0 : if ( aNewKey.getLength() )
779 : {
780 0 : if ( !m_xBaseEncryptionData.is() )
781 0 : m_xBaseEncryptionData = new BaseEncryptionData;
782 :
783 0 : m_aEncryptionKey = aNewKey;
784 : // In case of new raw stream, the stream must not be encrypted on storing
785 0 : bHaveOwnKey = sal_True;
786 0 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
787 0 : bToBeEncrypted = sal_True;
788 : }
789 : else
790 : {
791 0 : bHaveOwnKey = sal_False;
792 0 : m_aEncryptionKey.realloc( 0 );
793 : }
794 :
795 0 : m_aStorageEncryptionKeys.realloc( 0 );
796 : }
797 5390 : else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
798 : {
799 2471 : if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
800 0 : throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
801 :
802 2471 : uno::Sequence< beans::NamedValue > aKeys;
803 2471 : if ( !( aValue >>= aKeys ) )
804 : {
805 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n",
806 : uno::Reference< XInterface >(),
807 0 : 2 );
808 : }
809 :
810 2471 : if ( aKeys.getLength() )
811 : {
812 13 : if ( !m_xBaseEncryptionData.is() )
813 0 : m_xBaseEncryptionData = new BaseEncryptionData;
814 :
815 13 : m_aStorageEncryptionKeys = aKeys;
816 :
817 : // In case of new raw stream, the stream must not be encrypted on storing
818 13 : bHaveOwnKey = sal_True;
819 13 : if ( m_nStreamMode != PACKAGE_STREAM_RAW )
820 13 : bToBeEncrypted = sal_True;
821 : }
822 : else
823 : {
824 2458 : bHaveOwnKey = sal_False;
825 2458 : m_aStorageEncryptionKeys.realloc( 0 );
826 : }
827 :
828 2471 : m_aEncryptionKey.realloc( 0 );
829 : }
830 2919 : else if ( aPropertyName == "Compressed" )
831 : {
832 2919 : sal_Bool bCompr = sal_False;
833 :
834 2919 : if ( aValue >>= bCompr )
835 : {
836 : // In case of new raw stream, the stream must not be encrypted on storing
837 2919 : if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
838 : throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
839 : uno::Reference< XInterface >(),
840 0 : 2 );
841 :
842 2919 : bToBeCompressed = bCompr;
843 2919 : m_bCompressedIsSetFromOutside = sal_True;
844 : }
845 : else
846 : throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Compressed property!\n",
847 : uno::Reference< XInterface >(),
848 0 : 2 );
849 : }
850 : else
851 0 : throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
852 13217 : }
853 :
854 : //--------------------------------------------------------------------------
855 22141 : Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
856 : throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException )
857 : {
858 22141 : Any aAny;
859 22141 : if ( PropertyName == "MediaType" )
860 : {
861 4954 : aAny <<= sMediaType;
862 4954 : return aAny;
863 : }
864 17187 : else if ( PropertyName == "Size" )
865 : {
866 5599 : aAny <<= aEntry.nSize;
867 5599 : return aAny;
868 : }
869 11588 : else if ( PropertyName == "Encrypted" )
870 : {
871 2772 : aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) ? sal_True : bToBeEncrypted);
872 2772 : return aAny;
873 : }
874 8816 : else if ( PropertyName == "WasEncrypted" )
875 : {
876 3190 : aAny <<= bIsEncrypted;
877 3190 : return aAny;
878 : }
879 5626 : else if ( PropertyName == "Compressed" )
880 : {
881 5599 : aAny <<= bToBeCompressed;
882 5599 : return aAny;
883 : }
884 27 : else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
885 : {
886 0 : aAny <<= m_aEncryptionKey;
887 0 : return aAny;
888 : }
889 27 : else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
890 : {
891 27 : aAny <<= m_aStorageEncryptionKeys;
892 27 : return aAny;
893 : }
894 : else
895 0 : throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
896 : }
897 :
898 : //--------------------------------------------------------------------------
899 20 : void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
900 : {
901 20 : if ( aEntry.nCompressedSize != nNewSize )
902 20 : aEntry.nMethod = DEFLATED;
903 20 : aEntry.nSize = nNewSize;
904 20 : }
905 : //--------------------------------------------------------------------------
906 0 : OUString ZipPackageStream::getImplementationName()
907 : throw ( RuntimeException )
908 : {
909 0 : return OUString ("ZipPackageStream");
910 : }
911 :
912 : //--------------------------------------------------------------------------
913 0 : Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
914 : throw ( RuntimeException )
915 : {
916 0 : Sequence< OUString > aNames( 1 );
917 0 : aNames[0] = "com.sun.star.packages.PackageStream";
918 0 : return aNames;
919 : }
920 : //--------------------------------------------------------------------------
921 0 : sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
922 : throw ( RuntimeException )
923 : {
924 0 : return rServiceName == getSupportedServiceNames()[0];
925 : }
926 :
927 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|