diff options
author | Mikhail Voytenko <mav@openoffice.org> | 2011-03-24 14:30:07 +0100 |
---|---|---|
committer | Mikhail Voytenko <mav@openoffice.org> | 2011-03-24 14:30:07 +0100 |
commit | db79f11eaa47a31541d033a5c90d43cac014b265 (patch) | |
tree | a78b06270d8831b4a0cbeefe761424e54118cb43 /package | |
parent | 481a55dc3bbf3c97c828fa727f4c30f0d8ab171e (diff) | |
parent | 7f9327e90e1e04325ad091f1e20995da4cb2e929 (diff) |
mav60: rebase to DEV300_m103
Diffstat (limited to 'package')
-rw-r--r-- | package/inc/ZipPackageFolder.hxx | 7 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackageFolder.cxx | 694 |
2 files changed, 360 insertions, 341 deletions
diff --git a/package/inc/ZipPackageFolder.hxx b/package/inc/ZipPackageFolder.hxx index 43774572dd8c..505c057a7696 100644 --- a/package/inc/ZipPackageFolder.hxx +++ b/package/inc/ZipPackageFolder.hxx @@ -39,7 +39,12 @@ namespace beans { struct PropertyValue; } +namespace packages +{ + class ContentInfo; +} } } } + class ZipFile; class ZipPackage; class ZipOutputStream; @@ -85,6 +90,8 @@ public: void setPackageFormat_Impl( sal_Int32 nFormat ) { m_nFormat = nFormat; } void setRemoveOnInsertMode_Impl( sal_Bool bRemove ) { this->mbAllowRemoveOnInsert = bRemove; } + bool saveChild(const rtl::OUString &rShortName, const com::sun::star::packages::ContentInfo &rInfo, rtl::OUString &rPath, std::vector < com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > > &rManList, ZipOutputStream & rZipOut, com::sun::star::uno::Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool & rRandomPool); + // Recursive functions void saveContents(rtl::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) throw(::com::sun::star::uno::RuntimeException); diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx index 31ace7e34bf7..44809e5ff9ab 100644 --- a/package/source/zippackage/ZipPackageFolder.cxx +++ b/package/source/zippackage/ZipPackageFolder.cxx @@ -49,8 +49,8 @@ using namespace com::sun::star; using namespace com::sun::star::packages::zip::ZipConstants; using namespace com::sun::star::packages::zip; -using namespace com::sun::star::container; using namespace com::sun::star::packages; +using namespace com::sun::star::container; using namespace com::sun::star::beans; using namespace com::sun::star::lang; using namespace com::sun::star::io; @@ -304,428 +304,440 @@ static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< XInputStream> rEntry.nCrc = aCRC32.getValue(); } -void ZipPackageFolder::saveContents( ::rtl::OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const uno::Sequence < sal_Int8 >&rEncryptionKey, rtlRandomPool &rRandomPool) - throw(uno::RuntimeException) +bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo &rInfo, OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) { - sal_Bool bWritingFailed = sal_False; - ZipPackageFolder *pFolder = NULL; - ZipPackageStream *pStream = NULL; - const ::rtl::OUString sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); - const ::rtl::OUString sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); - const ::rtl::OUString sFullPathProperty ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); - const ::rtl::OUString sInitialisationVectorProperty ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ); - const ::rtl::OUString sSaltProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ); - const ::rtl::OUString sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); - const ::rtl::OUString sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); - const ::rtl::OUString sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); + bool bSuccess = true; + + const OUString sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); + const OUString sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); + const OUString sFullPathProperty ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); + const OUString sInitialisationVectorProperty ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ); + const OUString sSaltProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ); + const OUString sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); + const OUString sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); + const OUString sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); const ::rtl::OUString sEncryptionAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ); const ::rtl::OUString sStartKeyAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ); const ::rtl::OUString sDigestAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ); const ::rtl::OUString sDerivedKeySizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ); - sal_Bool bHaveEncryptionKey = rEncryptionKey.getLength() ? sal_True : sal_False; + Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST); - if ( maContents.begin() == maContents.end() && rPath.getLength() && m_nFormat != embed::StorageFormats::OFOPXML ) + OSL_ENSURE( ( rInfo.bFolder && rInfo.pFolder ) || ( !rInfo.bFolder && rInfo.pStream ), "A valid child object is expected!" ); + if ( rInfo.bFolder ) { - // it is an empty subfolder, use workaround to store it - ZipEntry* pTempEntry = new ZipEntry(); - ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry ); - pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getLength() ); - pTempEntry->nExtraLen = -1; - pTempEntry->sPath = rPath; + OUString sTempName = rPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); - try + if ( rInfo.pFolder->GetMediaType().getLength() ) { - rZipOut.putNextEntry( *pTempEntry, NULL, sal_False ); - rZipOut.rawCloseEntry(); - } - catch ( ZipException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; - } - catch ( IOException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; + 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 ); - for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end(); - aCI != aEnd; - aCI++) + rInfo.pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool); + } + else { - const ::rtl::OUString &rShortName = (*aCI).first; - const ContentInfo &rInfo = *(*aCI).second; - - uno::Sequence < PropertyValue > aPropSet( PKG_SIZE_NOENCR_MNFST ); + // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream + // and be deleted in the ZipOutputStream destructor + auto_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry ); + ZipEntry* pTempEntry = pAutoTempEntry.get(); - if ( rInfo.bFolder ) - pFolder = rInfo.pFolder; - else - pStream = rInfo.pStream; + // In case the entry we are reading is also the entry we are writing, we will + // store the ZipEntry data in pTempEntry - if ( rInfo.bFolder ) - { - ::rtl::OUString sTempName = rPath + rShortName + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); + ZipPackageFolder::copyZipEntry ( *pTempEntry, rInfo.pStream->aEntry ); + pTempEntry->sPath = rPath + rShortName; + pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() ); - if ( pFolder->GetMediaType().getLength() ) - { - aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty; - aPropSet[PKG_MNFST_MEDIATYPE].Value <<= pFolder->GetMediaType(); - aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty; - aPropSet[PKG_MNFST_VERSION].Value <<= pFolder->GetVersion(); - aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty; - aPropSet[PKG_MNFST_FULLPATH].Value <<= sTempName; - } - else - aPropSet.realloc( 0 ); + sal_Bool bToBeEncrypted = rInfo.pStream->IsToBeEncrypted() && (rEncryptionKey.getLength() || rInfo.pStream->HasOwnKey()); + sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : rInfo.pStream->IsToBeCompressed(); - pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool); - } - else - { - // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream - // and be deleted in the ZipOutputStream destructor - auto_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry ); - ZipEntry* pTempEntry = pAutoTempEntry.get(); + 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 <<= ::rtl::OUString(); // no version is stored for streams currently + aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty; + aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath; - // 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, pStream->aEntry ); - pTempEntry->sPath = rPath + rShortName; - pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() ); + OSL_ENSURE( rInfo.pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" ); - sal_Bool bToBeEncrypted = pStream->IsToBeEncrypted() && (bHaveEncryptionKey || pStream->HasOwnKey()); - sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : pStream->IsToBeCompressed(); + sal_Bool bRawStream = sal_False; + if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_DETECT ) + bRawStream = rInfo.pStream->ParsePackageRawStream(); + else if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_RAW ) + bRawStream = sal_True; - aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty; - aPropSet[PKG_MNFST_MEDIATYPE].Value <<= pStream->GetMediaType( ); - aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty; - aPropSet[PKG_MNFST_VERSION].Value <<= ::rtl::OUString(); // no version is stored for streams currently - aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty; - aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath; + sal_Bool bTransportOwnEncrStreamAsRaw = sal_False; + // During the storing the original size of the stream can be changed + // TODO/LATER: get rid of this hack + sal_Int32 nOwnStreamOrigSize = bRawStream ? rInfo.pStream->GetMagicalHackSize() : rInfo.pStream->getSize(); + sal_Bool bUseNonSeekableAccess = sal_False; + Reference < XInputStream > xStream; + if ( !rInfo.pStream->IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed ) + { + // 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 - OSL_ENSURE( pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" ); + xStream = rInfo.pStream->GetOwnStreamNoWrap(); + Reference < XSeekable > xSeek ( xStream, UNO_QUERY ); - sal_Bool bRawStream = sal_False; - if ( pStream->GetStreamMode() == PACKAGE_STREAM_DETECT ) - bRawStream = pStream->ParsePackageRawStream(); - else if ( pStream->GetStreamMode() == PACKAGE_STREAM_RAW ) - bRawStream = sal_True; + bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() ); + } - sal_Bool bTransportOwnEncrStreamAsRaw = sal_False; - // During the storing the original size of the stream can be changed - // TODO/LATER: get rid of this hack - sal_Int32 nOwnStreamOrigSize = bRawStream ? pStream->GetMagicalHackSize() : pStream->getSize(); + if ( !bUseNonSeekableAccess ) + { + xStream = rInfo.pStream->getRawData(); - sal_Bool bUseNonSeekableAccess = sal_False; - uno::Reference < XInputStream > xStream; - if ( !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 = pStream->GetOwnStreamNoWrap(); - uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY ); - - bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() ); + VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); + bSuccess = false; + return bSuccess; } - if ( !bUseNonSeekableAccess ) + Reference < XSeekable > xSeek ( xStream, UNO_QUERY ); + try { - xStream = pStream->getRawData(); - - if ( !xStream.is() ) - { - VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); - bWritingFailed = sal_True; - continue; - } - - uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY ); - try + if ( xSeek.is() ) { - 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 ? 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 = static_cast < sal_Int32 > ( xSeek->getLength() ); - nOwnStreamOrigSize = pTempEntry->nSize; - } + // 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 ); - xSeek->seek ( 0 ); + // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties! } - else + else if ( bToBeEncrypted ) { - // 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 ( pStream->IsPackageMember() ) - { - // if the password has been changed than the stream should not be package member any more - if ( pStream->IsEncrypted() && pStream->IsToBeEncrypted() ) - { - // Should be handled close to the raw stream handling - bTransportOwnEncrStreamAsRaw = sal_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 - { - VOS_ENSURE( 0, "The package component requires that every stream either be FROM a package or it must support XSeekable!" ); - continue; - } + // this is the correct original size + pTempEntry->nSize = static_cast < sal_Int32 > ( xSeek->getLength() ); + nOwnStreamOrigSize = pTempEntry->nSize; } - } - catch ( uno::Exception& ) - { - VOS_ENSURE( 0, "The stream provided to the package component has problems!" ); - bWritingFailed = sal_True; - continue; - } - if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw ) + xSeek->seek ( 0 ); + } + else { - if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) - { - sal_Int32 nVectorLen = pStream->GetBlockSize(); - uno::Sequence < sal_Int8 > aSalt ( 16 ), aVector ( nVectorLen ); - rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 ); - rtl_random_getBytes ( rRandomPool, aVector.getArray(), nVectorLen ); - sal_Int32 nIterationCount = 1024; - - if ( !pStream->HasOwnKey() ) - pStream->setKey ( rEncryptionKey ); - - pStream->setInitialisationVector ( aVector ); - pStream->setSalt ( aSalt ); - 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 <<= pStream->getInitialisationVector(); - aPropSet[PKG_MNFST_SALT].Name = sSaltProperty; - aPropSet[PKG_MNFST_SALT].Value <<= pStream->getSalt(); - aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty; - aPropSet[PKG_MNFST_ITERATION].Value <<= 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 ) + // 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() ) { - ::rtl::Reference< EncryptionData > xEncData = pStream->GetEncryptionData(); - if ( xEncData.is() ) + // if the password has been changed than the stream should not be package member any more + if ( rInfo.pStream->IsEncrypted() && rInfo.pStream->IsToBeEncrypted() ) { - aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; - aPropSet[PKG_MNFST_DIGEST].Value <<= xEncData->m_aDigest; - 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; + // Should be handled close to the raw stream handling + bTransportOwnEncrStreamAsRaw = sal_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 + { + VOS_ENSURE( 0, "The package component requires that every stream either be FROM a package or it must support XSeekable!" ); + bSuccess = false; + return bSuccess; + } } } + catch ( Exception& ) + { + VOS_ENSURE( 0, "The stream provided to the package component has problems!" ); + bSuccess = false; + return 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 - || ( pStream->IsPackageMember() && !bToBeEncrypted - && ( ( pStream->aEntry.nMethod == DEFLATED && bToBeCompressed ) - || ( pStream->aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) ) + if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw ) { - // 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 ( pStream->IsPackageMember() ) + if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) { - xStream = pStream->getRawData(); - if ( !xStream.is() ) - { - // Make sure that we actually _got_ a new one ! - VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); - continue; - } - } + Sequence < sal_uInt8 > aSalt ( 16 ), aVector ( 8 ); + rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 ); + rtl_random_getBytes ( rRandomPool, aVector.getArray(), 8 ); + sal_Int32 nIterationCount = 1024; - try - { - if ( bRawStream ) - xStream->skipBytes( pStream->GetMagicalHackPos() ); + if ( !rInfo.pStream->HasOwnKey() ) + rInfo.pStream->setKey ( rEncryptionKey ); - rZipOut.putNextEntry( *pTempEntry, pStream, sal_False ); - // the entry is provided to the ZipOutputStream that will delete it - pAutoTempEntry.release(); + rInfo.pStream->setInitialisationVector ( aVector ); + rInfo.pStream->setSalt ( aSalt ); + rInfo.pStream->setIterationCount ( nIterationCount ); + } - uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize ); - sal_Int32 nLength; + // last property is digest, which is inserted later if we didn't have + // a magic header + aPropSet.realloc(PKG_SIZE_ENCR_MNFST); - do - { - nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); - rZipOut.rawWrite(aSeq, 0, nLength); - } - while ( nLength == n_ConstBufferSize ); + 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 (); - rZipOut.rawCloseEntry(); - } - catch ( ZipException& ) + // 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 ) { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; + 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; } - catch ( IOException& ) + } + } + + // 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() ) { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; + // Make sure that we actually _got_ a new one ! + VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); + bSuccess = false; + return bSuccess; } } - else + + try { - // This stream is defenitly not a raw stream + if ( bRawStream ) + xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() ); - // 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! + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, sal_False ); + // the entry is provided to the ZipOutputStream that will delete it + pAutoTempEntry.release(); - // 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 ( pStream->IsPackageMember() ) - { - xStream = pStream->getInputStream(); - if ( !xStream.is() ) - { - // Make sure that we actually _got_ a new one ! - VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); - continue; - } - } + Sequence < sal_Int8 > aSeq ( n_ConstBufferSize ); + sal_Int32 nLength; - if ( bToBeCompressed ) + do { - pTempEntry->nMethod = DEFLATED; - pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1; + nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); + rZipOut.rawWrite(aSeq, 0, nLength); } + while ( nLength == n_ConstBufferSize ); - try - { - rZipOut.putNextEntry ( *pTempEntry, pStream, bToBeEncrypted); - // the entry is provided to the ZipOutputStream that will delete it - pAutoTempEntry.release(); + rZipOut.rawCloseEntry(); + } + catch ( ZipException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } + catch ( IOException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } + } + else + { + // This stream is defenitly not a raw stream - 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 ); + // 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! - rZipOut.closeEntry(); - } - catch ( ZipException& ) - { - bWritingFailed = sal_True; - } - catch ( IOException& ) + // 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() ) { - bWritingFailed = sal_True; + // Make sure that we actually _got_ a new one ! + VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); + bSuccess = false; + return bSuccess; } + } - if ( bToBeEncrypted ) - { - ::rtl::Reference< EncryptionData > xEncData = pStream->GetEncryptionData(); - if ( xEncData.is() ) - { - aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; - aPropSet[PKG_MNFST_DIGEST].Value <<= xEncData->m_aDigest; - 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; - - pStream->SetIsEncrypted ( sal_True ); - } - } + if ( bToBeCompressed ) + { + pTempEntry->nMethod = DEFLATED; + pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1; } - if( !bWritingFailed ) + try { - if ( !pStream->IsPackageMember() ) - { - pStream->CloseOwnStreamIfAny(); - pStream->SetPackageMember ( sal_True ); - } + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted); + // the entry is provided to the ZipOutputStream that will delete it + pAutoTempEntry.release(); - if ( bRawStream ) + sal_Int32 nLength; + Sequence < sal_Int8 > aSeq (n_ConstBufferSize); + do { - // the raw stream was integrated and now behaves - // as usual encrypted stream - pStream->SetToBeEncrypted( sal_True ); + nLength = xStream->readBytes(aSeq, n_ConstBufferSize); + rZipOut.write(aSeq, 0, nLength); } + while ( nLength == n_ConstBufferSize ); - // Remove hacky bit from entry flags - if ( pTempEntry->nFlag & ( 1 << 4 ) ) - { - pTempEntry->nFlag &= ~( 1 << 4 ); - pTempEntry->nMethod = STORED; - } + rZipOut.closeEntry(); + } + catch ( ZipException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } + catch ( IOException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } - // Then copy it back afterwards... - ZipPackageFolder::copyZipEntry ( pStream->aEntry, *pTempEntry ); + if ( bToBeEncrypted ) + { + 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 ( sal_True ); + } + } - // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving ) - if ( pStream->IsEncrypted() ) - pStream->setSize( nOwnStreamOrigSize ); + if( bSuccess ) + { + if ( !rInfo.pStream->IsPackageMember() ) + { + rInfo.pStream->CloseOwnStreamIfAny(); + rInfo.pStream->SetPackageMember ( sal_True ); + } - pStream->aEntry.nOffset *= -1; + if ( bRawStream ) + { + // the raw stream was integrated and now behaves + // as usual encrypted stream + rInfo.pStream->SetToBeEncrypted( sal_True ); } + + // Remove hacky bit from entry flags + if ( pTempEntry->nFlag & ( 1 << 4 ) ) + { + pTempEntry->nFlag &= ~( 1 << 4 ); + pTempEntry->nMethod = STORED; + } + + // Then copy it back afterwards... + ZipPackageFolder::copyZipEntry ( rInfo.pStream->aEntry, *pTempEntry ); + + // 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 ) ) ) + rManList.push_back( aPropSet ); + + return bSuccess; +} + +void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) + throw(RuntimeException) +{ + bool bWritingFailed = false; + + if ( maContents.begin() == maContents.end() && rPath.getLength() && m_nFormat != embed::StorageFormats::OFOPXML ) + { + // it is an empty subfolder, use workaround to store it + ZipEntry* pTempEntry = new ZipEntry(); + ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry ); + pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getLength() ); + pTempEntry->nExtraLen = -1; + pTempEntry->sPath = rPath; + + try + { + rZipOut.putNextEntry( *pTempEntry, NULL, sal_False ); + rZipOut.rawCloseEntry(); + } + catch ( ZipException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bWritingFailed = true; + } + catch ( IOException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bWritingFailed = true; + } + } + + bool bMimeTypeStreamStored = false; + ::rtl::OUString aMimeTypeStreamName( RTL_CONSTASCII_USTRINGPARAM( "mimetype" ) ); + if ( m_nFormat == embed::StorageFormats::ZIP && !rPath.getLength() ) + { + // let the "mimtype" stream in root folder be stored as the first stream if it is zip format + ContentHash::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 ); } + } + + for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end(); + aCI != aEnd; + aCI++) + { + const ::rtl::OUString &rShortName = (*aCI).first; + const ContentInfo &rInfo = *(*aCI).second; - // folder can have a mediatype only in package format - if ( aPropSet.getLength() - && ( m_nFormat == embed::StorageFormats::PACKAGE || ( m_nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) ) - rManList.push_back( aPropSet ); + if ( !bMimeTypeStreamStored || !rShortName.equals( aMimeTypeStreamName ) ) + bWritingFailed = !saveChild( rShortName, rInfo, rPath, rManList, rZipOut, rEncryptionKey, rRandomPool ); } if( bWritingFailed ) |