summaryrefslogtreecommitdiff
path: root/package/source/zippackage
diff options
context:
space:
mode:
Diffstat (limited to 'package/source/zippackage')
-rw-r--r--package/source/zippackage/ContentInfo.hxx70
-rw-r--r--package/source/zippackage/ZipPackage.cxx1717
-rw-r--r--package/source/zippackage/ZipPackageBuffer.cxx139
-rw-r--r--package/source/zippackage/ZipPackageEntry.cxx140
-rw-r--r--package/source/zippackage/ZipPackageEntry.hxx106
-rw-r--r--package/source/zippackage/ZipPackageFolder.cxx819
-rw-r--r--package/source/zippackage/ZipPackageFolderEnumeration.cxx82
-rw-r--r--package/source/zippackage/ZipPackageFolderEnumeration.hxx67
-rw-r--r--package/source/zippackage/ZipPackageSink.cxx51
-rw-r--r--package/source/zippackage/ZipPackageSink.hxx51
-rw-r--r--package/source/zippackage/ZipPackageStream.cxx805
-rw-r--r--package/source/zippackage/ZipPackageStream.hxx196
-rw-r--r--package/source/zippackage/makefile.mk58
-rw-r--r--package/source/zippackage/wrapstreamforshare.cxx182
-rw-r--r--package/source/zippackage/wrapstreamforshare.hxx75
-rw-r--r--package/source/zippackage/zipfileaccess.cxx492
16 files changed, 5050 insertions, 0 deletions
diff --git a/package/source/zippackage/ContentInfo.hxx b/package/source/zippackage/ContentInfo.hxx
new file mode 100644
index 000000000000..baf5078147a2
--- /dev/null
+++ b/package/source/zippackage/ContentInfo.hxx
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _CONTENT_INFO_HXX_
+#define _CONTENT_INFO_HXX_
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <ZipPackageFolder.hxx>
+#include <ZipPackageStream.hxx>
+
+namespace com { namespace sun { namespace star { namespace packages {
+class ContentInfo : public cppu::OWeakObject
+{
+public:
+ com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel > xTunnel;
+ bool bFolder;
+ union
+ {
+ ZipPackageFolder *pFolder;
+ ZipPackageStream *pStream;
+ };
+ ContentInfo ( ZipPackageStream * pNewStream )
+ : xTunnel ( pNewStream )
+ , bFolder ( false )
+ , pStream ( pNewStream )
+ {
+ }
+ ContentInfo ( ZipPackageFolder * pNewFolder )
+ : xTunnel ( pNewFolder )
+ , bFolder ( true )
+ , pFolder ( pNewFolder )
+ {
+ }
+ virtual ~ContentInfo ()
+ {
+ if ( bFolder )
+ pFolder->releaseUpwardRef();
+ else
+ pStream->clearParent();
+ }
+};
+} } } }
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
new file mode 100644
index 000000000000..e156150fb9f8
--- /dev/null
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -0,0 +1,1717 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackage.hxx>
+#include <ZipPackageSink.hxx>
+#include <ZipEnumeration.hxx>
+#include <ZipPackageStream.hxx>
+#include <ZipPackageFolder.hxx>
+#include <ZipOutputStream.hxx>
+#include <ZipPackageBuffer.hxx>
+#include <ZipFile.hxx>
+#include <PackageConstants.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <com/sun/star/packages/manifest/XManifestReader.hpp>
+#include <com/sun/star/packages/manifest/XManifestWriter.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XTruncate.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#include <ucbhelper/content.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <com/sun/star/ucb/TransferInfo.hpp>
+#include <com/sun/star/ucb/NameClash.hpp>
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/embed/UseBackupException.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <ContentInfo.hxx>
+#include <cppuhelper/typeprovider.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/random.h>
+#include <rtl/logfile.hxx>
+#include <rtl/instance.hxx>
+#include <osl/time.h>
+#include <osl/file.hxx>
+#include "com/sun/star/io/XAsyncOutputMonitor.hpp"
+
+#include <memory>
+#include <vector>
+
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/fileidentifierconverter.hxx>
+#include <comphelper/seekableinput.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/ofopxmlhelper.hxx>
+#include <comphelper/documentconstants.hxx>
+
+using namespace std;
+using namespace osl;
+using namespace cppu;
+using namespace ucbhelper;
+using namespace com::sun::star;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::util;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::task;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::packages;
+using namespace com::sun::star::container;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::packages::manifest;
+using namespace com::sun::star::packages::zip::ZipConstants;
+
+using ::rtl::OUString;
+using ::rtl::OString;
+
+#define LOGFILE_AUTHOR "mg115289"
+
+
+namespace {
+
+sal_Bool isLocalFile_Impl( ::rtl::OUString aURL )
+{
+ ::rtl::OUString aSystemPath;
+ ContentBroker* pBroker = ContentBroker::get();
+ if ( !pBroker )
+ {
+ ::rtl::OUString aRet;
+ if ( FileBase::getSystemPathFromFileURL( aURL, aRet ) == FileBase::E_None )
+ aSystemPath = aRet;
+ }
+ else
+ {
+ uno::Reference< XContentProviderManager > xManager =
+ pBroker->getContentProviderManagerInterface();
+ try
+ {
+ aSystemPath = getSystemPathFromFileURL( xManager, aURL );
+ }
+ catch ( Exception& )
+ {
+ }
+ }
+
+ return ( aSystemPath.getLength() != 0 );
+}
+
+}
+
+//===========================================================================
+
+class ActiveDataStreamer : public ::cppu::WeakImplHelper1< XActiveDataStreamer >
+{
+ uno::Reference< XStream > mStream;
+public:
+
+ virtual uno::Reference< XStream > SAL_CALL getStream()
+ throw( RuntimeException )
+ { return mStream; }
+
+ virtual void SAL_CALL setStream( const uno::Reference< XStream >& stream )
+ throw( RuntimeException )
+ { mStream = stream; }
+};
+
+class DummyInputStream : public ::cppu::WeakImplHelper1< XInputStream >
+{
+ virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >&, sal_Int32 )
+ throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ { return 0; }
+
+ virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >&, sal_Int32 )
+ throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ { return 0; }
+
+ virtual void SAL_CALL skipBytes( sal_Int32 )
+ throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ {}
+
+ virtual sal_Int32 SAL_CALL available()
+ throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ { return 0; }
+
+ virtual void SAL_CALL closeInput()
+ throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+ {}
+};
+
+//===========================================================================
+
+ZipPackage::ZipPackage (const uno::Reference < XMultiServiceFactory > &xNewFactory)
+: m_aMutexHolder( new SotMutexHolder )
+, m_bHasEncryptedEntries ( sal_False )
+, m_bHasNonEncryptedEntries ( sal_False )
+, m_bInconsistent ( sal_False )
+, m_bUseManifest ( sal_True )
+, m_bForceRecovery ( sal_False )
+, m_bMediaTypeFallbackUsed ( sal_False )
+, m_nFormat( embed::StorageFormats::PACKAGE ) // package is the default format
+, m_bAllowRemoveOnInsert( sal_True )
+, m_eMode ( e_IMode_None )
+, m_xFactory( xNewFactory )
+, m_pRootFolder( NULL )
+, m_pZipFile( NULL )
+{
+ m_xRootFolder = m_pRootFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert );
+}
+
+ZipPackage::~ZipPackage( void )
+{
+ delete m_pZipFile;
+
+ // All folders and streams contain pointers to their parents, when a parent diappeares
+ // it should disconnect all the children from itself during destruction automatically.
+ // So there is no need in explicit m_pRootFolder->releaseUpwardRef() call here any more
+ // since m_pRootFolder has no parent and cleaning of it's children will be done automatically
+ // during m_pRootFolder dieing by refcount.
+
+#if 0
+ // As all folders and streams contain references to their parents,
+ // we must remove these references so that they will be deleted when
+ // the boost::unordered_map of the root folder is cleared, releasing all subfolders
+ // and substreams which in turn release theirs, etc. When m_xRootFolder is
+ // released when this destructor completes, the folder tree should be
+ // deleted fully (and automagically).
+
+ m_pRootFolder->releaseUpwardRef();
+#endif
+}
+
+void ZipPackage::parseManifest()
+{
+ if ( m_nFormat == embed::StorageFormats::PACKAGE )
+ {
+ sal_Bool bManifestParsed = sal_False;
+ const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) );
+ if ( m_xRootFolder->hasByName( sMeta ) )
+ {
+ const OUString sManifest (RTL_CONSTASCII_USTRINGPARAM( "manifest.xml") );
+
+ try {
+ uno::Reference< XUnoTunnel > xTunnel;
+ Any aAny = m_xRootFolder->getByName( sMeta );
+ aAny >>= xTunnel;
+ uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY );
+ if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) )
+ {
+ aAny = xMetaInfFolder->getByName( sManifest );
+ aAny >>= xTunnel;
+ uno::Reference < XActiveDataSink > xSink (xTunnel, UNO_QUERY);
+ if (xSink.is())
+ {
+ OUString sManifestReader ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestReader" ) );
+ uno::Reference < XManifestReader > xReader (m_xFactory->createInstance( sManifestReader ), UNO_QUERY );
+ if ( xReader.is() )
+ {
+ const OUString sPropFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
+ const OUString sPropVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) );
+ const OUString sPropMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
+ const OUString sPropInitialisationVector ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) );
+ const OUString sPropSalt ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) );
+ const OUString sPropIterationCount ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) );
+ const OUString sPropSize ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) );
+ const OUString sPropDigest ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) );
+
+ Sequence < Sequence < PropertyValue > > aManifestSequence = xReader->readManifestSequence ( xSink->getInputStream() );
+ sal_Int32 nLength = aManifestSequence.getLength();
+ const Sequence < PropertyValue > *pSequence = aManifestSequence.getConstArray();
+ ZipPackageStream *pStream = NULL;
+ ZipPackageFolder *pFolder = NULL;
+
+ for (sal_Int32 i = 0; i < nLength ; i++, pSequence++)
+ {
+ OUString sPath, sMediaType, sVersion;
+ const PropertyValue *pValue = pSequence->getConstArray();
+ const Any *pSalt = NULL, *pVector = NULL, *pCount = NULL, *pSize = NULL, *pDigest = NULL;
+ for (sal_Int32 j = 0, nNum = pSequence->getLength(); j < nNum; j++ )
+ {
+ if (pValue[j].Name.equals( sPropFullPath ) )
+ pValue[j].Value >>= sPath;
+ else if (pValue[j].Name.equals( sPropVersion ) )
+ pValue[j].Value >>= sVersion;
+ else if (pValue[j].Name.equals( sPropMediaType ) )
+ pValue[j].Value >>= sMediaType;
+ else if (pValue[j].Name.equals( sPropSalt ) )
+ pSalt = &(pValue[j].Value);
+ else if (pValue[j].Name.equals( sPropInitialisationVector ) )
+ pVector = &(pValue[j].Value);
+ else if (pValue[j].Name.equals( sPropIterationCount ) )
+ pCount = &(pValue[j].Value);
+ else if (pValue[j].Name.equals( sPropSize ) )
+ pSize = &(pValue[j].Value);
+ else if (pValue[j].Name.equals( sPropDigest ) )
+ pDigest = &(pValue[j].Value);
+ }
+
+ if (sPath.getLength() && hasByHierarchicalName ( sPath ) )
+ {
+ aAny = getByHierarchicalName( sPath );
+ uno::Reference < XUnoTunnel > xUnoTunnel;
+ aAny >>= xUnoTunnel;
+ sal_Int64 nTest=0;
+ if ((nTest = xUnoTunnel->getSomething(ZipPackageFolder::static_getImplementationId())) != 0)
+ {
+ pFolder = reinterpret_cast < ZipPackageFolder* > ( nTest );
+ pFolder->SetMediaType ( sMediaType );
+ pFolder->SetVersion ( sVersion );
+ }
+ else
+ {
+ pStream = reinterpret_cast < ZipPackageStream* > ( xUnoTunnel->getSomething(ZipPackageStream::static_getImplementationId()));
+ pStream->SetMediaType ( sMediaType );
+ pStream->SetFromManifest( sal_True );
+
+ if (pSalt && pVector && pCount && pSize)
+ {
+ Sequence < sal_uInt8 > aSequence;
+ sal_Int32 nCount = 0, nSize = 0;
+ pStream->SetToBeEncrypted ( sal_True );
+
+ *pSalt >>= aSequence;
+ pStream->setSalt ( aSequence );
+
+ *pVector >>= aSequence;
+ pStream->setInitialisationVector ( aSequence );
+
+ *pCount >>= nCount;
+ pStream->setIterationCount ( nCount );
+
+ *pSize >>= nSize;
+ pStream->setSize ( nSize );
+
+ if ( pDigest )
+ {
+ *pDigest >>= aSequence;
+ pStream->setDigest ( aSequence );
+ }
+
+ pStream->SetToBeCompressed ( sal_True );
+ pStream->SetToBeEncrypted ( sal_True );
+ pStream->SetIsEncrypted ( sal_True );
+ if ( !m_bHasEncryptedEntries
+ && pStream->getName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) ) )
+ m_bHasEncryptedEntries = sal_True;
+ }
+ else
+ m_bHasNonEncryptedEntries = sal_True;
+ }
+ }
+ }
+
+ bManifestParsed = sal_True;
+ }
+ else
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No manifes parser!" ) ), uno::Reference< uno::XInterface >() );
+ }
+
+ // now hide the manifest.xml file from user
+ xMetaInfFolder->removeByName( sManifest );
+ }
+ }
+ catch( Exception& )
+ {
+ if ( !m_bForceRecovery )
+ throw;
+ }
+ }
+
+ if ( !bManifestParsed && !m_bForceRecovery )
+ throw ZipIOException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Could not parse manifest.xml\n" ) ),
+ uno::Reference< uno::XInterface >() );
+
+ const OUString sMimetype ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) );
+ if ( m_xRootFolder->hasByName( sMimetype ) )
+ {
+ // get mediatype from the "mimetype" stream
+ ::rtl::OUString aPackageMediatype;
+ uno::Reference< lang::XUnoTunnel > xMimeTypeTunnel;
+ m_xRootFolder->getByName( sMimetype ) >>= xMimeTypeTunnel;
+ uno::Reference < io::XActiveDataSink > xMimeSink( xMimeTypeTunnel, UNO_QUERY );
+ if ( xMimeSink.is() )
+ {
+ uno::Reference< io::XInputStream > xMimeInStream = xMimeSink->getInputStream();
+ if ( xMimeInStream.is() )
+ {
+ // Mediatypes longer than 1024 symbols should not appear here
+ uno::Sequence< sal_Int8 > aData( 1024 );
+ sal_Int32 nRead = xMimeInStream->readBytes( aData, 1024 );
+ if ( nRead > aData.getLength() )
+ nRead = aData.getLength();
+
+ if ( nRead )
+ aPackageMediatype = ::rtl::OUString( (sal_Char*)aData.getConstArray(), nRead, RTL_TEXTENCODING_ASCII_US );
+ }
+ }
+
+
+ if ( !bManifestParsed )
+ {
+ // the manifest.xml could not be successfuly parsed, this is an inconsistent package
+ if ( aPackageMediatype.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "application/vnd." ) ) == 0 )
+ {
+ // accept only types that look similar to own mediatypes
+ m_pRootFolder->SetMediaType( aPackageMediatype );
+ m_bMediaTypeFallbackUsed = sal_True;
+ }
+ }
+ else if ( !m_bForceRecovery )
+ {
+ // the mimetype stream should contain the information from manifest.xml
+ if ( !m_pRootFolder->GetMediaType().equals( aPackageMediatype ) )
+ throw ZipIOException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "mimetype conflicts with manifest.xml\n" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ m_xRootFolder->removeByName( sMimetype );
+ }
+
+ m_bInconsistent = m_pRootFolder->LookForUnexpectedODF12Streams( ::rtl::OUString() );
+
+ sal_Bool bODF12AndOlder = ( m_pRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 );
+ if ( !m_bForceRecovery && bODF12AndOlder && m_bInconsistent )
+ {
+ // this is an ODF1.2 document that contains streams not referred in the manifest.xml;
+ // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent
+ // should be checked later
+ throw ZipIOException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "there are streams not referred in manifest.xml\n" ) ),
+ uno::Reference< uno::XInterface >() );
+ }
+
+ // in case it is a correct ODF1.2 document, the version must be set
+ // and the META-INF folder is reserved for package format
+ if ( bODF12AndOlder )
+ m_xRootFolder->removeByName( sMeta );
+ }
+}
+
+void ZipPackage::parseContentType()
+{
+ if ( m_nFormat == embed::StorageFormats::OFOPXML )
+ {
+ const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) );
+ try {
+ // the content type must exist in OFOPXML format!
+ if ( !m_xRootFolder->hasByName( aContentTypes ) )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong format!" ) ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XUnoTunnel > xTunnel;
+ uno::Any aAny = m_xRootFolder->getByName( aContentTypes );
+ aAny >>= xTunnel;
+ uno::Reference < io::XActiveDataSink > xSink( xTunnel, UNO_QUERY );
+ if ( xSink.is() )
+ {
+ uno::Reference< io::XInputStream > xInStream = xSink->getInputStream();
+ if ( xInStream.is() )
+ {
+ sal_Int32 nInd = 0;
+ // here aContentTypeInfo[0] - Defaults, and aContentTypeInfo[1] - Overrides
+ uno::Sequence< uno::Sequence< beans::StringPair > > aContentTypeInfo =
+ ::comphelper::OFOPXMLHelper::ReadContentTypeSequence( xInStream, m_xFactory );
+
+ if ( aContentTypeInfo.getLength() != 2 )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // set the implicit types fist
+ for ( nInd = 0; nInd < aContentTypeInfo[0].getLength(); nInd++ )
+ m_pRootFolder->setChildStreamsTypeByExtension( aContentTypeInfo[0][nInd] );
+
+ // now set the explicit types
+ for ( nInd = 0; nInd < aContentTypeInfo[1].getLength(); nInd++ )
+ {
+ ::rtl::OUString aPath;
+ if ( aContentTypeInfo[1][nInd].First.toChar() == (sal_Unicode)'/' )
+ aPath = aContentTypeInfo[1][nInd].First.copy( 1 );
+ else
+ aPath = aContentTypeInfo[1][nInd].First;
+
+ if ( aPath.getLength() && hasByHierarchicalName( aPath ) )
+ {
+ uno::Any aIterAny = getByHierarchicalName( aPath );
+ uno::Reference < lang::XUnoTunnel > xIterTunnel;
+ aIterAny >>= xIterTunnel;
+ sal_Int64 nTest = xIterTunnel->getSomething( ZipPackageStream::static_getImplementationId() );
+ if ( nTest != 0 )
+ {
+ // this is a package stream, in OFOPXML format only streams can have mediatype
+ ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream* > ( nTest );
+ pStream->SetMediaType( aContentTypeInfo[1][nInd].Second );
+ }
+ }
+ }
+ }
+ }
+
+ m_xRootFolder->removeByName( aContentTypes );
+ }
+ catch( uno::Exception& )
+ {
+ if ( !m_bForceRecovery )
+ throw;
+ }
+ }
+}
+
+void ZipPackage::getZipFileContents()
+{
+ auto_ptr < ZipEnumeration > pEnum ( m_pZipFile->entries() );
+ ZipPackageStream *pPkgStream;
+ ZipPackageFolder *pPkgFolder, *pCurrent;
+ OUString sTemp, sDirName;
+ sal_Int32 nOldIndex, nIndex, nStreamIndex;
+ FolderHash::iterator aIter;
+
+ while (pEnum->hasMoreElements())
+ {
+ nIndex = nOldIndex = 0;
+ pCurrent = m_pRootFolder;
+ const ZipEntry & rEntry = *pEnum->nextElement();
+ OUString rName = rEntry.sPath;
+
+ if ( m_bForceRecovery )
+ {
+ // the PKZIP Application note version 6.2 does not allows to use '\' as separator
+ // unfortunately it is used by some implementations, so we have to support it in recovery mode
+ rName = rName.replace( '\\', '/' );
+ }
+
+ nStreamIndex = rName.lastIndexOf ( '/' );
+ if ( nStreamIndex != -1 )
+ {
+ sDirName = rName.copy ( 0, nStreamIndex);
+ aIter = m_aRecent.find ( sDirName );
+ if ( aIter != m_aRecent.end() )
+ pCurrent = (*aIter).second;
+ }
+
+ if ( pCurrent == m_pRootFolder )
+ {
+ while ( (nIndex = rName.indexOf('/', nOldIndex) ) != -1 )
+ {
+ sTemp = rName.copy ( nOldIndex, nIndex - nOldIndex );
+ if (nIndex == nOldIndex)
+ break;
+ if ( !pCurrent->hasByName( sTemp ) )
+ {
+ pPkgFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert );
+ pPkgFolder->setName( sTemp );
+ pPkgFolder->doSetParent( pCurrent, sal_True );
+ pCurrent = pPkgFolder;
+ }
+ else
+ pCurrent = pCurrent->doGetByName(sTemp).pFolder;
+ nOldIndex = nIndex+1;
+ }
+ if ( nStreamIndex != -1 && sDirName.getLength() )
+ m_aRecent [ sDirName ] = pCurrent;
+ }
+ if ( rName.getLength() -1 != nStreamIndex )
+ {
+ nStreamIndex++;
+ sTemp = rName.copy( nStreamIndex, rName.getLength() - nStreamIndex);
+ pPkgStream = new ZipPackageStream( *this, m_xFactory, m_bAllowRemoveOnInsert );
+ pPkgStream->SetPackageMember( sal_True );
+ pPkgStream->setZipEntryOnLoading( rEntry );
+ pPkgStream->setName( sTemp );
+ pPkgStream->doSetParent( pCurrent, sal_True );
+ }
+ }
+
+ if ( m_nFormat == embed::StorageFormats::PACKAGE )
+ parseManifest();
+ else if ( m_nFormat == embed::StorageFormats::OFOPXML )
+ parseContentType();
+}
+
+// XInitialization
+void SAL_CALL ZipPackage::initialize( const Sequence< Any >& aArguments )
+ throw(Exception, RuntimeException)
+{
+ RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::initialize" );
+ sal_Bool bBadZipFile = sal_False, bHaveZipFile = sal_True;
+ uno::Reference< XProgressHandler > xProgressHandler;
+ beans::NamedValue aNamedValue;
+
+ if ( aArguments.getLength() )
+ {
+ for( int ind = 0; ind < aArguments.getLength(); ind++ )
+ {
+ OUString aParamUrl;
+ if ( (aArguments[ind] >>= aParamUrl))
+ {
+ m_eMode = e_IMode_URL;
+ try
+ {
+ sal_Int32 nParam = aParamUrl.indexOf( '?' );
+ if ( nParam >= 0 )
+ {
+ m_aURL = aParamUrl.copy( 0, nParam );
+ OUString aParam = aParamUrl.copy( nParam + 1 );
+
+ sal_Int32 nIndex = 0;
+ do
+ {
+ ::rtl::OUString aCommand = aParam.getToken( 0, '&', nIndex );
+ if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "repairpackage" )) ) )
+ {
+ m_bForceRecovery = sal_True;
+ break;
+ }
+ else if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "purezip" )) ) )
+ {
+ m_nFormat = embed::StorageFormats::ZIP;
+ m_pRootFolder->setPackageFormat_Impl( m_nFormat );
+ break;
+ }
+ else if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "ofopxml" )) ) )
+ {
+ m_nFormat = embed::StorageFormats::OFOPXML;
+ m_pRootFolder->setPackageFormat_Impl( m_nFormat );
+ break;
+ }
+ }
+ while ( nIndex >= 0 );
+ }
+ else
+ m_aURL = aParamUrl;
+
+ Content aContent ( m_aURL, uno::Reference < XCommandEnvironment >() );
+ Any aAny = aContent.getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM( "Size" )) );
+ sal_uInt64 aSize = 0;
+ // kind of optimisation: treat empty files as nonexistent files
+ // and write to such files directly. Note that "Size" property is optional.
+ bool bHasSizeProperty = aAny >>= aSize;
+ if( !bHasSizeProperty || ( bHasSizeProperty && aSize ) )
+ {
+ uno::Reference < XActiveDataSink > xSink = new ZipPackageSink;
+ if (aContent.openStream ( xSink ) )
+ m_xContentStream = xSink->getInputStream();
+ }
+ else
+ bHaveZipFile = sal_False;
+ }
+ catch (com::sun::star::uno::Exception&)
+ {
+ // Exception derived from uno::Exception thrown. This probably
+ // means the file doesn't exist...we'll create it at
+ // commitChanges time
+ bHaveZipFile = sal_False;
+ }
+ }
+ else if ( (aArguments[ind] >>= m_xStream ) )
+ {
+ // a writable stream can implement both XStream & XInputStream
+ m_eMode = e_IMode_XStream;
+ m_xContentStream = m_xStream->getInputStream();
+ }
+ else if ( (aArguments[ind] >>= m_xContentStream) )
+ {
+ m_eMode = e_IMode_XInputStream;
+ }
+ else if ( ( aArguments[ind] >>= aNamedValue ) )
+ {
+ if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ) ) )
+ aNamedValue.Value >>= m_bForceRecovery;
+ else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PackageFormat" ) ) )
+ {
+ // setting this argument to true means Package format
+ // setting it to false means plain Zip format
+
+ sal_Bool bPackFormat = sal_True;
+ aNamedValue.Value >>= bPackFormat;
+ if ( !bPackFormat )
+ m_nFormat = embed::StorageFormats::ZIP;
+
+ m_pRootFolder->setPackageFormat_Impl( m_nFormat );
+ }
+ else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StorageFormat" ) ) )
+ {
+ ::rtl::OUString aFormatName;
+ sal_Int32 nFormatID = 0;
+ if ( aNamedValue.Value >>= aFormatName )
+ {
+ if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) )
+ m_nFormat = embed::StorageFormats::PACKAGE;
+ else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) )
+ m_nFormat = embed::StorageFormats::ZIP;
+ else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) )
+ m_nFormat = embed::StorageFormats::OFOPXML;
+ else
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+ }
+ else if ( aNamedValue.Value >>= nFormatID )
+ {
+ if ( nFormatID != embed::StorageFormats::PACKAGE
+ && nFormatID != embed::StorageFormats::ZIP
+ && nFormatID != embed::StorageFormats::OFOPXML )
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+
+ m_nFormat = nFormatID;
+ }
+ else
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+
+ m_pRootFolder->setPackageFormat_Impl( m_nFormat );
+ }
+ else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "AllowRemoveOnInsert" ) ) )
+ {
+ aNamedValue.Value >>= m_bAllowRemoveOnInsert;
+ m_pRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert );
+ }
+
+ // for now the progress handler is not used, probably it will never be
+ // if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ProgressHandler" ) )
+ }
+ else
+ {
+ // The URL is not acceptable
+ throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad arguments." ) ),
+ static_cast < ::cppu::OWeakObject * > ( this ) );
+ }
+ }
+
+ try
+ {
+ if (m_xContentStream.is())
+ {
+ // the stream must be seekable, if it is not it will be wrapped
+ m_xContentStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xContentStream, m_xFactory );
+ m_xContentSeek = uno::Reference < XSeekable > ( m_xContentStream, UNO_QUERY );
+ if ( ! m_xContentSeek.is() )
+ throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "The package component _requires_ an XSeekable interface!" ) ),
+ static_cast < ::cppu::OWeakObject * > ( this ) );
+
+ if ( !m_xContentSeek->getLength() )
+ bHaveZipFile = sal_False;
+ }
+ else
+ bHaveZipFile = sal_False;
+ }
+ catch (com::sun::star::uno::Exception&)
+ {
+ // Exception derived from uno::Exception thrown. This probably
+ // means the file doesn't exist...we'll create it at
+ // commitChanges time
+ bHaveZipFile = sal_False;
+ }
+ if ( bHaveZipFile )
+ {
+ try
+ {
+ m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_True, m_bForceRecovery, xProgressHandler );
+ getZipFileContents();
+ }
+ catch ( IOException & )
+ {
+ bBadZipFile = sal_True;
+ }
+ catch ( ZipException & )
+ {
+ bBadZipFile = sal_True;
+ }
+ catch ( Exception & )
+ {
+ if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; }
+ throw;
+ }
+
+ if ( bBadZipFile )
+ {
+ // clean up the memory, and tell the UCB about the error
+ if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; }
+
+ throw com::sun::star::packages::zip::ZipIOException (
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad Zip File." ) ),
+ static_cast < ::cppu::OWeakObject * > ( this ) );
+ }
+ }
+ }
+
+ RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::initialize" );
+}
+
+Any SAL_CALL ZipPackage::getByHierarchicalName( const OUString& aName )
+ throw(NoSuchElementException, RuntimeException)
+{
+ OUString sTemp, sDirName;
+ sal_Int32 nOldIndex, nIndex, nStreamIndex;
+ FolderHash::iterator aIter;
+
+ if ( (nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' )
+ return makeAny ( uno::Reference < XUnoTunnel > (m_pRootFolder) );
+ else
+ {
+ nStreamIndex = aName.lastIndexOf ( '/' );
+ bool bFolder = nStreamIndex == nIndex-1;
+ if ( nStreamIndex != -1 )
+ {
+ sDirName = aName.copy ( 0, nStreamIndex);
+ aIter = m_aRecent.find ( sDirName );
+ if ( aIter != m_aRecent.end() )
+ {
+ if ( bFolder )
+ {
+ sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex );
+ sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 );
+ if ( sTemp == (*aIter).second->getName() )
+ return makeAny ( uno::Reference < XUnoTunnel > ( (*aIter).second ) );
+ else
+ m_aRecent.erase ( aIter );
+ }
+ else
+ {
+ sTemp = aName.copy ( nStreamIndex + 1 );
+ if ( (*aIter).second->hasByName( sTemp ) )
+ return (*aIter).second->getByName( sTemp );
+ else
+ m_aRecent.erase( aIter );
+ }
+ }
+ }
+ else
+ {
+ if ( m_pRootFolder->hasByName ( aName ) )
+ return m_pRootFolder->getByName ( aName );
+ }
+ nOldIndex = 0;
+ ZipPackageFolder * pCurrent = m_pRootFolder;
+ ZipPackageFolder * pPrevious = NULL;
+ while ( ( nIndex = aName.indexOf('/', nOldIndex)) != -1)
+ {
+ sTemp = aName.copy (nOldIndex, nIndex - nOldIndex);
+ if ( nIndex == nOldIndex )
+ break;
+ if ( pCurrent->hasByName( sTemp ) )
+ {
+ pPrevious = pCurrent;
+ pCurrent = pCurrent->doGetByName(sTemp).pFolder;
+ }
+ else
+ throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ nOldIndex = nIndex+1;
+ }
+ if ( bFolder )
+ {
+ if (nStreamIndex != -1 )
+ m_aRecent[sDirName] = pPrevious;
+ return makeAny ( uno::Reference < XUnoTunnel > ( pCurrent ) );
+ }
+ else
+ {
+ sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex);
+ if ( pCurrent->hasByName ( sTemp ) )
+ {
+ if (nStreamIndex != -1 )
+ m_aRecent[sDirName] = pCurrent;
+ return pCurrent->getByName( sTemp );
+ }
+ else
+ throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+ }
+}
+
+sal_Bool SAL_CALL ZipPackage::hasByHierarchicalName( const OUString& aName )
+ throw(RuntimeException)
+{
+ OUString sTemp, sDirName;
+ sal_Int32 nOldIndex, nIndex, nStreamIndex;
+ FolderHash::iterator aIter;
+
+ if ( (nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' )
+ return sal_True;
+ else
+ {
+ nStreamIndex = aName.lastIndexOf ( '/' );
+ bool bFolder = nStreamIndex == nIndex-1;
+ if ( nStreamIndex != -1 )
+ {
+ sDirName = aName.copy ( 0, nStreamIndex);
+ aIter = m_aRecent.find ( sDirName );
+ if ( aIter != m_aRecent.end() )
+ {
+ if ( bFolder )
+ {
+ sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex );
+ sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 );
+ if ( sTemp == (*aIter).second->getName() )
+ return sal_True;
+ else
+ m_aRecent.erase ( aIter );
+ }
+ else
+ {
+ sTemp = aName.copy ( nStreamIndex + 1 );
+ if ( (*aIter).second->hasByName( sTemp ) )
+ return sal_True;
+ else
+ m_aRecent.erase( aIter );
+ }
+ }
+ }
+ else
+ {
+ if ( m_pRootFolder->hasByName ( aName ) )
+ return sal_True;
+ }
+ ZipPackageFolder * pCurrent = m_pRootFolder;
+ ZipPackageFolder * pPrevious = NULL;
+ nOldIndex = 0;
+ while ( ( nIndex = aName.indexOf('/', nOldIndex)) != -1)
+ {
+ sTemp = aName.copy (nOldIndex, nIndex - nOldIndex);
+ if ( nIndex == nOldIndex )
+ break;
+ if ( pCurrent->hasByName( sTemp ) )
+ {
+ pPrevious = pCurrent;
+ pCurrent = pCurrent->doGetByName( sTemp ).pFolder;
+ }
+ else
+ return sal_False;
+ nOldIndex = nIndex+1;
+ }
+ if ( bFolder )
+ {
+ m_aRecent[sDirName] = pPrevious;
+ return sal_True;
+ }
+ else
+ {
+ sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex);
+
+ if ( pCurrent->hasByName( sTemp ) )
+ {
+ m_aRecent[sDirName] = pCurrent;
+ return sal_True;
+ }
+ }
+ return sal_False;
+ }
+}
+
+// XSingleServiceFactory
+uno::Reference< XInterface > SAL_CALL ZipPackage::createInstance( )
+ throw(Exception, RuntimeException)
+{
+ uno::Reference < XInterface > xRef = *(new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert ));
+ return xRef;
+}
+uno::Reference< XInterface > SAL_CALL ZipPackage::createInstanceWithArguments( const Sequence< Any >& aArguments )
+ throw(Exception, RuntimeException)
+{
+ sal_Bool bArg = sal_False;
+ uno::Reference < XInterface > xRef;
+ if ( aArguments.getLength() )
+ aArguments[0] >>= bArg;
+ if (bArg)
+ xRef = *new ZipPackageFolder ( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert );
+ else
+ xRef = *new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert );
+
+ return xRef;
+}
+
+void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
+{
+ const OUString sMime ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) );
+ if (m_xRootFolder->hasByName( sMime ) )
+ m_xRootFolder->removeByName( sMime );
+
+ ZipEntry * pEntry = new ZipEntry;
+ sal_Int32 nBufferLength = m_pRootFolder->GetMediaType( ).getLength();
+ OString sMediaType = OUStringToOString( m_pRootFolder->GetMediaType(), RTL_TEXTENCODING_ASCII_US );
+ Sequence< sal_Int8 > aType( (sal_Int8*)sMediaType.getStr(),
+ nBufferLength );
+
+
+ pEntry->sPath = sMime;
+ pEntry->nMethod = STORED;
+ pEntry->nSize = pEntry->nCompressedSize = nBufferLength;
+ pEntry->nTime = ZipOutputStream::getCurrentDosTime();
+
+ CRC32 aCRC32;
+ aCRC32.update( aType );
+ pEntry->nCrc = aCRC32.getValue();
+
+ try
+ {
+ rtl::Reference < EncryptionData > xEmpty;
+ aZipOut.putNextEntry( *pEntry, xEmpty );
+ aZipOut.write( aType, 0, nBufferLength );
+ aZipOut.closeEntry();
+ }
+ catch ( ::com::sun::star::io::IOException & r )
+ {
+ OSL_ENSURE( 0, "Error adding mimetype to the ZipOutputStream" );
+ throw WrappedTargetException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Error adding mimetype to the ZipOutputStream!" ) ),
+ static_cast < OWeakObject * > ( this ),
+ makeAny( r ) );
+ }
+}
+
+void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< Sequence < PropertyValue > >& aManList )
+{
+ // Write the manifest
+ uno::Reference < XOutputStream > xManOutStream;
+ OUString sManifestWriter( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestWriter" ) );
+ uno::Reference < XManifestWriter > xWriter ( m_xFactory->createInstance( sManifestWriter ), UNO_QUERY );
+ if ( xWriter.is() )
+ {
+ ZipEntry * pEntry = new ZipEntry;
+ ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize );
+ xManOutStream = uno::Reference < XOutputStream > (*pBuffer, UNO_QUERY);
+
+ pEntry->sPath = OUString( RTL_CONSTASCII_USTRINGPARAM ( "META-INF/manifest.xml") );
+ pEntry->nMethod = DEFLATED;
+ pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1;
+ pEntry->nTime = ZipOutputStream::getCurrentDosTime();
+
+ // Convert vector into a Sequence
+ Sequence < Sequence < PropertyValue > > aManifestSequence ( aManList.size() );
+ Sequence < PropertyValue > * pSequence = aManifestSequence.getArray();
+ for (vector < Sequence < PropertyValue > >::const_iterator aIter = aManList.begin(), aEnd = aManList.end();
+ aIter != aEnd;
+ ++aIter, ++pSequence)
+ *pSequence= (*aIter);
+ xWriter->writeManifestSequence ( xManOutStream, aManifestSequence );
+
+ sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() );
+ pBuffer->realloc( nBufferLength );
+
+ // the manifest.xml is never encrypted - so pass an empty reference
+ rtl::Reference < EncryptionData > xEmpty;
+ aZipOut.putNextEntry( *pEntry, xEmpty );
+ aZipOut.write( pBuffer->getSequence(), 0, nBufferLength );
+ aZipOut.closeEntry();
+ }
+ else
+ {
+ OSL_ENSURE ( 0, "Couldn't get a ManifestWriter!" );
+ IOException aException;
+ throw WrappedTargetException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Couldn't get a ManifestWriter!" ) ),
+ static_cast < OWeakObject * > ( this ),
+ makeAny( aException ) );
+ }
+}
+
+void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< Sequence < PropertyValue > >& aManList )
+{
+ const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
+ const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
+
+ ZipEntry* pEntry = new ZipEntry;
+ ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize );
+ uno::Reference< io::XOutputStream > xConTypeOutStream( *pBuffer, UNO_QUERY );
+
+ pEntry->sPath = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml") );
+ pEntry->nMethod = DEFLATED;
+ pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1;
+ pEntry->nTime = ZipOutputStream::getCurrentDosTime();
+
+ // Convert vector into a Sequence
+ // TODO/LATER: use Defaulst entries in future
+ uno::Sequence< beans::StringPair > aDefaultsSequence;
+ uno::Sequence< beans::StringPair > aOverridesSequence( aManList.size() );
+ sal_Int32 nSeqLength = 0;
+ for ( vector< uno::Sequence< beans::PropertyValue > >::const_iterator aIter = aManList.begin(),
+ aEnd = aManList.end();
+ aIter != aEnd;
+ ++aIter)
+ {
+ ::rtl::OUString aPath;
+ ::rtl::OUString aType;
+ OSL_ENSURE( (*aIter)[PKG_MNFST_MEDIATYPE].Name.equals( sMediaType ) && (*aIter)[PKG_MNFST_FULLPATH].Name.equals( sFullPath ),
+ "The mediatype sequence format is wrong!\n" );
+ (*aIter)[PKG_MNFST_MEDIATYPE].Value >>= aType;
+ if ( aType.getLength() )
+ {
+ // only nonempty type makes sence here
+ nSeqLength++;
+ (*aIter)[PKG_MNFST_FULLPATH].Value >>= aPath;
+ aOverridesSequence[nSeqLength-1].First = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + aPath;
+ aOverridesSequence[nSeqLength-1].Second = aType;
+ }
+ }
+ aOverridesSequence.realloc( nSeqLength );
+
+ ::comphelper::OFOPXMLHelper::WriteContentSequence(
+ xConTypeOutStream, aDefaultsSequence, aOverridesSequence, m_xFactory );
+
+ sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() );
+ pBuffer->realloc( nBufferLength );
+
+ // there is no encryption in this format currently
+ rtl::Reference < EncryptionData > xEmpty;
+ aZipOut.putNextEntry( *pEntry, xEmpty );
+ aZipOut.write( pBuffer->getSequence(), 0, nBufferLength );
+ aZipOut.closeEntry();
+}
+
+void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream )
+{
+ m_xContentSeek.set( xInStream, uno::UNO_QUERY_THROW );
+ m_xContentStream = xInStream;
+
+ // seek back to the beginning of the temp file so we can read segments from it
+ m_xContentSeek->seek( 0 );
+ if ( m_pZipFile )
+ m_pZipFile->setInputStream( m_xContentStream );
+ else
+ m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_False );
+}
+
+uno::Reference< io::XInputStream > ZipPackage::writeTempFile()
+{
+ // In case the target local file does not exist or empty
+ // write directly to it otherwize create a temporary file to write to.
+ // If a temporary file is created it is returned back by the method.
+ // If the data written directly, xComponentStream will be switched here
+
+ sal_Bool bUseTemp = sal_True;
+ uno::Reference < io::XInputStream > xResult;
+ uno::Reference < io::XInputStream > xTempIn;
+
+ uno::Reference < io::XOutputStream > xTempOut;
+ uno::Reference< io::XActiveDataStreamer > xSink;
+
+ if ( m_eMode == e_IMode_URL && !m_pZipFile && isLocalFile_Impl( m_aURL ) )
+ {
+ xSink = openOriginalForOutput();
+ if( xSink.is() )
+ {
+ uno::Reference< io::XStream > xStr = xSink->getStream();
+ if( xStr.is() )
+ {
+ xTempOut = xStr->getOutputStream();
+ if( xTempOut.is() )
+ bUseTemp = sal_False;
+ }
+ }
+ }
+ else if ( m_eMode == e_IMode_XStream && !m_pZipFile )
+ {
+ // write directly to an empty stream
+ xTempOut = m_xStream->getOutputStream();
+ if( xTempOut.is() )
+ bUseTemp = sal_False;
+ }
+
+ if( bUseTemp )
+ {
+ // create temporary file
+ const OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
+ uno::Reference < io::XStream > xTempFile( m_xFactory->createInstance ( sServiceName ), UNO_QUERY_THROW );
+ xTempOut.set( xTempFile->getOutputStream(), UNO_SET_THROW );
+ xTempIn.set( xTempFile->getInputStream(), UNO_SET_THROW );
+ }
+
+ // Hand it to the ZipOutputStream:
+ ZipOutputStream aZipOut ( xTempOut );
+ aZipOut.setMethod(DEFLATED);
+ aZipOut.setLevel(DEFAULT_COMPRESSION);
+
+ try
+ {
+ if ( m_nFormat == embed::StorageFormats::PACKAGE )
+ {
+ // Remove the old manifest.xml file as the
+ // manifest will be re-generated and the
+ // META-INF directory implicitly created if does not exist
+ const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) );
+
+ if ( m_xRootFolder->hasByName( sMeta ) )
+ {
+ const OUString sManifest (RTL_CONSTASCII_USTRINGPARAM( "manifest.xml") );
+
+ uno::Reference< XUnoTunnel > xTunnel;
+ Any aAny = m_xRootFolder->getByName( sMeta );
+ aAny >>= xTunnel;
+ uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY );
+ if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) )
+ xMetaInfFolder->removeByName( sManifest );
+ }
+
+ // Write a magic file with mimetype
+ WriteMimetypeMagicFile( aZipOut );
+ }
+ else if ( m_nFormat == embed::StorageFormats::OFOPXML )
+ {
+ // Remove the old [Content_Types].xml file as the
+ // file will be re-generated
+
+ const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) );
+
+ if ( m_xRootFolder->hasByName( aContentTypes ) )
+ m_xRootFolder->removeByName( aContentTypes );
+ }
+
+ // Create a vector to store data for the manifest.xml file
+ vector < Sequence < PropertyValue > > aManList;
+
+ const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) );
+ const OUString sVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) );
+ const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) );
+
+ if ( m_nFormat == embed::StorageFormats::PACKAGE )
+ {
+ Sequence < PropertyValue > aPropSeq ( PKG_SIZE_NOENCR_MNFST );
+ aPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType;
+ aPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_pRootFolder->GetMediaType( );
+ aPropSeq [PKG_MNFST_VERSION].Name = sVersion;
+ aPropSeq [PKG_MNFST_VERSION].Value <<= m_pRootFolder->GetVersion( );
+ aPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath;
+ aPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString ( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
+
+ aManList.push_back( aPropSeq );
+ }
+
+ // Get a random number generator and seed it with current timestamp
+ // This will be used to generate random salt and initialisation vectors
+ // for encrypted streams
+ TimeValue aTime;
+ osl_getSystemTime( &aTime );
+ rtlRandomPool aRandomPool = rtl_random_createPool ();
+ rtl_random_addBytes ( aRandomPool, &aTime, 8 );
+
+
+ // call saveContents (it will recursively save sub-directories
+ OUString aEmptyString;
+ m_pRootFolder->saveContents( aEmptyString, aManList, aZipOut, m_aEncryptionKey, aRandomPool );
+
+ // Clean up random pool memory
+ rtl_random_destroyPool ( aRandomPool );
+
+ if( m_bUseManifest && m_nFormat == embed::StorageFormats::PACKAGE )
+ {
+ WriteManifest( aZipOut, aManList );
+ }
+ else if( m_nFormat == embed::StorageFormats::OFOPXML )
+ {
+ WriteContentTypes( aZipOut, aManList );
+ }
+
+ aZipOut.finish();
+
+ if( bUseTemp )
+ xResult = xTempIn;
+
+ // Update our References to point to the new temp file
+ if( !bUseTemp )
+ {
+ // the case when the original contents were written directly
+ xTempOut->flush();
+
+ // in case the stream is based on a file it will implement the following interface
+ // the call should be used to be sure that the contents are written to the file system
+ uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( xTempOut, uno::UNO_QUERY );
+ if ( asyncOutputMonitor.is() )
+ asyncOutputMonitor->waitForCompletion();
+
+ // no need to postpone switching to the new stream since the target was written directly
+ uno::Reference< io::XInputStream > xNewStream;
+ if ( m_eMode == e_IMode_URL )
+ xNewStream = xSink->getStream()->getInputStream();
+ else if ( m_eMode == e_IMode_XStream && m_xStream.is() )
+ xNewStream = m_xStream->getInputStream();
+
+ if ( xNewStream.is() )
+ ConnectTo( xNewStream );
+ }
+ }
+ catch ( uno::Exception& )
+ {
+ if( bUseTemp )
+ {
+ // no information loss appeares, thus no special handling is required
+ uno::Any aCaught( ::cppu::getCaughtException() );
+
+ // it is allowed to throw WrappedTargetException
+ WrappedTargetException aException;
+ if ( aCaught >>= aException )
+ throw aException;
+
+ throw WrappedTargetException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Problem writing the original content!" ) ),
+ static_cast < OWeakObject * > ( this ),
+ aCaught );
+ }
+ else
+ {
+ // the document is written directly, although it was empty it is important to notify that the writing has failed
+ // TODO/LATER: let the package be able to recover in this situation
+ ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is unusable!" ) );
+ embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), ::rtl::OUString() );
+ throw WrappedTargetException( aErrTxt,
+ static_cast < OWeakObject * > ( this ),
+ makeAny ( aException ) );
+ }
+ }
+
+ return xResult;
+}
+
+uno::Reference< XActiveDataStreamer > ZipPackage::openOriginalForOutput()
+{
+ // open and truncate the original file
+ Content aOriginalContent (m_aURL, uno::Reference < XCommandEnvironment >() );
+ uno::Reference< XActiveDataStreamer > xSink = new ActiveDataStreamer;
+
+ if ( m_eMode == e_IMode_URL )
+ {
+ try
+ {
+ sal_Bool bTruncSuccess = sal_False;
+
+ try
+ {
+ Exception aDetect;
+ sal_Int64 aSize = 0;
+ Any aAny = aOriginalContent.setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM( "Size" )), makeAny( aSize ) );
+ if( !( aAny >>= aDetect ) )
+ bTruncSuccess = sal_True;
+ }
+ catch( Exception& )
+ {
+ }
+
+ if( !bTruncSuccess )
+ {
+ // the file is not accessible
+ // just try to write an empty stream to it
+
+ uno::Reference< XInputStream > xTempIn = new DummyInputStream; //uno::Reference< XInputStream >( xTempOut, UNO_QUERY );
+ aOriginalContent.writeStream( xTempIn , sal_True );
+ }
+
+ OpenCommandArgument2 aArg;
+ aArg.Mode = OpenMode::DOCUMENT;
+ aArg.Priority = 0; // unused
+ aArg.Sink = xSink;
+ aArg.Properties = Sequence< Property >( 0 ); // unused
+
+ aOriginalContent.executeCommand( OUString(RTL_CONSTASCII_USTRINGPARAM( "open" )), makeAny( aArg ) );
+ }
+ catch( Exception& )
+ {
+ // seems to be nonlocal file
+ // temporary file mechanics should be used
+ }
+ }
+
+ return xSink;
+}
+
+// XChangesBatch
+void SAL_CALL ZipPackage::commitChanges()
+ throw(WrappedTargetException, RuntimeException)
+{
+ // lock the component for the time of commiting
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_eMode == e_IMode_XInputStream )
+ {
+ IOException aException;
+ throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ),
+ static_cast < OWeakObject * > ( this ), makeAny ( aException ) );
+ }
+
+ RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::commitChanges" );
+
+ // first the writeTempFile is called, if it returns a stream the stream should be written to the target
+ // if no stream was returned, the file was written directly, nothing should be done
+
+ uno::Reference< io::XInputStream > xTempInStream = writeTempFile();
+ if ( xTempInStream.is() )
+ {
+ uno::Reference< io::XSeekable > xTempSeek( xTempInStream, uno::UNO_QUERY_THROW );
+
+ try
+ {
+ xTempSeek->seek( 0 );
+ }
+ catch( uno::Exception& r )
+ {
+ throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Temporary file should be seekable!" ) ),
+ static_cast < OWeakObject * > ( this ), makeAny ( r ) );
+ }
+
+ // connect to the temporary stream
+ ConnectTo( xTempInStream );
+
+ if ( m_eMode == e_IMode_XStream )
+ {
+ // First truncate our output stream
+ uno::Reference < XOutputStream > xOutputStream;
+
+ // preparation for copy step
+ try
+ {
+ xOutputStream = m_xStream->getOutputStream();
+ uno::Reference < XTruncate > xTruncate ( xOutputStream, UNO_QUERY );
+ if ( !xTruncate.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // after successful truncation the original file contents are already lost
+ xTruncate->truncate();
+ }
+ catch( uno::Exception& r )
+ {
+ throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ),
+ static_cast < OWeakObject * > ( this ), makeAny ( r ) );
+ }
+
+ try
+ {
+ // then copy the contents of the tempfile to our output stream
+ ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutputStream );
+ xOutputStream->flush();
+ uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor(
+ xOutputStream, uno::UNO_QUERY);
+ if (asyncOutputMonitor.is()) {
+ asyncOutputMonitor->waitForCompletion();
+ }
+ }
+ catch( uno::Exception& )
+ {
+ // if anything goes wrong in this block the target file becomes corrupted
+ // so an exception should be thrown as a notification about it
+ // and the package must disconnect from the stream
+ DisconnectFromTargetAndThrowException_Impl( xTempInStream );
+ }
+ }
+ else if ( m_eMode == e_IMode_URL )
+ {
+ uno::Reference< XOutputStream > aOrigFileStream;
+ sal_Bool bCanBeCorrupted = sal_False;
+
+ if( isLocalFile_Impl( m_aURL ) )
+ {
+ // write directly in case of local file
+ uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleAccess(
+ m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess") ) ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( xSimpleAccess.is(), "Can't instatiate SimpleFileAccess service!\n" );
+ uno::Reference< io::XTruncate > xOrigTruncate;
+ if ( xSimpleAccess.is() )
+ {
+ try
+ {
+ aOrigFileStream = xSimpleAccess->openFileWrite( m_aURL );
+ xOrigTruncate = uno::Reference< io::XTruncate >( aOrigFileStream, uno::UNO_QUERY_THROW );
+ // after successful truncation the file is already corrupted
+ xOrigTruncate->truncate();
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ if( xOrigTruncate.is() )
+ {
+ try
+ {
+ ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, aOrigFileStream );
+ aOrigFileStream->closeOutput();
+ }
+ catch( uno::Exception& )
+ {
+ try {
+ aOrigFileStream->closeOutput();
+ } catch ( uno::Exception& ) {}
+
+ aOrigFileStream = uno::Reference< XOutputStream >();
+ // the original file can already be corrupted
+ bCanBeCorrupted = sal_True;
+ }
+ }
+ }
+
+ if( !aOrigFileStream.is() )
+ {
+ try
+ {
+ uno::Reference < XPropertySet > xPropSet ( xTempInStream, UNO_QUERY );
+ OSL_ENSURE( xPropSet.is(), "This is a temporary file that must implement XPropertySet!\n" );
+ if ( !xPropSet.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ OUString sTargetFolder = m_aURL.copy ( 0, m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) );
+ Content aContent ( sTargetFolder, uno::Reference < XCommandEnvironment > () );
+
+ OUString sTempURL;
+ Any aAny = xPropSet->getPropertyValue ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Uri" ) ) );
+ aAny >>= sTempURL;
+
+ TransferInfo aInfo;
+ aInfo.NameClash = NameClash::OVERWRITE;
+ aInfo.MoveData = sal_False;
+ aInfo.SourceURL = sTempURL;
+ aInfo.NewTitle = rtl::Uri::decode ( m_aURL.copy ( 1 + m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) ),
+ rtl_UriDecodeWithCharset,
+ RTL_TEXTENCODING_UTF8 );
+ aAny <<= aInfo;
+
+ // if the file is still not corrupted, it can become after the next step
+ aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "transfer" ) ), aAny );
+ }
+ catch (::com::sun::star::uno::Exception& r)
+ {
+ if ( bCanBeCorrupted )
+ DisconnectFromTargetAndThrowException_Impl( xTempInStream );
+
+ throw WrappedTargetException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package may be read only!" ) ),
+ static_cast < OWeakObject * > ( this ),
+ makeAny ( r ) );
+ }
+ }
+ }
+ }
+
+ // after successful storing it can be set to false
+ m_bMediaTypeFallbackUsed = sal_False;
+
+ RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::commitChanges" );
+}
+
+void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Reference< io::XInputStream >& xTempStream )
+{
+ m_xStream = uno::Reference< io::XStream >( xTempStream, uno::UNO_QUERY );
+ if ( m_xStream.is() )
+ m_eMode = e_IMode_XStream;
+ else
+ m_eMode = e_IMode_XInputStream;
+
+ ::rtl::OUString aTempURL;
+ try {
+ uno::Reference< beans::XPropertySet > xTempFile( xTempStream, uno::UNO_QUERY_THROW );
+ uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Uri") ) );
+ aUrl >>= aTempURL;
+ xTempFile->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile") ),
+ uno::makeAny( sal_False ) );
+ }
+ catch ( uno::Exception& )
+ {
+ OSL_ENSURE( sal_False, "These calls are pretty simple, they should not fail!\n" );
+ }
+
+ ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) );
+ embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL );
+ throw WrappedTargetException( aErrTxt,
+ static_cast < OWeakObject * > ( this ),
+ makeAny ( aException ) );
+}
+
+sal_Bool SAL_CALL ZipPackage::hasPendingChanges( )
+ throw(RuntimeException)
+{
+ return sal_False;
+}
+Sequence< ElementChange > SAL_CALL ZipPackage::getPendingChanges( )
+ throw(RuntimeException)
+{
+ return Sequence < ElementChange > ();
+}
+
+/**
+ * Function to create a new component instance; is needed by factory helper implementation.
+ * @param xMgr service manager to if the components needs other component instances
+ */
+uno::Reference < XInterface >SAL_CALL ZipPackage_createInstance(
+ const uno::Reference< XMultiServiceFactory > & xMgr )
+{
+ return uno::Reference< XInterface >( *new ZipPackage(xMgr) );
+}
+
+OUString ZipPackage::static_getImplementationName()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.comp.ZipPackage" ) );
+}
+
+Sequence< OUString > ZipPackage::static_getSupportedServiceNames()
+{
+ Sequence< OUString > aNames(1);
+ aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.Package" ) );
+ return aNames;
+}
+sal_Bool SAL_CALL ZipPackage::static_supportsService( OUString const & rServiceName )
+{
+ return rServiceName == getSupportedServiceNames()[0];
+}
+
+OUString ZipPackage::getImplementationName()
+ throw (RuntimeException)
+{
+ return static_getImplementationName();
+}
+
+Sequence< OUString > ZipPackage::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ return static_getSupportedServiceNames();
+}
+sal_Bool SAL_CALL ZipPackage::supportsService( OUString const & rServiceName )
+ throw (RuntimeException)
+{
+ return static_supportsService ( rServiceName );
+}
+uno::Reference < XSingleServiceFactory > ZipPackage::createServiceFactory( uno::Reference < XMultiServiceFactory > const & rServiceFactory )
+{
+ return cppu::createSingleFactory (rServiceFactory,
+ static_getImplementationName(),
+ ZipPackage_createInstance,
+ static_getSupportedServiceNames());
+}
+
+namespace { struct lcl_ImplId : public rtl::Static< ::cppu::OImplementationId, lcl_ImplId > {}; }
+
+// XUnoTunnel
+Sequence< sal_Int8 > ZipPackage::getUnoTunnelImplementationId( void )
+ throw (RuntimeException)
+{
+ ::cppu::OImplementationId &rId = lcl_ImplId::get();
+ return rId.getImplementationId();
+}
+
+sal_Int64 SAL_CALL ZipPackage::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+ throw(RuntimeException)
+{
+ if (aIdentifier.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
+ return reinterpret_cast < sal_Int64 > ( this );
+ return 0;
+}
+
+uno::Reference< XPropertySetInfo > SAL_CALL ZipPackage::getPropertySetInfo( )
+ throw(RuntimeException)
+{
+ return uno::Reference < XPropertySetInfo > ();
+}
+void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ if ( m_nFormat != embed::StorageFormats::PACKAGE )
+ throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("HasEncryptedEntries") )
+ ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("HasNonEncryptedEntries") )
+ ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("IsInconsistent") )
+ ||aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaTypeFallbackUsed") ) )
+ throw PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EncryptionKey") ) )
+ {
+ if (!( aValue >>= m_aEncryptionKey ) )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 );
+ }
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("UseManifest") ) )
+ {
+ if (!( aValue >>= m_bUseManifest ) )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 );
+ }
+ else
+ throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+Any SAL_CALL ZipPackage::getPropertyValue( const OUString& PropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ // TODO/LATER: Activate the check when zip-ucp is ready
+ // if ( m_nFormat != embed::StorageFormats::PACKAGE )
+ // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Any aAny;
+ if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "EncryptionKey" ) ) )
+ {
+ aAny <<= m_aEncryptionKey;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "HasEncryptedEntries" ) ) )
+ {
+ aAny <<= m_bHasEncryptedEntries;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "HasNonEncryptedEntries" ) ) )
+ {
+ aAny <<= m_bHasNonEncryptedEntries;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "IsInconsistent" ) ) )
+ {
+ aAny <<= m_bInconsistent;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "UseManifest" ) ) )
+ {
+ aAny <<= m_bUseManifest;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "MediaTypeFallbackUsed" ) ) )
+ {
+ aAny <<= m_bMediaTypeFallbackUsed;
+ return aAny;
+ }
+ throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+void SAL_CALL ZipPackage::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackage::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackage::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackage::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageBuffer.cxx b/package/source/zippackage/ZipPackageBuffer.cxx
new file mode 100644
index 000000000000..d6a20eb0b96c
--- /dev/null
+++ b/package/source/zippackage/ZipPackageBuffer.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackageBuffer.hxx>
+#include <string.h> // for memcpy
+
+using namespace ::com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using com::sun::star::lang::IllegalArgumentException;
+
+ZipPackageBuffer::ZipPackageBuffer(sal_Int64 nNewBufferSize )
+: m_nBufferSize (nNewBufferSize)
+, m_nEnd(0)
+, m_nCurrent(0)
+, m_bMustInitBuffer ( sal_True )
+{
+}
+ZipPackageBuffer::~ZipPackageBuffer(void)
+{
+}
+
+sal_Int32 SAL_CALL ZipPackageBuffer::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ if (nBytesToRead < 0)
+ throw BufferSizeExceededException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), *this );
+
+ if (nBytesToRead + m_nCurrent > m_nEnd)
+ nBytesToRead = static_cast < sal_Int32 > (m_nEnd - m_nCurrent);
+
+ aData.realloc ( nBytesToRead );
+ memcpy(aData.getArray(), m_aBuffer.getConstArray() + m_nCurrent, nBytesToRead);
+ m_nCurrent +=nBytesToRead;
+ return nBytesToRead;
+}
+
+sal_Int32 SAL_CALL ZipPackageBuffer::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ return readBytes(aData, nMaxBytesToRead);
+}
+void SAL_CALL ZipPackageBuffer::skipBytes( sal_Int32 nBytesToSkip )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ if (nBytesToSkip < 0)
+ throw BufferSizeExceededException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), *this );
+
+ if (nBytesToSkip + m_nCurrent > m_nEnd)
+ nBytesToSkip = static_cast < sal_Int32 > (m_nEnd - m_nCurrent);
+
+ m_nCurrent+=nBytesToSkip;
+}
+sal_Int32 SAL_CALL ZipPackageBuffer::available( )
+ throw(NotConnectedException, IOException, RuntimeException)
+{
+ return static_cast < sal_Int32 > (m_nEnd - m_nCurrent);
+}
+void SAL_CALL ZipPackageBuffer::closeInput( )
+ throw(NotConnectedException, IOException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageBuffer::writeBytes( const Sequence< sal_Int8 >& aData )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ sal_Int64 nDataLen = aData.getLength(), nCombined = m_nEnd + nDataLen;
+
+ if ( nCombined > m_nBufferSize)
+ {
+ do
+ m_nBufferSize *=2;
+ while (nCombined > m_nBufferSize);
+ m_aBuffer.realloc(static_cast < sal_Int32 > (m_nBufferSize));
+ m_bMustInitBuffer = sal_False;
+ }
+ else if (m_bMustInitBuffer)
+ {
+ m_aBuffer.realloc ( static_cast < sal_Int32 > ( m_nBufferSize ) );
+ m_bMustInitBuffer = sal_False;
+ }
+ memcpy( m_aBuffer.getArray() + m_nCurrent, aData.getConstArray(), static_cast < sal_Int32 > (nDataLen));
+ m_nCurrent+=nDataLen;
+ if (m_nCurrent>m_nEnd)
+ m_nEnd = m_nCurrent;
+}
+void SAL_CALL ZipPackageBuffer::flush( )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageBuffer::closeOutput( )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageBuffer::seek( sal_Int64 location )
+ throw( IllegalArgumentException, IOException, RuntimeException)
+{
+ if ( location > m_nEnd || location < 0 )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+ m_nCurrent = location;
+}
+sal_Int64 SAL_CALL ZipPackageBuffer::getPosition( )
+ throw(IOException, RuntimeException)
+{
+ return m_nCurrent;
+}
+sal_Int64 SAL_CALL ZipPackageBuffer::getLength( )
+ throw(IOException, RuntimeException)
+{
+ return m_nEnd;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageEntry.cxx b/package/source/zippackage/ZipPackageEntry.cxx
new file mode 100644
index 000000000000..df789850189f
--- /dev/null
+++ b/package/source/zippackage/ZipPackageEntry.cxx
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackageEntry.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <osl/diagnose.h>
+
+#include <ZipPackageFolder.hxx>
+#include <ZipPackageStream.hxx>
+#include <ContentInfo.hxx>
+
+#include <comphelper/storagehelper.hxx>
+
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::container;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::packages::zip::ZipConstants;
+
+using rtl::OUString;
+
+ZipPackageEntry::ZipPackageEntry ( bool bNewFolder )
+: mbIsFolder ( bNewFolder )
+, mbAllowRemoveOnInsert( sal_True )
+, pParent ( NULL )
+{
+}
+
+ZipPackageEntry::~ZipPackageEntry()
+{
+ // When the entry is destroyed it must be already disconnected from the parent
+ OSL_ENSURE( !pParent, "The parent must be disconnected already! Memory corruption is possible!\n" );
+}
+
+// XChild
+OUString SAL_CALL ZipPackageEntry::getName( )
+ throw(RuntimeException)
+{
+ return msName;
+}
+void SAL_CALL ZipPackageEntry::setName( const OUString& aName )
+ throw(RuntimeException)
+{
+ if ( pParent && msName.getLength() && pParent->hasByName ( msName ) )
+ pParent->removeByName ( msName );
+
+ // unfortunately no other exception than RuntimeException can be thrown here
+ // usually the package is used through storage implementation, the problem should be detected there
+ if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aName, sal_True ) )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected character is used in file name." ) ), Reference< XInterface >() );
+
+ msName = aName;
+
+ if ( pParent )
+ pParent->doInsertByName ( this, sal_False );
+}
+Reference< XInterface > SAL_CALL ZipPackageEntry::getParent( )
+ throw(RuntimeException)
+{
+ // return Reference< XInterface >( xParent, UNO_QUERY );
+ return Reference< XInterface >( static_cast< ::cppu::OWeakObject* >( pParent ), UNO_QUERY );
+}
+
+void ZipPackageEntry::doSetParent ( ZipPackageFolder * pNewParent, sal_Bool bInsert )
+{
+ // xParent = pParent = pNewParent;
+ pParent = pNewParent;
+ if ( bInsert && msName.getLength() && !pNewParent->hasByName ( msName ) )
+ pNewParent->doInsertByName ( this, sal_False );
+}
+
+void SAL_CALL ZipPackageEntry::setParent( const Reference< XInterface >& xNewParent )
+ throw(NoSupportException, RuntimeException)
+{
+ sal_Int64 nTest(0);
+ Reference < XUnoTunnel > xTunnel ( xNewParent, UNO_QUERY );
+ if ( !xNewParent.is() || ( nTest = xTunnel->getSomething ( ZipPackageFolder::static_getImplementationId () ) ) == 0 )
+ throw NoSupportException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ ZipPackageFolder *pNewParent = reinterpret_cast < ZipPackageFolder * > ( nTest );
+
+ if ( pNewParent != pParent )
+ {
+ if ( pParent && msName.getLength() && pParent->hasByName ( msName ) && mbAllowRemoveOnInsert )
+ pParent->removeByName( msName );
+ doSetParent ( pNewParent, sal_True );
+ }
+}
+ //XPropertySet
+Reference< beans::XPropertySetInfo > SAL_CALL ZipPackageEntry::getPropertySetInfo( )
+ throw(RuntimeException)
+{
+ return Reference < beans::XPropertySetInfo > ();
+}
+void SAL_CALL ZipPackageEntry::addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< beans::XPropertyChangeListener >& /*xListener*/ )
+ throw(beans::UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageEntry::removePropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< beans::XPropertyChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageEntry::addVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+void SAL_CALL ZipPackageEntry::removeVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< beans::XVetoableChangeListener >& /*aListener*/ )
+ throw(beans::UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageEntry.hxx b/package/source/zippackage/ZipPackageEntry.hxx
new file mode 100644
index 000000000000..6ae623a50664
--- /dev/null
+++ b/package/source/zippackage/ZipPackageEntry.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ZIP_PACKAGE_ENTRY_HXX
+#define _ZIP_PACKAGE_ENTRY_HXX
+
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <ZipEntry.hxx>
+#include <cppuhelper/implbase5.hxx>
+
+class ZipPackageFolder;
+
+class ZipPackageEntry : public cppu::WeakImplHelper5
+<
+ com::sun::star::container::XNamed,
+ com::sun::star::container::XChild,
+ com::sun::star::lang::XUnoTunnel,
+ com::sun::star::beans::XPropertySet,
+ com::sun::star::lang::XServiceInfo
+>
+{
+protected:
+ ::rtl::OUString msName;
+ bool mbIsFolder:1;
+ bool mbAllowRemoveOnInsert:1;
+ // com::sun::star::uno::Reference < com::sun::star::container::XNameContainer > xParent;
+ ::rtl::OUString sMediaType;
+ ZipPackageFolder * pParent;
+public:
+ ZipEntry aEntry;
+ ZipPackageEntry ( bool bNewFolder = sal_False );
+ virtual ~ZipPackageEntry( void );
+
+ ::rtl::OUString & GetMediaType () { return sMediaType; }
+ void SetMediaType ( const ::rtl::OUString & sNewType) { sMediaType = sNewType; }
+ void doSetParent ( ZipPackageFolder * pNewParent, sal_Bool bInsert );
+ bool IsFolder ( ) { return mbIsFolder; }
+ ZipPackageFolder* GetParent ( ) { return pParent; }
+ void SetFolder ( bool bSetFolder ) { mbIsFolder = bSetFolder; }
+
+ void clearParent ( void )
+ {
+ // xParent.clear();
+ pParent = NULL;
+ }
+ // XNamed
+ virtual ::rtl::OUString SAL_CALL getName( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setName( const ::rtl::OUString& aName )
+ throw(::com::sun::star::uno::RuntimeException);
+ // XChild
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getParent( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setParent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Parent )
+ throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
+ throw(::com::sun::star::uno::RuntimeException) = 0;
+ // XPropertySet
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) = 0;
+ virtual void SAL_CALL addPropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removePropertyChangeListener( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL addVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL removeVetoableChangeListener( const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx
new file mode 100644
index 000000000000..34170c4594b3
--- /dev/null
+++ b/package/source/zippackage/ZipPackageFolder.cxx
@@ -0,0 +1,819 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackageFolder.hxx>
+#include <ZipFile.hxx>
+#include <ZipOutputStream.hxx>
+#include <ZipPackageStream.hxx>
+#include <PackageConstants.hxx>
+#include <ZipPackageFolderEnumeration.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <osl/diagnose.h>
+#include <osl/time.h>
+#include <rtl/digest.h>
+#include <ContentInfo.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <EncryptedDataHeader.hxx>
+#include <rtl/random.h>
+#include <rtl/instance.hxx>
+#include <memory>
+
+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::beans;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace cppu;
+using namespace std;
+using namespace ::com::sun::star;
+
+using rtl::OUString;
+
+namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
+
+ZipPackageFolder::ZipPackageFolder ( const Reference< XMultiServiceFactory >& xFactory,
+ sal_Int32 nFormat,
+ sal_Bool bAllowRemoveOnInsert )
+: m_xFactory( xFactory )
+, m_nFormat( nFormat )
+{
+ OSL_ENSURE( m_xFactory.is(), "No factory is provided to the package folder!" );
+
+ this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
+
+ SetFolder ( sal_True );
+ aEntry.nVersion = -1;
+ aEntry.nFlag = 0;
+ aEntry.nMethod = STORED;
+ aEntry.nTime = -1;
+ aEntry.nCrc = 0;
+ aEntry.nCompressedSize = 0;
+ aEntry.nSize = 0;
+ aEntry.nOffset = -1;
+ Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
+ if ( !rCachedImplId.getLength() )
+ rCachedImplId = getImplementationId();
+}
+
+
+ZipPackageFolder::~ZipPackageFolder()
+{
+}
+
+sal_Bool ZipPackageFolder::LookForUnexpectedODF12Streams( const ::rtl::OUString& aPath )
+{
+ sal_Bool bHasUnexpected = sal_False;
+
+ for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
+ !bHasUnexpected && aCI != aEnd;
+ ++aCI)
+ {
+ const OUString &rShortName = (*aCI).first;
+ const ContentInfo &rInfo = *(*aCI).second;
+
+ if ( rInfo.bFolder )
+ {
+ if ( aPath.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF/" ) ) ) )
+ {
+ // META-INF is not allowed to contain subfolders
+ bHasUnexpected = sal_True;
+ }
+ else
+ {
+ OUString sOwnPath = aPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
+ bHasUnexpected = rInfo.pFolder->LookForUnexpectedODF12Streams( sOwnPath );
+ }
+ }
+ else
+ {
+ if ( aPath.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF/" ) ) ) )
+ {
+ if ( !rShortName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ) )
+ && rShortName.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "signatures" ) ) ) == -1 )
+ {
+ // a stream from META-INF with unexpected name
+ bHasUnexpected = sal_True;
+ }
+
+ // streams from META-INF with expected names are allowed not to be registered in manifest.xml
+ }
+ else if ( !rInfo.pStream->IsFromManifest() )
+ {
+ // the stream is not in META-INF and ist notregistered in manifest.xml,
+ // check whether it is an internal part of the package format
+ if ( aPath.getLength()
+ || !rShortName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "mimetype" ) ) ) )
+ {
+ // if it is not "mimetype" from the root it is not a part of the package
+ bHasUnexpected = sal_True;
+ }
+ }
+ }
+ }
+
+ return bHasUnexpected;
+}
+
+void ZipPackageFolder::setChildStreamsTypeByExtension( const beans::StringPair& aPair )
+{
+ ::rtl::OUString aExt;
+ if ( aPair.First.toChar() == (sal_Unicode)'.' )
+ aExt = aPair.First;
+ else
+ aExt = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) + aPair.First;
+
+ for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
+ aCI != aEnd;
+ ++aCI)
+ {
+ const OUString &rShortName = (*aCI).first;
+ const ContentInfo &rInfo = *(*aCI).second;
+
+ if ( rInfo.bFolder )
+ rInfo.pFolder->setChildStreamsTypeByExtension( aPair );
+ else
+ {
+ sal_Int32 nPathLength = rShortName.getLength();
+ sal_Int32 nExtLength = aExt.getLength();
+ if ( nPathLength >= nExtLength && rShortName.match( aExt, nPathLength - nExtLength ) )
+ rInfo.pStream->SetMediaType( aPair.Second );
+ }
+ }
+}
+
+void ZipPackageFolder::copyZipEntry( ZipEntry &rDest, const ZipEntry &rSource)
+{
+ rDest.nVersion = rSource.nVersion;
+ rDest.nFlag = rSource.nFlag;
+ rDest.nMethod = rSource.nMethod;
+ rDest.nTime = rSource.nTime;
+ rDest.nCrc = rSource.nCrc;
+ rDest.nCompressedSize = rSource.nCompressedSize;
+ rDest.nSize = rSource.nSize;
+ rDest.nOffset = rSource.nOffset;
+ rDest.sPath = rSource.sPath;
+ rDest.nPathLen = rSource.nPathLen;
+ rDest.nExtraLen = rSource.nExtraLen;
+}
+
+const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageFolder::static_getImplementationId()
+{
+ return lcl_CachedImplId::get();
+}
+
+ // XNameContainer
+void SAL_CALL ZipPackageFolder::insertByName( const OUString& aName, const Any& aElement )
+ throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
+{
+ if (hasByName(aName))
+ throw ElementExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ else
+ {
+ Reference < XUnoTunnel > xRef;
+ aElement >>= xRef;
+ if ( ( aElement >>= xRef ) )
+ {
+ sal_Int64 nTest;
+ ZipPackageEntry *pEntry;
+ if ( ( nTest = xRef->getSomething ( ZipPackageFolder::static_getImplementationId() ) ) != 0 )
+ {
+ ZipPackageFolder *pFolder = reinterpret_cast < ZipPackageFolder * > ( nTest );
+ pEntry = static_cast < ZipPackageEntry * > ( pFolder );
+ }
+ else if ( ( nTest = xRef->getSomething ( ZipPackageStream::static_getImplementationId() ) ) != 0 )
+ {
+ ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream * > ( nTest );
+ pEntry = static_cast < ZipPackageEntry * > ( pStream );
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 );
+
+ if (pEntry->getName() != aName )
+ pEntry->setName (aName);
+ doInsertByName ( pEntry, sal_True );
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 );
+ }
+}
+void SAL_CALL ZipPackageFolder::removeByName( const OUString& Name )
+ throw(NoSuchElementException, WrappedTargetException, RuntimeException)
+{
+ ContentHash::iterator aIter = maContents.find ( Name );
+ if ( aIter == maContents.end() )
+ throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ maContents.erase( aIter );
+}
+ // XEnumerationAccess
+Reference< XEnumeration > SAL_CALL ZipPackageFolder::createEnumeration( )
+ throw(RuntimeException)
+{
+ return Reference < XEnumeration> (new ZipPackageFolderEnumeration(maContents));
+}
+ // XElementAccess
+Type SAL_CALL ZipPackageFolder::getElementType( )
+ throw(RuntimeException)
+{
+ return ::getCppuType ((const Reference< XUnoTunnel > *) 0);
+}
+sal_Bool SAL_CALL ZipPackageFolder::hasElements( )
+ throw(RuntimeException)
+{
+ return maContents.size() > 0;
+}
+ // XNameAccess
+ContentInfo& ZipPackageFolder::doGetByName( const OUString& aName )
+ throw(NoSuchElementException, WrappedTargetException, RuntimeException)
+{
+ ContentHash::iterator aIter = maContents.find ( aName );
+ if ( aIter == maContents.end())
+ throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ return *(*aIter).second;
+}
+Any SAL_CALL ZipPackageFolder::getByName( const OUString& aName )
+ throw(NoSuchElementException, WrappedTargetException, RuntimeException)
+{
+ return makeAny ( doGetByName ( aName ).xTunnel );
+}
+Sequence< OUString > SAL_CALL ZipPackageFolder::getElementNames( )
+ throw(RuntimeException)
+{
+ sal_uInt32 i=0, nSize = maContents.size();
+ Sequence < OUString > aSequence ( nSize );
+ OUString *pNames = aSequence.getArray();
+ for ( ContentHash::const_iterator aIterator = maContents.begin(), aEnd = maContents.end();
+ aIterator != aEnd;
+ ++i, ++aIterator)
+ pNames[i] = (*aIterator).first;
+ return aSequence;
+}
+sal_Bool SAL_CALL ZipPackageFolder::hasByName( const OUString& aName )
+ throw(RuntimeException)
+{
+ return maContents.find ( aName ) != maContents.end ();
+}
+ // XNameReplace
+void SAL_CALL ZipPackageFolder::replaceByName( const OUString& aName, const Any& aElement )
+ throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
+{
+ if ( hasByName( aName ) )
+ removeByName( aName );
+ else
+ throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ insertByName(aName, aElement);
+}
+
+static void ImplSetStoredData( ZipEntry & rEntry, Reference < XInputStream> & rStream )
+{
+ // It's very annoying that we have to do this, but lots of zip packages
+ // don't allow data descriptors for STORED streams, meaning we have to
+ // know the size and CRC32 of uncompressed streams before we actually
+ // write them !
+ CRC32 aCRC32;
+ rEntry.nMethod = STORED;
+ rEntry.nCompressedSize = rEntry.nSize = aCRC32.updateStream ( rStream );
+ rEntry.nCrc = aCRC32.getValue();
+}
+
+void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool)
+ throw(RuntimeException)
+{
+ sal_Bool bWritingFailed = sal_False;
+ ZipPackageFolder *pFolder = NULL;
+ ZipPackageStream *pStream = NULL;
+ 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" ) );
+
+ sal_Bool bHaveEncryptionKey = rEncryptionKey.getLength() ? sal_True : sal_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
+ {
+ rtl::Reference < EncryptionData > aEmptyEncr;
+ rZipOut.putNextEntry ( *pTempEntry, aEmptyEncr, sal_False );
+ rZipOut.rawCloseEntry();
+ }
+ catch ( ZipException& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+ catch ( IOException& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+ }
+
+ for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
+ aCI != aEnd;
+ ++aCI)
+ {
+ const OUString &rShortName = (*aCI).first;
+ const ContentInfo &rInfo = *(*aCI).second;
+
+ Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
+ PropertyValue *pValue = aPropSet.getArray();
+
+ if ( rInfo.bFolder )
+ pFolder = rInfo.pFolder;
+ else
+ pStream = rInfo.pStream;
+
+ if ( rInfo.bFolder )
+ {
+ OUString sTempName = rPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) );
+
+ pValue[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
+ pValue[PKG_MNFST_MEDIATYPE].Value <<= pFolder->GetMediaType();
+ pValue[PKG_MNFST_VERSION].Name = sVersionProperty;
+ pValue[PKG_MNFST_VERSION].Value <<= pFolder->GetVersion();
+ pValue[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
+ pValue[PKG_MNFST_FULLPATH].Value <<= sTempName;
+
+ 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
+
+ ZipPackageFolder::copyZipEntry ( *pTempEntry, pStream->aEntry );
+ pTempEntry->sPath = rPath + rShortName;
+ pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
+
+ sal_Bool bToBeEncrypted = pStream->IsToBeEncrypted() && (bHaveEncryptionKey || pStream->HasOwnKey());
+ sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : pStream->IsToBeCompressed();
+
+ pValue[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
+ pValue[PKG_MNFST_MEDIATYPE].Value <<= pStream->GetMediaType( );
+ pValue[PKG_MNFST_VERSION].Name = sVersionProperty;
+ pValue[PKG_MNFST_VERSION].Value <<= ::rtl::OUString(); // no version is stored for streams currently
+ pValue[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
+ pValue[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
+
+
+ OSL_ENSURE( pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
+
+ sal_Bool bRawStream = sal_False;
+ if ( pStream->GetStreamMode() == PACKAGE_STREAM_DETECT )
+ bRawStream = pStream->ParsePackageRawStream();
+ else if ( pStream->GetStreamMode() == PACKAGE_STREAM_RAW )
+ bRawStream = sal_True;
+
+ 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();
+
+ sal_Bool bUseNonSeekableAccess = sal_False;
+ Reference < XInputStream > xStream;
+ if ( !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
+
+ xStream = pStream->GetOwnStreamNoWrap();
+ Reference < XSeekable > xSeek ( xStream, UNO_QUERY );
+
+ bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
+ }
+
+ if ( !bUseNonSeekableAccess )
+ {
+ xStream = pStream->getRawData();
+
+ if ( !xStream.is() )
+ {
+ OSL_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" );
+ bWritingFailed = sal_True;
+ continue;
+ }
+
+ Reference < XSeekable > xSeek ( xStream, 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 )
+ {
+ // 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;
+ }
+
+ 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
+ {
+ OSL_ENSURE( 0, "The package component requires that every stream either be FROM a package or it must support XSeekable!" );
+ continue;
+ }
+ }
+ }
+ catch ( Exception& )
+ {
+ OSL_ENSURE( 0, "The stream provided to the package component has problems!" );
+ bWritingFailed = sal_True;
+ continue;
+ }
+
+ if ( bToBeEncrypted || bRawStream || 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;
+
+ 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);
+
+ pValue = aPropSet.getArray();
+ pValue[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
+ pValue[PKG_MNFST_INIVECTOR].Value <<= pStream->getInitialisationVector();
+ pValue[PKG_MNFST_SALT].Name = sSaltProperty;
+ pValue[PKG_MNFST_SALT].Value <<= pStream->getSalt();
+ pValue[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
+ pValue[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" );
+ pValue[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
+ pValue[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
+
+ if ( bRawStream || bTransportOwnEncrStreamAsRaw )
+ {
+ pValue[PKG_MNFST_DIGEST].Name = sDigestProperty;
+ pValue[PKG_MNFST_DIGEST].Value <<= 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 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 = pStream->getRawData();
+ if ( !xStream.is() )
+ {
+ // Make sure that we actually _got_ a new one !
+ OSL_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" );
+ continue;
+ }
+ }
+
+ 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();
+
+ 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& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+ catch ( IOException& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+ }
+ 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 ( pStream->IsPackageMember() )
+ {
+ xStream = pStream->getInputStream();
+ if ( !xStream.is() )
+ {
+ // Make sure that we actually _got_ a new one !
+ OSL_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" );
+ continue;
+ }
+ }
+
+ if ( bToBeCompressed )
+ {
+ pTempEntry->nMethod = DEFLATED;
+ pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
+ }
+
+ try
+ {
+ rZipOut.putNextEntry ( *pTempEntry, 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
+ {
+ nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
+ rZipOut.write(aSeq, 0, nLength);
+ }
+ while ( nLength == n_ConstBufferSize );
+
+ rZipOut.closeEntry();
+ }
+ catch ( ZipException& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+ catch ( IOException& )
+ {
+ OSL_ENSURE( 0, "Error writing ZipOutputStream" );
+ bWritingFailed = sal_True;
+ }
+
+ if ( bToBeEncrypted )
+ {
+ pValue[PKG_MNFST_DIGEST].Name = sDigestProperty;
+ pValue[PKG_MNFST_DIGEST].Value <<= pStream->getDigest();
+ pStream->SetIsEncrypted ( sal_True );
+ }
+ }
+
+ if( !bWritingFailed )
+ {
+ if ( !pStream->IsPackageMember() )
+ {
+ pStream->CloseOwnStreamIfAny();
+ pStream->SetPackageMember ( sal_True );
+ }
+
+ if ( bRawStream )
+ {
+ // the raw stream was integrated and now behaves
+ // as usual encrypted stream
+ 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 ( pStream->aEntry, *pTempEntry );
+
+ // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
+ if ( pStream->IsEncrypted() )
+ pStream->setSize( nOwnStreamOrigSize );
+
+ pStream->aEntry.nOffset *= -1;
+ }
+ }
+
+ // folder can have a mediatype only in package format
+ if ( m_nFormat == embed::StorageFormats::PACKAGE || ( m_nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) )
+ rManList.push_back( aPropSet );
+ }
+
+ if( bWritingFailed )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+void ZipPackageFolder::releaseUpwardRef( void )
+{
+ // Now it is possible that a package folder is disconnected from the package before removing of the folder.
+ // Such a scenario is used in storage implementation. When a new version of a folder is provided the old
+ // one is retrieved, removed from the package but preserved for the error handling.
+ // In this scenario the referencing to the parent is not really useful, since it requires disposing.
+
+ // Actually there is no need in having a reference to the parent, it even make things more complicated and
+ // requires disposing mechanics. Using of a simple pointer seems to be easier solution and also a safe enough.
+
+ clearParent();
+
+#if 0
+ for ( ContentHash::const_iterator aCI = maContents.begin();
+ aCI!=maContents.end();
+ aCI++)
+ {
+ ContentInfo &rInfo = * (*aCI).second;
+ if ( rInfo.bFolder )// && ! rInfo.pFolder->HasReleased () )
+ rInfo.pFolder->releaseUpwardRef();
+ else //if ( !rInfo.bFolder && !rInfo.pStream->HasReleased() )
+ rInfo.pStream->clearParent();
+ }
+ clearParent();
+
+ OSL_ENSURE ( m_refCount == 1, "Ref-count is not 1!" );
+#endif
+}
+
+sal_Int64 SAL_CALL ZipPackageFolder::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+ throw(RuntimeException)
+{
+ sal_Int64 nMe = 0;
+ if ( aIdentifier.getLength() == 16 &&
+ 0 == rtl_compareMemory(static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
+ nMe = reinterpret_cast < sal_Int64 > ( this );
+ return nMe;
+}
+void SAL_CALL ZipPackageFolder::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
+ throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaType")))
+ {
+ // TODO/LATER: activate when zip ucp is ready
+ // if ( m_nFormat != embed::StorageFormats::PACKAGE )
+ // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ aValue >>= sMediaType;
+ }
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Version")))
+ aValue >>= m_sVersion;
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Size") ) )
+ aValue >>= aEntry.nSize;
+ else
+ throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+Any SAL_CALL ZipPackageFolder::getPropertyValue( const OUString& PropertyName )
+ throw(UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
+ {
+ // TODO/LATER: activate when zip ucp is ready
+ // if ( m_nFormat != embed::StorageFormats::PACKAGE )
+ // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return makeAny ( sMediaType );
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Version" ) ) )
+ return makeAny( m_sVersion );
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Size" ) ) )
+ return makeAny ( aEntry.nSize );
+ else
+ throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+void ZipPackageFolder::doInsertByName ( ZipPackageEntry *pEntry, sal_Bool bSetParent )
+ throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
+{
+ try
+ {
+ if ( pEntry->IsFolder() )
+ maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageFolder *> ( pEntry ) );
+ else
+ maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageStream *> ( pEntry ) );
+ }
+ catch(const uno::Exception& rEx)
+ {
+ (void)rEx;
+ throw;
+ }
+ if ( bSetParent )
+ pEntry->setParent ( *this );
+}
+OUString ZipPackageFolder::getImplementationName()
+ throw (RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageFolder" ) );
+}
+
+Sequence< OUString > ZipPackageFolder::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ Sequence< OUString > aNames(1);
+ aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageFolder" ) );
+ return aNames;
+}
+sal_Bool SAL_CALL ZipPackageFolder::supportsService( OUString const & rServiceName )
+ throw (RuntimeException)
+{
+ return rServiceName == getSupportedServiceNames()[0];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageFolderEnumeration.cxx b/package/source/zippackage/ZipPackageFolderEnumeration.cxx
new file mode 100644
index 000000000000..ed1bfbdf1d30
--- /dev/null
+++ b/package/source/zippackage/ZipPackageFolderEnumeration.cxx
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackageFolderEnumeration.hxx>
+#include <ContentInfo.hxx>
+
+using namespace com::sun::star;
+using rtl::OUString;
+
+ZipPackageFolderEnumeration::ZipPackageFolderEnumeration ( ContentHash &rInput)
+: rContents (rInput)
+, aIterator (rContents.begin())
+{
+}
+
+ZipPackageFolderEnumeration::~ZipPackageFolderEnumeration( void )
+{
+}
+
+sal_Bool SAL_CALL ZipPackageFolderEnumeration::hasMoreElements( )
+ throw(uno::RuntimeException)
+{
+ return (aIterator != rContents.end() );
+}
+uno::Any SAL_CALL ZipPackageFolderEnumeration::nextElement( )
+ throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ uno::Any aAny;
+ if (aIterator == rContents.end() )
+ throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ aAny <<= (*aIterator).second->xTunnel;
+ aIterator++;
+ return aAny;
+}
+
+OUString ZipPackageFolderEnumeration::getImplementationName()
+ throw (uno::RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageFolderEnumeration" ) );
+}
+
+uno::Sequence< OUString > ZipPackageFolderEnumeration::getSupportedServiceNames()
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< OUString > aNames(1);
+ aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageFolderEnumeration" ) );
+ return aNames;
+}
+sal_Bool SAL_CALL ZipPackageFolderEnumeration::supportsService( OUString const & rServiceName )
+ throw (uno::RuntimeException)
+{
+ return rServiceName == getSupportedServiceNames()[0];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageFolderEnumeration.hxx b/package/source/zippackage/ZipPackageFolderEnumeration.hxx
new file mode 100644
index 000000000000..d136faa9be49
--- /dev/null
+++ b/package/source/zippackage/ZipPackageFolderEnumeration.hxx
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ZIP_PACKAGE_FOLDER_ENUMERATION_HXX
+#define _ZIP_PACKAGE_FOLDER_ENUMERATION_HXX
+
+#include <cppuhelper/implbase2.hxx> // helper for implementations
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <HashMaps.hxx>
+
+class ZipPackageFolderEnumeration : public cppu::WeakImplHelper2
+<
+ com::sun::star::container::XEnumeration,
+ com::sun::star::lang::XServiceInfo
+>
+{
+protected:
+ ContentHash& rContents;
+ ContentHash::const_iterator aIterator;
+public:
+ //ZipPackageFolderEnumeration (boost::unordered_map < rtl::OUString, com::sun::star::uno::Reference < com::sun::star::container::XNamed >, hashFunc, eqFunc > &rInput);
+ ZipPackageFolderEnumeration (ContentHash &rInput);
+ virtual ~ZipPackageFolderEnumeration( void );
+
+ // XEnumeration
+ virtual sal_Bool SAL_CALL hasMoreElements( )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL nextElement( )
+ throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageSink.cxx b/package/source/zippackage/ZipPackageSink.cxx
new file mode 100644
index 000000000000..2f9202398493
--- /dev/null
+++ b/package/source/zippackage/ZipPackageSink.cxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipPackageSink.hxx>
+
+ZipPackageSink::ZipPackageSink(void)
+: xStream ( com::sun::star::uno::Reference < com::sun::star::io::XInputStream > (NULL))
+{
+}
+ZipPackageSink::~ZipPackageSink(void)
+{
+}
+void SAL_CALL ZipPackageSink::setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ xStream = aStream;
+}
+::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL ZipPackageSink::getInputStream( )
+ throw(::com::sun::star::uno::RuntimeException)
+{
+ return xStream;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageSink.hxx b/package/source/zippackage/ZipPackageSink.hxx
new file mode 100644
index 000000000000..a90d40131072
--- /dev/null
+++ b/package/source/zippackage/ZipPackageSink.hxx
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ZIP_PACKAGE_SINK_HXX
+#define _ZIP_PACKAGE_SINK_HXX
+
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <cppuhelper/implbase1.hxx>
+
+class ZipPackageSink : public ::cppu::WeakImplHelper1
+<
+ com::sun::star::io::XActiveDataSink
+>
+{
+protected:
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xStream;
+public:
+ ZipPackageSink();
+ virtual ~ZipPackageSink();
+ virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream( )
+ throw(::com::sun::star::uno::RuntimeException);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
new file mode 100644
index 000000000000..318a6a52b873
--- /dev/null
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -0,0 +1,805 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+
+
+#include <ZipPackageStream.hxx>
+#include <ZipPackage.hxx>
+#include <ZipFile.hxx>
+#include <EncryptedDataHeader.hxx>
+#include <osl/diagnose.h>
+#include "wrapstreamforshare.hxx"
+
+#include <comphelper/seekableinput.hxx>
+#include <comphelper/storagehelper.hxx>
+
+#include <rtl/instance.hxx>
+
+#include <PackageConstants.hxx>
+
+using namespace com::sun::star::packages::zip::ZipConstants;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star;
+using namespace cppu;
+
+using rtl::OUString;
+
+namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
+
+const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageStream::static_getImplementationId()
+{
+ return lcl_CachedImplId::get();
+}
+
+ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
+ const Reference< XMultiServiceFactory >& xFactory,
+ sal_Bool bAllowRemoveOnInsert )
+: m_xFactory( xFactory )
+, rZipPackage(rNewPackage)
+, bToBeCompressed ( sal_True )
+, bToBeEncrypted ( sal_False )
+, bHaveOwnKey ( sal_False )
+, bIsEncrypted ( sal_False )
+, xEncryptionData ( )
+, m_nStreamMode( PACKAGE_STREAM_NOTSET )
+, m_nMagicalHackPos( 0 )
+, m_nMagicalHackSize( 0 )
+, m_bHasSeekable( sal_False )
+, m_bCompressedIsSetFromOutside( sal_False )
+, m_bFromManifest( sal_False )
+{
+ OSL_ENSURE( m_xFactory.is(), "No factory is provided to ZipPackageStream!\n" );
+
+ this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
+
+ SetFolder ( sal_False );
+ aEntry.nVersion = -1;
+ aEntry.nFlag = 0;
+ aEntry.nMethod = -1;
+ aEntry.nTime = -1;
+ aEntry.nCrc = -1;
+ aEntry.nCompressedSize = -1;
+ aEntry.nSize = -1;
+ aEntry.nOffset = -1;
+ aEntry.nPathLen = -1;
+ aEntry.nExtraLen = -1;
+
+ Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
+ if ( !rCachedImplId.getLength() )
+ rCachedImplId = getImplementationId();
+}
+
+ZipPackageStream::~ZipPackageStream( void )
+{
+}
+
+void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry)
+{
+ aEntry.nVersion = rInEntry.nVersion;
+ aEntry.nFlag = rInEntry.nFlag;
+ aEntry.nMethod = rInEntry.nMethod;
+ aEntry.nTime = rInEntry.nTime;
+ aEntry.nCrc = rInEntry.nCrc;
+ aEntry.nCompressedSize = rInEntry.nCompressedSize;
+ aEntry.nSize = rInEntry.nSize;
+ aEntry.nOffset = rInEntry.nOffset;
+ aEntry.sPath = rInEntry.sPath;
+ aEntry.nPathLen = rInEntry.nPathLen;
+ aEntry.nExtraLen = rInEntry.nExtraLen;
+
+ if ( aEntry.nMethod == STORED )
+ bToBeCompressed = sal_False;
+}
+
+//--------------------------------------------------------------------------
+void ZipPackageStream::CloseOwnStreamIfAny()
+{
+ if ( xStream.is() )
+ {
+ xStream->closeInput();
+ xStream = uno::Reference< io::XInputStream >();
+ m_bHasSeekable = sal_False;
+ }
+}
+
+//--------------------------------------------------------------------------
+uno::Reference< io::XInputStream >& ZipPackageStream::GetOwnSeekStream()
+{
+ if ( !m_bHasSeekable && xStream.is() )
+ {
+ // The package component requires that every stream either be FROM a package or it must support XSeekable!
+ // The only exception is a nonseekable stream that is provided only for storing, if such a stream
+ // is accessed before commit it MUST be wrapped.
+ // Wrap the stream in case it is not seekable
+ xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream, m_xFactory );
+ Reference< io::XSeekable > xSeek( xStream, UNO_QUERY );
+ if ( !xSeek.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must support XSeekable!" ) ),
+ Reference< XInterface >() );
+
+ m_bHasSeekable = sal_True;
+ }
+
+ return xStream;
+}
+
+//--------------------------------------------------------------------------
+uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
+{
+ if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !xEncryptionData.is() )
+ throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Encrypted stream without encryption data!\n" ) ),
+ Reference< XInterface >() );
+
+ uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
+ if ( !xSeek.is() )
+ throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must be seekable!\n" ) ),
+ Reference< XInterface >() );
+
+ // skip header
+ xSeek->seek( n_ConstHeaderSize + xEncryptionData->aInitVector.getLength() +
+ xEncryptionData->aSalt.getLength() + xEncryptionData->aDigest.getLength() );
+
+ // create temporary stream
+ uno::Reference < io::XOutputStream > xTempOut(
+ m_xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
+ uno::UNO_QUERY );
+ uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY );
+ uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY );
+ if ( !xTempOut.is() || !xTempIn.is() || !xTempSeek.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // copy the raw stream to the temporary file starting from the current position
+ ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
+ xTempOut->closeOutput();
+ xTempSeek->seek( 0 );
+
+ return xTempIn;
+}
+
+//--------------------------------------------------------------------------
+Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr )
+{
+ if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || (bAddHeaderForEncr && !bToBeEncrypted) )
+ throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Sequence< sal_Int8 > aKey;
+
+ if ( bToBeEncrypted )
+ {
+ aKey = ( !xEncryptionData.is() || !bHaveOwnKey ) ? rZipPackage.getEncryptionKey() :
+ xEncryptionData->aKey;
+ if ( !aKey.getLength() )
+ throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+
+ try
+ {
+ // create temporary file
+ uno::Reference < io::XStream > xTempStream(
+ m_xFactory->createInstance ( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
+ uno::UNO_QUERY );
+ if ( !xTempStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // create a package based on it
+ ZipPackage* pPackage = new ZipPackage( m_xFactory );
+ Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
+ if ( !xPackageAsFactory.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Sequence< Any > aArgs( 1 );
+ aArgs[0] <<= xTempStream;
+ pPackage->initialize( aArgs );
+
+ // create a new package stream
+ Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
+ if ( !xNewPackStream.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
+ new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ) ) );
+
+ Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
+ if ( !xNewPSProps.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // copy all the properties of this stream to the new stream
+ xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), makeAny( sMediaType ) );
+ xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), makeAny( bToBeCompressed ) );
+ if ( bToBeEncrypted )
+ {
+ xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionKey" ) ), makeAny( aKey ) );
+ xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ), makeAny( sal_True ) );
+ }
+
+ // insert a new stream in the package
+ Reference< XUnoTunnel > xTunnel;
+ Any aRoot = pPackage->getByHierarchicalName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) );
+ aRoot >>= xTunnel;
+ Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
+ if ( !xRootNameContainer.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
+ xRootNameContainer->insertByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "dummy" ) ), makeAny( xNPSTunnel ) );
+
+ // commit the temporary package
+ pPackage->commitChanges();
+
+ // get raw stream from the temporary package
+ Reference< io::XInputStream > xInRaw;
+ if ( bAddHeaderForEncr )
+ xInRaw = xNewPackStream->getRawStream();
+ else
+ xInRaw = xNewPackStream->getPlainRawStream();
+
+ // create another temporary file
+ uno::Reference < io::XOutputStream > xTempOut(
+ m_xFactory->createInstance ( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
+ uno::UNO_QUERY );
+ uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY );
+ uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY );
+ if ( !xTempOut.is() || !xTempIn.is() || !xTempSeek.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // copy the raw stream to the temporary file
+ ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
+ xTempOut->closeOutput();
+ xTempSeek->seek( 0 );
+
+ // close raw stream, package stream and folder
+ xInRaw = Reference< io::XInputStream >();
+ xNewPSProps = Reference< XPropertySet >();
+ xNPSTunnel = Reference< XUnoTunnel >();
+ xNewPackStream = Reference< XDataSinkEncrSupport >();
+ xTunnel = Reference< XUnoTunnel >();
+ xRootNameContainer = Reference< container::XNameContainer >();
+
+ // return the stream representing the first temporary file
+ return xTempIn;
+ }
+ catch ( RuntimeException& )
+ {
+ throw;
+ }
+ catch ( Exception& )
+ {
+ }
+
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+//--------------------------------------------------------------------------
+sal_Bool ZipPackageStream::ParsePackageRawStream()
+{
+ OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
+
+ if ( !GetOwnSeekStream().is() )
+ return sal_False;
+
+ sal_Bool bOk = sal_False;
+
+ rtl::Reference < EncryptionData > xTempEncrData;
+ sal_Int32 nMagHackSize = 0;
+ Sequence < sal_Int8 > aHeader ( 4 );
+
+ try
+ {
+ if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
+ {
+ const sal_Int8 *pHeader = aHeader.getConstArray();
+ sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
+ ( pHeader [1] & 0xFF ) << 8 |
+ ( pHeader [2] & 0xFF ) << 16 |
+ ( pHeader [3] & 0xFF ) << 24;
+ if ( nHeader == n_ConstHeader )
+ {
+ // this is one of our god-awful, but extremely devious hacks, everyone cheer
+ xTempEncrData = new EncryptionData;
+
+ ::rtl::OUString aMediaType;
+ if ( ZipFile::StaticFillData ( xTempEncrData, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
+ {
+ // We'll want to skip the data we've just read, so calculate how much we just read
+ // and remember it
+ m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->aSalt.getLength()
+ + xTempEncrData->aInitVector.getLength()
+ + xTempEncrData->aDigest.getLength()
+ + aMediaType.getLength() * sizeof( sal_Unicode );
+ m_nMagicalHackSize = nMagHackSize;
+ sMediaType = aMediaType;
+
+ bOk = sal_True;
+ }
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ }
+
+ if ( !bOk )
+ {
+ // the provided stream is not a raw stream
+ return sal_False;
+ }
+
+ xEncryptionData = xTempEncrData;
+ SetIsEncrypted ( sal_True );
+ // it's already compressed and encrypted
+ bToBeEncrypted = bToBeCompressed = sal_False;
+
+ return sal_True;
+}
+
+void ZipPackageStream::SetPackageMember( sal_Bool bNewValue )
+{
+ if ( bNewValue )
+ {
+ m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
+ m_nMagicalHackPos = 0;
+ m_nMagicalHackSize = 0;
+ }
+ else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
+ m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
+}
+
+// XActiveDataSink
+//--------------------------------------------------------------------------
+void SAL_CALL ZipPackageStream::setInputStream( const Reference< io::XInputStream >& aStream )
+ throw(RuntimeException)
+{
+ // if seekable access is required the wrapping will be done on demand
+ xStream = aStream;
+ m_bHasSeekable = sal_False;
+ SetPackageMember ( sal_False );
+ aEntry.nTime = -1;
+ m_nStreamMode = PACKAGE_STREAM_DETECT;
+}
+
+//--------------------------------------------------------------------------
+Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
+ throw(RuntimeException)
+{
+ try
+ {
+ if (IsPackageMember())
+ {
+ if ( xEncryptionData.is() && !bHaveOwnKey )
+ xEncryptionData->aKey = rZipPackage.getEncryptionKey();
+ return rZipPackage.getZipFile().getRawData( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( GetOwnSeekStream().is() )
+ {
+ return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
+ }
+ else
+ return Reference < io::XInputStream > ();
+ }
+ catch (ZipException &)//rException)
+ {
+ OSL_ENSURE( 0, "ZipException thrown");//rException.Message);
+ return Reference < io::XInputStream > ();
+ }
+ catch (Exception &)
+ {
+ OSL_ENSURE( 0, "Exception is thrown during stream wrapping!\n");
+ return Reference < io::XInputStream > ();
+ }
+}
+
+//--------------------------------------------------------------------------
+Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream( )
+ throw(RuntimeException)
+{
+ try
+ {
+ if (IsPackageMember())
+ {
+ if ( xEncryptionData.is() && !bHaveOwnKey )
+ xEncryptionData->aKey = rZipPackage.getEncryptionKey();
+ return rZipPackage.getZipFile().getInputStream( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( GetOwnSeekStream().is() )
+ {
+ return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
+ }
+ else
+ return Reference < io::XInputStream > ();
+ }
+ catch (ZipException &)//rException)
+ {
+ OSL_ENSURE( 0,"ZipException thrown");//rException.Message);
+ return Reference < io::XInputStream > ();
+ }
+ catch (Exception &)
+ {
+ OSL_ENSURE( 0, "Exception is thrown during stream wrapping!\n");
+ return Reference < io::XInputStream > ();
+ }
+}
+
+// XDataSinkEncrSupport
+//--------------------------------------------------------------------------
+Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
+ throw ( packages::WrongPasswordException,
+ io::IOException,
+ RuntimeException )
+{
+ // There is no stream attached to this object
+ if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
+ return Reference< io::XInputStream >();
+
+ // this method can not be used together with old approach
+ if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
+ throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( xEncryptionData.is() && !bHaveOwnKey )
+ xEncryptionData->aKey = rZipPackage.getEncryptionKey();
+
+ if (IsPackageMember())
+ {
+ if ( xEncryptionData.is() && !bHaveOwnKey )
+ xEncryptionData->aKey = rZipPackage.getEncryptionKey();
+
+ return rZipPackage.getZipFile().getDataStream( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
+ return ZipFile::StaticGetDataFromRawStream( GetOwnSeekStream(), xEncryptionData );
+ else if ( GetOwnSeekStream().is() )
+ {
+ return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
+ }
+ else
+ return uno::Reference< io::XInputStream >();
+}
+
+//--------------------------------------------------------------------------
+Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
+ throw ( packages::NoEncryptionException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ // There is no stream attached to this object
+ if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
+ return Reference< io::XInputStream >();
+
+ // this method can not be used together with old approach
+ if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
+ throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if (IsPackageMember())
+ {
+ if ( !bIsEncrypted || !xEncryptionData.is() )
+ throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return rZipPackage.getZipFile().getWrappedRawStream( aEntry, xEncryptionData, sMediaType, rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( GetOwnSeekStream().is() )
+ {
+ if ( m_nStreamMode == PACKAGE_STREAM_RAW )
+ {
+ return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
+ return TryToGetRawFromDataStream( sal_True );
+ }
+
+ throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+
+//--------------------------------------------------------------------------
+void SAL_CALL ZipPackageStream::setDataStream( const Reference< io::XInputStream >& aStream )
+ throw ( io::IOException,
+ RuntimeException )
+{
+ setInputStream( aStream );
+ m_nStreamMode = PACKAGE_STREAM_DATA;
+}
+
+//--------------------------------------------------------------------------
+void SAL_CALL ZipPackageStream::setRawStream( const Reference< io::XInputStream >& aStream )
+ throw ( packages::EncryptionNotAllowedException,
+ packages::NoRawFormatException,
+ io::IOException,
+ RuntimeException)
+{
+ // wrap the stream in case it is not seekable
+ Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xFactory );
+ Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
+ if ( !xSeek.is() )
+ throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must support XSeekable!" ) ),
+ Reference< XInterface >() );
+
+ xSeek->seek( 0 );
+ Reference< io::XInputStream > xOldStream = xStream;
+ xStream = xNewStream;
+ if ( !ParsePackageRawStream() )
+ {
+ xStream = xOldStream;
+ throw packages::NoRawFormatException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+
+ // the raw stream MUST have seekable access
+ m_bHasSeekable = sal_True;
+
+ SetPackageMember ( sal_False );
+ aEntry.nTime = -1;
+ m_nStreamMode = PACKAGE_STREAM_RAW;
+}
+
+//--------------------------------------------------------------------------
+uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
+ throw ( io::IOException,
+ uno::RuntimeException )
+{
+ // There is no stream attached to this object
+ if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
+ return Reference< io::XInputStream >();
+
+ // this method can not be used together with old approach
+ if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
+ throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if (IsPackageMember())
+ {
+ return rZipPackage.getZipFile().getRawData( aEntry, xEncryptionData, bIsEncrypted, rZipPackage.GetSharedMutexRef() );
+ }
+ else if ( GetOwnSeekStream().is() )
+ {
+ if ( m_nStreamMode == PACKAGE_STREAM_RAW )
+ {
+ // the header should not be returned here
+ return GetRawEncrStreamNoHeaderCopy();
+ }
+ else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
+ return TryToGetRawFromDataStream( sal_False );
+ }
+
+ return Reference< io::XInputStream >();
+}
+
+// XUnoTunnel
+
+//--------------------------------------------------------------------------
+sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
+ throw(RuntimeException)
+{
+ sal_Int64 nMe = 0;
+ if ( aIdentifier.getLength() == 16 &&
+ 0 == rtl_compareMemory( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
+ nMe = reinterpret_cast < sal_Int64 > ( this );
+ return nMe;
+}
+
+// XPropertySet
+//--------------------------------------------------------------------------
+void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
+ throw(beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
+{
+ if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaType")))
+ {
+ if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
+ throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( aValue >>= sMediaType )
+ {
+ if (sMediaType.getLength() > 0)
+ {
+ if ( sMediaType.indexOf (OUString( RTL_CONSTASCII_USTRINGPARAM ( "text" ) ) ) != -1
+ || sMediaType.equals( OUString( RTL_CONSTASCII_USTRINGPARAM ( "application/vnd.sun.star.oleobject" ) ) ) )
+ bToBeCompressed = sal_True;
+ else if ( !m_bCompressedIsSetFromOutside )
+ bToBeCompressed = sal_False;
+ }
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MediaType must be a string!\n" ) ),
+ Reference< XInterface >(),
+ 2 );
+
+ }
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Size") ) )
+ {
+ if ( !( aValue >>= aEntry.nSize ) )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Size property!\n" ) ),
+ Reference< XInterface >(),
+ 2 );
+ }
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Encrypted") ) )
+ {
+ if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
+ throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ sal_Bool bEnc = sal_False;
+ if ( aValue >>= bEnc )
+ {
+ // In case of new raw stream, the stream must not be encrypted on storing
+ if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
+ Reference< XInterface >(),
+ 2 );
+
+ bToBeEncrypted = bEnc;
+ if ( bToBeEncrypted && !xEncryptionData.is())
+ xEncryptionData = new EncryptionData;
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Encrypted property!\n" ) ),
+ Reference< XInterface >(),
+ 2 );
+
+ }
+ else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("EncryptionKey") ) )
+ {
+ if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
+ throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Sequence < sal_Int8 > aNewKey;
+
+ if ( !( aValue >>= aNewKey ) )
+ {
+ OUString sTempString;
+ if ( ( aValue >>= sTempString ) )
+ {
+ sal_Int32 nPathLength = sTempString.getLength();
+ Sequence < sal_Int8 > aSequence ( nPathLength );
+ sal_Int8 *pArray = aSequence.getArray();
+ const sal_Unicode *pChar = sTempString.getStr();
+ for ( sal_Int16 i = 0; i < nPathLength; i++)
+ pArray[i] = static_cast < const sal_Int8 > (pChar[i]);
+ aNewKey = aSequence;
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n" ) ),
+ Reference< XInterface >(),
+ 2 );
+ }
+
+ if ( aNewKey.getLength() )
+ {
+ if ( !xEncryptionData.is())
+ xEncryptionData = new EncryptionData;
+
+ xEncryptionData->aKey = aNewKey;
+ // In case of new raw stream, the stream must not be encrypted on storing
+ bHaveOwnKey = sal_True;
+ if ( m_nStreamMode != PACKAGE_STREAM_RAW )
+ bToBeEncrypted = sal_True;
+ }
+ else
+ bHaveOwnKey = sal_False;
+ }
+ else if (aPropertyName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
+ {
+ sal_Bool bCompr = sal_False;
+
+ if ( aValue >>= bCompr )
+ {
+ // In case of new raw stream, the stream must not be encrypted on storing
+ if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
+ Reference< XInterface >(),
+ 2 );
+
+ bToBeCompressed = bCompr;
+ m_bCompressedIsSetFromOutside = sal_True;
+ }
+ else
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Compressed property!\n" ) ),
+ Reference< XInterface >(),
+ 2 );
+ }
+ else
+ throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+//--------------------------------------------------------------------------
+Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
+ throw(beans::UnknownPropertyException, WrappedTargetException, RuntimeException)
+{
+ Any aAny;
+ if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
+ {
+ aAny <<= sMediaType;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Size" ) ) )
+ {
+ aAny <<= aEntry.nSize;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Encrypted" ) ) )
+ {
+ aAny <<= ( m_nStreamMode == PACKAGE_STREAM_RAW ) ? sal_True : bToBeEncrypted;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "WasEncrypted" ) ) )
+ {
+ aAny <<= bIsEncrypted;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
+ {
+ aAny <<= bToBeCompressed;
+ return aAny;
+ }
+ else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionKey" ) ) )
+ {
+ aAny <<= !xEncryptionData.is() ? Sequence < sal_Int8 > () : xEncryptionData->aKey;
+ return aAny;
+ }
+ else
+ throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+//--------------------------------------------------------------------------
+void ZipPackageStream::setSize (const sal_Int32 nNewSize)
+{
+ if (aEntry.nCompressedSize != nNewSize )
+ aEntry.nMethod = DEFLATED;
+ aEntry.nSize = nNewSize;
+}
+//--------------------------------------------------------------------------
+OUString ZipPackageStream::getImplementationName()
+ throw (RuntimeException)
+{
+ return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageStream" ) );
+}
+
+//--------------------------------------------------------------------------
+Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
+ throw (RuntimeException)
+{
+ Sequence< OUString > aNames(1);
+ aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageStream" ) );
+ return aNames;
+}
+//--------------------------------------------------------------------------
+sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
+ throw (RuntimeException)
+{
+ return rServiceName == getSupportedServiceNames()[0];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackageStream.hxx b/package/source/zippackage/ZipPackageStream.hxx
new file mode 100644
index 000000000000..9bdc09d04f92
--- /dev/null
+++ b/package/source/zippackage/ZipPackageStream.hxx
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ZIP_PACKAGE_STREAM_HXX
+#define _ZIP_PACKAGE_STREAM_HXX
+
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/packages/XDataSinkEncrSupport.hpp>
+#include <ZipPackageEntry.hxx>
+#include <rtl/ref.hxx>
+#include <EncryptionData.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <mutexholder.hxx>
+
+#define PACKAGE_STREAM_NOTSET 0
+#define PACKAGE_STREAM_PACKAGEMEMBER 1
+#define PACKAGE_STREAM_DETECT 2
+#define PACKAGE_STREAM_DATA 3
+#define PACKAGE_STREAM_RAW 4
+
+class ZipPackage;
+struct ZipEntry;
+class ZipPackageStream : public cppu::ImplInheritanceHelper2
+<
+ ZipPackageEntry,
+ ::com::sun::star::io::XActiveDataSink,
+ ::com::sun::star::packages::XDataSinkEncrSupport
+>
+{
+protected:
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xStream;
+ const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory > m_xFactory;
+ ZipPackage &rZipPackage;
+ sal_Bool bToBeCompressed, bToBeEncrypted, bHaveOwnKey, bIsEncrypted;
+ rtl::Reference < EncryptionData > xEncryptionData;
+
+ sal_uInt8 m_nStreamMode;
+ sal_uInt32 m_nMagicalHackPos;
+ sal_uInt32 m_nMagicalHackSize;
+
+ sal_Bool m_bHasSeekable;
+
+ sal_Bool m_bCompressedIsSetFromOutside;
+
+ sal_Bool m_bFromManifest;
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& GetOwnSeekStream();
+
+public:
+ sal_Bool HasOwnKey () const { return bHaveOwnKey;}
+ sal_Bool IsToBeCompressed () const { return bToBeCompressed;}
+ sal_Bool IsToBeEncrypted () const { return bToBeEncrypted;}
+ sal_Bool IsEncrypted () const { return bIsEncrypted;}
+ sal_Bool IsPackageMember () const { return m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER;}
+
+ sal_Bool IsFromManifest() const { return m_bFromManifest; }
+ void SetFromManifest( sal_Bool bValue ) { m_bFromManifest = bValue; }
+
+ rtl::Reference < EncryptionData > & getEncryptionData ()
+ { return xEncryptionData;}
+ const com::sun::star::uno::Sequence < sal_Int8 >& getKey () const
+ { return xEncryptionData->aKey;}
+ const com::sun::star::uno::Sequence < sal_uInt8 >& getInitialisationVector () const
+ { return xEncryptionData->aInitVector;}
+ const com::sun::star::uno::Sequence < sal_uInt8 >& getDigest () const
+ { return xEncryptionData->aDigest;}
+ const com::sun::star::uno::Sequence < sal_uInt8 >& getSalt () const
+ { return xEncryptionData->aSalt;}
+ sal_Int32 getIterationCount () const
+ { return xEncryptionData->nIterationCount;}
+ sal_Int32 getSize () const
+ { return aEntry.nSize;}
+
+ sal_uInt8 GetStreamMode() const { return m_nStreamMode; }
+ sal_uInt32 GetMagicalHackPos() const { return m_nMagicalHackPos; }
+ sal_uInt32 GetMagicalHackSize() const { return m_nMagicalHackSize; }
+
+ void SetToBeCompressed (sal_Bool bNewValue) { bToBeCompressed = bNewValue;}
+ void SetIsEncrypted (sal_Bool bNewValue) { bIsEncrypted = bNewValue;}
+ void SetToBeEncrypted (sal_Bool bNewValue)
+ {
+ bToBeEncrypted = bNewValue;
+ if ( bToBeEncrypted && !xEncryptionData.is())
+ xEncryptionData = new EncryptionData;
+ else if ( !bToBeEncrypted && xEncryptionData.is() )
+ xEncryptionData.clear();
+ }
+ void SetPackageMember (sal_Bool bNewValue);
+ void setKey (const com::sun::star::uno::Sequence < sal_Int8 >& rNewKey )
+ { xEncryptionData->aKey = rNewKey;}
+ void setInitialisationVector (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewVector )
+ { xEncryptionData->aInitVector = rNewVector;}
+ void setSalt (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewSalt )
+ { xEncryptionData->aSalt = rNewSalt;}
+ void setDigest (const com::sun::star::uno::Sequence < sal_uInt8 >& rNewDigest )
+ { xEncryptionData->aDigest = rNewDigest;}
+ void setIterationCount (const sal_Int32 nNewCount)
+ { xEncryptionData->nIterationCount = nNewCount;}
+ void setSize (const sal_Int32 nNewSize);
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnStreamNoWrap() { return xStream; }
+
+ void CloseOwnStreamIfAny();
+
+ ZipPackageStream ( ZipPackage & rNewPackage,
+ const ::com::sun::star::uno::Reference < com::sun::star::lang::XMultiServiceFactory >& xFactory,
+ sal_Bool bAllowRemoveOnInsert );
+ virtual ~ZipPackageStream( void );
+
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetRawEncrStreamNoHeaderCopy();
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > TryToGetRawFromDataStream(
+ sal_Bool bAddHeaderForEncr );
+
+ sal_Bool ParsePackageRawStream();
+
+ void setZipEntryOnLoading( const ZipEntry &rInEntry);
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
+ throw(::com::sun::star::uno::RuntimeException);
+
+ static const ::com::sun::star::uno::Sequence < sal_Int8 >& static_getImplementationId();
+
+ // XActiveDataSink
+ virtual void SAL_CALL setInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
+ throw(::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getInputStream( )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XDataSinkEncrSupport
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getDataStream()
+ throw ( ::com::sun::star::packages::WrongPasswordException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawStream()
+ throw ( ::com::sun::star::packages::NoEncryptionException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL setDataStream(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
+ throw ( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL setRawStream(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& aStream )
+ throw ( ::com::sun::star::packages::EncryptionNotAllowedException,
+ ::com::sun::star::packages::NoRawFormatException,
+ ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getPlainRawStream()
+ throw ( ::com::sun::star::io::IOException,
+ ::com::sun::star::uno::RuntimeException );
+
+ // XUnoTunnel
+ virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& aIdentifier )
+ throw(::com::sun::star::uno::RuntimeException);
+
+ // XPropertySet
+ virtual void SAL_CALL setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Any SAL_CALL getPropertyValue( const ::rtl::OUString& PropertyName )
+ throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( )
+ throw (::com::sun::star::uno::RuntimeException);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/makefile.mk b/package/source/zippackage/makefile.mk
new file mode 100644
index 000000000000..c729b945f0df
--- /dev/null
+++ b/package/source/zippackage/makefile.mk
@@ -0,0 +1,58 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJNAME=package
+TARGET=zippackage
+AUTOSEG=true
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(L10N_framework)"==""
+
+SLOFILES= \
+ $(SLO)$/ZipPackage.obj \
+ $(SLO)$/ZipPackageBuffer.obj \
+ $(SLO)$/ZipPackageEntry.obj \
+ $(SLO)$/ZipPackageFolder.obj \
+ $(SLO)$/ZipPackageFolderEnumeration.obj \
+ $(SLO)$/ZipPackageSink.obj \
+ $(SLO)$/ZipPackageStream.obj \
+ $(SLO)$/wrapstreamforshare.obj \
+ $(SLO)$/zipfileaccess.obj
+
+.ENDIF # L10N_framework
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/package/source/zippackage/wrapstreamforshare.cxx b/package/source/zippackage/wrapstreamforshare.cxx
new file mode 100644
index 000000000000..9afb2f8f9428
--- /dev/null
+++ b/package/source/zippackage/wrapstreamforshare.cxx
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <osl/diagnose.h>
+
+#include "wrapstreamforshare.hxx"
+
+using namespace ::com::sun::star;
+
+
+WrapStreamForShare::WrapStreamForShare( const uno::Reference< io::XInputStream >& xInStream,
+ const SotMutexHolderRef& rMutexRef )
+: m_rMutexRef( rMutexRef )
+, m_xInStream( xInStream )
+, m_nCurPos( 0 )
+{
+ m_xSeekable = uno::Reference< io::XSeekable >( m_xInStream, uno::UNO_QUERY );
+ if ( !m_rMutexRef.Is() || !m_xInStream.is() || !m_xSeekable.is() )
+ {
+ OSL_ENSURE( sal_False, "Wrong initialization of wrapping stream!\n" );
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+}
+
+WrapStreamForShare::~WrapStreamForShare()
+{
+}
+
+// XInputStream
+sal_Int32 SAL_CALL WrapStreamForShare::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ m_xSeekable->seek( m_nCurPos );
+
+ sal_Int32 nRead = m_xInStream->readBytes( aData, nBytesToRead );
+ m_nCurPos += nRead;
+
+ return nRead;
+}
+
+sal_Int32 SAL_CALL WrapStreamForShare::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ m_xSeekable->seek( m_nCurPos );
+
+ sal_Int32 nRead = m_xInStream->readSomeBytes( aData, nMaxBytesToRead );
+ m_nCurPos += nRead;
+
+ return nRead;
+}
+
+void SAL_CALL WrapStreamForShare::skipBytes( sal_Int32 nBytesToSkip )
+ throw ( io::NotConnectedException,
+ io::BufferSizeExceededException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ m_xSeekable->seek( m_nCurPos );
+
+ m_xInStream->skipBytes( nBytesToSkip );
+ m_nCurPos = m_xSeekable->getPosition();
+}
+
+sal_Int32 SAL_CALL WrapStreamForShare::available()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return m_xInStream->available();
+}
+
+void SAL_CALL WrapStreamForShare::closeInput()
+ throw ( io::NotConnectedException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // the package is the owner so it will close the stream
+ // m_xInStream->closeInput();
+ m_xInStream = uno::Reference< io::XInputStream >();
+ m_xSeekable = uno::Reference< io::XSeekable >();
+}
+
+// XSeekable
+void SAL_CALL WrapStreamForShare::seek( sal_Int64 location )
+ throw ( lang::IllegalArgumentException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // let stream implementation do all the checking
+ m_xSeekable->seek( location );
+
+ m_nCurPos = m_xSeekable->getPosition();
+}
+
+sal_Int64 SAL_CALL WrapStreamForShare::getPosition()
+ throw ( io::IOException,
+ uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return m_nCurPos;
+}
+
+sal_Int64 SAL_CALL WrapStreamForShare::getLength()
+ throw ( io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
+
+ if ( !m_xInStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return m_xSeekable->getLength();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/wrapstreamforshare.hxx b/package/source/zippackage/wrapstreamforshare.hxx
new file mode 100644
index 000000000000..85b03c62943c
--- /dev/null
+++ b/package/source/zippackage/wrapstreamforshare.hxx
@@ -0,0 +1,75 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WRAPSTREAMFORSHARE_HXX_
+#define _WRAPSTREAMFORSHARE_HXX_
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <cppuhelper/implbase2.hxx>
+
+#include <mutexholder.hxx>
+
+class WrapStreamForShare : public cppu::WeakImplHelper2 < ::com::sun::star::io::XInputStream
+ , ::com::sun::star::io::XSeekable >
+{
+protected:
+ SotMutexHolderRef m_rMutexRef;
+ ::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > m_xInStream;
+ ::com::sun::star::uno::Reference < ::com::sun::star::io::XSeekable > m_xSeekable;
+
+ sal_Int64 m_nCurPos;
+
+public:
+ WrapStreamForShare( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& xInStream,
+ const SotMutexHolderRef& rMutexRef );
+ virtual ~WrapStreamForShare();
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL available( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL closeInput( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+
+
+ //XSeekable
+ virtual void SAL_CALL seek( sal_Int64 location ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getPosition() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getLength() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/zipfileaccess.cxx b/package/source/zippackage/zipfileaccess.cxx
new file mode 100644
index 000000000000..cb5996aa3c8e
--- /dev/null
+++ b/package/source/zippackage/zipfileaccess.cxx
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <com/sun/star/lang/DisposedException.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+
+#include <zipfileaccess.hxx>
+#include <ZipEnumeration.hxx>
+#include <ZipPackageSink.hxx>
+#include <EncryptionData.hxx>
+
+#include <ucbhelper/content.hxx>
+
+#include <memory>
+
+
+using namespace ::com::sun::star;
+
+// ----------------------------------------------------------------
+OZipFileAccess::OZipFileAccess( const uno::Reference< lang::XMultiServiceFactory >& xFactory )
+: m_aMutexHolder( new SotMutexHolder )
+, m_xFactory( xFactory )
+, m_pZipFile( NULL )
+, m_pListenersContainer( NULL )
+, m_bDisposed( sal_False )
+{
+ if ( !xFactory.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+// ----------------------------------------------------------------
+OZipFileAccess::~OZipFileAccess()
+{
+ {
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+ if ( !m_bDisposed )
+ {
+ try {
+ m_refCount++; // dispose will use refcounting so the further distruction must be avoided
+ dispose();
+ } catch( uno::Exception& )
+ {}
+ }
+ }
+}
+
+// ----------------------------------------------------------------
+uno::Sequence< ::rtl::OUString > OZipFileAccess::GetPatternsFromString_Impl( const ::rtl::OUString& aString )
+{
+ if ( !aString.getLength() )
+ return uno::Sequence< ::rtl::OUString >();
+
+ uno::Sequence< ::rtl::OUString > aPattern( 1 );
+ sal_Int32 nInd = 0;
+
+ const sal_Unicode* pString = aString.getStr();
+ while( *pString )
+ {
+ if ( *pString == (sal_Unicode)'\\' )
+ {
+ pString++;
+
+ if ( *pString == (sal_Unicode)'\\' )
+ {
+ aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'\\' );
+ pString++;
+ }
+ else if ( *pString == (sal_Unicode)'*' )
+ {
+ aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'*' );
+ pString++;
+ }
+ else
+ {
+ OSL_ENSURE( sal_False, "The backslash is not guarded!\n" );
+ aPattern[nInd] += ::rtl::OUString::valueOf( (sal_Unicode)'\\' );
+ }
+ }
+ else if ( *pString == (sal_Unicode)'*' )
+ {
+ aPattern.realloc( ( ++nInd ) + 1 );
+ pString++;
+ }
+ else
+ {
+ aPattern[nInd] += ::rtl::OUString::valueOf( *pString );
+ pString++;
+ }
+ }
+
+ return aPattern;
+}
+
+// ----------------------------------------------------------------
+sal_Bool OZipFileAccess::StringGoodForPattern_Impl( const ::rtl::OUString& aString,
+ const uno::Sequence< ::rtl::OUString >& aPattern )
+{
+ sal_Int32 nInd = aPattern.getLength() - 1;
+ if ( nInd < 0 )
+ return sal_False;
+
+ if ( nInd == 0 )
+ {
+ if ( !aPattern[0].getLength() )
+ return sal_True;
+
+ return aString.equals( aPattern[0] );
+ }
+
+ sal_Int32 nBeginInd = aPattern[0].getLength();
+ sal_Int32 nEndInd = aString.getLength() - aPattern[nInd].getLength();
+ if ( nEndInd >= nBeginInd
+ && ( nEndInd == aString.getLength() || aString.copy( nEndInd ).equals( aPattern[nInd] ) )
+ && ( nBeginInd == 0 || aString.copy( 0, nBeginInd ).equals( aPattern[0] ) ) )
+ {
+ for ( sal_Int32 nCurInd = aPattern.getLength() - 2; nCurInd > 0; nCurInd-- )
+ {
+ if ( !aPattern[nCurInd].getLength() )
+ continue;
+
+ if ( nEndInd == nBeginInd )
+ return sal_False;
+
+ // check that search does not use nEndInd position
+ sal_Int32 nLastInd = aString.lastIndexOf( aPattern[nCurInd], nEndInd - 1 );
+
+ if ( nLastInd == -1 )
+ return sal_False;
+
+ if ( nLastInd < nBeginInd )
+ return sal_False;
+
+ nEndInd = nLastInd;
+ }
+
+ return sal_True;
+ }
+
+ return sal_False;
+}
+
+// XInitialization
+// ----------------------------------------------------------------
+void SAL_CALL OZipFileAccess::initialize( const uno::Sequence< uno::Any >& aArguments )
+ throw ( uno::Exception,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( m_pZipFile )
+ throw uno::Exception( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); // initialization is allowed only one time
+
+ if ( !aArguments.getLength() )
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+
+ OSL_ENSURE( aArguments.getLength() == 1, "Too meny arguments are provided, only the first one will be used!\n" );
+
+ ::rtl::OUString aParamURL;
+ uno::Reference< io::XStream > xStream;
+ uno::Reference< io::XSeekable > xSeekable;
+
+ if ( ( aArguments[0] >>= aParamURL ) )
+ {
+ ::ucbhelper::Content aContent ( aParamURL, uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >() );
+ uno::Reference < io::XActiveDataSink > xSink = new ZipPackageSink;
+ if ( aContent.openStream ( xSink ) )
+ {
+ m_xContentStream = xSink->getInputStream();
+ xSeekable = uno::Reference< io::XSeekable >( m_xContentStream, uno::UNO_QUERY );
+ }
+ }
+ else if ( (aArguments[0] >>= xStream ) )
+ {
+ // a writable stream can implement both XStream & XInputStream
+ m_xContentStream = xStream->getInputStream();
+ xSeekable = uno::Reference< io::XSeekable >( xStream, uno::UNO_QUERY );
+ }
+ else if ( !( aArguments[0] >>= m_xContentStream ) )
+ {
+ xSeekable = uno::Reference< io::XSeekable >( m_xContentStream, uno::UNO_QUERY );
+ }
+ else
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+
+ if ( !m_xContentStream.is() )
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !xSeekable.is() )
+ {
+ // TODO: after fwkbugfix02 is integrated a helper class can be used to make the stream seekable
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+
+ // TODO: in case xSeekable is implemented on separated XStream implementation a wrapper is required
+ m_pZipFile = new ZipFile(
+ m_xContentStream,
+ m_xFactory,
+ sal_True );
+}
+
+// XNameAccess
+// ----------------------------------------------------------------
+uno::Any SAL_CALL OZipFileAccess::getByName( const ::rtl::OUString& aName )
+ throw ( container::NoSuchElementException,
+ lang::WrappedTargetException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ EntryHash::iterator aIter = m_pZipFile->GetEntryHash().find( aName );
+ if ( aIter == m_pZipFile->GetEntryHash().end() )
+ throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second,
+ new EncryptionData(),
+ sal_False,
+ m_aMutexHolder ) );
+
+ if ( !xEntryStream.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return uno::makeAny ( xEntryStream );
+}
+
+// ----------------------------------------------------------------
+uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::getElementNames()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ uno::Sequence< ::rtl::OUString > aNames( m_pZipFile->GetEntryHash().size() );
+ sal_Int32 nLen = 0;
+
+ for ( EntryHash::iterator aIter = m_pZipFile->GetEntryHash().begin(); aIter != m_pZipFile->GetEntryHash().end(); ++aIter )
+ {
+ if ( aNames.getLength() < ++nLen )
+ {
+ OSL_ENSURE( sal_False, "The size must be the same!\n" );
+ aNames.realloc( nLen );
+ }
+
+ aNames[nLen-1] = (*aIter).second.sPath;
+ }
+
+ if ( aNames.getLength() != nLen )
+ {
+ OSL_ENSURE( sal_False, "The size must be the same!\n" );
+ aNames.realloc( nLen );
+ }
+
+ return aNames;
+}
+
+// ----------------------------------------------------------------
+sal_Bool SAL_CALL OZipFileAccess::hasByName( const ::rtl::OUString& aName )
+ throw (uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ EntryHash::iterator aIter = m_pZipFile->GetEntryHash().find( aName );
+
+ return ( aIter != m_pZipFile->GetEntryHash().end() );
+}
+
+// ----------------------------------------------------------------
+uno::Type SAL_CALL OZipFileAccess::getElementType()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return getCppuType( ( const uno::Reference< io::XInputStream >* )NULL );
+}
+
+// ----------------------------------------------------------------
+sal_Bool SAL_CALL OZipFileAccess::hasElements()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ return ( m_pZipFile->GetEntryHash().size() != 0 );
+}
+
+// XZipFileAccess
+// ----------------------------------------------------------------
+uno::Reference< io::XInputStream > SAL_CALL OZipFileAccess::getStreamByPattern( const ::rtl::OUString& aPatternString )
+ throw ( container::NoSuchElementException,
+ io::IOException,
+ uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pZipFile )
+ throw io::NotConnectedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ // Code to compare strings by patterns
+ uno::Sequence< ::rtl::OUString > aPattern = GetPatternsFromString_Impl( aPatternString );
+
+ for ( EntryHash::iterator aIter = m_pZipFile->GetEntryHash().begin(); aIter != m_pZipFile->GetEntryHash().end(); ++aIter )
+ {
+ if ( StringGoodForPattern_Impl( (*aIter).second.sPath, aPattern ) )
+ {
+ uno::Reference< io::XInputStream > xEntryStream( m_pZipFile->getDataStream( (*aIter).second,
+ new EncryptionData(),
+ sal_False,
+ m_aMutexHolder ) );
+
+ if ( !xEntryStream.is() )
+ throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ return xEntryStream;
+ }
+ }
+
+ throw container::NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+// XComponent
+// ----------------------------------------------------------------
+void SAL_CALL OZipFileAccess::dispose()
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( m_pListenersContainer )
+ {
+ lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) );
+ m_pListenersContainer->disposeAndClear( aSource );
+ delete m_pListenersContainer;
+ m_pListenersContainer = NULL;
+ }
+
+ if ( m_pZipFile )
+ {
+ delete m_pZipFile;
+ m_pZipFile = NULL;
+ }
+
+ if ( m_xContentStream.is() )
+ try {
+ m_xContentStream->closeInput();
+ } catch( uno::Exception& )
+ {}
+
+ m_bDisposed = sal_True;
+}
+
+// ----------------------------------------------------------------
+void SAL_CALL OZipFileAccess::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( !m_pListenersContainer )
+ m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutexHolder->GetMutex() );
+ m_pListenersContainer->addInterface( xListener );
+}
+
+// ----------------------------------------------------------------
+void SAL_CALL OZipFileAccess::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
+ throw ( uno::RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
+
+ if ( m_bDisposed )
+ throw lang::DisposedException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( m_pListenersContainer )
+ m_pListenersContainer->removeInterface( xListener );
+}
+
+//-------------------------------------------------------------------------
+uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::impl_staticGetSupportedServiceNames()
+{
+ uno::Sequence< ::rtl::OUString > aRet(2);
+ aRet[0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.packages.zip.ZipFileAccess") );
+ aRet[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.packages.zip.ZipFileAccess") );
+ return aRet;
+}
+
+//-------------------------------------------------------------------------
+::rtl::OUString SAL_CALL OZipFileAccess::impl_staticGetImplementationName()
+{
+ return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.package.zip.ZipFileAccess") );
+}
+
+//-------------------------------------------------------------------------
+uno::Reference< uno::XInterface > SAL_CALL OZipFileAccess::impl_staticCreateSelfInstance(
+ const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
+{
+ return uno::Reference< uno::XInterface >( *new OZipFileAccess( xServiceManager ) );
+}
+
+//-------------------------------------------------------------------------
+::rtl::OUString SAL_CALL OZipFileAccess::getImplementationName()
+ throw ( uno::RuntimeException )
+{
+ return impl_staticGetImplementationName();
+}
+
+//-------------------------------------------------------------------------
+sal_Bool SAL_CALL OZipFileAccess::supportsService( const ::rtl::OUString& ServiceName )
+ throw ( uno::RuntimeException )
+{
+ uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
+
+ for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
+ if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
+ return sal_True;
+
+ return sal_False;
+}
+
+//-------------------------------------------------------------------------
+uno::Sequence< ::rtl::OUString > SAL_CALL OZipFileAccess::getSupportedServiceNames()
+ throw ( uno::RuntimeException )
+{
+ return impl_staticGetSupportedServiceNames();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */