22#include <com/sun/star/beans/PropertyValue.hpp>
23#include <com/sun/star/container/XNameContainer.hpp>
24#include <com/sun/star/packages/NoRawFormatException.hpp>
25#include <com/sun/star/packages/zip/ZipConstants.hpp>
26#include <com/sun/star/embed/StorageFormats.hpp>
27#include <com/sun/star/packages/zip/ZipIOException.hpp>
28#include <com/sun/star/packages/NoEncryptionException.hpp>
29#include <com/sun/star/packages/zip/ZipException.hpp>
30#include <com/sun/star/packages/WrongPasswordException.hpp>
31#include <com/sun/star/io/TempFile.hpp>
32#include <com/sun/star/io/XInputStream.hpp>
33#include <com/sun/star/io/XOutputStream.hpp>
34#include <com/sun/star/io/XStream.hpp>
35#include <com/sun/star/io/XSeekable.hpp>
36#include <com/sun/star/xml/crypto/DigestID.hpp>
37#include <com/sun/star/xml/crypto/CipherID.hpp>
45#include <osl/diagnose.h>
54#include <rtl/random.h>
63using namespace com::sun::star::packages::zip::ZipConstants;
64using namespace com::sun::star::packages::zip;
70#if OSL_DEBUG_LEVEL > 0
71#define THROW_WHERE SAL_WHERE
77 const uno::Reference< XComponentContext >& xContext,
79 bool bAllowRemoveOnInsert )
80: m_rZipPackage( rNewPackage )
81, m_bToBeCompressed ( true )
82, m_bToBeEncrypted ( false )
83, m_bHaveOwnKey ( false )
84, m_bIsEncrypted ( false )
85, m_nImportedStartKeyAlgorithm( 0 )
86, m_nImportedEncryptionAlgorithm( 0 )
87, m_nImportedChecksumAlgorithm( 0 )
88, m_nImportedDerivedKeySize( 0 )
90, m_nMagicalHackPos( 0 )
91, m_nMagicalHackSize( 0 )
92, m_nOwnStreamOrigSize( 0 )
93, m_bHasSeekable( false )
94, m_bCompressedIsSetFromOutside( false )
95, m_bFromManifest( false )
96, m_bUseWinEncoding( false )
97, m_bRawStream( false )
101 mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
103 aEntry.nVersion = -1;
108 aEntry.nCompressedSize = -1;
111 aEntry.nPathLen = -1;
112 aEntry.nExtraLen = -1;
121 aEntry.nVersion = rInEntry.
nVersion;
122 aEntry.nFlag = rInEntry.
nFlag;
123 aEntry.nMethod = rInEntry.
nMethod;
124 aEntry.nTime = rInEntry.
nTime;
125 aEntry.nCrc = rInEntry.
nCrc;
127 aEntry.nSize = rInEntry.
nSize;
128 aEntry.nOffset = rInEntry.
nOffset;
129 aEntry.sPath = rInEntry.
sPath;
130 aEntry.nPathLen = rInEntry.
nPathLen;
133 if ( aEntry.nMethod == STORED )
146 uno::Reference< io::XSeekable > xSeek(
m_xStream, UNO_QUERY_THROW );
160 throw ZipIOException(
THROW_WHERE "Encrypted stream without encryption data!" );
164 throw ZipIOException(
THROW_WHERE "The stream must be seekable!" );
172 uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();
176 xTempFile->closeOutput();
177 xTempFile->seek( 0 );
210 uno::Sequence< sal_Int8 > aResult;
216 OUString aNameToFind;
217 if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
219 else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
221 aNameToFind = bUseWinEncoding
228 throw uno::RuntimeException(
THROW_WHERE "No expected key is provided!" );
231 if ( rKey.Name == aNameToFind )
232 rKey.Value >>= aResult;
236 if ( !aResult.hasElements() )
237 throw uno::RuntimeException(
THROW_WHERE "No expected key is provided!" );
258 throw packages::NoEncryptionException(
THROW_WHERE );
265 if ( !aKey.hasElements() )
266 throw packages::NoEncryptionException(
THROW_WHERE );
278 pPackage->initialize( aArgs );
281 uno::Reference< XDataSinkEncrSupport > xNewPackStream( pPackage->createInstance(), UNO_QUERY_THROW );
282 xNewPackStream->setDataStream(
285 uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY_THROW );
288 xNewPSProps->setPropertyValue(
"MediaType",
Any( msMediaType ) );
293 xNewPSProps->setPropertyValue(
"Encrypted",
Any(
true ) );
297 uno::Reference< XInterface > xTmp;
298 Any aRoot = pPackage->getByHierarchicalName(
"/");
300 uno::Reference< container::XNameContainer > xRootNameContainer( xTmp, UNO_QUERY_THROW );
302 uno::Reference< XInterface > xNPSDummy( xNewPackStream, UNO_QUERY );
303 xRootNameContainer->insertByName(
"dummy",
Any( xNPSDummy ) );
306 pPackage->commitChanges();
309 uno::Reference< io::XInputStream > xInRaw;
310 if ( bAddHeaderForEncr )
311 xInRaw = xNewPackStream->getRawStream();
313 xInRaw = xNewPackStream->getPlainRawStream();
317 uno::Reference < io::XInputStream > xTempIn( xTempOut );
321 xTempOut->closeOutput();
328 xNewPackStream.clear();
330 xRootNameContainer.clear();
362 const sal_Int8 *pHeader = aHeader.getConstArray();
363 sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
364 ( pHeader [1] & 0xFF ) << 8 |
365 ( pHeader [2] & 0xFF ) << 16 |
366 ( pHeader [3] & 0xFF ) << 24;
373 sal_Int32 nEncAlgorithm = 0;
374 sal_Int32 nChecksumAlgorithm = 0;
375 sal_Int32 nDerivedKeySize = 0;
376 sal_Int32 nStartKeyGenID = 0;
377 sal_Int32 nMagHackSize = 0;
378 if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType,
GetOwnSeekStream() ) )
383 + xTempEncrData->m_aInitVector.getLength()
384 + xTempEncrData->m_aDigest.getLength()
391 msMediaType = aMediaType;
429 const OUString &rPath,
430 std::vector < uno::Sequence < beans::PropertyValue > > &rManList,
432 const uno::Sequence < sal_Int8 >& rEncryptionKey,
433 sal_Int32 nPBKDF2IterationCount,
436 bool bSuccess =
true;
438 static constexpr OUStringLiteral sDigestProperty (
u"Digest");
439 static constexpr OUStringLiteral sEncryptionAlgProperty (
u"EncryptionAlgorithm");
440 static constexpr OUStringLiteral sStartKeyAlgProperty (
u"StartKeyAlgorithm");
441 static constexpr OUStringLiteral sDigestAlgProperty (
u"DigestAlgorithm");
442 static constexpr OUStringLiteral sDerivedKeySizeProperty (
u"DerivedKeySize");
451 std::unique_ptr < ZipEntry > pAutoTempEntry (
new ZipEntry(aEntry) );
452 ZipEntry* pTempEntry = pAutoTempEntry.get();
454 pTempEntry->
sPath = rPath;
460 auto pPropSet = aPropSet.getArray();
476 bool bBackgroundThreadDeflate =
false;
477 bool bTransportOwnEncrStreamAsRaw =
false;
482 bool bUseNonSeekableAccess =
false;
483 uno::Reference < io::XInputStream >
xStream;
491 uno::Reference < io::XSeekable > xSeek (
xStream, uno::UNO_QUERY );
493 bUseNonSeekableAccess = (
xStream.is() && !xSeek.is() );
496 if ( !bUseNonSeekableAccess )
502 OSL_FAIL(
"ZipPackageStream didn't have a stream associated with it, skipping!" );
507 uno::Reference < io::XSeekable > xSeek (
xStream, uno::UNO_QUERY );
517 OSL_ENSURE( !
m_bRawStream || !(bToBeCompressed || bToBeEncrypted),
"The stream is already encrypted!" );
523 else if ( bToBeEncrypted )
526 pTempEntry->
nSize = xSeek->getLength();
544 bTransportOwnEncrStreamAsRaw =
true;
560 catch ( uno::Exception& )
566 if ( bToBeEncrypted ||
m_bRawStream || bTransportOwnEncrStreamAsRaw )
568 if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
570 uno::Sequence < sal_Int8 > aSalt( 16 ), aVector(
GetBlockSize() );
571 rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
572 rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
587 pPropSet = aPropSet.getArray();
603 if ( !xEncData.is() )
604 throw uno::RuntimeException();
622 if ( !bUseNonSeekableAccess
625 && ( ( aEntry.nMethod == DEFLATED && bToBeCompressed )
626 || ( aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
649 pAutoTempEntry.release();
670 catch ( io::IOException& )
698 if ( bToBeCompressed )
700 pTempEntry->
nMethod = DEFLATED;
701 pTempEntry->
nCrc = -1;
705 uno::Reference< io::XSeekable > xSeek(
xStream, uno::UNO_QUERY);
718 pAutoTempEntry.release();
720 if (pTempEntry->
nMethod == STORED)
724 rZipOut.
writeLOC(pTempEntry, bToBeEncrypted);
739 bBackgroundThreadDeflate = !bToBeEncrypted;
743 sal_Int64 estimatedSize = xSeek.is() ? xSeek->getLength() :
xStream->available();
745 if (estimatedSize > 1000000)
750 bBackgroundThreadDeflate =
false;
751 rZipOut.
writeLOC(pTempEntry, bToBeEncrypted);
756 else if (bBackgroundThreadDeflate && estimatedSize > 100000)
768 m_xContext, *pTempEntry,
this, bToBeEncrypted);
774 bBackgroundThreadDeflate =
false;
775 rZipOut.
writeLOC(pTempEntry, bToBeEncrypted);
786 catch ( io::IOException& )
791 if ( bToBeEncrypted )
794 if ( !xEncData.is() )
795 throw uno::RuntimeException();
812 if (bSuccess && !bBackgroundThreadDeflate)
815 if ( aPropSet.hasElements()
816 && (
m_nFormat == embed::StorageFormats::PACKAGE ||
m_nFormat == embed::StorageFormats::OFOPXML ) )
817 rManList.push_back( aPropSet );
849 aEntry.nOffset *= -1;
889 return uno::Reference < io::XInputStream > ();
894 return uno::Reference < io::XInputStream > ();
899 return uno::Reference < io::XInputStream > ();
916 return uno::Reference < io::XInputStream > ();
921 return uno::Reference < io::XInputStream > ();
926 return uno::Reference < io::XInputStream > ();
935 return uno::Reference< io::XInputStream >();
943 uno::Reference< io::XInputStream > xResult;
948 catch(
const packages::WrongPasswordException& )
952 SAL_WARN(
"package",
"ZipPackageStream::getDataStream(): SHA1 mismatch, trying fallbacks...");
958 catch (
const packages::WrongPasswordException&)
975 catch (
const packages::WrongPasswordException&)
1003 return uno::Reference< io::XInputStream >();
1010 return uno::Reference< io::XInputStream >();
1014 throw packages::zip::ZipIOException(
THROW_WHERE );
1019 throw packages::NoEncryptionException(
THROW_WHERE );
1033 throw packages::NoEncryptionException(
THROW_WHERE );
1046 uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY_THROW );
1048 uno::Reference< io::XInputStream > xOldStream =
m_xStream;
1053 throw packages::NoRawFormatException(
THROW_WHERE );
1068 return uno::Reference< io::XInputStream >();
1072 throw packages::zip::ZipIOException(
THROW_WHERE );
1089 return uno::Reference< io::XInputStream >();
1095 if ( aPropertyName ==
"MediaType" )
1100 if ( !(aValue >>= msMediaType) )
1101 throw IllegalArgumentException(
THROW_WHERE "MediaType must be a string!",
1102 uno::Reference< XInterface >(),
1105 if ( !msMediaType.isEmpty() )
1107 if ( msMediaType.indexOf (
"text" ) != -1
1108 || msMediaType ==
"application/vnd.sun.star.oleobject" )
1114 else if ( aPropertyName ==
"Size" )
1116 if ( !( aValue >>= aEntry.nSize ) )
1117 throw IllegalArgumentException(
THROW_WHERE "Wrong type for Size property!",
1118 uno::Reference< XInterface >(),
1121 else if ( aPropertyName ==
"Encrypted" )
1127 if ( !(aValue >>= bEnc) )
1128 throw IllegalArgumentException(
THROW_WHERE "Wrong type for Encrypted property!",
1129 uno::Reference< XInterface >(),
1134 throw IllegalArgumentException(
THROW_WHERE "Raw stream can not be encrypted on storing",
1135 uno::Reference< XInterface >(),
1148 uno::Sequence< sal_Int8 > aNewKey;
1150 if ( !( aValue >>= aNewKey ) )
1152 OUString sTempString;
1153 if ( !(aValue >>= sTempString) )
1154 throw IllegalArgumentException(
THROW_WHERE "Wrong type for EncryptionKey property!",
1155 uno::Reference< XInterface >(),
1158 sal_Int32 nPathLength = sTempString.getLength();
1160 sal_Int8 *pArray = aSequence.getArray();
1162 for ( sal_Int32
i = 0;
i < nPathLength;
i++ )
1164 aNewKey = aSequence;
1167 if ( aNewKey.hasElements() )
1191 uno::Sequence< beans::NamedValue > aKeys;
1192 if ( !( aValue >>= aKeys ) )
1194 throw IllegalArgumentException(
THROW_WHERE "Wrong type for StorageEncryptionKeys property!",
1195 uno::Reference< XInterface >(),
1199 if ( aKeys.hasElements() )
1219 else if ( aPropertyName ==
"Compressed" )
1221 bool bCompr =
false;
1223 if ( !(aValue >>= bCompr) )
1224 throw IllegalArgumentException(
THROW_WHERE "Wrong type for Compressed property!",
1225 uno::Reference< XInterface >(),
1230 throw IllegalArgumentException(
THROW_WHERE "Raw stream can not be encrypted on storing",
1231 uno::Reference< XInterface >(),
1238 throw beans::UnknownPropertyException(aPropertyName);
1243 if ( PropertyName ==
"MediaType" )
1245 return Any(msMediaType);
1247 else if ( PropertyName ==
"Size" )
1249 return Any(aEntry.nSize);
1251 else if ( PropertyName ==
"Encrypted" )
1255 else if ( PropertyName ==
"WasEncrypted" )
1259 else if ( PropertyName ==
"Compressed" )
1272 throw beans::UnknownPropertyException(PropertyName);
1277 if ( aEntry.nCompressedSize != nNewSize )
1278 aEntry.nMethod = DEFLATED;
1279 aEntry.nSize = nNewSize;
1283 return "ZipPackageStream";
1288 return {
"com.sun.star.packages.PackageStream" };
Reference< XComponentContext > m_xContext
#define PKG_MNFST_DERKEYSIZE
#define PKG_MNFST_DIGESTALG
#define PKG_MNFST_UCOMPSIZE
#define PKG_SIZE_NOENCR_MNFST
#define PKG_MNFST_ITERATION
#define PKG_MNFST_MEDIATYPE
#define PKG_MNFST_STARTALG
constexpr OUStringLiteral STORAGE_ENCRYPTION_KEYS_PROPERTY
#define PKG_MNFST_VERSION
#define PKG_SIZE_ENCR_MNFST
const sal_Int32 n_ConstBufferSize
#define PKG_MNFST_FULLPATH
#define PKG_MNFST_INIVECTOR
constexpr OUStringLiteral ENCRYPTION_KEY_PROPERTY
static void ImplSetStoredData(ZipEntry &rEntry, uno::Reference< io::XInputStream > const &rStream)
#define PACKAGE_STREAM_PACKAGEMEMBER
#define PACKAGE_STREAM_RAW
#define PACKAGE_STREAM_NOTSET
#define PACKAGE_STREAM_DETECT
#define PACKAGE_STREAM_DATA
sal_Int32 getValue() const
sal_Int64 updateStream(css::uno::Reference< css::io::XInputStream > const &xStream)
std::unique_ptr< comphelper::ThreadTask > createTask(const std::shared_ptr< comphelper::ThreadTaskTag > &pTag, const css::uno::Reference< css::io::XInputStream > &xInStream)
void writeStream(const css::uno::Reference< css::io::XInputStream > &xInStream) override
void writeStream(const css::uno::Reference< css::io::XInputStream > &xInStream) override
void writeLOC(ZipEntry *pEntry, bool bEncrypt=false)
void rawCloseEntry(bool bEncrypt=false)
const css::uno::Reference< css::io::XOutputStream > & getStream() const
void rawWrite(const css::uno::Sequence< sal_Int8 > &rBuffer)
const std::shared_ptr< comphelper::ThreadTaskTag > & getThreadTaskTag() const
static void setEntry(ZipEntry *pEntry)
void addDeflatingThreadTask(ZipOutputEntryInThread *pEntry, std::unique_ptr< comphelper::ThreadTask > pThreadTask)
void reduceScheduledThreadTasksToGivenNumberOrLess(std::size_t nThreadTasks)
virtual css::uno::Any SAL_CALL getPropertyValue(const OUString &PropertyName) override
virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getPlainRawStream() override
sal_Int32 m_nImportedChecksumAlgorithm
sal_Int32 GetBlockSize() const
void successfullyWritten(ZipEntry const *pEntry)
::rtl::Reference< BaseEncryptionData > m_xBaseEncryptionData
virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getDataStream() override
css::uno::Reference< css::io::XInputStream > GetRawEncrStreamNoHeaderCopy()
css::uno::Sequence< sal_Int8 > m_aEncryptionKey
virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getRawStream() override
css::uno::Reference< css::io::XInputStream > getRawData()
get raw data using unbuffered stream
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual css::uno::Reference< css::io::XInputStream > SAL_CALL getInputStream() override
void SetPackageMember(bool bNewValue)
css::uno::Reference< css::io::XInputStream > TryToGetRawFromDataStream(bool bAddHeaderForEncr)
virtual void SAL_CALL setInputStream(const css::uno::Reference< css::io::XInputStream > &aStream) override
sal_Int64 m_nOwnStreamOrigSize
virtual void SAL_CALL setPropertyValue(const OUString &aPropertyName, const css::uno::Any &aValue) override
sal_Int32 m_nImportedStartKeyAlgorithm
ZipPackageStream(ZipPackage &rNewPackage, const css::uno::Reference< css::uno::XComponentContext > &xContext, sal_Int32 nFormat, bool bAllowRemoveOnInsert)
::rtl::Reference< EncryptionData > GetEncryptionData(Bugs bugs=Bugs::None)
void SetToBeEncrypted(bool bNewValue)
ZipPackage & m_rZipPackage
sal_uInt32 m_nMagicalHackPos
void SetIsEncrypted(bool bNewValue)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
sal_Int32 m_nImportedDerivedKeySize
virtual void SAL_CALL setDataStream(const css::uno::Reference< css::io::XInputStream > &aStream) override
bool ParsePackageRawStream()
sal_Int32 GetStartKeyGenID() const
bool IsPackageMember() const
virtual bool saveChild(const OUString &rPath, std::vector< css::uno::Sequence< css::beans::PropertyValue > > &rManList, ZipOutputStream &rZipOut, const css::uno::Sequence< sal_Int8 > &rEncryptionKey, sal_Int32 nPBKDF2IterationCount, const rtlRandomPool &rRandomPool) override
sal_Int32 GetEncryptionAlgorithm() const
virtual ~ZipPackageStream() override
void setInitialisationVector(const css::uno::Sequence< sal_Int8 > &rNewVector)
void setSalt(const css::uno::Sequence< sal_Int8 > &rNewSalt)
virtual OUString SAL_CALL getImplementationName() override
bool m_bCompressedIsSetFromOutside
css::uno::Sequence< css::beans::NamedValue > m_aStorageEncryptionKeys
css::uno::Reference< css::io::XInputStream > const & GetOwnSeekStream()
Check that m_xStream implements io::XSeekable and return it.
sal_uInt32 m_nMagicalHackSize
sal_Int32 m_nImportedEncryptionAlgorithm
void setSize(const sal_Int64 nNewSize)
virtual void SAL_CALL setRawStream(const css::uno::Reference< css::io::XInputStream > &aStream) override
css::uno::Reference< css::io::XInputStream > m_xStream
void setZipEntryOnLoading(const ZipEntry &rInEntry)
void setIterationCount(const sal_Int32 nNewCount)
css::uno::Sequence< sal_Int8 > GetEncryptionKey(Bugs bugs=Bugs::None)
sal_Int32 getFormat() const
rtl::Reference< comphelper::RefCountedMutex > & GetSharedMutexRef()
sal_Int32 GetStartKeyGenID() const
sal_Int32 GetDefaultDerivedKeySize() const
sal_Int32 GetChecksumAlgID() const
sal_Int32 GetEncAlgID() const
css::uno::Sequence< sal_Int8 > GetEncryptionKey()
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
static std::size_t getPreferredConcurrency()
#define TOOLS_WARN_EXCEPTION(area, stream)
Sequence< sal_Int8 > aSeq
#define SAL_WARN(area, stream)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
sal_uInt16 const m_nFormat
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1UTF8
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1CORRECT
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA1MS1252
constexpr OUStringLiteral PACKAGE_ENCRYPTIONDATA_SHA256UTF8
sal_Int64 nCompressedSize