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