diff options
author | Oliver Bolte <obo@openoffice.org> | 2009-09-07 14:41:16 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2009-09-07 14:41:16 +0000 |
commit | 9fa41b880dcfef94fa3b7b057f601d97f8a37763 (patch) | |
tree | e9fa09c313164699137f72e8350585a0c8571849 | |
parent | c2f366873f2a3b423265a1ebfdb5e1547d49f3e5 (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'
32 files changed, 1325 insertions, 568 deletions
diff --git a/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu b/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu index 9efffbea65c5..53a7f5b74ead 100644 --- a/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu +++ b/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu @@ -1,5 +1,5 @@ <node oor:name="writer_MS_Word_2007" oor:op="replace" > - <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.WriterFilterDetector</value></prop> + <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop> <prop oor:name="URLPattern"/> <prop oor:name="Extensions"><value>docx docm</value></prop> <prop oor:name="MediaType"><value>application/msword</value></prop> diff --git a/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu index 84e652587920..c0ec68200f22 100644 --- a/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu +++ b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu @@ -1,5 +1,5 @@ <node oor:name="writer_MS_Word_2007_Template" oor:op="replace" > - <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.WriterFilterDetector</value></prop> + <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop> <prop oor:name="URLPattern"/> <prop oor:name="Extensions"><value>dotx dotm</value></prop> <prop oor:name="MediaType"><value>application/msword</value></prop> 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) diff --git a/writerfilter/source/filter/ImportFilter.cxx b/writerfilter/source/filter/ImportFilter.cxx index b67b7dd283ac..af27bac94540 100644 --- a/writerfilter/source/filter/ImportFilter.cxx +++ b/writerfilter/source/filter/ImportFilter.cxx @@ -32,6 +32,8 @@ #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> #include <com/sun/star/io/XInputStream.hpp> +#include <comphelper/mediadescriptor.hxx> +#include <oox/core/filterdetect.hxx> #include <dmapper/DomainMapper.hxx> #include <WriterFilter.hxx> #include <doctok/WW8Document.hxx> @@ -44,6 +46,7 @@ #include <resourcemodel/TagLogger.hxx> using namespace ::rtl; using namespace ::com::sun::star; +using ::comphelper::MediaDescriptor; /*-- 09.06.2006 10:15:20--------------------------------------------------- @@ -62,28 +65,29 @@ sal_Bool WriterFilter::filter( const uno::Sequence< beans::PropertyValue >& aDes if (!xExprtr.is() || !xFltr.is()) return sal_False; xExprtr->setSourceDocument(m_xSrcDoc); - if (xFltr->filter(aDescriptor)) - return sal_True; - return sal_False; + return xFltr->filter(aDescriptor); } else if (m_xDstDoc.is()) { - - sal_Int32 nLength = aDescriptor.getLength(); - const beans::PropertyValue * pValue = aDescriptor.getConstArray(); - uno::Reference < io::XInputStream > xInputStream; - ::rtl::OUString sFilterName; - for ( sal_Int32 i = 0 ; i < nLength; i++) - { - if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) - pValue[i].Value >>= xInputStream; - else if( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "FilterName" ) ) ) - pValue[i].Value >>= sFilterName; - } - if ( !xInputStream.is() ) - { - return sal_False; - } + MediaDescriptor aMediaDesc( aDescriptor ); + OUString sFilterName = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_FILTERNAME(), OUString() ); + + uno::Reference< io::XInputStream > xInputStream; + try + { + // use the oox.core.FilterDetect implementation to extract the decrypted ZIP package + uno::Reference< lang::XMultiServiceFactory > xFactory( m_xContext->getServiceManager(), uno::UNO_QUERY_THROW ); + ::oox::core::FilterDetect aDetector( xFactory ); + xInputStream = aDetector.extractUnencryptedPackage( aMediaDesc ); + } + catch( uno::Exception& ) + { + } + + if ( !xInputStream.is() ) + { + return sal_False; + } #ifdef DEBUG_ELEMENT writerfilter::TagLogger::Pointer_t debugLogger diff --git a/writerfilter/util/makefile.mk b/writerfilter/util/makefile.mk index 08033ab9c8df..4e99764c688f 100644 --- a/writerfilter/util/makefile.mk +++ b/writerfilter/util/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************ # # 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 @@ -63,7 +63,8 @@ SHL1STDLIBS=\ $(CPPUHELPERLIB) \ $(COMPHELPERLIB) \ $(CPPULIB) \ - $(SALLIB) + $(SALLIB) \ + $(OOXLIB) SHL1DEPN= |