diff options
author | Mikhail Voytenko <mav@openoffice.org> | 2011-02-07 17:10:57 +0100 |
---|---|---|
committer | Mikhail Voytenko <mav@openoffice.org> | 2011-02-07 17:10:57 +0100 |
commit | 32536e53e61a93120b759e5db669dc1007e21c1b (patch) | |
tree | c09438d66d4ff6487630dab019ca75f9a7dc11e0 /package | |
parent | CWS-TOOLING: integrate CWS dba34b (diff) | |
download | core-32536e53e61a93120b759e5db669dc1007e21c1b.tar.gz core-32536e53e61a93120b759e5db669dc1007e21c1b.zip |
fwk165: #i116290# let mimetype stream be zipped as the first one
Diffstat (limited to 'package')
-rw-r--r-- | package/inc/ZipPackageFolder.hxx | 7 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackageFolder.cxx | 636 |
2 files changed, 335 insertions, 308 deletions
diff --git a/package/inc/ZipPackageFolder.hxx b/package/inc/ZipPackageFolder.hxx index 037c27f1fdd7..635aca16ba92 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, 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 ba83b34910ed..7f8027ecd4ba 100644 --- a/package/source/zippackage/ZipPackageFolder.cxx +++ b/package/source/zippackage/ZipPackageFolder.cxx @@ -48,8 +48,8 @@ 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::uno; @@ -305,12 +305,10 @@ static void ImplSetStoredData( ZipEntry & rEntry, Reference < XInputStream> & rS rEntry.nCrc = aCRC32.getValue(); } -void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) - throw(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; + bool bSuccess = true; + const OUString sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); const OUString sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); const OUString sFullPathProperty ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); @@ -320,386 +318,408 @@ void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < Pr const OUString sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); const OUString sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); - sal_Bool bHaveEncryptionKey = rEncryptionKey.getLength() ? sal_True : sal_False; + Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST); + ZipPackageStream *pStream = NULL; - 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 - { - vos::ORef < EncryptionData > aEmptyEncr; - rZipOut.putNextEntry ( *pTempEntry, aEmptyEncr, sal_False ); - rZipOut.rawCloseEntry(); - } - catch ( ZipException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; - } - catch ( IOException& ) + if ( rInfo.pFolder->GetMediaType().getLength() ) { - 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 OUString &rShortName = (*aCI).first; - const ContentInfo &rInfo = *(*aCI).second; + // 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(); - Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST); + // 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 ) - pFolder = rInfo.pFolder; - else - pStream = rInfo.pStream; + ZipPackageFolder::copyZipEntry ( *pTempEntry, rInfo.pStream->aEntry ); + pTempEntry->sPath = rPath + rShortName; + pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() ); - if ( rInfo.bFolder ) - { - OUString sTempName = rPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); + sal_Bool bToBeEncrypted = rInfo.pStream->IsToBeEncrypted() && (rEncryptionKey.getLength() || rInfo.pStream->HasOwnKey()); + sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : rInfo.pStream->IsToBeCompressed(); - 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 ); + 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; - 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(); - // In case the entry we are reading is also the entry we are writing, we will - // store the ZipEntry data in pTempEntry + OSL_ENSURE( rInfo.pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" ); - ZipPackageFolder::copyZipEntry ( *pTempEntry, pStream->aEntry ); - pTempEntry->sPath = rPath + rShortName; - pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() ); + 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; - sal_Bool bToBeEncrypted = pStream->IsToBeEncrypted() && (bHaveEncryptionKey || pStream->HasOwnKey()); - sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : pStream->IsToBeCompressed(); - - 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; - 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(); - Reference < XSeekable > xSeek ( xStream, 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() ) + if ( xSeek.is() ) { - VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); - bWritingFailed = sal_True; - continue; - } + // 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 ); - Reference < XSeekable > xSeek ( xStream, UNO_QUERY ); - try - { - if ( xSeek.is() ) + // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties! + } + else if ( bToBeEncrypted ) { - // 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 ); + // this is the correct original size + pTempEntry->nSize = static_cast < sal_Int32 > ( xSeek->getLength() ); + nOwnStreamOrigSize = pTempEntry->nSize; + } - // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties! - } - else if ( bToBeEncrypted ) + 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() ) { - // this is the correct original size - pTempEntry->nSize = static_cast < sal_Int32 > ( xSeek->getLength() ); - nOwnStreamOrigSize = pTempEntry->nSize; + // 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; } - - 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 ( 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; - } + 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!" ); - bWritingFailed = sal_True; - continue; - } + } + catch ( Exception& ) + { + VOS_ENSURE( 0, "The stream provided to the package component has problems!" ); + bSuccess = false; + return bSuccess; + } - if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw ) + if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw ) + { + if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) { - if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) - { - 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; + 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; - if ( !pStream->HasOwnKey() ) - pStream->setKey ( rEncryptionKey ); + if ( !rInfo.pStream->HasOwnKey() ) + rInfo.pStream->setKey ( rEncryptionKey ); - pStream->setInitialisationVector ( aVector ); - pStream->setSalt ( aSalt ); - pStream->setIterationCount ( nIterationCount ); - } + 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); + // 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 (); + 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; + // 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 ) - { - aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; - aPropSet[PKG_MNFST_DIGEST].Value <<= pStream->getDigest(); - } + if ( bRawStream || bTransportOwnEncrStreamAsRaw ) + { + aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; + aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest(); } } + } - // 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 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 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() ) + xStream = rInfo.pStream->getRawData(); + if ( !xStream.is() ) { - 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; - } + // 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; } + } - try - { - if ( bRawStream ) - xStream->skipBytes( pStream->GetMagicalHackPos() ); - - rZipOut.putNextEntry ( *pTempEntry, pStream->getEncryptionData(), sal_False ); - // the entry is provided to the ZipOutputStream that will delete it - pAutoTempEntry.release(); + try + { + if ( bRawStream ) + xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() ); - Sequence < sal_Int8 > aSeq ( n_ConstBufferSize ); - sal_Int32 nLength; + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream->getEncryptionData(), sal_False ); + // the entry is provided to the ZipOutputStream that will delete it + pAutoTempEntry.release(); - do - { - nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); - rZipOut.rawWrite(aSeq, 0, nLength); - } - while ( nLength == n_ConstBufferSize ); + Sequence < sal_Int8 > aSeq ( n_ConstBufferSize ); + sal_Int32 nLength; - rZipOut.rawCloseEntry(); - } - catch ( ZipException& ) + do { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; - } - catch ( IOException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; + nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); + rZipOut.rawWrite(aSeq, 0, nLength); } + while ( nLength == n_ConstBufferSize ); + + rZipOut.rawCloseEntry(); } - else + catch ( ZipException& ) { - // This stream is defenitly not a raw stream + 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 - // 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 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 ( pStream->IsPackageMember() ) + // 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() ) { - 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; - } + // 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 ( bToBeCompressed ) + if ( bToBeCompressed ) + { + pTempEntry->nMethod = DEFLATED; + pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1; + } + + try + { + rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream->getEncryptionData(), bToBeEncrypted); + // the entry is provided to the ZipOutputStream that will delete it + pAutoTempEntry.release(); + + sal_Int32 nLength; + Sequence < sal_Int8 > aSeq (n_ConstBufferSize); + do { - pTempEntry->nMethod = DEFLATED; - pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1; + nLength = xStream->readBytes(aSeq, n_ConstBufferSize); + rZipOut.write(aSeq, 0, nLength); } + while ( nLength == n_ConstBufferSize ); - try - { - rZipOut.putNextEntry ( *pTempEntry, pStream->getEncryptionData(), bToBeEncrypted); - // the entry is provided to the ZipOutputStream that will delete it - pAutoTempEntry.release(); + rZipOut.closeEntry(); + } + catch ( ZipException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } + catch ( IOException& ) + { + VOS_ENSURE( 0, "Error writing ZipOutputStream" ); + bSuccess = false; + } - sal_Int32 nLength; - Sequence < sal_Int8 > aSeq (n_ConstBufferSize); - do - { - nLength = xStream->readBytes(aSeq, n_ConstBufferSize); - rZipOut.write(aSeq, 0, nLength); - } - while ( nLength == n_ConstBufferSize ); + if ( bToBeEncrypted ) + { + aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; + aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest(); + rInfo.pStream->SetIsEncrypted ( sal_True ); + } + } - rZipOut.closeEntry(); - } - catch ( ZipException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; - } - catch ( IOException& ) - { - VOS_ENSURE( 0, "Error writing ZipOutputStream" ); - bWritingFailed = sal_True; - } + if( bSuccess ) + { + if ( !rInfo.pStream->IsPackageMember() ) + { + rInfo.pStream->CloseOwnStreamIfAny(); + rInfo.pStream->SetPackageMember ( sal_True ); + } - if ( bToBeEncrypted ) - { - aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty; - aPropSet[PKG_MNFST_DIGEST].Value <<= pStream->getDigest(); - pStream->SetIsEncrypted ( sal_True ); - } + if ( bRawStream ) + { + // the raw stream was integrated and now behaves + // as usual encrypted stream + rInfo.pStream->SetToBeEncrypted( sal_True ); } - if( !bWritingFailed ) + // Remove hacky bit from entry flags + if ( pTempEntry->nFlag & ( 1 << 4 ) ) { - if ( !pStream->IsPackageMember() ) - { - pStream->CloseOwnStreamIfAny(); - pStream->SetPackageMember ( sal_True ); - } + pTempEntry->nFlag &= ~( 1 << 4 ); + pTempEntry->nMethod = STORED; + } - if ( bRawStream ) - { - // the raw stream was integrated and now behaves - // as usual encrypted stream - pStream->SetToBeEncrypted( sal_True ); - } + // Then copy it back afterwards... + ZipPackageFolder::copyZipEntry ( rInfo.pStream->aEntry, *pTempEntry ); - // Remove hacky bit from entry flags - if ( pTempEntry->nFlag & ( 1 << 4 ) ) - { - pTempEntry->nFlag &= ~( 1 << 4 ); - pTempEntry->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 ); - // Then copy it back afterwards... - ZipPackageFolder::copyZipEntry ( pStream->aEntry, *pTempEntry ); + rInfo.pStream->aEntry.nOffset *= -1; + } + } - // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving ) - if ( pStream->IsEncrypted() ) - pStream->setSize( nOwnStreamOrigSize ); + // 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 ); - pStream->aEntry.nOffset *= -1; - } + 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 + { + vos::ORef < EncryptionData > aEmptyEncr; + rZipOut.putNextEntry ( *pTempEntry, aEmptyEncr, 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 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 ) |