summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2009-09-07 14:41:16 +0000
committerOliver Bolte <obo@openoffice.org>2009-09-07 14:41:16 +0000
commit9fa41b880dcfef94fa3b7b057f601d97f8a37763 (patch)
treee9fa09c313164699137f72e8350585a0c8571849 /oox
parentc2f366873f2a3b423265a1ebfdb5e1547d49f3e5 (diff)
CWS-TOOLING: integrate CWS dr72
2009-08-26 10:24:00 +0200 dr r275402 : #i92645# CODEPAGE is encrypted... 2009-08-24 14:37:36 +0200 dr r275316 : #i10000# enable exceptions for xlroot.cxx 2009-08-24 14:33:15 +0200 dr r275313 : #i10000# link openssl under solaris correctly 2009-08-21 17:41:16 +0200 dr r275267 : #i10000# unxlngi6 warning 2009-08-21 15:35:56 +0200 dr r275265 : #i10000# remove files again, already deleted in previous milestone... 2009-08-21 11:24:57 +0200 dr r275227 : #160401# port to DEV300 2009-08-21 09:53:45 +0200 dr r275221 : #i92645# full support for encrypted Word2007 files 2009-08-21 09:50:52 +0200 dr r275219 : #i92645# final changes for decryption 2009-08-20 19:48:40 +0200 dr r275195 : #i104370# missing parentheses, patch from cmc 2009-08-20 18:28:22 +0200 dr r275193 : #i92645# rework package decryption to repair 'Reload Document' functionality 2009-08-20 13:55:14 +0200 dr r275179 : #i92645# add new property names 2009-08-19 19:24:21 +0200 dr r275159 : #160401# open writeprotected files read-only, merged to DEV300 2009-08-18 14:41:47 +0200 dr r275109 : #i92645# add 'Aborted' property 2009-08-18 11:20:34 +0200 dr r275084 : #i92645# write back password to medium 2009-08-17 17:52:51 +0200 dr r275066 : #i92645# detect Word2007 docs with oox detection impl, this adds support of encryped Word2007; correct detection of templates and macro-enabled docs 2009-08-17 17:51:31 +0200 dr r275065 : #i92645# detect Word2007 docs with oox detection impl, this adds support of encryped Word2007; correct detection of templates and macro-enabled docs 2009-08-17 11:06:39 +0200 dr r275035 : #i92645# more password handling 2009-08-17 11:05:21 +0200 dr r275034 : #i92645# use new password input mechanism for BIFF filter and dumper in oox 2009-08-14 16:33:53 +0200 nn r274996 : #i104228# DelBroadcastAreasInRange: remove area from hash_set before deleting 2009-08-14 16:27:12 +0200 nn r274995 : #i104059# restore a change lost in the integration of fhawfixes1 2009-08-14 16:24:00 +0200 dr r274994 : #i92645# adapt BIFF import to latest changes 2009-08-14 16:21:30 +0200 dr r274993 : #i92645# adapt BIFF import to latest changes 2009-08-14 16:20:43 +0200 dr r274992 : #i92645# do not add default passwords to media descriptor 2009-08-13 19:20:45 +0200 dr r274965 : #i92645# add a helper to request a document password 2009-08-13 19:09:35 +0200 dr r274964 : #i92645# add a helper to request a document password 2009-08-13 19:09:03 +0200 dr r274963 : #i92645# add a helper to request a document password 2009-08-13 14:35:01 +0200 dr r274946 : #i92645# comment typo 2009-08-13 14:33:47 +0200 dr r274945 : #i92645# add a helper to request a document password 2009-08-13 14:04:47 +0200 dr r274941 : #i92645# add a helper to request a document password 2009-08-13 14:04:22 +0200 dr r274940 : #i92645# add a helper to request a document password 2009-08-13 11:16:27 +0200 dr r274927 : #i42303# show quick help if field name too long for button 2009-08-13 10:55:48 +0200 dr r274925 : #i31600# cut field name and add ellipsis, if too long for button 2009-08-12 18:47:26 +0200 dr r274914 : #i92645# ask user for a password 2009-08-12 18:02:39 +0200 dr r274909 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:59:11 +0200 dr r274906 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:41:18 +0200 dr r274905 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:40:33 +0200 dr r274904 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:40:08 +0200 dr r274903 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:39:30 +0200 dr r274902 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-12 16:15:28 +0200 dr r274899 : #i104183# move svtools/DocPasswordRequest to comphelper to be able to use it in oox 2009-08-11 19:51:12 +0200 dr r274877 : #i92645# open encrypted MSOOXML package protected with standard XL password 'VelvetSweatshop'
Diffstat (limited to 'oox')
-rw-r--r--oox/inc/oox/core/binarycodec.hxx33
-rw-r--r--oox/inc/oox/core/binaryfilterbase.hxx5
-rw-r--r--oox/inc/oox/core/filterbase.hxx30
-rw-r--r--oox/inc/oox/core/filterdetect.hxx168
-rw-r--r--oox/inc/oox/core/xmlfilterbase.hxx9
-rw-r--r--oox/inc/oox/dump/dumperbase.hxx50
-rw-r--r--oox/inc/oox/xls/biffcodec.hxx111
-rw-r--r--oox/inc/oox/xls/biffhelper.hxx3
-rw-r--r--oox/inc/oox/xls/workbooksettings.hxx19
-rw-r--r--oox/prj/build.lst2
-rw-r--r--oox/prj/d.lst23
-rw-r--r--oox/source/core/binarycodec.cxx23
-rw-r--r--oox/source/core/binaryfilterbase.cxx17
-rw-r--r--oox/source/core/filterbase.cxx174
-rw-r--r--oox/source/core/filterdetect.cxx535
-rw-r--r--oox/source/core/makefile.mk4
-rw-r--r--oox/source/core/xmlfilterbase.cxx49
-rw-r--r--oox/source/dump/biffdumper.cxx84
-rw-r--r--oox/source/dump/biffdumper.ini5
-rw-r--r--oox/source/dump/dumperbase.cxx55
-rw-r--r--oox/source/dump/pptxdumper.cxx4
-rw-r--r--oox/source/dump/xlsbdumper.cxx10
-rw-r--r--oox/source/vml/vmlshape.cxx2
-rw-r--r--oox/source/xls/biffcodec.cxx289
-rw-r--r--oox/source/xls/workbookfragment.cxx64
-rw-r--r--oox/source/xls/workbooksettings.cxx45
-rw-r--r--oox/source/xls/worksheetsettings.cxx15
-rw-r--r--oox/util/makefile.mk14
28 files changed, 1297 insertions, 545 deletions
diff --git a/oox/inc/oox/core/binarycodec.hxx b/oox/inc/oox/core/binarycodec.hxx
index bb33c214f42d..767b9c2be936 100644
--- a/oox/inc/oox/core/binarycodec.hxx
+++ b/oox/inc/oox/core/binarycodec.hxx
@@ -34,11 +34,26 @@
#include <rtl/cipher.h>
#include <rtl/digest.h>
+namespace oox { class AttributeList; }
+
namespace oox {
namespace core {
// ============================================================================
+class CodecHelper
+{
+public:
+ /** Returns the password hash if it is in the required 16-bit limit. */
+ static sal_uInt16 getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement );
+
+private:
+ CodecHelper();
+ ~CodecHelper();
+};
+
+// ============================================================================
+
/** Encodes and decodes data from/to protected MS Office documents.
Implements a simple XOR encoding/decoding algorithm used in MS Office
@@ -182,12 +197,12 @@ public:
@param pnPassData
Unicode character array containing the password. Must be zero
terminated, which results in a maximum length of 15 characters.
- @param pnUnique
- Unique document identifier read from or written to the file.
+ @param pnSalt
+ Random salt data block read from or written to the file.
*/
void initKey(
const sal_uInt16 pnPassData[ 16 ],
- const sal_uInt8 pnUnique[ 16 ] );
+ const sal_uInt8 pnSalt[ 16 ] );
/** Verifies the validity of the password using the passed salt data.
@@ -195,17 +210,17 @@ public:
The codec must be initialized with the initKey() function before
this function can be used.
- @param pnSaltData
- Salt data block read from the file.
- @param pnSaltDigest
- Salt digest read from the file.
+ @param pnVerifier
+ Verifier block read from the file.
+ @param pnVerifierHash
+ Verifier hash read from the file.
@return
True = test was successful.
*/
bool verifyKey(
- const sal_uInt8 pnSaltData[ 16 ],
- const sal_uInt8 pnSaltDigest[ 16 ] );
+ const sal_uInt8 pnVerifier[ 16 ],
+ const sal_uInt8 pnVerifierHash[ 16 ] );
/** Rekeys the codec using the specified counter.
diff --git a/oox/inc/oox/core/binaryfilterbase.hxx b/oox/inc/oox/core/binaryfilterbase.hxx
index ce2c4f2c31d7..c051934f550c 100644
--- a/oox/inc/oox/core/binaryfilterbase.hxx
+++ b/oox/inc/oox/core/binaryfilterbase.hxx
@@ -49,8 +49,9 @@ public:
private:
virtual StorageRef implCreateStorage(
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream,
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream ) const;
+ virtual StorageRef implCreateStorage(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const;
};
typedef ::rtl::Reference< BinaryFilterBase > BinaryFilterRef;
diff --git a/oox/inc/oox/core/filterbase.hxx b/oox/inc/oox/core/filterbase.hxx
index 001b537444c1..9115c88be4e7 100644
--- a/oox/inc/oox/core/filterbase.hxx
+++ b/oox/inc/oox/core/filterbase.hxx
@@ -44,7 +44,7 @@
#include <cppuhelper/implbase5.hxx>
#include "oox/helper/binarystreambase.hxx"
#include "oox/helper/storagebase.hxx"
-#include <oox/dllapi.h>
+#include "oox/dllapi.h"
namespace com { namespace sun { namespace star {
namespace lang { class XMultiServiceFactory; }
@@ -58,6 +58,11 @@ namespace com { namespace sun { namespace star {
namespace graphic { class XGraphic; }
} } }
+namespace comphelper {
+ class IDocPasswordVerifier;
+ class MediaDescriptor;
+}
+
namespace oox {
class GraphicHelper;
class ModelObjectHelper;
@@ -110,6 +115,9 @@ public:
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
getGlobalFactory() const;
+ /** Returns the media descriptor. */
+ ::comphelper::MediaDescriptor& getMediaDescriptor() const;
+
/** Returns the document model (always existing). */
const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >&
getModel() const;
@@ -193,6 +201,10 @@ public:
/** Returns a system color specified by the passed XML token identifier. */
sal_Int32 getSystemColor( sal_Int32 nToken, sal_Int32 nDefaultRgb = -1 ) const;
+ /** Requests a password from the media descriptor or from the user. On
+ success, the password will be inserted into the media descriptor. */
+ ::rtl::OUString requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier ) const;
+
/** Imports the raw binary data from the specified stream.
@return True, if the data could be imported from the stream. */
bool importBinaryData( StreamDataSequence& orDataSeq, const ::rtl::OUString& rStreamName );
@@ -251,19 +263,29 @@ public:
// com.sun.star.document.XFilter interface --------------------------------
virtual sal_Bool SAL_CALL filter(
- const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rDescriptor )
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rMediaDescSeq )
throw( ::com::sun::star::uno::RuntimeException );
virtual void SAL_CALL cancel()
throw( ::com::sun::star::uno::RuntimeException );
// ------------------------------------------------------------------------
+protected:
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >
+ implGetInputStream( ::comphelper::MediaDescriptor& rMediaDesc ) const;
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >
+ implGetOutputStream( ::comphelper::MediaDescriptor& rMediaDesc ) const;
+
private:
+ void setMediaDescriptor(
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rMediaDescSeq );
+
virtual ::rtl::OUString implGetImplementationName() const = 0;
virtual StorageRef implCreateStorage(
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream,
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const = 0;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream ) const = 0;
+ virtual StorageRef implCreateStorage(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const = 0;
private:
::std::auto_ptr< FilterBaseImpl > mxImpl;
diff --git a/oox/inc/oox/core/filterdetect.hxx b/oox/inc/oox/core/filterdetect.hxx
new file mode 100644
index 000000000000..bd9e3a84ff3a
--- /dev/null
+++ b/oox/inc/oox/core/filterdetect.hxx
@@ -0,0 +1,168 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: filterdetect.hxx,v $
+ * $Revision: 1.1 $
+ *
+ * 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 OOX_CORE_FILTERDETECT_HXX
+#define OOX_CORE_FILTERDETECT_HXX
+
+#include <vector>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include "oox/dllapi.h"
+
+namespace com { namespace sun { namespace star {
+ namespace io { class XInputStream; }
+} } }
+
+namespace comphelper { class MediaDescriptor; }
+namespace oox { class AttributeList; }
+
+namespace oox {
+namespace core {
+
+// ============================================================================
+
+/** Document handler specifically designed for detecting OOXML file formats.
+
+ It takes a reference to the filter string object via its constructor, and
+ puts the name of the detected filter to it, if it successfully finds one.
+ */
+class FilterDetectDocHandler : public ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastDocumentHandler >
+{
+public:
+ explicit FilterDetectDocHandler( ::rtl::OUString& rFilter );
+ virtual ~FilterDetectDocHandler();
+
+ // XFastDocumentHandler
+ virtual void SAL_CALL startDocument() throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endDocument() throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL setDocumentLocator( const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XLocator >& xLocator ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+
+ // XFastContextHandler
+ virtual void SAL_CALL startFastElement( sal_Int32 nElement, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL startUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endFastElement( sal_Int32 Element ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL endUnknownElement( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XFastAttributeList >& Attribs ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL characters( const ::rtl::OUString& aChars ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL ignorableWhitespace( const ::rtl::OUString& aWhitespaces ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL processingInstruction( const ::rtl::OUString& aTarget, const ::rtl::OUString& aData ) throw (::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeException);
+
+private:
+ void parseRelationship( const AttributeList& rAttribs );
+
+ ::rtl::OUString getFilterNameFromContentType( const ::rtl::OUString& rContentType ) const;
+ void parseContentTypesDefault( const AttributeList& rAttribs );
+ void parseContentTypesOverride( const AttributeList& rAttribs );
+
+private:
+ typedef ::std::vector< sal_Int32 > ContextVector;
+
+ ::rtl::OUString& mrFilterName;
+ ContextVector maContextStack;
+ ::rtl::OUString maTargetPath;
+};
+
+// ============================================================================
+
+class OOX_DLLPUBLIC FilterDetect : public ::cppu::WeakImplHelper2< ::com::sun::star::document::XExtendedFilterDetection, ::com::sun::star::lang::XServiceInfo >
+{
+public:
+ explicit FilterDetect( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory );
+ virtual ~FilterDetect();
+
+ /** Tries to extract an unencrypted ZIP package from the passed media
+ descriptor.
+
+ First, this function checks if the input stream provided by the media
+ descriptor property 'InputStream' contains a ZIP package. If yes, this
+ stream is returned.
+
+ Second, this function checks if the 'ComponentData' property exists and
+ contains a sequence of com.sun.star.beans.NamedValue. If yes, a named
+ value is searched with the name 'DecryptedPackage' and a value of type
+ com.sun.star.io.XStream. If the input stream provided by this XStream
+ contains a ZIP package, this input stream is returned.
+
+ Third, this function checks if the input stream of the media descriptor
+ contains an OLE package. If yes, it checks the existence of the streams
+ 'EncryptionInfo' and 'EncyptedPackage' and tries to decrypt the package
+ into a temporary file. This may include requesting a password from the
+ media descriptor property 'Password' or from the user, using the
+ interaction handler provided by the descriptor. On success, and if the
+ decrypted package is a ZIP package, the XStream of the temporary file
+ is stored in the property 'ComponentData' of the media descriptor and
+ its input stream is returned.
+ */
+ ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >
+ extractUnencryptedPackage( ::comphelper::MediaDescriptor& rMediaDesc ) const;
+
+ // com.sun.star.lang.XServiceInfo interface -------------------------------
+
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& rServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ // com.sun.star.document.XExtendedFilterDetection interface ---------------
+
+ /** Detects MS Office 2007 file types and supports package decryption.
+
+ The following file types are detected:
+ - MS Word 2007 XML Document (*.docx, *.docm)
+ - MS Word 2007 XML Template (*.dotx, *.dotm)
+ - MS Excel 2007 XML Document (*.xlsx, *.xlsm)
+ - MS Excel 2007 BIFF12 Document (*.xlsb)
+ - MS Excel 2007 XML Template (*.xltx, *.xltm)
+ - MS Powerpoint 2007 XML Document (*.pptx, *.pptm)
+ - MS Powerpoint 2007 XML Template (*.potx, *.potm)
+
+ If the package is encrypted, the detection tries to decrypt it into a
+ temporary file. The user may be asked for a password. The XStream
+ interface of the temporary file will be stored in the 'ComponentData'
+ property of the passed media descriptor.
+ */
+ virtual ::rtl::OUString SAL_CALL detect(
+ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rMediaDescSeq )
+ throw( ::com::sun::star::uno::RuntimeException );
+
+private:
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxFactory;
+};
+
+// ============================================================================
+
+} // namespace core
+} // namespace oox
+
+#endif
+
diff --git a/oox/inc/oox/core/xmlfilterbase.hxx b/oox/inc/oox/core/xmlfilterbase.hxx
index f88554457e36..d1b79dc116d8 100644
--- a/oox/inc/oox/core/xmlfilterbase.hxx
+++ b/oox/inc/oox/core/xmlfilterbase.hxx
@@ -204,10 +204,15 @@ public:
*/
XmlFilterBase& exportDocumentProperties( ::com::sun::star::uno::Reference< ::com::sun::star::document::XDocumentProperties > xProperties );
+protected:
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >
+ implGetInputStream( ::comphelper::MediaDescriptor& rMediaDesc ) const;
+
private:
virtual StorageRef implCreateStorage(
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream,
- ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const;
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream ) const;
+ virtual StorageRef implCreateStorage(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream ) const;
private:
::std::auto_ptr< XmlFilterBaseImpl > mxImpl;
diff --git a/oox/inc/oox/dump/dumperbase.hxx b/oox/inc/oox/dump/dumperbase.hxx
index 0c5314c4adc7..9a791942ce4e 100644
--- a/oox/inc/oox/dump/dumperbase.hxx
+++ b/oox/inc/oox/dump/dumperbase.hxx
@@ -41,6 +41,7 @@
#include <rtl/ustrbuf.hxx>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/util/DateTime.hpp>
+#include <comphelper/mediadescriptor.hxx>
#include "oox/helper/helper.hxx"
#include "oox/helper/storagebase.hxx"
#include "oox/helper/binaryinputstream.hxx"
@@ -57,6 +58,10 @@ namespace com { namespace sun { namespace star {
namespace lang { class XMultiServiceFactory; }
} } }
+namespace comphelper {
+ class IDocPasswordVerifier;
+}
+
namespace oox {
class BinaryOutputStream;
}
@@ -866,7 +871,8 @@ public:
const ::rtl::OUString& rFileName,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory,
const StorageRef& rxRootStrg,
- const ::rtl::OUString& rSysFileName );
+ const ::rtl::OUString& rSysFileName,
+ ::comphelper::MediaDescriptor& rMediaDesc );
virtual ~SharedConfigData();
@@ -883,6 +889,9 @@ public:
void eraseNameList( const ::rtl::OUString& rListName );
NameListRef getNameList( const ::rtl::OUString& rListName ) const;
+ ::rtl::OUString requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier );
+ inline bool isPasswordCancelled() const { return mbPwCancelled; }
+
protected:
virtual bool implIsValid() const;
virtual void implProcessConfigItemStr(
@@ -905,11 +914,13 @@ private:
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxFactory;
StorageRef mxRootStrg;
::rtl::OUString maSysFileName;
+ ::comphelper::MediaDescriptor& mrMediaDesc;
ConfigFileSet maConfigFiles;
ConfigDataMap maConfigData;
NameListMap maNameLists;
::rtl::OUString maConfigPath;
bool mbLoaded;
+ bool mbPwCancelled;
};
// ----------------------------------------------------------------------------
@@ -947,7 +958,8 @@ public:
const sal_Char* pcEnvVar,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory,
const StorageRef& rxRootStrg,
- const ::rtl::OUString& rSysFileName );
+ const ::rtl::OUString& rSysFileName,
+ ::comphelper::MediaDescriptor& rMediaDesc );
virtual ~Config();
@@ -978,6 +990,9 @@ public:
template< typename Type >
bool hasName( const NameListWrapper& rListWrp, Type nKey ) const;
+ ::rtl::OUString requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier );
+ bool isPasswordCancelled() const;
+
protected:
inline explicit Config() {}
void construct( const Config& rParent );
@@ -988,7 +1003,8 @@ protected:
const sal_Char* pcEnvVar,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory,
const StorageRef& rxRootStrg,
- const ::rtl::OUString& rSysFileName );
+ const ::rtl::OUString& rSysFileName,
+ ::comphelper::MediaDescriptor& rMediaDesc );
virtual bool implIsValid() const;
virtual const ::rtl::OUString* implGetOption( const ::rtl::OUString& rKey ) const;
@@ -1822,11 +1838,6 @@ class RecordObjectBase : public InputObjectBase
protected:
inline explicit RecordObjectBase() {}
- inline sal_Int64 getRecPos() const { return mnRecPos; }
- inline sal_Int64 getRecId() const { return mnRecId; }
- inline sal_Int64 getRecSize() const { return mnRecSize; }
- inline NameListRef getRecNames() const { return maRecNames.getNameList( cfg() ); }
-
using InputObjectBase::construct;
void construct(
const ObjectBase& rParent,
@@ -1842,6 +1853,14 @@ protected:
const String& rRecNames,
const String& rSimpleRecs = EMPTY_STRING );
+ inline sal_Int64 getRecPos() const { return mnRecPos; }
+ inline sal_Int64 getRecId() const { return mnRecId; }
+ inline sal_Int64 getRecSize() const { return mnRecSize; }
+ inline NameListRef getRecNames() const { return maRecNames.getNameList( cfg() ); }
+
+ inline void setBinaryOnlyMode( bool bBinaryOnly ) { mbBinaryOnly = bBinaryOnly; }
+ inline bool isBinaryOnlyMode() const { return mbBinaryOnly; }
+
virtual bool implIsValid() const;
virtual void implDump();
@@ -1865,6 +1884,7 @@ private:
sal_Int64 mnRecId;
sal_Int64 mnRecSize;
bool mbShowRecPos;
+ bool mbBinaryOnly;
};
// ============================================================================
@@ -1922,6 +1942,7 @@ public:
virtual ~DumperBase();
bool isImportEnabled() const;
+ bool isImportCancelled() const;
protected:
inline explicit DumperBase() {}
@@ -1936,12 +1957,13 @@ protected:
} // namespace dump
} // namespace oox
-#define OOX_DUMP_FILE( DumperClassName ) \
-do { \
- DumperClassName aDumper( *this ); \
- aDumper.dump(); \
- if( !aDumper.isImportEnabled() ) \
- return aDumper.isValid(); \
+#define OOX_DUMP_FILE( DumperClassName ) \
+do { \
+ DumperClassName aDumper( *this ); \
+ aDumper.dump(); \
+ bool bCancelled = aDumper.isImportCancelled(); \
+ if( !aDumper.isImportEnabled() || bCancelled ) \
+ return aDumper.isValid() && !bCancelled; \
} while( false )
#else // OOX_INCLUDE_DUMPER
diff --git a/oox/inc/oox/xls/biffcodec.hxx b/oox/inc/oox/xls/biffcodec.hxx
index 165a608d46fd..3fc5d77b474e 100644
--- a/oox/inc/oox/xls/biffcodec.hxx
+++ b/oox/inc/oox/xls/biffcodec.hxx
@@ -32,6 +32,7 @@
#define OOX_XLS_BIFFCODEC_HXX
#include <vector>
+#include <comphelper/docpasswordhelper.hxx>
#include "oox/core/binarycodec.hxx"
#include "oox/xls/workbookhelper.hxx"
@@ -40,29 +41,27 @@ namespace xls {
// ============================================================================
-const sal_Int32 CODEC_OK = 0;
-const sal_Int32 CODEC_ERROR_WRONG_PASS = 1;
-const sal_Int32 CODEC_ERROR_UNSUPP_CRYPT = 2;
-
const sal_Int64 BIFF_RCF_BLOCKSIZE = 1024;
// ============================================================================
/** Base class for BIFF stream decoders. */
-class BiffDecoderBase : public WorkbookHelper
+class BiffDecoderBase : public ::comphelper::IDocPasswordVerifier
{
public:
- explicit BiffDecoderBase( const WorkbookHelper& rHelper );
+ explicit BiffDecoderBase();
virtual ~BiffDecoderBase();
/** Derived classes return a clone of the decoder for usage in new streams. */
inline BiffDecoderBase* clone() { return implClone(); }
- /** Returns the current error code of the decoder. */
- inline sal_Int32 getErrorCode() const { return mnError; }
- /** Returns true, if the decoder has been constructed successfully.
- This means especially that construction happened with a valid password. */
- inline bool isValid() const { return mnError == CODEC_OK; }
+ /** Implementation of the ::comphelper::IDocPasswordVerifier interface,
+ calls the new virtual function implVerify(). */
+ virtual ::comphelper::DocPasswordVerifierResult
+ verifyPassword( const ::rtl::OUString& rPassword );
+
+ /** Returns true, if the decoder has been initialized correctly. */
+ inline bool isValid() const { return mbValid; }
/** Decodes nBytes bytes and writes encrypted data into the buffer pnDestData. */
void decode(
@@ -71,17 +70,14 @@ public:
sal_Int64 nStreamPos,
sal_uInt16 nBytes );
-protected:
- /** Copy constructor for cloning. */
- BiffDecoderBase( const BiffDecoderBase& rDecoder );
-
- /** Sets the decoder to a state showing whether the password was correct. */
- void setHasValidPassword( bool bValid );
-
private:
/** Derived classes return a clone of the decoder for usage in new streams. */
virtual BiffDecoderBase* implClone() = 0;
+ /** Derived classes implement password verification and initialization of
+ the decoder. */
+ virtual bool implVerify( const ::rtl::OUString& rPassword ) = 0;
+
/** Implementation of decryption of a memory block. */
virtual void implDecode(
sal_uInt8* pnDestData,
@@ -90,7 +86,7 @@ private:
sal_uInt16 nBytes ) = 0;
private:
- sal_Int32 mnError; /// Decoder error code.
+ bool mbValid; /// True = decoder is correctly initialized.
};
typedef ::boost::shared_ptr< BiffDecoderBase > BiffDecoderRef;
@@ -101,31 +97,18 @@ typedef ::boost::shared_ptr< BiffDecoderBase > BiffDecoderRef;
class BiffDecoder_XOR : public BiffDecoderBase
{
public:
- /** Constructs the decoder.
-
- Checks if the passed key and hash specify workbook protection. Asks for
- a password otherwise.
-
- @param nKey
- Password key from FILEPASS record to verify password.
- @param nHash
- Password hash value from FILEPASS record to verify password.
- */
- explicit BiffDecoder_XOR(
- const WorkbookHelper& rHelper,
- sal_uInt16 nKey, sal_uInt16 nHash );
+ explicit BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash );
private:
/** Copy constructor for cloning. */
BiffDecoder_XOR( const BiffDecoder_XOR& rDecoder );
- /** Initializes the wrapped codec object. After that, internal status can
- be querried with isValid(). */
- void init( const ::rtl::OString& rPass );
-
/** Returns a clone of the decoder for usage in new streams. */
virtual BiffDecoder_XOR* implClone();
+ /** Implements password verification and initialization of the decoder. */
+ virtual bool implVerify( const ::rtl::OUString& rPassword );
+
/** Implementation of decryption of a memory block. */
virtual void implDecode(
sal_uInt8* pnDestData,
@@ -135,7 +118,7 @@ private:
private:
::oox::core::BinaryCodec_XOR maCodec; /// Cipher algorithm implementation.
- ::rtl::OString maPass;
+ ::std::vector< sal_uInt8 > maPassword;
sal_uInt16 mnKey;
sal_uInt16 mnHash;
};
@@ -146,35 +129,21 @@ private:
class BiffDecoder_RCF : public BiffDecoderBase
{
public:
- /** Constructs the decoder.
-
- Checks if the passed salt data specifies workbook protection. Asks for
- a password otherwise.
-
- @param pnDocId
- Unique document identifier from FILEPASS record.
- @param pnSaltData
- Salt data from FILEPASS record.
- @param pnSaltHash
- Salt hash value from FILEPASS record.
- */
explicit BiffDecoder_RCF(
- const WorkbookHelper& rHelper,
- sal_uInt8 pnDocId[ 16 ],
- sal_uInt8 pnSaltData[ 16 ],
- sal_uInt8 pnSaltHash[ 16 ] );
+ sal_uInt8 pnSalt[ 16 ],
+ sal_uInt8 pnVerifier[ 16 ],
+ sal_uInt8 pnVerifierHash[ 16 ] );
private:
/** Copy constructor for cloning. */
BiffDecoder_RCF( const BiffDecoder_RCF& rDecoder );
- /** Initializes the wrapped codec object. After that, internal status can
- be querried with isValid(). */
- void init( const ::rtl::OUString& rPass );
-
/** Returns a clone of the decoder for usage in new streams. */
virtual BiffDecoder_RCF* implClone();
+ /** Implements password verification and initialization of the decoder. */
+ virtual bool implVerify( const ::rtl::OUString& rPassword );
+
/** Implementation of decryption of a memory block. */
virtual void implDecode(
sal_uInt8* pnDestData,
@@ -184,10 +153,10 @@ private:
private:
::oox::core::BinaryCodec_RCF maCodec; /// Cipher algorithm implementation.
- ::rtl::OUString maPass;
- ::std::vector< sal_uInt8 > maDocId;
- ::std::vector< sal_uInt8 > maSaltData;
- ::std::vector< sal_uInt8 > maSaltHash;
+ ::std::vector< sal_uInt16 > maPassword;
+ ::std::vector< sal_uInt8 > maSalt;
+ ::std::vector< sal_uInt8 > maVerifier;
+ ::std::vector< sal_uInt8 > maVerifierHash;
};
// ============================================================================
@@ -198,30 +167,16 @@ class BiffCodecHelper : public WorkbookHelper
public:
explicit BiffCodecHelper( const WorkbookHelper& rHelper );
- /** Returns the fixed password for workbook protection. */
- static const ::rtl::OString& getBiff5WbProtPassword();
- /** Returns the fixed password for workbook protection. */
- static const ::rtl::OUString& getBiff8WbProtPassword();
+ /** Implementation helper, reads the FILEPASS and returns a decoder object. */
+ static BiffDecoderRef implReadFilePass( BiffInputStream& rStrm, BiffType eBiff );
- /** Looks for a password provided via API, or queries it via GUI. */
- ::rtl::OUString queryPassword();
-
- /** Imports the FILEPASS record and sets a decoder at the stream. */
+ /** Imports the FILEPASS record, asks for a password and sets a decoder at the stream. */
bool importFilePass( BiffInputStream& rStrm );
/** Clones the contained decoder object if existing and sets it at the passed stream. */
void cloneDecoder( BiffInputStream& rStrm );
private:
- void importFilePass_XOR( BiffInputStream& rStrm );
- void importFilePass_RCF( BiffInputStream& rStrm );
- void importFilePass_Strong( BiffInputStream& rStrm );
- void importFilePass2( BiffInputStream& rStrm );
- void importFilePass8( BiffInputStream& rStrm );
-
-private:
BiffDecoderRef mxDecoder; /// The decoder for import filter.
- ::rtl::OUString maPassword; /// Password for stream encoder/decoder.
- bool mbHasPassword; /// True = password already querried.
};
// ============================================================================
diff --git a/oox/inc/oox/xls/biffhelper.hxx b/oox/inc/oox/xls/biffhelper.hxx
index 8d9aac767bba..1da2c362170f 100644
--- a/oox/inc/oox/xls/biffhelper.hxx
+++ b/oox/inc/oox/xls/biffhelper.hxx
@@ -120,6 +120,7 @@ const sal_Int32 OOBIN_ID_EXTROW = 0x016E;
const sal_Int32 OOBIN_ID_EXTSHEETDATA = 0x016B;
const sal_Int32 OOBIN_ID_EXTERNALNAMEFLAGS = 0x024A;
const sal_Int32 OOBIN_ID_EXTSHEETNAMES = 0x0167;
+const sal_Int32 OOBIN_ID_FILESHARING = 0x0224;
const sal_Int32 OOBIN_ID_FILEVERSION = 0x0080;
const sal_Int32 OOBIN_ID_FILL = 0x002D;
const sal_Int32 OOBIN_ID_FILLS = 0x025B;
@@ -369,6 +370,7 @@ const sal_uInt16 BIFF5_ID_EXTERNALNAME = 0x0023;
const sal_uInt16 BIFF_ID_EXTERNSHEET = 0x0017;
const sal_uInt16 BIFF_ID_EXTSST = 0x00FF;
const sal_uInt16 BIFF_ID_FILEPASS = 0x002F;
+const sal_uInt16 BIFF_ID_FILESHARING = 0x005B;
const sal_uInt16 BIFF2_ID_FONT = 0x0031;
const sal_uInt16 BIFF3_ID_FONT = 0x0231;
const sal_uInt16 BIFF5_ID_FONT = 0x0031;
@@ -388,6 +390,7 @@ const sal_uInt16 BIFF_ID_HYPERLINK = 0x01B8;
const sal_uInt16 BIFF3_ID_IMGDATA = 0x007F;
const sal_uInt16 BIFF8_ID_IMGDATA = 0x00E9;
const sal_uInt16 BIFF2_ID_INTEGER = 0x0002;
+const sal_uInt16 BIFF_ID_INTERFACEHDR = 0x00E1;
const sal_uInt16 BIFF_ID_ITERATION = 0x0011;
const sal_uInt16 BIFF_ID_IXFE = 0x0044;
const sal_uInt16 BIFF2_ID_LABEL = 0x0004;
diff --git a/oox/inc/oox/xls/workbooksettings.hxx b/oox/inc/oox/xls/workbooksettings.hxx
index 683747c03ed6..81712bd5c5a1 100644
--- a/oox/inc/oox/xls/workbooksettings.hxx
+++ b/oox/inc/oox/xls/workbooksettings.hxx
@@ -40,6 +40,18 @@ namespace xls {
// ============================================================================
+/** Settings for workbook write protection. */
+struct FileSharingModel
+{
+ ::rtl::OUString maUserName; /// User who added the write protection password.
+ sal_uInt16 mnPasswordHash; /// Hash value of the write protection password.
+ bool mbRecommendReadOnly; /// True = recommend read-only mode on opening.
+
+ explicit FileSharingModel();
+};
+
+// ============================================================================
+
/** Global workbook settings. */
struct WorkbookSettingsModel
{
@@ -84,11 +96,15 @@ class WorkbookSettings : public WorkbookHelper
public:
explicit WorkbookSettings( const WorkbookHelper& rHelper );
+ /** Imports the fileSharing element containing write protection settings. */
+ void importFileSharing( const AttributeList& rAttribs );
/** Imports the workbookPr element containing global workbook settings. */
void importWorkbookPr( const AttributeList& rAttribs );
/** Imports the calcPr element containing workbook calculation settings. */
void importCalcPr( const AttributeList& rAttribs );
+ /** Imports the FILESHARING record containing write protection settings. */
+ void importFileSharing( RecordInputStream& rStrm );
/** Imports the WORKBOOKPR record containing global workbook settings. */
void importWorkbookPr( RecordInputStream& rStrm );
/** Imports the CALCPR record containing workbook calculation settings. */
@@ -96,6 +112,8 @@ public:
/** Sets the save external linked values flag, e.g. from the WSBOOL record. */
void setSaveExtLinkValues( bool bSaveExtLinks );
+ /** Imports the FILESHARING record. */
+ void importFileSharing( BiffInputStream& rStrm );
/** Imports the BOOKBOOL record. */
void importBookBool( BiffInputStream& rStrm );
/** Imports the CALCCOUNT record. */
@@ -136,6 +154,7 @@ private:
void setDateMode( bool bDateMode1904 );
private:
+ FileSharingModel maFileSharing;
WorkbookSettingsModel maBookSettings;
CalcSettingsModel maCalcSettings;
};
diff --git a/oox/prj/build.lst b/oox/prj/build.lst
index b95c5cba0164..a1dfa584543c 100644
--- a/oox/prj/build.lst
+++ b/oox/prj/build.lst
@@ -1,4 +1,4 @@
-oox oox : vos cppu cppuhelper comphelper sal offapi sax basegfx tools vcl BOOST:boost NULL
+oox oox : vos cppu cppuhelper comphelper sal offapi sax basegfx tools vcl BOOST:boost OPENSSL:openssl NULL
oox oox usr1 - all oox_mkout NULL
oox oox\prj get - all oox_prj NULL
oox oox\source\token nmake - all oox_token NULL
diff --git a/oox/prj/d.lst b/oox/prj/d.lst
index df4430bcd058..50ec05955ca6 100644
--- a/oox/prj/d.lst
+++ b/oox/prj/d.lst
@@ -1,10 +1,10 @@
mkdir: %_DEST%\inc%_EXT%\oox
-mkdir: %_DEST%\inc%_EXT%\oox\core
mkdir: %_DEST%\inc%_EXT%\oox\helper
-mkdir: %_DEST%\inc%_EXT%\oox\vml
+mkdir: %_DEST%\inc%_EXT%\oox\core
mkdir: %_DEST%\inc%_EXT%\oox\drawingml
mkdir: %_DEST%\inc%_EXT%\oox\drawingml\chart
mkdir: %_DEST%\inc%_EXT%\oox\drawingml\table
+mkdir: %_DEST%\inc%_EXT%\oox\vml
..\%__SRC%\misc\*.map %_DEST%\bin%_EXT%\*.map
..\%__SRC%\lib\ixo.lib %_DEST%\lib%_EXT%\ixo.lib
@@ -13,23 +13,24 @@ mkdir: %_DEST%\inc%_EXT%\oox\drawingml\table
..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll
..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT%\lib*.so
..\%__SRC%\lib\i*.lib %_DEST%\lib%_EXT%\i*.lib
+..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
-..\inc\oox\dllapi.h %_DEST%\inc%_EXT%\oox\dllapi.h
-..\source\token\tokens.txt %_DEST%\inc%_EXT%\oox\token.txt
-..\inc\oox\core\filterbase.hxx %_DEST%\inc%_EXT%\oox\core\filterbase.hxx
-..\inc\oox\core\relations.hxx %_DEST%\inc%_EXT%\oox\core\relations.hxx
..\%__SRC%\inc\tokens.hxx %_DEST%\inc%_EXT%\oox\core\tokens.hxx
-..\inc\oox\core\xmlfilterbase.hxx %_DEST%\inc%_EXT%\oox\core\xmlfilterbase.hxx
+
+..\source\token\tokens.txt %_DEST%\inc%_EXT%\oox\token.txt
+..\inc\oox\dllapi.h %_DEST%\inc%_EXT%\oox\dllapi.h
..\inc\oox\helper\binarystreambase.hxx %_DEST%\inc%_EXT%\oox\helper\binarystreambase.hxx
..\inc\oox\helper\helper.hxx %_DEST%\inc%_EXT%\oox\helper\helper.hxx
..\inc\oox\helper\storagebase.hxx %_DEST%\inc%_EXT%\oox\helper\storagebase.hxx
..\inc\oox\helper\zipstorage.hxx %_DEST%\inc%_EXT%\oox\helper\zipstorage.hxx
-..\inc\oox\vml\drawing.hxx %_DEST%\inc%_EXT%\oox\vml\drawing.hxx
+..\inc\oox\core\filterbase.hxx %_DEST%\inc%_EXT%\oox\core\filterbase.hxx
+..\inc\oox\core\filterdetect.hxx %_DEST%\inc%_EXT%\oox\core\filterdetect.hxx
+..\inc\oox\core\relations.hxx %_DEST%\inc%_EXT%\oox\core\relations.hxx
+..\inc\oox\core\xmlfilterbase.hxx %_DEST%\inc%_EXT%\oox\core\xmlfilterbase.hxx
..\inc\oox\drawingml\chart\chartconverter.hxx %_DEST%\inc%_EXT%\oox\drawingml\chart\chartconverter.hxx
..\inc\oox\drawingml\table\tablestylelist.hxx %_DEST%\inc%_EXT%\oox\drawingml\table\tablestylelist.hxx
-..\inc\oox\vml\shape.hxx %_DEST%\inc%_EXT%\oox\vml\shape.hxx
-
-..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
+..\inc\oox\vml\vmldrawing.hxx %_DEST%\inc%_EXT%\oox\vml\vmldrawing.hxx
+..\inc\oox\vml\vmlshape.hxx %_DEST%\inc%_EXT%\oox\vml\vmlshape.hxx
dos: sh -c "if test %OS% = MACOSX; then create-bundle %_DEST%\lib%_EXT%\*.dylib; fi"
diff --git a/oox/source/core/binarycodec.cxx b/oox/source/core/binarycodec.cxx
index 78161b161aab..b6a7e92986b6 100644
--- a/oox/source/core/binarycodec.cxx
+++ b/oox/source/core/binarycodec.cxx
@@ -31,7 +31,7 @@
#include "oox/core/binarycodec.hxx"
#include <algorithm>
#include <string.h>
-#include <osl/diagnose.h>
+#include "oox/helper/attributelist.hxx"
namespace oox {
namespace core {
@@ -113,6 +113,15 @@ sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, sal_Int32 nBufferSize )
// ============================================================================
+/*static*/ sal_uInt16 CodecHelper::getPasswordHash( const AttributeList& rAttribs, sal_Int32 nElement )
+{
+ sal_Int32 nPasswordHash = rAttribs.getIntegerHex( nElement, 0 );
+ OSL_ENSURE( (0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16), "CodecHelper::getPasswordHash - invalid password hash" );
+ return static_cast< sal_uInt16 >( ((0 <= nPasswordHash) && (nPasswordHash <= SAL_MAX_UINT16)) ? nPasswordHash : 0 );
+}
+
+// ============================================================================
+
BinaryCodec_XOR::BinaryCodec_XOR( CodecType eCodecType ) :
meCodecType( eCodecType ),
mnOffset( 0 ),
@@ -249,7 +258,7 @@ BinaryCodec_RCF::~BinaryCodec_RCF()
rtl_cipher_destroy( mhCipher );
}
-void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnUnique[ 16 ] )
+void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt8 pnSalt[ 16 ] )
{
// create little-endian key data array from password data
sal_uInt8 pnKeyData[ 64 ];
@@ -271,11 +280,11 @@ void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt
(void)rtl_digest_updateMD5( mhDigest, pnKeyData, sizeof( pnKeyData ) );
(void)rtl_digest_rawMD5( mhDigest, pnKeyData, RTL_DIGEST_LENGTH_MD5 );
- // update digest with key data and passed unique data
+ // update digest with key data and passed salt data
for( size_t nIndex = 0; nIndex < 16; ++nIndex )
{
rtl_digest_updateMD5( mhDigest, pnKeyData, 5 );
- rtl_digest_updateMD5( mhDigest, pnUnique, 16 );
+ rtl_digest_updateMD5( mhDigest, pnSalt, 16 );
}
// update digest with padding
@@ -292,7 +301,7 @@ void BinaryCodec_RCF::initKey( const sal_uInt16 pnPassData[ 16 ], const sal_uInt
(void)memset( pnKeyData, 0, sizeof( pnKeyData ) );
}
-bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnSaltData[ 16 ], const sal_uInt8 pnSaltDigest[ 16 ] )
+bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnVerifier[ 16 ], const sal_uInt8 pnVerifierHash[ 16 ] )
{
if( !startBlock( 0 ) )
return false;
@@ -301,7 +310,7 @@ bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnSaltData[ 16 ], const sal_uIn
sal_uInt8 pnBuffer[ 64 ];
// decode salt data into buffer
- rtl_cipher_decode( mhCipher, pnSaltData, 16, pnBuffer, sizeof( pnBuffer ) );
+ rtl_cipher_decode( mhCipher, pnVerifier, 16, pnBuffer, sizeof( pnBuffer ) );
pnBuffer[ 16 ] = 0x80;
(void)memset( pnBuffer + 17, 0, sizeof( pnBuffer ) - 17 );
@@ -312,7 +321,7 @@ bool BinaryCodec_RCF::verifyKey( const sal_uInt8 pnSaltData[ 16 ], const sal_uIn
rtl_digest_rawMD5( mhDigest, pnDigest, sizeof( pnDigest ) );
// decode original salt digest into buffer
- rtl_cipher_decode( mhCipher, pnSaltDigest, 16, pnBuffer, sizeof( pnBuffer ) );
+ rtl_cipher_decode( mhCipher, pnVerifierHash, 16, pnBuffer, sizeof( pnBuffer ) );
// compare buffer with computed digest
bool bResult = memcmp( pnBuffer, pnDigest, sizeof( pnDigest ) ) == 0;
diff --git a/oox/source/core/binaryfilterbase.cxx b/oox/source/core/binaryfilterbase.cxx
index 86e89318d476..c883284de664 100644
--- a/oox/source/core/binaryfilterbase.cxx
+++ b/oox/source/core/binaryfilterbase.cxx
@@ -51,15 +51,16 @@ BinaryFilterBase::~BinaryFilterBase()
{
}
-StorageRef BinaryFilterBase::implCreateStorage(
- Reference< XInputStream >& rxInStream, Reference< XStream >& rxOutStream ) const
+// private --------------------------------------------------------------------
+
+StorageRef BinaryFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const
+{
+ return StorageRef( new OleStorage( getGlobalFactory(), rxInStream, true ) );
+}
+
+StorageRef BinaryFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const
{
- StorageRef xStorage;
- if( rxInStream.is() )
- xStorage.reset( new OleStorage( getGlobalFactory(), rxInStream, true ) );
- else if( rxOutStream.is() )
- xStorage.reset( new OleStorage( getGlobalFactory(), rxOutStream, true ) );
- return xStorage;
+ return StorageRef( new OleStorage( getGlobalFactory(), rxOutStream, true ) );
}
// ============================================================================
diff --git a/oox/source/core/filterbase.cxx b/oox/source/core/filterbase.cxx
index 23363db46ed5..55793859fe2e 100644
--- a/oox/source/core/filterbase.cxx
+++ b/oox/source/core/filterbase.cxx
@@ -38,6 +38,7 @@
#include <osl/mutex.hxx>
#include <rtl/instance.hxx>
#include <rtl/uri.hxx>
+#include <comphelper/docpasswordhelper.hxx>
#include <comphelper/mediadescriptor.hxx>
#include "tokens.hxx"
#include "oox/helper/binaryinputstream.hxx"
@@ -58,7 +59,6 @@ using ::com::sun::star::uno::UNO_SET_THROW;
using ::com::sun::star::lang::IllegalArgumentException;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::lang::XComponent;
-using ::com::sun::star::beans::NamedValue;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::awt::DeviceInfo;
using ::com::sun::star::awt::XDevice;
@@ -72,6 +72,7 @@ using ::com::sun::star::task::XStatusIndicator;
using ::com::sun::star::task::XInteractionHandler;
using ::com::sun::star::graphic::XGraphic;
using ::comphelper::MediaDescriptor;
+using ::comphelper::SequenceAsHashMap;
using ::oox::ole::OleObjectHelper;
namespace oox {
@@ -125,6 +126,16 @@ DocumentOpenedGuard::~DocumentOpenedGuard()
// ============================================================================
+/** Specifies whether this filter is an import or export filter. */
+enum FilterDirection
+{
+ FILTERDIRECTION_UNKNOWN,
+ FILTERDIRECTION_IMPORT,
+ FILTERDIRECTION_EXPORT
+};
+
+// ----------------------------------------------------------------------------
+
struct FilterBaseImpl
{
typedef ::boost::shared_ptr< GraphicHelper > GraphicHelperRef;
@@ -132,9 +143,10 @@ struct FilterBaseImpl
typedef ::boost::shared_ptr< OleObjectHelper > OleObjHelperRef;
typedef ::std::map< OUString, Reference< XGraphic > > EmbeddedGraphicMap;
typedef ::std::map< sal_Int32, sal_Int32 > SystemPalette;
- typedef ::std::map< OUString, Any > ArgumentMap;
- MediaDescriptor maDescriptor;
+ FilterDirection meDirection;
+ SequenceAsHashMap maArguments;
+ MediaDescriptor maMediaDesc;
DeviceInfo maDeviceInfo;
OUString maFileUrl;
StorageRef mxStorage;
@@ -145,7 +157,6 @@ struct FilterBaseImpl
EmbeddedGraphicMap maEmbeddedGraphics; /// Maps all imported embedded graphics by their path.
SystemPalette maSystemPalette; /// Maps system colors (XML tokens) to RGB color values.
- ArgumentMap maArguments;
Reference< XMultiServiceFactory > mxGlobalFactory;
Reference< XModel > mxModel;
Reference< XMultiServiceFactory > mxModelFactory;
@@ -157,14 +168,16 @@ struct FilterBaseImpl
explicit FilterBaseImpl( const Reference< XMultiServiceFactory >& rxGlobalFactory );
void setDocumentModel( const Reference< XComponent >& rxComponent );
- void setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor );
-
bool hasDocumentModel() const;
+
+ void initializeFilter();
+ void finalizeFilter();
};
// ----------------------------------------------------------------------------
FilterBaseImpl::FilterBaseImpl( const Reference< XMultiServiceFactory >& rxGlobalFactory ) :
+ meDirection( FILTERDIRECTION_UNKNOWN ),
mxGlobalFactory( rxGlobalFactory )
{
OSL_ENSURE( mxGlobalFactory.is(), "FilterBaseImpl::FilterBaseImpl - missing service factory" );
@@ -223,23 +236,39 @@ void FilterBaseImpl::setDocumentModel( const Reference< XComponent >& rxComponen
mxModelFactory.set( rxComponent, UNO_QUERY );
}
-void FilterBaseImpl::setMediaDescriptor( const Sequence< PropertyValue >& rDescriptor )
+bool FilterBaseImpl::hasDocumentModel() const
{
- maDescriptor = rDescriptor;
-
- maFileUrl = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), maFileUrl );
- mxInStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), mxInStream );
- mxOutStream = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), mxOutStream );
- mxStatusIndicator = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_STATUSINDICATOR(), mxStatusIndicator );
- mxInteractionHandler = maDescriptor.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER(), mxInteractionHandler );
+ return mxGlobalFactory.is() && mxModel.is() && mxModelFactory.is();
+}
- if( mxInStream.is() )
- maDescriptor.addInputStream();
+void FilterBaseImpl::initializeFilter()
+{
+ try
+ {
+ // lock the model controllers
+ mxModel->lockControllers();
+ }
+ catch( Exception& )
+ {
+ }
}
-bool FilterBaseImpl::hasDocumentModel() const
+void FilterBaseImpl::finalizeFilter()
{
- return mxGlobalFactory.is() && mxModel.is() && mxModelFactory.is();
+ try
+ {
+ // clear the 'ComponentData' property in the descriptor
+ MediaDescriptor::iterator aIt = maMediaDesc.find( MediaDescriptor::PROP_COMPONENTDATA() );
+ if( aIt != maMediaDesc.end() )
+ aIt->second.clear();
+ // write the descriptor back to the document model (adds the password)
+ mxModel->attachResource( maFileUrl, maMediaDesc.getAsConstPropertyValueList() );
+ // unlock the model controllers
+ mxModel->unlockControllers();
+ }
+ catch( Exception& )
+ {
+ }
}
// ============================================================================
@@ -255,19 +284,19 @@ FilterBase::~FilterBase()
bool FilterBase::isImportFilter() const
{
- return mxImpl->mxInStream.is();
+ return mxImpl->meDirection == FILTERDIRECTION_IMPORT;
}
bool FilterBase::isExportFilter() const
{
- return mxImpl->mxOutStream.is();
+ return mxImpl->meDirection == FILTERDIRECTION_EXPORT;
}
// ----------------------------------------------------------------------------
Any FilterBase::getArgument( const OUString& rArgName ) const
{
- FilterBaseImpl::ArgumentMap::const_iterator aIt = mxImpl->maArguments.find( rArgName );
+ SequenceAsHashMap::const_iterator aIt = mxImpl->maArguments.find( rArgName );
return (aIt == mxImpl->maArguments.end()) ? Any() : aIt->second;
}
@@ -276,6 +305,11 @@ const Reference< XMultiServiceFactory >& FilterBase::getGlobalFactory() const
return mxImpl->mxGlobalFactory;
}
+MediaDescriptor& FilterBase::getMediaDescriptor() const
+{
+ return mxImpl->maMediaDesc;
+}
+
const Reference< XModel >& FilterBase::getModel() const
{
return mxImpl->mxModel;
@@ -440,6 +474,14 @@ sal_Int32 FilterBase::getSystemColor( sal_Int32 nToken, sal_Int32 nDefaultRgb )
return (aIt == mxImpl->maSystemPalette.end()) ? ((nDefaultRgb < 0) ? API_RGB_WHITE : nDefaultRgb) : aIt->second;
}
+OUString FilterBase::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier ) const
+{
+ ::std::vector< OUString > aDefaultPasswords;
+ aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
+ return ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
+ rVerifier, mxImpl->maMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
+}
+
bool FilterBase::importBinaryData( StreamDataSequence& orDataSeq, const OUString& rStreamName )
{
OSL_ENSURE( rStreamName.getLength() > 0, "FilterBase::importBinaryData - empty stream name" );
@@ -508,17 +550,12 @@ Sequence< OUString > SAL_CALL FilterBase::getSupportedServiceNames() throw( Runt
void SAL_CALL FilterBase::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException )
{
- if( rArgs.getLength() >= 2 )
+ if( rArgs.getLength() >= 2 ) try
+ {
+ mxImpl->maArguments << rArgs[ 1 ];
+ }
+ catch( Exception& )
{
- Sequence< NamedValue > aArgSeq;
- if( (rArgs[ 1 ] >>= aArgSeq) && aArgSeq.hasElements() )
- {
- const NamedValue* pArg = aArgSeq.getConstArray();
- const NamedValue* pEnd = pArg + aArgSeq.getLength();
- for( ; pArg < pEnd; ++pArg )
- if( pArg->Name.getLength() > 0 )
- mxImpl->maArguments[ pArg->Name ] = pArg->Value;
- }
}
}
@@ -529,6 +566,7 @@ void SAL_CALL FilterBase::setTargetDocument( const Reference< XComponent >& rxDo
mxImpl->setDocumentModel( rxDocument );
if( !mxImpl->hasDocumentModel() )
throw IllegalArgumentException();
+ mxImpl->meDirection = FILTERDIRECTION_IMPORT;
}
// com.sun.star.document.XExporter interface ----------------------------------
@@ -538,29 +576,41 @@ void SAL_CALL FilterBase::setSourceDocument( const Reference< XComponent >& rxDo
mxImpl->setDocumentModel( rxDocument );
if( !mxImpl->hasDocumentModel() )
throw IllegalArgumentException();
+ mxImpl->meDirection = FILTERDIRECTION_EXPORT;
}
// com.sun.star.document.XFilter interface ------------------------------------
-sal_Bool SAL_CALL FilterBase::filter( const Sequence< PropertyValue >& rDescriptor ) throw( RuntimeException )
+sal_Bool SAL_CALL FilterBase::filter( const Sequence< PropertyValue >& rMediaDescSeq ) throw( RuntimeException )
{
sal_Bool bRet = sal_False;
- if( mxImpl->hasDocumentModel() )
+ if( mxImpl->hasDocumentModel() && (mxImpl->meDirection != FILTERDIRECTION_UNKNOWN) )
{
- mxImpl->setMediaDescriptor( rDescriptor );
+ setMediaDescriptor( rMediaDescSeq );
DocumentOpenedGuard aOpenedGuard( mxImpl->maFileUrl );
if( aOpenedGuard.isValid() )
{
- mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream, mxImpl->mxOutStream );
- if( mxImpl->mxStorage.get() )
+ mxImpl->initializeFilter();
+ switch( mxImpl->meDirection )
{
- mxImpl->mxModel->lockControllers();
- if( mxImpl->mxInStream.is() )
- bRet = importDocument();
- else if( mxImpl->mxOutStream.is() )
- bRet = exportDocument();
- mxImpl->mxModel->unlockControllers();
+ case FILTERDIRECTION_UNKNOWN:
+ break;
+ case FILTERDIRECTION_IMPORT:
+ if( mxImpl->mxInStream.is() )
+ {
+ mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream );
+ bRet = mxImpl->mxStorage.get() && importDocument();
+ }
+ break;
+ case FILTERDIRECTION_EXPORT:
+ if( mxImpl->mxOutStream.is() )
+ {
+ mxImpl->mxStorage = implCreateStorage( mxImpl->mxOutStream );
+ bRet = mxImpl->mxStorage.get() && exportDocument();
+ }
+ break;
}
+ mxImpl->finalizeFilter();
}
}
return bRet;
@@ -570,6 +620,46 @@ void SAL_CALL FilterBase::cancel() throw( RuntimeException )
{
}
+// protected ------------------------------------------------------------------
+
+Reference< XInputStream > FilterBase::implGetInputStream( MediaDescriptor& rMediaDesc ) const
+{
+ return rMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), Reference< XInputStream >() );
+}
+
+Reference< XStream > FilterBase::implGetOutputStream( MediaDescriptor& rMediaDesc ) const
+{
+ return rMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), Reference< XStream >() );
+}
+
+// private --------------------------------------------------------------------
+
+void FilterBase::setMediaDescriptor( const Sequence< PropertyValue >& rMediaDescSeq )
+{
+ mxImpl->maMediaDesc = rMediaDescSeq;
+
+ switch( mxImpl->meDirection )
+ {
+ case FILTERDIRECTION_UNKNOWN:
+ OSL_ENSURE( false, "FilterBase::setMediaDescriptor - invalid filter direction" );
+ break;
+ case FILTERDIRECTION_IMPORT:
+ mxImpl->maMediaDesc.addInputStream();
+ mxImpl->mxInStream = implGetInputStream( mxImpl->maMediaDesc );
+ OSL_ENSURE( mxImpl->mxInStream.is(), "FilterBase::setMediaDescriptor - missing input stream" );
+ break;
+ case FILTERDIRECTION_EXPORT:
+ mxImpl->mxOutStream = implGetOutputStream( mxImpl->maMediaDesc );
+ OSL_ENSURE( mxImpl->mxOutStream.is(), "FilterBase::setMediaDescriptor - missing output stream" );
+ break;
+ }
+
+ mxImpl->maFileUrl = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), OUString() );
+ mxImpl->mxStatusIndicator = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >() );
+ mxImpl->mxInteractionHandler = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER(), Reference< XInteractionHandler >() );
+}
+
+
// ============================================================================
} // namespace core
diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx
index b0496de26589..434adb9576dd 100644
--- a/oox/source/core/filterdetect.cxx
+++ b/oox/source/core/filterdetect.cxx
@@ -28,89 +28,52 @@
*
************************************************************************/
-#include <com/sun/star/document/XExtendedFilterDetection.hpp>
-#include <com/sun/star/lang/XMultiServiceFactory.hpp>
-#include <com/sun/star/lang/XServiceInfo.hpp>
-#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
-
-#include <com/sun/star/xml/sax/XFastDocumentHandler.hpp>
-#include <com/sun/star/xml/sax/XFastContextHandler.hpp>
+#include "oox/core/filterdetect.hxx"
+#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>
-
+#include <rtl/digest.h>
+#include <openssl/evp.h>
+#include <comphelper/docpasswordhelper.hxx>
#include <comphelper/mediadescriptor.hxx>
-#include <cppuhelper/implbase1.hxx>
-#include <cppuhelper/implbase2.hxx>
-
#include "oox/helper/attributelist.hxx"
+#include "oox/helper/binaryinputstream.hxx"
+#include "oox/helper/binaryoutputstream.hxx"
+#include "oox/helper/olestorage.hxx"
#include "oox/helper/zipstorage.hxx"
#include "oox/core/fasttokenhandler.hxx"
#include "oox/core/namespaces.hxx"
-#include "tokens.hxx"
-
-#include <vector>
using ::rtl::OUString;
-using ::rtl::OString;
+using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::RuntimeException;
+using ::com::sun::star::uno::Sequence;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::uno::UNO_QUERY_THROW;
+using ::com::sun::star::uno::UNO_SET_THROW;
+using ::com::sun::star::uno::XInterface;
+using ::com::sun::star::lang::XMultiServiceFactory;
+using ::com::sun::star::beans::NamedValue;
+using ::com::sun::star::beans::PropertyValue;
+using ::com::sun::star::io::XInputStream;
+using ::com::sun::star::io::XOutputStream;
+using ::com::sun::star::io::XStream;
+using ::com::sun::star::xml::sax::InputSource;
+using ::com::sun::star::xml::sax::SAXException;
+using ::com::sun::star::xml::sax::XFastAttributeList;
+using ::com::sun::star::xml::sax::XFastContextHandler;
+using ::com::sun::star::xml::sax::XFastParser;
+using ::com::sun::star::xml::sax::XLocator;
using ::comphelper::MediaDescriptor;
-using namespace ::com::sun::star::document;
-using namespace ::com::sun::star::lang;
-using namespace ::com::sun::star::uno;
-using namespace ::com::sun::star::beans;
-using namespace ::com::sun::star::io;
-using namespace ::com::sun::star::embed;
-using namespace ::com::sun::star::xml::sax;
+using ::comphelper::SequenceAsHashMap;
namespace oox {
namespace core {
// ============================================================================
-/** Document handler specifically designed for detecting OOXML file formats.
-
- It takes a reference to the filter string object via its constructor, and
- puts the name of the detected filter to it if it successfully finds one.
- */
-class FilterDetectDocHandler : public ::cppu::WeakImplHelper1< XFastDocumentHandler >
-{
-public:
- explicit FilterDetectDocHandler( OUString& rFilter );
- virtual ~FilterDetectDocHandler();
-
- // XFastDocumentHandler
- virtual void SAL_CALL startDocument() throw (SAXException, RuntimeException);
- virtual void SAL_CALL endDocument() throw (SAXException, RuntimeException);
- virtual void SAL_CALL setDocumentLocator( const Reference< XLocator >& xLocator ) throw (SAXException, RuntimeException);
-
- // XFastContextHandler
- virtual void SAL_CALL startFastElement( sal_Int32 nElement, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL startUnknownElement( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL endFastElement( sal_Int32 Element ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL endUnknownElement( const OUString& Namespace, const OUString& Name ) throw (SAXException, RuntimeException);
- virtual Reference< XFastContextHandler > SAL_CALL createFastChildContext( sal_Int32 Element, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
- virtual Reference< XFastContextHandler > SAL_CALL createUnknownChildContext( const OUString& Namespace, const OUString& Name, const Reference< XFastAttributeList >& Attribs ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL characters( const OUString& aChars ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) throw (SAXException, RuntimeException);
- virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) throw (SAXException, RuntimeException);
-
-private:
- void parseRelationship( const AttributeList& rAttribs );
-
- OUString getFilterNameFromContentType( const OUString& rContentType ) const;
- void parseContentTypesDefault( const AttributeList& rAttribs );
- void parseContentTypesOverride( const AttributeList& rAttribs );
-
-private:
- typedef ::std::vector< sal_Int32 > ContextVector;
-
- OUString& mrFilter;
- ContextVector maContextStack;
- OUString maTargetPath;
-};
-
-// ============================================================================
-
-FilterDetectDocHandler::FilterDetectDocHandler( OUString& rFilter ) :
- mrFilter( rFilter )
+FilterDetectDocHandler::FilterDetectDocHandler( OUString& rFilterName ) :
+ mrFilterName( rFilterName )
{
maContextStack.reserve( 2 );
}
@@ -134,8 +97,6 @@ void SAL_CALL FilterDetectDocHandler::setDocumentLocator( const Reference<XLocat
{
}
-// ===========================================================================
-
void SAL_CALL FilterDetectDocHandler::startFastElement(
sal_Int32 nElement, const Reference< XFastAttributeList >& rAttribs )
throw (SAXException,RuntimeException)
@@ -213,8 +174,6 @@ void SAL_CALL FilterDetectDocHandler::processingInstruction(
{
}
-// ============================================================================
-
void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs )
{
OUString aType = rAttribs.getString( XML_Type, OUString() );
@@ -224,6 +183,14 @@ void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs )
OUString FilterDetectDocHandler::getFilterNameFromContentType( const OUString& rContentType ) const
{
+ if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) ||
+ rContentType.equalsAscii( "application/vnd.ms-word.document.macroEnabled.main+xml" ) )
+ return CREATE_OUSTRING( "writer_MS_Word_2007" );
+
+ if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml" ) ||
+ rContentType.equalsAscii( "application/vnd.ms-word.template.macroEnabledTemplate.main+xml" ) )
+ return CREATE_OUSTRING( "writer_MS_Word_2007_Template" );
+
if( rContentType.equalsAscii( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" ) ||
rContentType.equalsAscii( "application/vnd.ms-excel.sheet.macroEnabled.main+xml" ) )
return CREATE_OUSTRING( "MS Excel 2007 XML" );
@@ -249,44 +216,24 @@ OUString FilterDetectDocHandler::getFilterNameFromContentType( const OUString& r
void FilterDetectDocHandler::parseContentTypesDefault( const AttributeList& rAttribs )
{
// only if no overridden part name found
- if( mrFilter.getLength() == 0 )
+ if( mrFilterName.getLength() == 0 )
{
// check if target path ends with extension
OUString aExtension = rAttribs.getString( XML_Extension, OUString() );
sal_Int32 nExtPos = maTargetPath.getLength() - aExtension.getLength();
if( (nExtPos > 0) && (maTargetPath[ nExtPos - 1 ] == '.') && maTargetPath.match( aExtension, nExtPos ) )
- mrFilter = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
+ mrFilterName = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
}
}
void FilterDetectDocHandler::parseContentTypesOverride( const AttributeList& rAttribs )
{
if( rAttribs.getString( XML_PartName, OUString() ).equals( maTargetPath ) )
- mrFilter = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
+ mrFilterName = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
}
// ============================================================================
-class FilterDetect : public ::cppu::WeakImplHelper2< XExtendedFilterDetection, XServiceInfo >
-{
-public:
- explicit FilterDetect( const Reference< XMultiServiceFactory >& xFactory );
- virtual ~FilterDetect();
-
- // XServiceInfo
- virtual OUString SAL_CALL getImplementationName() throw( RuntimeException );
- virtual sal_Bool SAL_CALL supportsService( const OUString& rServiceName ) throw( RuntimeException );
- virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( RuntimeException );
-
- // XExtendedFilterDetect
- virtual OUString SAL_CALL detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException );
-
-private:
- Reference< XMultiServiceFactory > mxFactory;
-};
-
-// ----------------------------------------------------------------------------
-
/* Helper for XServiceInfo */
Sequence< OUString > FilterDetect_getSupportedServiceNames()
{
@@ -307,8 +254,10 @@ Reference< XInterface > SAL_CALL FilterDetect_createInstance( const Reference< X
return Reference< XInterface >( *new FilterDetect( xServiceManager ) );
}
-FilterDetect::FilterDetect( const Reference< XMultiServiceFactory >& xFactory ) :
- mxFactory( xFactory )
+// ----------------------------------------------------------------------------
+
+FilterDetect::FilterDetect( const Reference< XMultiServiceFactory >& rxFactory ) :
+ mxFactory( rxFactory )
{
OSL_ENSURE( mxFactory.is(), "FilterDetect::FilterDetect - no service factory" );
}
@@ -317,45 +266,319 @@ FilterDetect::~FilterDetect()
{
}
-// com.sun.star.document.XExtendedFilterDetect interface ----------------------
+/* =========================================================================== */
+/* Kudos to Caolan McNamara who provided the core decryption implementations. */
+/* =========================================================================== */
+
+namespace {
+
+const sal_uInt32 ENCRYPTINFO_CRYPTOAPI = 0x00000004;
+const sal_uInt32 ENCRYPTINFO_DOCPROPS = 0x00000008;
+const sal_uInt32 ENCRYPTINFO_EXTERNAL = 0x00000010;
+const sal_uInt32 ENCRYPTINFO_AES = 0x00000020;
+
+const sal_uInt32 ENCRYPT_ALGO_AES128 = 0x0000660E;
+const sal_uInt32 ENCRYPT_ALGO_AES192 = 0x0000660F;
+const sal_uInt32 ENCRYPT_ALGO_AES256 = 0x00006610;
+const sal_uInt32 ENCRYPT_ALGO_RC4 = 0x00006801;
+
+const sal_uInt32 ENCRYPT_HASH_SHA1 = 0x00008004;
+
+// ----------------------------------------------------------------------------
+
+bool lclIsZipPackage( const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm )
+{
+ ZipStorage aZipStorage( rxFactory, rxInStrm );
+ return aZipStorage.isStorage();
+}
+
+// ----------------------------------------------------------------------------
+
+struct PackageEncryptionInfo
+{
+ sal_uInt8 mpnSalt[ 16 ];
+ sal_uInt8 mpnEncrVerifier[ 16 ];
+ sal_uInt8 mpnEncrVerifierHash[ 32 ];
+ sal_uInt32 mnFlags;
+ sal_uInt32 mnAlgorithmId;
+ sal_uInt32 mnAlgorithmIdHash;
+ sal_uInt32 mnKeySize;
+ sal_uInt32 mnSaltSize;
+ sal_uInt32 mnVerifierHashSize;
+};
+
+bool lclReadEncryptionInfo( PackageEncryptionInfo& rEncrInfo, BinaryInputStream& rStrm )
+{
+ rStrm.skip( 4 );
+ rStrm >> rEncrInfo.mnFlags;
+ if( getFlag( rEncrInfo.mnFlags, ENCRYPTINFO_EXTERNAL ) )
+ return false;
+
+ sal_uInt32 nHeaderSize, nRepeatedFlags;
+ rStrm >> nHeaderSize >> nRepeatedFlags;
+ if( (nHeaderSize < 20) || (nRepeatedFlags != rEncrInfo.mnFlags) )
+ return false;
+
+ rStrm.skip( 4 );
+ rStrm >> rEncrInfo.mnAlgorithmId >> rEncrInfo.mnAlgorithmIdHash >> rEncrInfo.mnKeySize;
+ rStrm.skip( nHeaderSize - 20 );
+ rStrm >> rEncrInfo.mnSaltSize;
+ if( rEncrInfo.mnSaltSize != 16 )
+ return false;
+
+ rStrm.readMemory( rEncrInfo.mpnSalt, 16 );
+ rStrm.readMemory( rEncrInfo.mpnEncrVerifier, 16 );
+ rStrm >> rEncrInfo.mnVerifierHashSize;
+ rStrm.readMemory( rEncrInfo.mpnEncrVerifierHash, 32 );
+ return !rStrm.isEof();
+}
+
+// ----------------------------------------------------------------------------
+
+void lclDeriveKey( const sal_uInt8* pnHash, sal_uInt32 nHashLen, sal_uInt8* pnKeyDerived, sal_uInt32 nRequiredKeyLen )
+{
+ sal_uInt8 pnBuffer[ 64 ];
+ memset( pnBuffer, 0x36, sizeof( pnBuffer ) );
+ for( sal_uInt32 i = 0; i < nHashLen; ++i )
+ pnBuffer[ i ] ^= pnHash[ i ];
+
+ rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ rtlDigestError aError = rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
+ sal_uInt8 pnX1[ RTL_DIGEST_LENGTH_SHA1 ];
+ aError = rtl_digest_get( aDigest, pnX1, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ memset( pnBuffer, 0x5C, sizeof( pnBuffer ) );
+ for( sal_uInt32 i = 0; i < nHashLen; ++i )
+ pnBuffer[ i ] ^= pnHash[ i ];
+
+ aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ aError = rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
+ sal_uInt8 pnX2[ RTL_DIGEST_LENGTH_SHA1 ];
+ aError = rtl_digest_get( aDigest, pnX2, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ if( nRequiredKeyLen > RTL_DIGEST_LENGTH_SHA1 )
+ {
+ memcpy( pnKeyDerived + RTL_DIGEST_LENGTH_SHA1, pnX2, nRequiredKeyLen - RTL_DIGEST_LENGTH_SHA1 );
+ nRequiredKeyLen = RTL_DIGEST_LENGTH_SHA1;
+ }
+ memcpy( pnKeyDerived, pnX1, nRequiredKeyLen );
+}
+
+// ----------------------------------------------------------------------------
-OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& lDescriptor ) throw( RuntimeException )
+bool lclGenerateEncryptionKey( const PackageEncryptionInfo& rEncrInfo, const OUString& rPassword, sal_uInt8* pnKey, sal_uInt32 nRequiredKeyLen )
{
- OUString aFilter;
+ size_t nBufferSize = rEncrInfo.mnSaltSize + 2 * rPassword.getLength();
+ sal_uInt8* pnBuffer = new sal_uInt8[ nBufferSize ];
+ memcpy( pnBuffer, rEncrInfo.mpnSalt, rEncrInfo.mnSaltSize );
+
+ sal_uInt8* pnPasswordLoc = pnBuffer + rEncrInfo.mnSaltSize;
+ const sal_Unicode* pStr = rPassword.getStr();
+ for( sal_Int32 i = 0, nLen = rPassword.getLength(); i < nLen; ++i, ++pStr, pnPasswordLoc += 2 )
+ ByteOrderConverter::writeLittleEndian( pnPasswordLoc, static_cast< sal_uInt16 >( *pStr ) );
+
+ rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ rtlDigestError aError = rtl_digest_update( aDigest, pnBuffer, nBufferSize );
+ delete[] pnBuffer;
- if( mxFactory.is() ) try
+ size_t nHashSize = RTL_DIGEST_LENGTH_SHA1 + 4;
+ sal_uInt8* pnHash = new sal_uInt8[ nHashSize ];
+ aError = rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ for( sal_uInt32 i = 0; i < 50000; ++i )
{
- Reference< XFastParser > xParser( mxFactory->createInstance(
- CREATE_OUSTRING( "com.sun.star.xml.sax.FastParser" ) ), UNO_QUERY_THROW );
-
- xParser->setFastDocumentHandler( new FilterDetectDocHandler( aFilter ) );
- xParser->setTokenHandler( new FastTokenHandler );
-
- xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships" ), NMSP_PACKAGE_RELATIONSHIPS );
- xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ), NMSP_RELATIONSHIPS );
- xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/content-types" ), NMSP_CONTENT_TYPES );
-
- MediaDescriptor aDescriptor( lDescriptor );
- aDescriptor.addInputStream();
- Reference< XInputStream > xInputStream( aDescriptor[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY_THROW );
- StorageRef xStorage( new ZipStorage( mxFactory, xInputStream ) );
-
- // Parse _rels/.rels to get the target path.
- InputSource aParserInput;
- aParserInput.sSystemId = CREATE_OUSTRING( "_rels/.rels" );
- aParserInput.aInputStream = xStorage->openInputStream( aParserInput.sSystemId );
- xParser->parseStream( aParserInput );
-
- // Parse [Content_Types].xml to determine the content type of the part at the target path.
- aParserInput.sSystemId = CREATE_OUSTRING( "[Content_Types].xml" );
- aParserInput.aInputStream = xStorage->openInputStream( aParserInput.sSystemId );
- xParser->parseStream( aParserInput );
+ ByteOrderConverter::writeLittleEndian( pnHash, i );
+ aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ aError = rtl_digest_update( aDigest, pnHash, nHashSize );
+ aError = rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
}
- catch ( const Exception& )
+
+ memmove( pnHash, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
+ memset( pnHash + RTL_DIGEST_LENGTH_SHA1, 0, 4 );
+ aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ aError = rtl_digest_update( aDigest, pnHash, nHashSize );
+ aError = rtl_digest_get( aDigest, pnHash, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ lclDeriveKey( pnHash, RTL_DIGEST_LENGTH_SHA1, pnKey, nRequiredKeyLen );
+ delete[] pnHash;
+
+ // check password
+ EVP_CIPHER_CTX aes_ctx;
+ EVP_CIPHER_CTX_init( &aes_ctx );
+ EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
+ EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
+ int nOutLen = 0;
+ sal_uInt8 pnVerifier[ 16 ] = { 0 };
+ /*int*/ EVP_DecryptUpdate( &aes_ctx, pnVerifier, &nOutLen, rEncrInfo.mpnEncrVerifier, sizeof( rEncrInfo.mpnEncrVerifier ) );
+ EVP_CIPHER_CTX_cleanup( &aes_ctx );
+
+ EVP_CIPHER_CTX_init( &aes_ctx );
+ EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
+ EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
+ sal_uInt8 pnVerifierHash[ 32 ] = { 0 };
+ /*int*/ EVP_DecryptUpdate( &aes_ctx, pnVerifierHash, &nOutLen, rEncrInfo.mpnEncrVerifierHash, sizeof( rEncrInfo.mpnEncrVerifierHash ) );
+ EVP_CIPHER_CTX_cleanup( &aes_ctx );
+
+ aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
+ aError = rtl_digest_update( aDigest, pnVerifier, sizeof( pnVerifier ) );
+ sal_uInt8 pnSha1Hash[ RTL_DIGEST_LENGTH_SHA1 ];
+ aError = rtl_digest_get( aDigest, pnSha1Hash, RTL_DIGEST_LENGTH_SHA1 );
+ rtl_digest_destroy( aDigest );
+
+ return memcmp( pnSha1Hash, pnVerifierHash, RTL_DIGEST_LENGTH_SHA1 ) == 0;
+}
+
+// the password verifier ------------------------------------------------------
+
+class PasswordVerifier : public ::comphelper::IDocPasswordVerifier
+{
+public:
+ explicit PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo );
+
+ virtual ::comphelper::DocPasswordVerifierResult
+ verifyPassword( const OUString& rPassword );
+
+ inline const sal_uInt8* getKey() const { return &maKey.front(); }
+
+private:
+ const PackageEncryptionInfo& mrEncryptInfo;
+ ::std::vector< sal_uInt8 > maKey;
+};
+
+PasswordVerifier::PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo ) :
+ mrEncryptInfo( rEncryptInfo ),
+ maKey( static_cast< size_t >( rEncryptInfo.mnKeySize / 8 ), 0 )
+{
+}
+
+::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword )
+{
+ // verifies the password and writes the related decryption key into maKey
+ return lclGenerateEncryptionKey( mrEncryptInfo, rPassword, &maKey.front(), maKey.size() ) ?
+ ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescriptor& rMediaDesc ) const
+{
+ if( mxFactory.is() )
{
+ // try the plain input stream
+ Reference< XInputStream > xInStrm( rMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY );
+ if( !xInStrm.is() || lclIsZipPackage( mxFactory, xInStrm ) )
+ return xInStrm;
+
+ // check if a temporary file is passed in the 'ComponentData' property
+ Sequence< NamedValue > aCompData = rMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_COMPONENTDATA(), Sequence< NamedValue >() );
+ SequenceAsHashMap aCompDataMap( aCompData );
+ Reference< XStream > xDecrypted = aCompDataMap.getUnpackedValueOrDefault( CREATE_OUSTRING( "DecryptedPackage" ), Reference< XStream >() );
+ if( xDecrypted.is() )
+ {
+ Reference< XInputStream > xDecrInStrm = xDecrypted->getInputStream();
+ if( lclIsZipPackage( mxFactory, xDecrInStrm ) )
+ return xDecrInStrm;
+ }
+
+ // try to decrypt an encrypted OLE package
+ OleStorage aOleStorage( mxFactory, xInStrm, false );
+ if( aOleStorage.isStorage() ) try
+ {
+ // open the required input streams in the encrypted package
+ Reference< XInputStream > xEncryptionInfo( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptionInfo" ) ), UNO_SET_THROW );
+ Reference< XInputStream > xEncryptedPackage( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptedPackage" ) ), UNO_SET_THROW );
+
+ // read the encryption info stream
+ PackageEncryptionInfo aEncryptInfo;
+ BinaryXInputStream aInfoStrm( xEncryptionInfo, true );
+ bool bValidInfo = lclReadEncryptionInfo( aEncryptInfo, aInfoStrm );
+
+ // check flags and agorithm IDs, requiered are AES128 and SHA-1
+ bool bImplemented = bValidInfo &&
+ getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_CRYPTOAPI ) &&
+ getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_AES ) &&
+ // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set
+ ((aEncryptInfo.mnAlgorithmId == 0) || (aEncryptInfo.mnAlgorithmId == ENCRYPT_ALGO_AES128)) &&
+ // hash algorithm ID 0 defaults to SHA-1 too
+ ((aEncryptInfo.mnAlgorithmIdHash == 0) || (aEncryptInfo.mnAlgorithmIdHash == ENCRYPT_HASH_SHA1)) &&
+ (aEncryptInfo.mnVerifierHashSize == 20);
+
+ if( bImplemented )
+ {
+ /* "VelvetSweatshop" is the built-in default encryption
+ password used by MS Excel for the "workbook protection"
+ feature with password. Try this first before prompting the
+ user for a password. */
+ ::std::vector< OUString > aDefaultPasswords;
+ aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
+
+ /* Use the comphelper password helper to request a password.
+ This helper returns either with the correct password
+ (according to the verifier), or with an empty string if
+ user has cancelled the password input dialog. */
+ PasswordVerifier aVerifier( aEncryptInfo );
+ OUString aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
+ aVerifier, rMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
+
+ if( aPassword.getLength() == 0 )
+ {
+ rMediaDesc[ MediaDescriptor::PROP_ABORTED() ] <<= true;
+ }
+ else
+ {
+ // create temporary file for unencrypted package
+ Reference< XStream > xTempFile( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
+ Reference< XOutputStream > xDecryptedPackage( xTempFile->getOutputStream(), UNO_SET_THROW );
+ BinaryXOutputStream aDecryptedPackage( xDecryptedPackage, true );
+ BinaryXInputStream aEncryptedPackage( xEncryptedPackage, true );
+
+ EVP_CIPHER_CTX aes_ctx;
+ EVP_CIPHER_CTX_init( &aes_ctx );
+ EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, aVerifier.getKey(), 0 );
+ EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
+
+ sal_uInt8 pnInBuffer[ 1024 ];
+ sal_uInt8 pnOutBuffer[ 1024 ];
+ sal_Int32 nInLen;
+ int nOutLen;
+ aEncryptedPackage.skip( 8 ); // decrypted size
+ while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 )
+ {
+ EVP_DecryptUpdate( &aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen );
+ aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
+ }
+ EVP_DecryptFinal_ex( &aes_ctx, pnOutBuffer, &nOutLen );
+ aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
+
+ EVP_CIPHER_CTX_cleanup( &aes_ctx );
+ xDecryptedPackage->flush();
+ aDecryptedPackage.seekToStart();
+
+ // store temp file in media descriptor to keep it alive
+ Sequence< NamedValue > aPropSeq( 1 );
+ aPropSeq[ 0 ].Name = CREATE_OUSTRING( "DecryptedPackage" );
+ aPropSeq[ 0 ].Value <<= xTempFile;
+ rMediaDesc[ MediaDescriptor::PROP_COMPONENTDATA() ] <<= aPropSeq;
+
+ Reference< XInputStream > xDecrInStrm = xTempFile->getInputStream();
+ if( lclIsZipPackage( mxFactory, xDecrInStrm ) )
+ return xDecrInStrm;
+ }
+ }
+ }
+ catch( Exception& )
+ {
+ }
}
- return aFilter;
+ return Reference< XInputStream >();
}
// com.sun.star.lang.XServiceInfo interface -----------------------------------
@@ -378,6 +601,62 @@ Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames() throw( Ru
return FilterDetect_getSupportedServiceNames();
}
+// com.sun.star.document.XExtendedFilterDetection interface -------------------
+
+OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& rMediaDescSeq ) throw( RuntimeException )
+{
+ OUString aFilterName;
+ MediaDescriptor aMediaDesc( rMediaDescSeq );
+
+ /* Check that the user has not choosen to abort detection, e.g. by hitting
+ 'Cancel' in the password input dialog. This may happen because this
+ filter detection is used by different filters. */
+ bool bAborted = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_ABORTED(), false );
+ if( !bAborted && mxFactory.is() ) try
+ {
+ aMediaDesc.addInputStream();
+
+ /* Get the unencrypted input stream. This may include creation of a
+ temporary file that contains the decrypted package. This temporary
+ file will be stored in the 'ComponentData' property of the media
+ descriptor. */
+ Reference< XInputStream > xInStrm( extractUnencryptedPackage( aMediaDesc ), UNO_SET_THROW );
+
+ // try to detect the file type, must be a ZIP package
+ ZipStorage aZipStorage( mxFactory, xInStrm );
+ if( aZipStorage.isStorage() )
+ {
+ Reference< XFastParser > xParser( mxFactory->createInstance(
+ CREATE_OUSTRING( "com.sun.star.xml.sax.FastParser" ) ), UNO_QUERY_THROW );
+
+ xParser->setFastDocumentHandler( new FilterDetectDocHandler( aFilterName ) );
+ xParser->setTokenHandler( new FastTokenHandler );
+
+ xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships" ), NMSP_PACKAGE_RELATIONSHIPS );
+ xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships" ), NMSP_RELATIONSHIPS );
+ xParser->registerNamespace( CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/content-types" ), NMSP_CONTENT_TYPES );
+
+ // Parse _rels/.rels to get the target path.
+ InputSource aParserInput;
+ aParserInput.sSystemId = CREATE_OUSTRING( "_rels/.rels" );
+ aParserInput.aInputStream = aZipStorage.openInputStream( aParserInput.sSystemId );
+ xParser->parseStream( aParserInput );
+
+ // Parse [Content_Types].xml to determine the content type of the part at the target path.
+ aParserInput.sSystemId = CREATE_OUSTRING( "[Content_Types].xml" );
+ aParserInput.aInputStream = aZipStorage.openInputStream( aParserInput.sSystemId );
+ xParser->parseStream( aParserInput );
+ }
+ }
+ catch( Exception& )
+ {
+ }
+
+ // write back changed media descriptor members
+ aMediaDesc >> rMediaDescSeq;
+ return aFilterName;
+}
+
// ============================================================================
} // namespace core
diff --git a/oox/source/core/makefile.mk b/oox/source/core/makefile.mk
index 3443bd35c7f8..51804e1d04c8 100644
--- a/oox/source/core/makefile.mk
+++ b/oox/source/core/makefile.mk
@@ -42,6 +42,10 @@ ENABLE_EXCEPTIONS=TRUE
.INCLUDE : settings.mk
.INCLUDE: $(PRJ)$/util$/makefile.pmk
+.IF "$(SYSTEM_OPENSSL)" == "YES"
+CFLAGS+= $(OPENSSL_CFLAGS)
+.ENDIF
+
# --- Files --------------------------------------------------------
SLOFILES = \
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index 6fb94434cc59..27b3eef0ce60 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -28,16 +28,7 @@
*
************************************************************************/
-#include "properties.hxx"
#include "oox/core/xmlfilterbase.hxx"
-#include "oox/core/fasttokenhandler.hxx"
-#include "oox/core/fragmenthandler.hxx"
-#include "oox/core/namespaces.hxx"
-#include "oox/core/recordparser.hxx"
-#include "oox/core/relationshandler.hxx"
-#include "oox/helper/containerhelper.hxx"
-#include "oox/helper/propertyset.hxx"
-#include "oox/helper/zipstorage.hxx"
#include <cstdio>
@@ -47,9 +38,19 @@
#include <com/sun/star/xml/sax/InputSource.hpp>
#include <com/sun/star/xml/sax/XFastParser.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <comphelper/mediadescriptor.hxx>
#include <sax/fshelper.hxx>
-
+#include "properties.hxx"
#include "tokens.hxx"
+#include "oox/helper/containerhelper.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/helper/zipstorage.hxx"
+#include "oox/core/fasttokenhandler.hxx"
+#include "oox/core/filterdetect.hxx"
+#include "oox/core/fragmenthandler.hxx"
+#include "oox/core/namespaces.hxx"
+#include "oox/core/recordparser.hxx"
+#include "oox/core/relationshandler.hxx"
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
@@ -76,6 +77,7 @@ using ::com::sun::star::xml::sax::InputSource;
using ::com::sun::star::xml::sax::SAXException;
using ::com::sun::star::document::XDocumentProperties;
using ::com::sun::star::util::DateTime;
+using ::comphelper::MediaDescriptor;
using ::sax_fastparser::FastSerializerHelper;
using ::sax_fastparser::FSHelperPtr;
@@ -479,16 +481,27 @@ XmlFilterBase& XmlFilterBase::exportDocumentProperties( Reference< XDocumentProp
return *this;
}
-StorageRef XmlFilterBase::implCreateStorage(
- Reference< XInputStream >& rxInStream, Reference< XStream >& rxOutStream ) const
+// protected ------------------------------------------------------------------
+
+Reference< XInputStream > XmlFilterBase::implGetInputStream( MediaDescriptor& rMediaDesc ) const
{
- StorageRef xStorage;
- if( rxInStream.is() )
- xStorage.reset( new ZipStorage( getGlobalFactory(), rxInStream ) );
- else if( rxOutStream.is() )
- xStorage.reset( new ZipStorage( getGlobalFactory(), rxOutStream ) );
+ /* Get the input stream directly from the media descriptor, or decrypt the
+ package again. The latter is needed e.g. when the document is reloaded.
+ All this is implemented in the detector service. */
+ FilterDetect aDetector( getGlobalFactory() );
+ return aDetector.extractUnencryptedPackage( rMediaDesc );
+}
+
+// private --------------------------------------------------------------------
+
+StorageRef XmlFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const
+{
+ return StorageRef( new ZipStorage( getGlobalFactory(), rxInStream ) );
+}
- return xStorage;
+StorageRef XmlFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const
+{
+ return StorageRef( new ZipStorage( getGlobalFactory(), rxOutStream ) );
}
// ============================================================================
diff --git a/oox/source/dump/biffdumper.cxx b/oox/source/dump/biffdumper.cxx
index 95b7da811a74..f4a53a4a0da0 100644
--- a/oox/source/dump/biffdumper.cxx
+++ b/oox/source/dump/biffdumper.cxx
@@ -50,6 +50,7 @@ using ::com::sun::star::uno::Reference;
using ::com::sun::star::util::DateTime;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::io::XInputStream;
+using ::comphelper::MediaDescriptor;
using ::oox::core::FilterBase;
using namespace ::oox::xls;
@@ -326,14 +327,6 @@ bool BiffObjectBase::implStartRecord( BinaryInputStream&, sal_Int64& ornRecPos,
ornRecPos = mxBiffStrm->tellBase() - 4;
ornRecId = mxBiffStrm->getRecId();
- // record specific settings
- switch( mxBiffStrm->getRecId() )
- {
- case BIFF_ID_CHEND:
- out().decIndent();
- break;
- }
-
// special CONTINUE handling
mxBiffStrm->resetRecord( mbMergeContRec );
if( mbMergeContRec ) switch( mxBiffStrm->getRecId() )
@@ -350,6 +343,21 @@ bool BiffObjectBase::implStartRecord( BinaryInputStream&, sal_Int64& ornRecPos,
break;
}
+ // record specific settings
+ switch( mxBiffStrm->getRecId() )
+ {
+ case BIFF2_ID_BOF:
+ case BIFF3_ID_BOF:
+ case BIFF4_ID_BOF:
+ case BIFF5_ID_BOF:
+ case BIFF_ID_INTERFACEHDR:
+ mxBiffStrm->enableDecoder( false );
+ break;
+ case BIFF_ID_CHEND:
+ out().decIndent();
+ break;
+ }
+
ornRecSize = mxBiffStrm->getLength();
return bValid;
}
@@ -2183,6 +2191,52 @@ void WorkbookStreamObject::implDumpRecordBody()
}
break;
+ case BIFF_ID_FILEPASS:
+ {
+ rStrm.enableDecoder( false );
+ if( eBiff == BIFF8 )
+ {
+ switch( dumpDec< sal_uInt16 >( "type", "FILEPASS-TYPE" ) )
+ {
+ case 0:
+ dumpHex< sal_uInt16 >( "key" );
+ dumpHex< sal_uInt16 >( "verifier" );
+ break;
+ case 1:
+ {
+ sal_uInt16 nMajor = dumpDec< sal_uInt16 >( "major-version", "FILEPASS-MAJOR" );
+ dumpDec< sal_uInt16 >( "minor-version" );
+ switch( nMajor )
+ {
+ case 1:
+ dumpArray( "salt", 16 );
+ dumpArray( "verifier", 16 );
+ dumpArray( "verifier-hash", 16 );
+ break;
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ dumpHex< sal_uInt16 >( "key" );
+ dumpHex< sal_uInt16 >( "verifier" );
+ }
+ rStrm.seekToStart();
+ BiffDecoderRef xDecoder = BiffCodecHelper::implReadFilePass( rStrm, eBiff );
+ if( xDecoder.get() )
+ cfg().requestPassword( *xDecoder );
+ setBinaryOnlyMode( !xDecoder || !xDecoder->isValid() );
+ }
+ break;
+
+ case BIFF_ID_FILESHARING:
+ dumpBool< sal_uInt16 >( "recommend-read-only" );
+ dumpHex< sal_uInt16 >( "password-hash" );
+ dumpString( "password-creator", BIFF_STR_8BITLENGTH, BIFF_STR_SMARTFLAGS );
+ break;
+
case BIFF2_ID_FONT:
case BIFF3_ID_FONT:
dumpFontRec();
@@ -2602,9 +2656,14 @@ void WorkbookStreamObject::implDumpRecordBody()
break;
case BIFF_ID_SHEET:
- if( eBiff >= BIFF5 ) dumpHex< sal_uInt32 >( "sheet-stream-pos", "CONV-DEC" );
- if( eBiff >= BIFF5 ) dumpDec< sal_uInt8 >( "sheet-state", "SHEET-STATE" );
- if( eBiff >= BIFF5 ) dumpDec< sal_uInt8 >( "sheet-type", "SHEET-TYPE" );
+ if( eBiff >= BIFF5 )
+ {
+ rStrm.enableDecoder( false );
+ dumpHex< sal_uInt32 >( "sheet-stream-pos", "CONV-DEC" );
+ rStrm.enableDecoder( true );
+ dumpDec< sal_uInt8 >( "sheet-state", "SHEET-STATE" );
+ dumpDec< sal_uInt8 >( "sheet-type", "SHEET-TYPE" );
+ }
dumpString( "sheet-name", BIFF_STR_8BITLENGTH, BIFF_STR_8BITLENGTH );
break;
@@ -3682,7 +3741,8 @@ Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Refere
if( rxFactory.is() && rxInStrm.is() )
{
StorageRef xStrg( new OleStorage( rxFactory, rxInStrm, true ) );
- ConfigRef xCfg( new Config( DUMP_BIFF_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName ) );
+ MediaDescriptor aMediaDesc;
+ ConfigRef xCfg( new Config( DUMP_BIFF_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) );
DumperBase::construct( xCfg );
}
}
diff --git a/oox/source/dump/biffdumper.ini b/oox/source/dump/biffdumper.ini
index 069e18d355ea..df9518e92726 100644
--- a/oox/source/dump/biffdumper.ini
+++ b/oox/source/dump/biffdumper.ini
@@ -1093,6 +1093,11 @@ constlist=EXTERNSHEET-IDX-BIFF8
-2=special
end
+# FILEPASS -------------------------------------------------------------------
+
+shortlist=FILEPASS-TYPE,0,xor,rc4
+shortlist=FILEPASS-MAJOR,1,rc4,crypto-api-2003,crypto-api-2007
+
# FONT -----------------------------------------------------------------------
flagslist=FONT-FLAGS
diff --git a/oox/source/dump/dumperbase.cxx b/oox/source/dump/dumperbase.cxx
index e3a553ffa523..81f63062b4ad 100644
--- a/oox/source/dump/dumperbase.cxx
+++ b/oox/source/dump/dumperbase.cxx
@@ -39,6 +39,7 @@
#include <com/sun/star/io/XTextOutputStream.hpp>
#include <rtl/math.hxx>
#include <osl/file.hxx>
+#include <comphelper/docpasswordhelper.hxx>
#include "oox/helper/binaryoutputstream.hxx"
#include "oox/core/filterbase.hxx"
#include "oox/xls/biffhelper.hxx"
@@ -51,8 +52,8 @@ using ::rtl::OStringToOUString;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::rtl::OUStringToOString;
-using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Exception;
+using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::util::DateTime;
using ::com::sun::star::lang::XMultiServiceFactory;
@@ -60,9 +61,10 @@ using ::com::sun::star::ucb::XSimpleFileAccess;
using ::com::sun::star::io::XActiveDataSink;
using ::com::sun::star::io::XActiveDataSource;
using ::com::sun::star::io::XInputStream;
-using ::com::sun::star::io::XTextInputStream;
using ::com::sun::star::io::XOutputStream;
+using ::com::sun::star::io::XTextInputStream;
using ::com::sun::star::io::XTextOutputStream;
+using ::comphelper::MediaDescriptor;
using ::oox::core::FilterBase;
namespace oox {
@@ -1465,11 +1467,14 @@ NameListRef NameListWrapper::getNameList( const Config& rCfg ) const
// ============================================================================
SharedConfigData::SharedConfigData( const OUString& rFileName,
- const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName ) :
+ const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg,
+ const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) :
mxFactory( rxFactory ),
mxRootStrg( rxRootStrg ),
maSysFileName( rSysFileName ),
- mbLoaded( false )
+ mrMediaDesc( rMediaDesc ),
+ mbLoaded( false ),
+ mbPwCancelled( false )
{
OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName );
if( aFileUrl.getLength() > 0 )
@@ -1515,6 +1520,20 @@ NameListRef SharedConfigData::getNameList( const OUString& rListName ) const
return xList;
}
+OUString SharedConfigData::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
+{
+ OUString aPassword;
+ if( !mbPwCancelled )
+ {
+ ::std::vector< OUString > aDefaultPasswords;
+ aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
+ aPassword = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
+ rVerifier, mrMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
+ mbPwCancelled = aPassword.getLength() == 0;
+ }
+ return aPassword;
+}
+
bool SharedConfigData::implIsValid() const
{
return mbLoaded && mxFactory.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0);
@@ -1614,9 +1633,9 @@ Config::Config( const sal_Char* pcEnvVar, const FilterBase& rFilter )
construct( pcEnvVar, rFilter );
}
-Config::Config( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName )
+Config::Config( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
{
- construct( pcEnvVar, rxFactory, rxRootStrg, rSysFileName );
+ construct( pcEnvVar, rxFactory, rxRootStrg, rSysFileName, rMediaDesc );
}
Config::~Config()
@@ -1631,14 +1650,14 @@ void Config::construct( const Config& rParent )
void Config::construct( const sal_Char* pcEnvVar, const FilterBase& rFilter )
{
if( rFilter.getFileUrl().getLength() > 0 )
- construct( pcEnvVar, rFilter.getGlobalFactory(), rFilter.getStorage(), rFilter.getFileUrl() );
+ construct( pcEnvVar, rFilter.getGlobalFactory(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() );
}
-void Config::construct( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName )
+void Config::construct( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc )
{
if( pcEnvVar && rxRootStrg.get() && (rSysFileName.getLength() > 0) )
if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) )
- mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxFactory, rxRootStrg, rSysFileName ) );
+ mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxFactory, rxRootStrg, rSysFileName, rMediaDesc ) );
}
void Config::setStringOption( const String& rKey, const String& rData )
@@ -1683,6 +1702,16 @@ NameListRef Config::getNameList( const String& rListName ) const
return implGetNameList( rListName );
}
+OUString Config::requestPassword( ::comphelper::IDocPasswordVerifier& rVerifier )
+{
+ return mxCfgData->requestPassword( rVerifier );
+}
+
+bool Config::isPasswordCancelled() const
+{
+ return mxCfgData->isPasswordCancelled();
+}
+
bool Config::implIsValid() const
{
return isValid( mxCfgData );
@@ -3050,7 +3079,7 @@ void RecordObjectBase::implDump()
sal_Int64 nRecPos = in().tell();
// record body
- if( cfg().hasName( xRecNames, mnRecId ) )
+ if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) )
{
ItemFormatMap::const_iterator aIt = aSimpleRecs.find( mnRecId );
if( aIt != aSimpleRecs.end() )
@@ -3081,6 +3110,7 @@ void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseSt
maRecNames = rRecNames;
maSimpleRecs = rSimpleRecs;
mnRecPos = mnRecId = mnRecSize = 0;
+ mbBinaryOnly = false;
if( InputObjectBase::implIsValid() )
mbShowRecPos = cfg().getBoolOption( "show-record-position", true );
}
@@ -3166,6 +3196,11 @@ bool DumperBase::isImportEnabled() const
return !isValid() || cfg().isImportEnabled();
}
+bool DumperBase::isImportCancelled() const
+{
+ return isValid() && cfg().isPasswordCancelled();
+}
+
void DumperBase::construct( const ConfigRef& rxConfig )
{
if( isValid( rxConfig ) && rxConfig->isDumperEnabled() )
diff --git a/oox/source/dump/pptxdumper.cxx b/oox/source/dump/pptxdumper.cxx
index d1694000f03b..0e04cb821d4a 100644
--- a/oox/source/dump/pptxdumper.cxx
+++ b/oox/source/dump/pptxdumper.cxx
@@ -41,6 +41,7 @@ using ::rtl::OUString;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::io::XInputStream;
+using ::comphelper::MediaDescriptor;
using ::oox::core::FilterBase;
namespace oox {
@@ -127,7 +128,8 @@ Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Refere
if( rxFactory.is() && rxInStrm.is() )
{
StorageRef xStrg( new ZipStorage( rxFactory, rxInStrm ) );
- ConfigRef xCfg( new Config( DUMP_PPTX_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName ) );
+ MediaDescriptor aMediaDesc;
+ ConfigRef xCfg( new Config( DUMP_PPTX_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) );
DumperBase::construct( xCfg );
}
}
diff --git a/oox/source/dump/xlsbdumper.cxx b/oox/source/dump/xlsbdumper.cxx
index 819aff6bed92..3db91fd7383d 100644
--- a/oox/source/dump/xlsbdumper.cxx
+++ b/oox/source/dump/xlsbdumper.cxx
@@ -48,6 +48,7 @@ using ::com::sun::star::uno::Reference;
using ::com::sun::star::util::DateTime;
using ::com::sun::star::lang::XMultiServiceFactory;
using ::com::sun::star::io::XInputStream;
+using ::comphelper::MediaDescriptor;
using ::oox::core::FilterBase;
using namespace ::oox::xls;
@@ -1492,6 +1493,12 @@ void RecordStreamObject::implDumpRecordBody()
dumpString( "#sheet-name" );
break;
+ case OOBIN_ID_FILESHARING:
+ dumpBool< sal_uInt16 >( "recommend-read-only" );
+ dumpHex< sal_uInt16 >( "password-hash" );
+ dumpString( "password-creator" );
+ break;
+
case OOBIN_ID_FILL:
dumpDec< sal_Int32 >( "fill-pattern", "FILLPATTERNS" );
dumpColor( "fg-color" );
@@ -2267,7 +2274,8 @@ Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Refere
if( rxFactory.is() && rxInStrm.is() )
{
StorageRef xStrg( new ZipStorage( rxFactory, rxInStrm ) );
- ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName ) );
+ MediaDescriptor aMediaDesc;
+ ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) );
DumperBase::construct( xCfg );
}
}
diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx
index e583248adcfa..d586196acee4 100644
--- a/oox/source/vml/vmlshape.cxx
+++ b/oox/source/vml/vmlshape.cxx
@@ -319,7 +319,7 @@ Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxS
if( !maShapeModel.mxClientData.get() || !mrDrawing.convertShapeClientAnchor( aShapeRect, maShapeModel.mxClientData->maAnchor ) )
aShapeRect = getRectangle( pParentAnchor );
// convert the shape, if the calculated rectangle is not empty
- if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) && rxShapes.is() )
+ if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() )
xShape = implConvertAndInsert( rxShapes, aShapeRect );
return xShape;
}
diff --git a/oox/source/xls/biffcodec.cxx b/oox/source/xls/biffcodec.cxx
index b76f51ad0e7e..a589b1b3218f 100644
--- a/oox/source/xls/biffcodec.cxx
+++ b/oox/source/xls/biffcodec.cxx
@@ -31,95 +31,89 @@
#include "oox/xls/biffcodec.hxx"
#include <osl/thread.h>
#include <string.h>
+#include "oox/core/filterbase.hxx"
#include "oox/xls/biffinputstream.hxx"
using ::rtl::OString;
using ::rtl::OUString;
using ::rtl::OStringToOUString;
+using ::oox::core::FilterBase;
namespace oox {
namespace xls {
// ============================================================================
-BiffDecoderBase::BiffDecoderBase( const WorkbookHelper& rHelper ) :
- WorkbookHelper( rHelper ),
- mnError( CODEC_ERROR_UNSUPP_CRYPT )
+BiffDecoderBase::BiffDecoderBase() :
+ mbValid( false )
{
}
-BiffDecoderBase::BiffDecoderBase( const BiffDecoderBase& rDecoder ) :
- WorkbookHelper( rDecoder ),
- mnError( rDecoder.mnError )
+BiffDecoderBase::~BiffDecoderBase()
{
}
-BiffDecoderBase::~BiffDecoderBase()
+::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyPassword( const OUString& rPassword )
{
+ mbValid = implVerify( rPassword );
+ return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
}
void BiffDecoderBase::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
{
if( pnDestData && pnSrcData && (nBytes > 0) )
{
- if( isValid() )
+ if( mbValid )
implDecode( pnDestData, pnSrcData, nStreamPos, nBytes );
else
memcpy( pnDestData, pnSrcData, nBytes );
}
}
-void BiffDecoderBase::setHasValidPassword( bool bValid )
-{
- mnError = bValid ? CODEC_OK : CODEC_ERROR_WRONG_PASS;
-}
-
// ============================================================================
-BiffDecoder_XOR::BiffDecoder_XOR( const WorkbookHelper& rHelper, sal_uInt16 nKey, sal_uInt16 nHash ) :
- BiffDecoderBase( rHelper ),
+BiffDecoder_XOR::BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash ) :
maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
+ maPassword( 16 ),
mnKey( nKey ),
mnHash( nHash )
{
- init( BiffCodecHelper::getBiff5WbProtPassword() );
- if( !isValid() )
- init( OUStringToOString( getCodecHelper().queryPassword(), osl_getThreadTextEncoding() ) );
}
BiffDecoder_XOR::BiffDecoder_XOR( const BiffDecoder_XOR& rDecoder ) :
- BiffDecoderBase( rDecoder ),
+ BiffDecoderBase(), // must be called to prevent compiler warning
maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
+ maPassword( rDecoder.maPassword ),
mnKey( rDecoder.mnKey ),
mnHash( rDecoder.mnHash )
{
- init( rDecoder.maPass );
+ if( isValid() )
+ maCodec.initKey( &maPassword.front() );
}
-void BiffDecoder_XOR::init( const OString& rPass )
+BiffDecoder_XOR* BiffDecoder_XOR::implClone()
{
- maPass = rPass;
- sal_Int32 nLen = maPass.getLength();
- bool bValid = (0 < nLen) && (nLen < 16);
+ return new BiffDecoder_XOR( *this );
+}
- if( bValid )
+bool BiffDecoder_XOR::implVerify( const OUString& rPassword )
+{
+ /* Convert password to a byte string. TODO: this needs some finetuning
+ according to the spec... */
+ OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() );
+ sal_Int32 nLen = aBytePassword.getLength();
+ if( (0 < nLen) && (nLen < 16) )
{
// copy byte string to sal_uInt8 array
- sal_uInt8 pnPassw[ 16 ];
- memset( pnPassw, 0, sizeof( pnPassw ) );
- memcpy( pnPassw, maPass.getStr(), static_cast< size_t >( nLen ) );
+ maPassword.clear();
+ maPassword.resize( 16, 0 );
+ memcpy( &maPassword.front(), aBytePassword.getStr(), static_cast< size_t >( nLen ) );
// init codec
- maCodec.initKey( pnPassw );
- bValid = maCodec.verifyKey( mnKey, mnHash );
+ maCodec.initKey( &maPassword.front() );
+ return maCodec.verifyKey( mnKey, mnHash );
}
-
- setHasValidPassword( bValid );
-}
-
-BiffDecoder_XOR* BiffDecoder_XOR::implClone()
-{
- return new BiffDecoder_XOR( *this );
+ return false;
}
void BiffDecoder_XOR::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
@@ -149,55 +143,49 @@ sal_Int32 lclGetRcfOffset( sal_Int64 nStreamPos )
// ----------------------------------------------------------------------------
-BiffDecoder_RCF::BiffDecoder_RCF( const WorkbookHelper& rHelper,
- sal_uInt8 pnDocId[ 16 ], sal_uInt8 pnSaltData[ 16 ], sal_uInt8 pnSaltHash[ 16 ] ) :
- BiffDecoderBase( rHelper ),
- maDocId( pnDocId, pnDocId + 16 ),
- maSaltData( pnSaltData, pnSaltData + 16 ),
- maSaltHash( pnSaltHash, pnSaltHash + 16 )
+BiffDecoder_RCF::BiffDecoder_RCF( sal_uInt8 pnSalt[ 16 ], sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
+ maPassword( 16, 0 ),
+ maSalt( pnSalt, pnSalt + 16 ),
+ maVerifier( pnVerifier, pnVerifier + 16 ),
+ maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
{
- init( BiffCodecHelper::getBiff8WbProtPassword() );
- if( !isValid() )
- init( getCodecHelper().queryPassword() );
}
BiffDecoder_RCF::BiffDecoder_RCF( const BiffDecoder_RCF& rDecoder ) :
- BiffDecoderBase( rDecoder ),
- maDocId( rDecoder.maDocId ),
- maSaltData( rDecoder.maSaltData ),
- maSaltHash( rDecoder.maSaltHash )
+ BiffDecoderBase(), // must be called to prevent compiler warning
+ maPassword( rDecoder.maPassword ),
+ maSalt( rDecoder.maSalt ),
+ maVerifier( rDecoder.maVerifier ),
+ maVerifierHash( rDecoder.maVerifierHash )
{
- init( rDecoder.maPass );
+ if( isValid() )
+ maCodec.initKey( &maPassword.front(), &maSalt.front() );
}
-void BiffDecoder_RCF::init( const OUString& rPass )
+BiffDecoder_RCF* BiffDecoder_RCF::implClone()
{
- maPass = rPass;
- sal_Int32 nLen = maPass.getLength();
- bool bValid = (0 < nLen) && (nLen < 16);
+ return new BiffDecoder_RCF( *this );
+}
- if( bValid )
+bool BiffDecoder_RCF::implVerify( const OUString& rPassword )
+{
+ sal_Int32 nLen = rPassword.getLength();
+ if( (0 < nLen) && (nLen < 16) )
{
// copy string to sal_uInt16 array
- sal_uInt16 pnPassw[ 16 ];
- memset( pnPassw, 0, sizeof( pnPassw ) );
- const sal_Unicode* pcChar = maPass.getStr();
+ maPassword.clear();
+ maPassword.resize( 16, 0 );
+ const sal_Unicode* pcChar = rPassword.getStr();
const sal_Unicode* pcCharEnd = pcChar + nLen;
- sal_uInt16* pnCurrPass = pnPassw;
- for( ; pcChar < pcCharEnd; ++pcChar, ++pnCurrPass )
- *pnCurrPass = static_cast< sal_uInt16 >( *pcChar );
+ ::std::vector< sal_uInt16 >::iterator aIt = maPassword.begin();
+ for( ; pcChar < pcCharEnd; ++pcChar, ++aIt )
+ *aIt = static_cast< sal_uInt16 >( *pcChar );
// init codec
- maCodec.initKey( pnPassw, &maDocId.front() );
- bValid = maCodec.verifyKey( &maSaltData.front(), &maSaltHash.front() );
+ maCodec.initKey( &maPassword.front(), &maSalt.front() );
+ return maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() );
}
-
- setHasValidPassword( bValid );
-}
-
-BiffDecoder_RCF* BiffDecoder_RCF::implClone()
-{
- return new BiffDecoder_RCF( *this );
+ return false;
}
void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
@@ -229,130 +217,117 @@ void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcD
namespace {
-const sal_uInt16 BIFF_FILEPASS_BIFF2 = 0x0000;
-const sal_uInt16 BIFF_FILEPASS_BIFF8 = 0x0001;
-const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 0x0001;
-const sal_uInt16 BIFF_FILEPASS_BIFF8_STRONG = 0x0002;
+const sal_uInt16 BIFF_FILEPASS_XOR = 0;
+const sal_uInt16 BIFF_FILEPASS_RCF = 1;
-} // namespace
+const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 1;
+const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003 = 2;
+const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007 = 3;
// ----------------------------------------------------------------------------
-BiffCodecHelper::BiffCodecHelper( const WorkbookHelper& rHelper ) :
- WorkbookHelper( rHelper ),
- mbHasPassword( false )
-{
-}
-
-const OString& BiffCodecHelper::getBiff5WbProtPassword()
-{
- static const OString saPass( "VelvetSweatshop" );
- return saPass;
-}
-
-const OUString& BiffCodecHelper::getBiff8WbProtPassword()
+BiffDecoderRef lclReadFilePass_XOR( BiffInputStream& rStrm )
{
- static const OUString saPass = OStringToOUString( getBiff5WbProtPassword(), RTL_TEXTENCODING_ASCII_US );
- return saPass;
-}
-
-OUString BiffCodecHelper::queryPassword()
-{
- if( !mbHasPassword )
- {
- //! TODO
- maPassword = OUString();
- // set to true, even if dialog has been cancelled (never ask twice)
- mbHasPassword = true;
- }
- return maPassword;
-}
-
-bool BiffCodecHelper::importFilePass( BiffInputStream& rStrm )
-{
- OSL_ENSURE( !mxDecoder, "BiffCodecHelper::importFilePass - multiple FILEPASS records" );
- rStrm.enableDecoder( false );
- mxDecoder.reset();
- if( getBiff() == BIFF8 ) importFilePass8( rStrm ); else importFilePass2( rStrm );
-
- // set decoder at import stream
- rStrm.setDecoder( mxDecoder );
- //! TODO remember encryption state for export
-// mrStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true;
-
- return mxDecoder.get() && mxDecoder->isValid();
-}
-
-void BiffCodecHelper::cloneDecoder( BiffInputStream& rStrm )
-{
- if( mxDecoder.get() )
- rStrm.setDecoder( BiffDecoderRef( mxDecoder->clone() ) );
-}
-
-// private --------------------------------------------------------------------
-
-void BiffCodecHelper::importFilePass_XOR( BiffInputStream& rStrm )
-{
- OSL_ENSURE( rStrm.getRemaining() == 4, "BiffCodecHelper::importFilePass_XOR - wrong record size" );
+ BiffDecoderRef xDecoder;
+ OSL_ENSURE( rStrm.getRemaining() == 4, "lclReadFilePass_XOR - wrong record size" );
if( rStrm.getRemaining() == 4 )
{
sal_uInt16 nBaseKey, nHash;
rStrm >> nBaseKey >> nHash;
- mxDecoder.reset( new BiffDecoder_XOR( *this, nBaseKey, nHash ) );
+ xDecoder.reset( new BiffDecoder_XOR( nBaseKey, nHash ) );
}
+ return xDecoder;
}
-void BiffCodecHelper::importFilePass_RCF( BiffInputStream& rStrm )
+BiffDecoderRef lclReadFilePass_RCF( BiffInputStream& rStrm )
{
- OSL_ENSURE( rStrm.getRemaining() == 48, "BiffCodecHelper::importFilePass_RCF - wrong record size" );
+ BiffDecoderRef xDecoder;
+ OSL_ENSURE( rStrm.getRemaining() == 48, "lclReadFilePass_RCF - wrong record size" );
if( rStrm.getRemaining() == 48 )
{
- sal_uInt8 pnDocId[ 16 ];
- sal_uInt8 pnSaltData[ 16 ];
- sal_uInt8 pnSaltHash[ 16 ];
- rStrm.readMemory( pnDocId, 16 );
- rStrm.readMemory( pnSaltData, 16 );
- rStrm.readMemory( pnSaltHash, 16 );
- mxDecoder.reset( new BiffDecoder_RCF( *this, pnDocId, pnSaltData, pnSaltHash ) );
+ sal_uInt8 pnSalt[ 16 ];
+ sal_uInt8 pnVerifier[ 16 ];
+ sal_uInt8 pnVerifierHash[ 16 ];
+ rStrm.readMemory( pnSalt, 16 );
+ rStrm.readMemory( pnVerifier, 16 );
+ rStrm.readMemory( pnVerifierHash, 16 );
+ xDecoder.reset( new BiffDecoder_RCF( pnSalt, pnVerifier, pnVerifierHash ) );
}
+ return xDecoder;
}
-void BiffCodecHelper::importFilePass_Strong( BiffInputStream& /*rStrm*/ )
+BiffDecoderRef lclReadFilePass_CryptoApi( BiffInputStream& /*rStrm*/ )
{
// not supported
+ return BiffDecoderRef();
}
-void BiffCodecHelper::importFilePass2( BiffInputStream& rStrm )
-{
- importFilePass_XOR( rStrm );
-}
-
-void BiffCodecHelper::importFilePass8( BiffInputStream& rStrm )
+BiffDecoderRef lclReadFilePassBiff8( BiffInputStream& rStrm )
{
+ BiffDecoderRef xDecoder;
switch( rStrm.readuInt16() )
{
- case BIFF_FILEPASS_BIFF2:
- importFilePass_XOR( rStrm );
+ case BIFF_FILEPASS_XOR:
+ xDecoder = lclReadFilePass_XOR( rStrm );
break;
- case BIFF_FILEPASS_BIFF8:
+ case BIFF_FILEPASS_RCF:
+ {
+ sal_uInt16 nMajor = rStrm.readuInt16();
rStrm.skip( 2 );
- switch( rStrm.readuInt16() )
+ switch( nMajor )
{
case BIFF_FILEPASS_BIFF8_RCF:
- importFilePass_RCF( rStrm );
+ xDecoder = lclReadFilePass_RCF( rStrm );
break;
- case BIFF_FILEPASS_BIFF8_STRONG:
- importFilePass_Strong( rStrm );
+ case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003:
+ case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007:
+ xDecoder = lclReadFilePass_CryptoApi( rStrm );
break;
default:
- OSL_ENSURE( false, "BiffCodecHelper::importFilePass8 - unknown BIFF8 encryption sub mode" );
+ OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown BIFF8 encryption sub mode" );
}
+ }
break;
default:
- OSL_ENSURE( false, "BiffCodecHelper::importFilePass8 - unknown encryption mode" );
+ OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown encryption mode" );
}
+ return xDecoder;
+}
+
+} // namespace
+
+// ----------------------------------------------------------------------------
+
+BiffCodecHelper::BiffCodecHelper( const WorkbookHelper& rHelper ) :
+ WorkbookHelper( rHelper )
+{
+}
+
+/*static*/ BiffDecoderRef BiffCodecHelper::implReadFilePass( BiffInputStream& rStrm, BiffType eBiff )
+{
+ rStrm.enableDecoder( false );
+ BiffDecoderRef xDecoder = (eBiff == BIFF8) ? lclReadFilePassBiff8( rStrm ) : lclReadFilePass_XOR( rStrm );
+ rStrm.setDecoder( xDecoder );
+ return xDecoder;
+}
+
+bool BiffCodecHelper::importFilePass( BiffInputStream& rStrm )
+{
+ OSL_ENSURE( !mxDecoder, "BiffCodecHelper::importFilePass - multiple FILEPASS records" );
+ mxDecoder = implReadFilePass( rStrm, getBiff() );
+ // request and verify a password (decoder implements IDocPasswordVerifier)
+ if( mxDecoder.get() )
+ getBaseFilter().requestPassword( *mxDecoder );
+ // correct password is indicated by isValid() function of decoder
+ return mxDecoder.get() && mxDecoder->isValid();
+}
+
+void BiffCodecHelper::cloneDecoder( BiffInputStream& rStrm )
+{
+ if( mxDecoder.get() )
+ rStrm.setDecoder( BiffDecoderRef( mxDecoder->clone() ) );
}
// ============================================================================
diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx
index d5904877b7ee..1779cb4a7691 100644
--- a/oox/source/xls/workbookfragment.cxx
+++ b/oox/source/xls/workbookfragment.cxx
@@ -101,8 +101,9 @@ ContextHandlerRef OoxWorkbookFragment::onCreateContext( sal_Int32 nElement, cons
case XLS_TOKEN( definedNames ):
case XLS_TOKEN( pivotCaches ): return this;
- case XLS_TOKEN( workbookPr ): getWorkbookSettings().importWorkbookPr( rAttribs ); break;
- case XLS_TOKEN( calcPr ): getWorkbookSettings().importCalcPr( rAttribs ); break;
+ case XLS_TOKEN( fileSharing ): getWorkbookSettings().importFileSharing( rAttribs ); break;
+ case XLS_TOKEN( workbookPr ): getWorkbookSettings().importWorkbookPr( rAttribs ); break;
+ case XLS_TOKEN( calcPr ): getWorkbookSettings().importCalcPr( rAttribs ); break;
}
break;
@@ -151,6 +152,7 @@ ContextHandlerRef OoxWorkbookFragment::onCreateRecordContext( sal_Int32 nRecId,
case OOBIN_ID_EXTERNALREFS:
case OOBIN_ID_PIVOTCACHES: return this;
+ case OOBIN_ID_FILESHARING: getWorkbookSettings().importFileSharing( rStrm ); break;
case OOBIN_ID_WORKBOOKPR: getWorkbookSettings().importWorkbookPr( rStrm ); break;
case OOBIN_ID_CALCPR: getWorkbookSettings().importCalcPr( rStrm ); break;
case OOBIN_ID_DEFINEDNAME: getDefinedNames().importDefinedName( rStrm ); break;
@@ -402,7 +404,8 @@ bool BiffWorkbookFragment::importFragment()
}
// final conversions, e.g. calculation settings and view settings
- finalizeWorkbookImport();
+ if( bRet )
+ finalizeWorkbookImport();
return bRet;
}
@@ -509,33 +512,35 @@ bool BiffWorkbookFragment::importGlobalsFragment( ISegmentProgressBar& rProgress
case BIFF3: switch( nRecId )
{
- case BIFF_ID_CRN: bExtLinkRec = true; break;
- case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
- case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
- case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
- case BIFF3_ID_FONT: rStyles.importFont( mrStrm ); break;
- case BIFF2_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
- case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
- case BIFF_ID_PALETTE: rStyles.importPalette( mrStrm ); break;
- case BIFF_ID_STYLE: rStyles.importStyle( mrStrm ); break;
- case BIFF_ID_XCT: bExtLinkRec = true; break;
- case BIFF3_ID_XF: rStyles.importXf( mrStrm ); break;
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF_ID_FILESHARING: rWorkbookSett.importFileSharing( mrStrm ); break;
+ case BIFF3_ID_FONT: rStyles.importFont( mrStrm ); break;
+ case BIFF2_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( mrStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( mrStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF3_ID_XF: rStyles.importXf( mrStrm ); break;
}
break;
case BIFF4: switch( nRecId )
{
- case BIFF_ID_CRN: bExtLinkRec = true; break;
- case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
- case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
- case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
- case BIFF3_ID_FONT: rStyles.importFont( mrStrm ); break;
- case BIFF4_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
- case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
- case BIFF_ID_PALETTE: rStyles.importPalette( mrStrm ); break;
- case BIFF_ID_STYLE: rStyles.importStyle( mrStrm ); break;
- case BIFF_ID_XCT: bExtLinkRec = true; break;
- case BIFF4_ID_XF: rStyles.importXf( mrStrm ); break;
+ case BIFF_ID_CRN: bExtLinkRec = true; break;
+ case BIFF3_ID_DEFINEDNAME: bExtLinkRec = true; break;
+ case BIFF3_ID_EXTERNALNAME: bExtLinkRec = true; break;
+ case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF_ID_FILESHARING: rWorkbookSett.importFileSharing( mrStrm ); break;
+ case BIFF3_ID_FONT: rStyles.importFont( mrStrm ); break;
+ case BIFF4_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
+ case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
+ case BIFF_ID_PALETTE: rStyles.importPalette( mrStrm ); break;
+ case BIFF_ID_STYLE: rStyles.importStyle( mrStrm ); break;
+ case BIFF_ID_XCT: bExtLinkRec = true; break;
+ case BIFF4_ID_XF: rStyles.importXf( mrStrm ); break;
}
break;
@@ -546,6 +551,7 @@ bool BiffWorkbookFragment::importGlobalsFragment( ISegmentProgressBar& rProgress
case BIFF5_ID_DEFINEDNAME: bExtLinkRec = true; break;
case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break;
case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF_ID_FILESHARING: rWorkbookSett.importFileSharing( mrStrm ); break;
case BIFF5_ID_FONT: rStyles.importFont( mrStrm ); break;
case BIFF4_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
@@ -567,6 +573,7 @@ bool BiffWorkbookFragment::importGlobalsFragment( ISegmentProgressBar& rProgress
case BIFF_ID_EXTERNALBOOK: bExtLinkRec = true; break;
case BIFF5_ID_EXTERNALNAME: bExtLinkRec = true; break;
case BIFF_ID_EXTERNSHEET: bExtLinkRec = true; break;
+ case BIFF_ID_FILESHARING: rWorkbookSett.importFileSharing( mrStrm ); break;
case BIFF5_ID_FONT: rStyles.importFont( mrStrm ); break;
case BIFF4_ID_FORMAT: rStyles.importFormat( mrStrm ); break;
case BIFF_ID_HIDEOBJ: rWorkbookSett.importHideObj( mrStrm ); break;
@@ -591,8 +598,11 @@ bool BiffWorkbookFragment::importGlobalsFragment( ISegmentProgressBar& rProgress
// finalize global buffers
rProgressBar.setPosition( 0.5 );
- rSharedStrings.finalizeImport();
- rStyles.finalizeImport();
+ if( bRet )
+ {
+ rSharedStrings.finalizeImport();
+ rStyles.finalizeImport();
+ }
/* Import external link data (EXTERNSHEET, EXTERNALNAME, DEFINEDNAME)
which need existing internal sheets (SHEET records). The SHEET records
diff --git a/oox/source/xls/workbooksettings.cxx b/oox/source/xls/workbooksettings.cxx
index b91315f663fb..e4de0ff2dd0c 100644
--- a/oox/source/xls/workbooksettings.cxx
+++ b/oox/source/xls/workbooksettings.cxx
@@ -32,10 +32,12 @@
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
#include <com/sun/star/sheet/XCalculatable.hpp>
+#include <comphelper/mediadescriptor.hxx>
#include "properties.hxx"
#include "oox/helper/attributelist.hxx"
#include "oox/helper/propertyset.hxx"
#include "oox/helper/recordinputstream.hxx"
+#include "oox/core/filterbase.hxx"
#include "oox/xls/biffinputstream.hxx"
#include "oox/xls/unitconverter.hxx"
@@ -45,6 +47,7 @@ using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::util::Date;
using ::com::sun::star::util::XNumberFormatsSupplier;
using ::com::sun::star::sheet::XCalculatable;
+using ::oox::core::CodecHelper;
namespace oox {
namespace xls {
@@ -73,6 +76,14 @@ const sal_Int16 API_SHOWMODE_PLACEHOLDER = 2; /// Show placeholder
// ============================================================================
+FileSharingModel::FileSharingModel() :
+ mnPasswordHash( 0 ),
+ mbRecommendReadOnly( false )
+{
+}
+
+// ============================================================================
+
WorkbookSettingsModel::WorkbookSettingsModel() :
mnShowObjectMode( XML_all ),
mnUpdateLinksMode( XML_userSet ),
@@ -113,6 +124,13 @@ WorkbookSettings::WorkbookSettings( const WorkbookHelper& rHelper ) :
{
}
+void WorkbookSettings::importFileSharing( const AttributeList& rAttribs )
+{
+ maFileSharing.maUserName = rAttribs.getXString( XML_userName, OUString() );
+ maFileSharing.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_reservationPassword );
+ maFileSharing.mbRecommendReadOnly = rAttribs.getBool( XML_readOnlyRecommended, false );
+}
+
void WorkbookSettings::importWorkbookPr( const AttributeList& rAttribs )
{
maBookSettings.maCodeName = rAttribs.getString( XML_codePage, OUString() );
@@ -138,6 +156,12 @@ void WorkbookSettings::importCalcPr( const AttributeList& rAttribs )
maCalcSettings.mbConcurrent = rAttribs.getBool( XML_concurrentCalc, true );
}
+void WorkbookSettings::importFileSharing( RecordInputStream& rStrm )
+{
+ maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0;
+ rStrm >> maFileSharing.mnPasswordHash >> maFileSharing.maUserName;
+}
+
void WorkbookSettings::importWorkbookPr( RecordInputStream& rStrm )
{
sal_uInt32 nFlags;
@@ -170,6 +194,23 @@ void WorkbookSettings::setSaveExtLinkValues( bool bSaveExtLinks )
maBookSettings.mbSaveExtLinkValues = bSaveExtLinks;
}
+void WorkbookSettings::importFileSharing( BiffInputStream& rStrm )
+{
+ maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0;
+ rStrm >> maFileSharing.mnPasswordHash;
+ if( getBiff() == BIFF8 )
+ {
+ sal_uInt16 nStrLen = rStrm.readuInt16();
+ // there is no string flags field if string is empty
+ if( nStrLen > 0 )
+ maFileSharing.maUserName = rStrm.readUniStringBody( nStrLen );
+ }
+ else
+ {
+ maFileSharing.maUserName = rStrm.readByteStringUC( false, getTextEncoding() );
+ }
+}
+
void WorkbookSettings::importBookBool( BiffInputStream& rStrm )
{
// value of 0 means save external values, value of 1 means strip external values
@@ -254,6 +295,10 @@ void WorkbookSettings::finalizeImport()
break;
}
+ // write protection
+ if( maFileSharing.mbRecommendReadOnly || (maFileSharing.mnPasswordHash != 0) )
+ getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "ReadOnly" ) ] <<= true;
+
// calculation settings
Date aNullDate = getNullDate();
diff --git a/oox/source/xls/worksheetsettings.cxx b/oox/source/xls/worksheetsettings.cxx
index 48cc9c3041df..d791e4801217 100644
--- a/oox/source/xls/worksheetsettings.cxx
+++ b/oox/source/xls/worksheetsettings.cxx
@@ -41,6 +41,7 @@ using ::com::sun::star::uno::Exception;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY_THROW;
using ::com::sun::star::util::XProtectable;
+using ::oox::core::CodecHelper;
namespace oox {
namespace xls {
@@ -112,16 +113,6 @@ SheetProtectionModel::SheetProtectionModel() :
// ============================================================================
-namespace {
-
-sal_uInt16 lclGetCheckedHash( sal_Int32 nHash )
-{
- OSL_ENSURE( (0 <= nHash) && (nHash <= SAL_MAX_UINT16), "lclGetCheckedHash - invalid password hash" );
- return getLimitedValue< sal_uInt16, sal_Int32 >( nHash, 0, SAL_MAX_UINT16 );
-}
-
-} // namespace
-
WorksheetSettings::WorksheetSettings( const WorksheetHelper& rHelper ) :
WorksheetHelper( rHelper ),
maPhoneticSett( rHelper )
@@ -153,7 +144,7 @@ void WorksheetSettings::importOutlinePr( const AttributeList& rAttribs )
void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs )
{
- maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getIntegerHex( XML_password, 0 ) );
+ maSheetProt.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_password );
maSheetProt.mbSheet = rAttribs.getBool( XML_sheet, false );
maSheetProt.mbObjects = rAttribs.getBool( XML_objects, false );
maSheetProt.mbScenarios = rAttribs.getBool( XML_scenarios, false );
@@ -174,7 +165,7 @@ void WorksheetSettings::importSheetProtection( const AttributeList& rAttribs )
void WorksheetSettings::importChartProtection( const AttributeList& rAttribs )
{
- maSheetProt.mnPasswordHash = lclGetCheckedHash( rAttribs.getIntegerHex( XML_password, 0 ) );
+ maSheetProt.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_password );
maSheetProt.mbSheet = rAttribs.getBool( XML_content, false );
maSheetProt.mbObjects = rAttribs.getBool( XML_objects, false );
}
diff --git a/oox/util/makefile.mk b/oox/util/makefile.mk
index f98003b0fe0d..93669d2d40b1 100644
--- a/oox/util/makefile.mk
+++ b/oox/util/makefile.mk
@@ -74,6 +74,20 @@ SHL1STDLIBS= \
$(BASEGFXLIB) \
$(SAXLIB)
+# link openssl, copied this bit from ucb/source/ucp/webdav/makefile.mk
+.IF "$(GUI)"=="WNT"
+SHL1STDLIBS+= $(OPENSSLLIB)
+.ELSE # WNT
+.IF "$(OS)"=="SOLARIS"
+SHL1STDLIBS+= -lnsl -lsocket -ldl
+.ENDIF # SOLARIS
+.IF "$(SYSTEM_OPENSSL)"=="YES"
+SHL1STDLIBS+= $(OPENSSLLIB)
+.ELSE
+SHL1STDLIBS+= $(OPENSSLLIBST)
+.ENDIF
+.ENDIF # WNT
+
SHL1DEF= $(MISC)$/$(SHL1TARGET).def
SHL1LIBS= $(LIB1TARGET)
DEF1NAME =$(SHL1TARGET)