Split ZipPackageFolder::saveChild into two functions

And make them static. Probably would be better to kill ContentInfo and
add saveChild as pure virtual into ZipPackageEntry, from which are both
ZipPackageFolder and ZipPackageStream inheriting.

This will also create a bit more sensible call graph when profiling.

Change-Id: If8151332cfa6359e8736c912b7a5633a9162ab36
This commit is contained in:
Matúš Kukan
2014-10-07 16:04:13 +02:00
parent 04ebf43708
commit 9f495d128e
2 changed files with 360 additions and 310 deletions

View File

@@ -79,10 +79,13 @@ public:
void setPackageFormat_Impl( sal_Int32 nFormat ) { m_nFormat = nFormat; }
void setRemoveOnInsertMode_Impl( bool bRemove ) { this->mbAllowRemoveOnInsert = bRemove; }
bool saveChild(const OUString &rShortName, const com::sun::star::packages::ContentInfo &rInfo, OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, const com::sun::star::uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool & rRandomPool) const;
// Recursive functions
void saveContents(OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, const com::sun::star::uno::Sequence< sal_Int8 > &rEncryptionKey, rtlRandomPool & rRandomPool) const
void saveContents(
const OUString &rPath,
std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList,
ZipOutputStream & rZipOut,
const com::sun::star::uno::Sequence< sal_Int8 > &rEncryptionKey,
const rtlRandomPool & rRandomPool) const
throw(::com::sun::star::uno::RuntimeException);
void releaseUpwardRef();

View File

@@ -294,7 +294,57 @@ static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< XInputStream>
rEntry.nCrc = aCRC32.getValue();
}
bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo &rInfo, OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool) const
static bool ZipPackageFolder_saveChild(
const ContentInfo &rInfo,
const OUString &rPath,
std::vector < uno::Sequence < PropertyValue > > &rManList,
ZipOutputStream & rZipOut,
const uno::Sequence < sal_Int8 >& rEncryptionKey,
const rtlRandomPool &rRandomPool,
sal_Int32 nFormat)
{
bool bSuccess = true;
const OUString sMediaTypeProperty ("MediaType");
const OUString sVersionProperty ("Version");
const OUString sFullPathProperty ("FullPath");
uno::Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
assert( rInfo.bFolder && rInfo.pFolder && "A valid child object is expected!" );
OUString sTempName = rPath + "/";
if ( !rInfo.pFolder->GetMediaType().isEmpty() )
{
aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pFolder->GetMediaType();
aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
aPropSet[PKG_MNFST_VERSION].Value <<= rInfo.pFolder->GetVersion();
aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
aPropSet[PKG_MNFST_FULLPATH].Value <<= sTempName;
}
else
aPropSet.realloc( 0 );
rInfo.pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool);
// folder can have a mediatype only in package format
if ( aPropSet.getLength()
&& ( nFormat == embed::StorageFormats::PACKAGE || ( nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) )
rManList.push_back( aPropSet );
return bSuccess;
}
static bool ZipPackageStream_saveChild(
const ContentInfo &rInfo,
const OUString &rPath,
std::vector < uno::Sequence < PropertyValue > > &rManList,
ZipOutputStream & rZipOut,
const uno::Sequence < sal_Int8 >& rEncryptionKey,
const rtlRandomPool &rRandomPool,
sal_Int32 nFormat)
{
bool bSuccess = true;
@@ -309,311 +359,165 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo
const OUString sEncryptionAlgProperty ("EncryptionAlgorithm");
const OUString sStartKeyAlgProperty ("StartKeyAlgorithm");
const OUString sDigestAlgProperty ("DigestAlgorithm");
const OUString sDerivedKeySizeProperty ("DerivedKeySize");
const OUString sDerivedKeySizeProperty ("DerivedKeySize");
uno::Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
OSL_ENSURE( ( rInfo.bFolder && rInfo.pFolder ) || ( !rInfo.bFolder && rInfo.pStream ), "A valid child object is expected!" );
if ( rInfo.bFolder )
assert( !rInfo.bFolder && rInfo.pStream && "A valid child object is expected!" );
// if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
// and be deleted in the ZipOutputStream destructor
unique_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry );
ZipEntry* pTempEntry = pAutoTempEntry.get();
// In case the entry we are reading is also the entry we are writing, we will
// store the ZipEntry data in pTempEntry
ZipPackageFolder::copyZipEntry ( *pTempEntry, rInfo.pStream->aEntry );
pTempEntry->sPath = rPath;
pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
bool bToBeEncrypted = rInfo.pStream->IsToBeEncrypted() && (rEncryptionKey.getLength() || rInfo.pStream->HasOwnKey());
bool bToBeCompressed = bToBeEncrypted ? sal_True : rInfo.pStream->IsToBeCompressed();
aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pStream->GetMediaType( );
aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
aPropSet[PKG_MNFST_VERSION].Value <<= OUString(); // no version is stored for streams currently
aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
OSL_ENSURE( rInfo.pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
bool bRawStream = false;
if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_DETECT )
bRawStream = rInfo.pStream->ParsePackageRawStream();
else if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_RAW )
bRawStream = true;
bool bTransportOwnEncrStreamAsRaw = false;
// During the storing the original size of the stream can be changed
// TODO/LATER: get rid of this hack
sal_Int64 nOwnStreamOrigSize = bRawStream ? rInfo.pStream->GetMagicalHackSize() : rInfo.pStream->getSize();
bool bUseNonSeekableAccess = false;
uno::Reference < XInputStream > xStream;
if ( !rInfo.pStream->IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed )
{
OUString sTempName = rPath + rShortName + "/";
// the stream is not a package member, not a raw stream,
// it should not be encrypted and it should be compressed,
// in this case nonseekable access can be used
if ( !rInfo.pFolder->GetMediaType().isEmpty() )
{
aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pFolder->GetMediaType();
aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
aPropSet[PKG_MNFST_VERSION].Value <<= rInfo.pFolder->GetVersion();
aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
aPropSet[PKG_MNFST_FULLPATH].Value <<= sTempName;
}
else
aPropSet.realloc( 0 );
xStream = rInfo.pStream->GetOwnStreamNoWrap();
uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
rInfo.pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool);
bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
}
else
if ( !bUseNonSeekableAccess )
{
// if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
// and be deleted in the ZipOutputStream destructor
unique_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry );
ZipEntry* pTempEntry = pAutoTempEntry.get();
xStream = rInfo.pStream->getRawData();
// In case the entry we are reading is also the entry we are writing, we will
// store the ZipEntry data in pTempEntry
ZipPackageFolder::copyZipEntry ( *pTempEntry, rInfo.pStream->aEntry );
pTempEntry->sPath = rPath + rShortName;
pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
bool bToBeEncrypted = rInfo.pStream->IsToBeEncrypted() && (rEncryptionKey.getLength() || rInfo.pStream->HasOwnKey());
bool bToBeCompressed = bToBeEncrypted ? sal_True : rInfo.pStream->IsToBeCompressed();
aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pStream->GetMediaType( );
aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
aPropSet[PKG_MNFST_VERSION].Value <<= OUString(); // no version is stored for streams currently
aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
OSL_ENSURE( rInfo.pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
bool bRawStream = false;
if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_DETECT )
bRawStream = rInfo.pStream->ParsePackageRawStream();
else if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_RAW )
bRawStream = true;
bool bTransportOwnEncrStreamAsRaw = false;
// During the storing the original size of the stream can be changed
// TODO/LATER: get rid of this hack
sal_Int64 nOwnStreamOrigSize = bRawStream ? rInfo.pStream->GetMagicalHackSize() : rInfo.pStream->getSize();
bool bUseNonSeekableAccess = false;
uno::Reference < XInputStream > xStream;
if ( !rInfo.pStream->IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed )
if ( !xStream.is() )
{
// the stream is not a package member, not a raw stream,
// it should not be encrypted and it should be compressed,
// in this case nonseekable access can be used
xStream = rInfo.pStream->GetOwnStreamNoWrap();
uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
bSuccess = false;
return bSuccess;
}
if ( !bUseNonSeekableAccess )
uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
try
{
xStream = rInfo.pStream->getRawData();
if ( !xStream.is() )
if ( xSeek.is() )
{
OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
bSuccess = false;
return bSuccess;
}
uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
try
{
if ( xSeek.is() )
// If the stream is a raw one, then we should be positioned
// at the beginning of the actual data
if ( !bToBeCompressed || bRawStream )
{
// If the stream is a raw one, then we should be positioned
// at the beginning of the actual data
if ( !bToBeCompressed || bRawStream )
{
// The raw stream can neither be encrypted nor connected
OSL_ENSURE( !bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
xSeek->seek ( bRawStream ? rInfo.pStream->GetMagicalHackPos() : 0 );
ImplSetStoredData ( *pTempEntry, xStream );
// The raw stream can neither be encrypted nor connected
OSL_ENSURE( !bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
xSeek->seek ( bRawStream ? rInfo.pStream->GetMagicalHackPos() : 0 );
ImplSetStoredData ( *pTempEntry, xStream );
// TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
}
else if ( bToBeEncrypted )
{
// this is the correct original size
pTempEntry->nSize = xSeek->getLength();
nOwnStreamOrigSize = pTempEntry->nSize;
}
// TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
}
else if ( bToBeEncrypted )
{
// this is the correct original size
pTempEntry->nSize = xSeek->getLength();
nOwnStreamOrigSize = pTempEntry->nSize;
}
xSeek->seek ( 0 );
xSeek->seek ( 0 );
}
else
{
// Okay, we don't have an xSeekable stream. This is possibly bad.
// check if it's one of our own streams, if it is then we know that
// each time we ask for it we'll get a new stream that will be
// at position zero...otherwise, assert and skip this stream...
if ( rInfo.pStream->IsPackageMember() )
{
// if the password has been changed than the stream should not be package member any more
if ( rInfo.pStream->IsEncrypted() && rInfo.pStream->IsToBeEncrypted() )
{
// Should be handled close to the raw stream handling
bTransportOwnEncrStreamAsRaw = true;
pTempEntry->nMethod = STORED;
// TODO/LATER: get rid of this situation
// this size should be different from the one that will be stored in manifest.xml
// it is used in storing algorithms and after storing the correct size will be set
pTempEntry->nSize = pTempEntry->nCompressedSize;
}
}
else
{
// Okay, we don't have an xSeekable stream. This is possibly bad.
// check if it's one of our own streams, if it is then we know that
// each time we ask for it we'll get a new stream that will be
// at position zero...otherwise, assert and skip this stream...
if ( rInfo.pStream->IsPackageMember() )
{
// if the password has been changed than the stream should not be package member any more
if ( rInfo.pStream->IsEncrypted() && rInfo.pStream->IsToBeEncrypted() )
{
// Should be handled close to the raw stream handling
bTransportOwnEncrStreamAsRaw = true;
pTempEntry->nMethod = STORED;
// TODO/LATER: get rid of this situation
// this size should be different from the one that will be stored in manifest.xml
// it is used in storing algorithms and after storing the correct size will be set
pTempEntry->nSize = pTempEntry->nCompressedSize;
}
}
else
{
bSuccess = false;
return bSuccess;
}
}
}
catch ( uno::Exception& )
{
bSuccess = false;
return bSuccess;
}
if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw )
{
if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
{
uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( rInfo.pStream->GetBlockSize() );
rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
sal_Int32 nIterationCount = 1024;
if ( !rInfo.pStream->HasOwnKey() )
rInfo.pStream->setKey ( rEncryptionKey );
rInfo.pStream->setInitialisationVector ( aVector );
rInfo.pStream->setSalt ( aSalt );
rInfo.pStream->setIterationCount ( nIterationCount );
}
// last property is digest, which is inserted later if we didn't have
// a magic header
aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
aPropSet[PKG_MNFST_INIVECTOR].Value <<= rInfo.pStream->getInitialisationVector();
aPropSet[PKG_MNFST_SALT].Name = sSaltProperty;
aPropSet[PKG_MNFST_SALT].Value <<= rInfo.pStream->getSalt();
aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
aPropSet[PKG_MNFST_ITERATION].Value <<= rInfo.pStream->getIterationCount ();
// Need to store the uncompressed size in the manifest
OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
if ( bRawStream || bTransportOwnEncrStreamAsRaw )
{
::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData();
if ( !xEncData.is() )
throw uno::RuntimeException();
aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest();
aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
}
}
}
// If the entry is already stored in the zip file in the format we
// want for this write...copy it raw
if ( !bUseNonSeekableAccess
&& ( bRawStream || bTransportOwnEncrStreamAsRaw
|| ( rInfo.pStream->IsPackageMember() && !bToBeEncrypted
&& ( ( rInfo.pStream->aEntry.nMethod == DEFLATED && bToBeCompressed )
|| ( rInfo.pStream->aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
{
// If it's a PackageMember, then it's an unbuffered stream and we need
// to get a new version of it as we can't seek backwards.
if ( rInfo.pStream->IsPackageMember() )
{
xStream = rInfo.pStream->getRawData();
if ( !xStream.is() )
{
// Make sure that we actually _got_ a new one !
bSuccess = false;
return bSuccess;
}
}
try
{
if ( bRawStream )
xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() );
rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, false );
// the entry is provided to the ZipOutputStream that will delete it
pAutoTempEntry.release();
uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
sal_Int32 nLength;
do
{
nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
rZipOut.rawWrite(aSeq, 0, nLength);
}
while ( nLength == n_ConstBufferSize );
rZipOut.rawCloseEntry();
}
catch ( ZipException& )
{
bSuccess = false;
}
catch ( IOException& )
{
bSuccess = false;
}
}
else
catch ( uno::Exception& )
{
// This stream is defenitly not a raw stream
bSuccess = false;
return bSuccess;
}
// If nonseekable access is used the stream should be at the beginning and
// is useless after the storing. Thus if the storing fails the package should
// be thrown away ( as actually it is done currently )!
// To allow to reuse the package after the error, the optimization must be removed!
// If it's a PackageMember, then our previous reference held a 'raw' stream
// so we need to re-get it, unencrypted, uncompressed and positioned at the
// beginning of the stream
if ( rInfo.pStream->IsPackageMember() )
if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw )
{
if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
{
xStream = rInfo.pStream->getInputStream();
if ( !xStream.is() )
{
// Make sure that we actually _got_ a new one !
bSuccess = false;
return bSuccess;
}
uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( rInfo.pStream->GetBlockSize() );
rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
sal_Int32 nIterationCount = 1024;
if ( !rInfo.pStream->HasOwnKey() )
rInfo.pStream->setKey ( rEncryptionKey );
rInfo.pStream->setInitialisationVector ( aVector );
rInfo.pStream->setSalt ( aSalt );
rInfo.pStream->setIterationCount ( nIterationCount );
}
if ( bToBeCompressed )
{
pTempEntry->nMethod = DEFLATED;
pTempEntry->nCrc = -1;
pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
}
// last property is digest, which is inserted later if we didn't have
// a magic header
aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
try
{
rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted);
// the entry is provided to the ZipOutputStream that will delete it
pAutoTempEntry.release();
aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
aPropSet[PKG_MNFST_INIVECTOR].Value <<= rInfo.pStream->getInitialisationVector();
aPropSet[PKG_MNFST_SALT].Name = sSaltProperty;
aPropSet[PKG_MNFST_SALT].Value <<= rInfo.pStream->getSalt();
aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
aPropSet[PKG_MNFST_ITERATION].Value <<= rInfo.pStream->getIterationCount ();
sal_Int32 nLength;
uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
do
{
nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
rZipOut.write(aSeq, 0, nLength);
}
while ( nLength == n_ConstBufferSize );
// Need to store the uncompressed size in the manifest
OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
rZipOut.closeEntry();
}
catch ( ZipException& )
{
bSuccess = false;
}
catch ( IOException& )
{
bSuccess = false;
}
if ( bToBeEncrypted )
if ( bRawStream || bTransportOwnEncrStreamAsRaw )
{
::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData();
if ( !xEncData.is() )
@@ -629,53 +533,184 @@ bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo
aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
rInfo.pStream->SetIsEncrypted ( true );
}
}
}
if( bSuccess )
// If the entry is already stored in the zip file in the format we
// want for this write...copy it raw
if ( !bUseNonSeekableAccess
&& ( bRawStream || bTransportOwnEncrStreamAsRaw
|| ( rInfo.pStream->IsPackageMember() && !bToBeEncrypted
&& ( ( rInfo.pStream->aEntry.nMethod == DEFLATED && bToBeCompressed )
|| ( rInfo.pStream->aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
{
// If it's a PackageMember, then it's an unbuffered stream and we need
// to get a new version of it as we can't seek backwards.
if ( rInfo.pStream->IsPackageMember() )
{
if ( !rInfo.pStream->IsPackageMember() )
xStream = rInfo.pStream->getRawData();
if ( !xStream.is() )
{
rInfo.pStream->CloseOwnStreamIfAny();
rInfo.pStream->SetPackageMember ( true );
// Make sure that we actually _got_ a new one !
bSuccess = false;
return bSuccess;
}
if ( bRawStream )
{
// the raw stream was integrated and now behaves
// as usual encrypted stream
rInfo.pStream->SetToBeEncrypted( true );
}
// Then copy it back afterwards...
ZipPackageFolder::copyZipEntry ( rInfo.pStream->aEntry, *pTempEntry );
// Remove hacky bit from entry flags
if ( rInfo.pStream->aEntry.nFlag & ( 1 << 4 ) )
{
rInfo.pStream->aEntry.nFlag &= ~( 1 << 4 );
rInfo.pStream->aEntry.nMethod = STORED;
}
// TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
if ( rInfo.pStream->IsEncrypted() )
rInfo.pStream->setSize( nOwnStreamOrigSize );
rInfo.pStream->aEntry.nOffset *= -1;
}
try
{
if ( bRawStream )
xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() );
rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, false );
// the entry is provided to the ZipOutputStream that will delete it
pAutoTempEntry.release();
uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
sal_Int32 nLength;
do
{
nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
rZipOut.rawWrite(aSeq, 0, nLength);
}
while ( nLength == n_ConstBufferSize );
rZipOut.rawCloseEntry();
}
catch ( ZipException& )
{
bSuccess = false;
}
catch ( IOException& )
{
bSuccess = false;
}
}
else
{
// This stream is defenitly not a raw stream
// If nonseekable access is used the stream should be at the beginning and
// is useless after the storing. Thus if the storing fails the package should
// be thrown away ( as actually it is done currently )!
// To allow to reuse the package after the error, the optimization must be removed!
// If it's a PackageMember, then our previous reference held a 'raw' stream
// so we need to re-get it, unencrypted, uncompressed and positioned at the
// beginning of the stream
if ( rInfo.pStream->IsPackageMember() )
{
xStream = rInfo.pStream->getInputStream();
if ( !xStream.is() )
{
// Make sure that we actually _got_ a new one !
bSuccess = false;
return bSuccess;
}
}
if ( bToBeCompressed )
{
pTempEntry->nMethod = DEFLATED;
pTempEntry->nCrc = -1;
pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
}
try
{
rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted);
// the entry is provided to the ZipOutputStream that will delete it
pAutoTempEntry.release();
sal_Int32 nLength;
uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
do
{
nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
rZipOut.write(aSeq, 0, nLength);
}
while ( nLength == n_ConstBufferSize );
rZipOut.closeEntry();
}
catch ( ZipException& )
{
bSuccess = false;
}
catch ( IOException& )
{
bSuccess = false;
}
if ( bToBeEncrypted )
{
::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData();
if ( !xEncData.is() )
throw uno::RuntimeException();
aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest();
aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
rInfo.pStream->SetIsEncrypted ( true );
}
}
if( bSuccess )
{
if ( !rInfo.pStream->IsPackageMember() )
{
rInfo.pStream->CloseOwnStreamIfAny();
rInfo.pStream->SetPackageMember ( true );
}
if ( bRawStream )
{
// the raw stream was integrated and now behaves
// as usual encrypted stream
rInfo.pStream->SetToBeEncrypted( true );
}
// Then copy it back afterwards...
ZipPackageFolder::copyZipEntry ( rInfo.pStream->aEntry, *pTempEntry );
// Remove hacky bit from entry flags
if ( rInfo.pStream->aEntry.nFlag & ( 1 << 4 ) )
{
rInfo.pStream->aEntry.nFlag &= ~( 1 << 4 );
rInfo.pStream->aEntry.nMethod = STORED;
}
// TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
if ( rInfo.pStream->IsEncrypted() )
rInfo.pStream->setSize( nOwnStreamOrigSize );
rInfo.pStream->aEntry.nOffset *= -1;
}
// folder can have a mediatype only in package format
if ( aPropSet.getLength()
&& ( m_nFormat == embed::StorageFormats::PACKAGE || ( m_nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) )
&& ( nFormat == embed::StorageFormats::PACKAGE || ( nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) )
rManList.push_back( aPropSet );
return bSuccess;
}
void ZipPackageFolder::saveContents( OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool ) const
void ZipPackageFolder::saveContents(
const OUString &rPath,
std::vector < uno::Sequence < PropertyValue > > &rManList,
ZipOutputStream & rZipOut,
const uno::Sequence < sal_Int8 >& rEncryptionKey,
const rtlRandomPool &rRandomPool ) const
throw( uno::RuntimeException )
{
bool bWritingFailed = false;
@@ -708,12 +743,13 @@ void ZipPackageFolder::saveContents( OUString &rPath, std::vector < uno::Sequenc
OUString aMimeTypeStreamName("mimetype");
if ( m_nFormat == embed::StorageFormats::ZIP && rPath.isEmpty() )
{
// let the "mimtype" stream in root folder be stored as the first stream if it is zip format
// let the "mimetype" stream in root folder be stored as the first stream if it is zip format
ContentHash::const_iterator aIter = maContents.find ( aMimeTypeStreamName );
if ( aIter != maContents.end() && !(*aIter).second->bFolder )
{
bMimeTypeStreamStored = true;
bWritingFailed = !saveChild( (*aIter).first, *(*aIter).second, rPath, rManList, rZipOut, rEncryptionKey, rRandomPool );
bWritingFailed = !ZipPackageStream_saveChild(
*aIter->second, rPath + aIter->first, rManList, rZipOut, rEncryptionKey, rRandomPool, m_nFormat );
}
}
@@ -725,7 +761,18 @@ void ZipPackageFolder::saveContents( OUString &rPath, std::vector < uno::Sequenc
const ContentInfo &rInfo = *(*aCI).second;
if ( !bMimeTypeStreamStored || !rShortName.equals( aMimeTypeStreamName ) )
bWritingFailed = !saveChild( rShortName, rInfo, rPath, rManList, rZipOut, rEncryptionKey, rRandomPool );
{
if (rInfo.bFolder)
{
bWritingFailed = !ZipPackageFolder_saveChild(
rInfo, rPath + rShortName, rManList, rZipOut, rEncryptionKey, rRandomPool, m_nFormat );
}
else
{
bWritingFailed = !ZipPackageStream_saveChild(
rInfo, rPath + rShortName, rManList, rZipOut, rEncryptionKey, rRandomPool, m_nFormat );
}
}
}
if( bWritingFailed )