[ooo-build-commit] .: sc/inc sc/source

Kohei Yoshida kohei at kemper.freedesktop.org
Tue Sep 28 08:46:35 PDT 2010


 sc/inc/tabprotection.hxx                |   42 ++++---
 sc/source/core/data/tabprotection.cxx   |  169 ++++++++++++++++++++++++--------
 sc/source/filter/xml/xmlbodyi.cxx       |    8 +
 sc/source/filter/xml/xmlbodyi.hxx       |    4 
 sc/source/filter/xml/xmlexprt.cxx       |   78 +++++++++++++-
 sc/source/filter/xml/xmlimprt.cxx       |   23 ++++
 sc/source/filter/xml/xmlimprt.hxx       |   13 ++
 sc/source/filter/xml/xmlsubti.cxx       |   27 +++--
 sc/source/filter/xml/xmlsubti.hxx       |   19 +++
 sc/source/filter/xml/xmltabi.cxx        |   85 ++++++++++++++--
 sc/source/filter/xml/xmltabi.hxx        |   22 ++++
 sc/source/ui/docshell/docsh.cxx         |    9 +
 sc/source/ui/miscdlgs/retypepassdlg.cxx |    2 
 13 files changed, 417 insertions(+), 84 deletions(-)

New commits:
commit 119b9645e95dd8df08dc57b7358958714fbf7cab
Author: Kohei Yoshida <kyoshida at novell.com>
Date:   Tue Sep 28 11:45:33 2010 -0400

    Ported calc-ods-sheet-protection-sc.diff from ooo-build.

diff --git a/sc/inc/tabprotection.hxx b/sc/inc/tabprotection.hxx
index 965ea30..4c87b6d 100644
--- a/sc/inc/tabprotection.hxx
+++ b/sc/inc/tabprotection.hxx
@@ -32,7 +32,6 @@
 #include <com/sun/star/uno/Sequence.hxx>
 
 #include "global.hxx"
-#include <vector>
 #include <boost/shared_ptr.hpp>
 
 #define ENABLE_SHEET_PROTECTION 1
@@ -42,8 +41,9 @@ class ScTableProtectionImpl;
 
 enum ScPasswordHash
 {
-    PASSHASH_OOO = 0,
-    PASSHASH_XL
+    PASSHASH_SHA1 = 0,
+    PASSHASH_XL,
+    PASSHASH_UNSPECIFIED
 };
 
 class ScPassHashHelper
@@ -53,7 +53,11 @@ public:
         least one hash that needs to be regenerated, it returns true.  If all
         hash values are compatible with the specified hash type, then it
         returns false. */
-    static bool needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash);
+    static bool needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
+
+    static ::rtl::OUString getHashURI(ScPasswordHash eHash);
+
+    static ScPasswordHash getHashTypeFromURI(const ::rtl::OUString& rURI);
 
 private:
     ScPassHashHelper();
@@ -72,11 +76,13 @@ public:
     virtual void setProtected(bool bProtected) = 0;
 
     virtual bool isPasswordEmpty() const = 0;
-    virtual bool hasPasswordHash(ScPasswordHash eHash) const = 0;
+    virtual bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const = 0;
     virtual void setPassword(const String& aPassText) = 0;
-    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const = 0;
-    virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, 
-                                 ScPasswordHash eHash = PASSHASH_OOO) = 0;
+    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
+        ScPasswordHash eHash, ScPasswordHash eHas2 = PASSHASH_UNSPECIFIED) const = 0;
+    virtual void setPasswordHash(
+        const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
+        ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) = 0;
     virtual bool verifyPassword(const String& aPassText) const = 0;
 };
 
@@ -102,11 +108,13 @@ public:
     virtual void setProtected(bool bProtected);
             
     virtual bool isPasswordEmpty() const;
-    virtual bool hasPasswordHash(ScPasswordHash eHash) const;
+    virtual bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
     virtual void setPassword(const String& aPassText);
-    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
-    virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, 
-                                 ScPasswordHash eHash = PASSHASH_OOO);
+    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
+        ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
+    virtual void setPasswordHash(
+        const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
+        ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
     virtual bool verifyPassword(const String& aPassText) const;
     
     bool isOptionEnabled(Option eOption) const;
@@ -159,11 +167,13 @@ public:
     virtual void setProtected(bool bProtected);
             
     virtual bool isPasswordEmpty() const;
-    virtual bool hasPasswordHash(ScPasswordHash eHash) const;
+    virtual bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
     virtual void setPassword(const String& aPassText);
-    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
-    virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, 
-                                 ScPasswordHash eHash = PASSHASH_OOO);
+    virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
+        ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
+    virtual void setPasswordHash(
+        const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
+        ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
     virtual bool verifyPassword(const String& aPassText) const;
     
     bool isOptionEnabled(Option eOption) const;
diff --git a/sc/source/core/data/tabprotection.cxx b/sc/source/core/data/tabprotection.cxx
index a80cafa..0e51d33 100644
--- a/sc/source/core/data/tabprotection.cxx
+++ b/sc/source/core/data/tabprotection.cxx
@@ -36,20 +36,27 @@
 #include <comphelper/docpasswordhelper.hxx>
 #include "document.hxx"
 
+#include <vector>
+
 #define DEBUG_TAB_PROTECTION 0
 
+#define URI_SHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
+#define URI_XLS_LEGACY "http://docs.oasis-open.org/office/ns/table/legacy-hash-excel"
+
 using namespace ::com::sun::star;
 using ::com::sun::star::uno::Sequence;
 using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+using ::std::vector;
 
 // ============================================================================
 
-bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash)
+bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2)
 {
     if (rDoc.IsDocProtected())
     {
         const ScDocProtection* p = rDoc.GetDocProtection();
-        if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash))
+        if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
             return true;
     }
 
@@ -61,13 +68,37 @@ bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash
             // Sheet not protected.  Skip it.
             continue;
 
-        if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash))
+        if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
             return true;
     }
 
     return false;
 }
 
+OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
+{
+    switch (eHash)
+    {
+        case PASSHASH_SHA1:
+            return OUString::createFromAscii(URI_SHA1);
+        case PASSHASH_XL:
+            return OUString::createFromAscii(URI_XLS_LEGACY);
+        case PASSHASH_UNSPECIFIED:
+        default:
+            ;
+    }
+    return OUString();
+}
+
+ScPasswordHash ScPassHashHelper::getHashTypeFromURI(const OUString& rURI)
+{
+    if (rURI.equalsAscii(URI_SHA1))
+        return PASSHASH_SHA1;
+    else if (rURI.equalsAscii(URI_XLS_LEGACY))
+        return PASSHASH_XL;
+    return PASSHASH_UNSPECIFIED;
+}
+
 // ============================================================================
 
 ScPassHashProtectable::~ScPassHashProtectable()
@@ -79,7 +110,8 @@ ScPassHashProtectable::~ScPassHashProtectable()
 class ScTableProtectionImpl
 {
 public:
-    static ::com::sun::star::uno::Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_OOO);
+    static Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_SHA1);
+    static Sequence<sal_Int8> hashPassword(const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash = PASSHASH_SHA1);
 
     explicit ScTableProtectionImpl(SCSIZE nOptSize);
     explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
@@ -89,10 +121,13 @@ public:
     void setProtected(bool bProtected);
 
     bool isPasswordEmpty() const;
-    bool hasPasswordHash(ScPasswordHash eHash) const;
+    bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
     void setPassword(const String& aPassText);
-    ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const;
-    void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO);
+    ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
+        ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
+    void setPasswordHash(
+        const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
+        ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
     bool verifyPassword(const String& aPassText) const;
 
     bool isOptionEnabled(SCSIZE nOptId) const;
@@ -104,7 +139,8 @@ private:
     ::std::vector<bool> maOptions;
     bool mbEmptyPass;
     bool mbProtected;
-    ScPasswordHash meHash;
+    ScPasswordHash meHash1;
+    ScPasswordHash meHash2;
 };
 
 Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, ScPasswordHash eHash)
@@ -115,19 +151,44 @@ Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText,
         case PASSHASH_XL:
             aHash = ::comphelper::DocPasswordHelper::GetXLHashAsSequence( aPassText, RTL_TEXTENCODING_UTF8 );
         break;
-        case PASSHASH_OOO:
-        default:
+        case PASSHASH_SHA1:
             SvPasswordHelper::GetHashPassword(aHash, aPassText);
         break;
+        default:
+            ;
     }
     return aHash;
 }
 
+Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(
+    const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash)
+{
+    if (!rPassHash.getLength() || eHash == PASSHASH_UNSPECIFIED)
+        return rPassHash;
+
+    // TODO: Right now, we only support double-hash by SHA1.
+    if (eHash == PASSHASH_SHA1)
+    {
+        vector<sal_Char> aChars;
+        sal_Int32 n = rPassHash.getLength();
+        aChars.reserve(n);
+        for (sal_Int32 i = 0; i < n; ++i)
+            aChars.push_back(static_cast<sal_Char>(rPassHash[i]));
+
+        Sequence<sal_Int8> aNewHash;
+        SvPasswordHelper::GetHashPassword(aNewHash, &aChars[0], aChars.size());
+        return aNewHash;
+    }
+
+    return rPassHash;
+}
+
 ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
     maOptions(nOptSize),
     mbEmptyPass(true),
     mbProtected(false),
-    meHash(PASSHASH_OOO)
+    meHash1(PASSHASH_SHA1),
+    meHash2(PASSHASH_UNSPECIFIED)
 {
 }
 
@@ -137,7 +198,8 @@ ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
     maOptions(r.maOptions),
     mbEmptyPass(r.mbEmptyPass),
     mbProtected(r.mbProtected),
-    meHash(r.meHash)
+    meHash1(r.meHash1),
+    meHash2(r.meHash2)
 {
 }
 
@@ -181,7 +243,7 @@ bool ScTableProtectionImpl::isPasswordEmpty() const
     return mbEmptyPass;
 }
 
-bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash) const
+bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
     if (mbEmptyPass)
         return true;
@@ -189,35 +251,65 @@ bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash) const
     if (maPassText.Len())
         return true;
 
-    if (meHash == eHash)
-        return true;
+    if (meHash1 == eHash)
+    {
+        if (meHash2 == PASSHASH_UNSPECIFIED)
+            // single hash.
+            return true;
+
+        return meHash2 == eHash2;
+    }
 
     return false;
 }
 
-Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(ScPasswordHash eHash) const
+Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(
+    ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
+    Sequence<sal_Int8> aPassHash;
+
     if (mbEmptyPass)
         // Flaged as empty.
-        return Sequence<sal_Int8>();
+        return aPassHash;
 
     if (maPassText.Len())
+    {
         // Cleartext password exists.  Hash it.
-        return hashPassword(maPassText, eHash);
+        aPassHash = hashPassword(maPassText, eHash);
+        if (eHash2 != PASSHASH_UNSPECIFIED)
+            // Double-hash it.
+            aPassHash = hashPassword(aPassHash, eHash2);
 
-    if (meHash == eHash)
-        // Stored hash exists.
-        return maPassHash;
+        return aPassHash;
+    }
+    else
+    {
+        // No clear text password.  Check if we have a hash value of the right hash type.
+        if (meHash1 == eHash)
+        {
+            aPassHash = maPassHash;
+
+            if (meHash2 == eHash2)
+                // Matching double-hash requested.
+                return aPassHash;
+            else if (meHash2 == PASSHASH_UNSPECIFIED)
+                // primary hashing type match.  Double hash it by the requested
+                // double-hash type.
+                return hashPassword(aPassHash, eHash2);
+        }
+    }
 
-    // Failed to find a matching hash.
+    // failed.
     return Sequence<sal_Int8>();
 }
 
-void ScTableProtectionImpl::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
+void ScTableProtectionImpl::setPasswordHash(
+    const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
 {
     sal_Int32 nLen = aPassword.getLength();
     mbEmptyPass = nLen <= 0 ? true : false;
-    meHash = eHash;
+    meHash1 = eHash;
+    meHash2 = eHash2;
     maPassHash = aPassword;
 
 #if DEBUG_TAB_PROTECTION
@@ -241,7 +333,8 @@ bool ScTableProtectionImpl::verifyPassword(const String& aPassText) const
         // Clear text password exists, and this one takes precedence.
         return aPassText.Equals(maPassText);
 
-    Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash);
+    Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash1);
+    aHash = hashPassword(aHash, meHash2);
 
 #if DEBUG_TAB_PROTECTION    
     fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = ");
@@ -317,9 +410,9 @@ bool ScDocProtection::isPasswordEmpty() const
     return mpImpl->isPasswordEmpty();
 }
 
-bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash) const
+bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
-    return mpImpl->hasPasswordHash(eHash);
+    return mpImpl->hasPasswordHash(eHash, eHash2);
 }
 
 void ScDocProtection::setPassword(const String& aPassText)
@@ -327,14 +420,15 @@ void ScDocProtection::setPassword(const String& aPassText)
     mpImpl->setPassword(aPassText);
 }
 
-uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash) const
+uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
-    return mpImpl->getPasswordHash(eHash);
+    return mpImpl->getPasswordHash(eHash, eHash2);
 }
 
-void ScDocProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
+void ScDocProtection::setPasswordHash(
+    const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
 {
-    mpImpl->setPasswordHash(aPassword, eHash);
+    mpImpl->setPasswordHash(aPassword, eHash, eHash2);
 }
 
 bool ScDocProtection::verifyPassword(const String& aPassText) const
@@ -392,9 +486,9 @@ bool ScTableProtection::isPasswordEmpty() const
     return mpImpl->isPasswordEmpty();
 }
 
-bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash) const
+bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
-    return mpImpl->hasPasswordHash(eHash);
+    return mpImpl->hasPasswordHash(eHash, eHash2);
 }
 
 void ScTableProtection::setPassword(const String& aPassText)
@@ -402,14 +496,15 @@ void ScTableProtection::setPassword(const String& aPassText)
     mpImpl->setPassword(aPassText);
 }
 
-Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash) const
+Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
 {
-    return mpImpl->getPasswordHash(eHash);
+    return mpImpl->getPasswordHash(eHash, eHash2);
 }
 
-void ScTableProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash)
+void ScTableProtection::setPasswordHash(
+    const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
 {
-    mpImpl->setPasswordHash(aPassword, eHash);
+    mpImpl->setPasswordHash(aPassword, eHash, eHash2);
 }
 
 bool ScTableProtection::verifyPassword(const String& aPassText) const
diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx
index 29775de..f0165aa 100644
--- a/sc/source/filter/xml/xmlbodyi.cxx
+++ b/sc/source/filter/xml/xmlbodyi.cxx
@@ -77,6 +77,8 @@ ScXMLBodyContext::ScXMLBodyContext( ScXMLImport& rImport,
                                               const uno::Reference<xml::sax::XAttributeList>& xAttrList ) :
     SvXMLImportContext( rImport, nPrfx, rLName ),
     sPassword(),
+    meHash1(PASSHASH_SHA1),
+    meHash2(PASSHASH_UNSPECIFIED),
     bProtected(sal_False),
     bHadCalculationSettings(sal_False),
     pChangeTrackingImportHelper(NULL)
@@ -122,6 +124,10 @@ ScXMLBodyContext::ScXMLBodyContext( ScXMLImport& rImport,
                 bProtected = IsXMLToken(sValue, XML_TRUE);
             else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY))
                 sPassword = sValue;
+            else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY_DIGEST_ALGORITHM))
+                meHash1 = ScPassHashHelper::getHashTypeFromURI(sValue);
+            else if (IsXMLToken(aLocalName, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2))
+                meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
         }
     }
 }
@@ -327,7 +333,7 @@ void ScXMLBodyContext::EndElement()
             if (sPassword.getLength())
             {
                 SvXMLUnitConverter::decodeBase64(aPass, sPassword);
-                pProtection->setPasswordHash(aPass, PASSHASH_OOO);
+                pProtection->setPasswordHash(aPass, meHash1, meHash2);
             }
 
             pDoc->SetDocProtection(pProtection.get());
diff --git a/sc/source/filter/xml/xmlbodyi.hxx b/sc/source/filter/xml/xmlbodyi.hxx
index e279431..fa3c29b 100644
--- a/sc/source/filter/xml/xmlbodyi.hxx
+++ b/sc/source/filter/xml/xmlbodyi.hxx
@@ -31,12 +31,16 @@
 #include <xmloff/xmlictxt.hxx>
 #include <xmloff/xmlimp.hxx>
 
+#include "tabprotection.hxx"
+
 class ScXMLImport;
 class ScXMLChangeTrackingImportHelper;
 
 class ScXMLBodyContext : public SvXMLImportContext
 {
     rtl::OUString	sPassword;
+    ScPasswordHash  meHash1;
+    ScPasswordHash  meHash2;
     sal_Bool		bProtected;
     sal_Bool        bHadCalculationSettings;
 
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 91f5ff4..d46080d 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -1520,12 +1520,36 @@ void ScXMLExport::SetBodyAttributes()
         AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE);
         rtl::OUStringBuffer aBuffer;
         uno::Sequence<sal_Int8> aPassHash;
+        ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
         const ScDocProtection* p = pDoc->GetDocProtection();
         if (p)
-            aPassHash = p->getPasswordHash(PASSHASH_OOO);
+        {
+            if (p->hasPasswordHash(PASSHASH_SHA1))
+            {
+                aPassHash = p->getPasswordHash(PASSHASH_SHA1);
+                eHashUsed = PASSHASH_SHA1;
+            }
+            else if (p->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
+            {
+                aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
+                eHashUsed = PASSHASH_XL;
+            }
+        }
         SvXMLUnitConverter::encodeBase64(aBuffer, aPassHash);
         if (aBuffer.getLength())
+        {
             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+            if (eHashUsed == PASSHASH_XL)
+            {
+                AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+                             ScPassHashHelper::getHashURI(PASSHASH_XL));
+                AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
+                             ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+            }
+            else if (eHashUsed == PASSHASH_SHA1)
+                AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+                             ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+        }
     }
 }
 
@@ -1725,18 +1749,46 @@ void ScXMLExport::_ExportContent()
                         AddAttribute(sAttrStyleName, aTableStyles[nTable]);
 
                         uno::Reference<util::XProtectable> xProtectable (xTable, uno::UNO_QUERY);
+                    ScTableProtection* pProtect = NULL;
                         if (xProtectable.is() && xProtectable->isProtected())
                         {
                             AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE);
-                            rtl::OUStringBuffer aBuffer;
                             if (pDoc)
                             {
-                                ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
+                            pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable));
                                 if (pProtect)
-                                    SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO));
+                            {
+                                rtl::OUStringBuffer aBuffer;
+                                ScPasswordHash eHashUsed = PASSHASH_UNSPECIFIED;
+                                if (pProtect->hasPasswordHash(PASSHASH_SHA1))
+                                {
+                                    SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_SHA1));
+                                    eHashUsed = PASSHASH_SHA1;
+                                }
+                                else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
+                                {
+                                    // Double-hash this by SHA1 on top of the legacy xls hash.
+                                    uno::Sequence<sal_Int8> aHash = pProtect->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
+                                    SvXMLUnitConverter::encodeBase64(aBuffer, aHash);
+                                    eHashUsed = PASSHASH_XL;
+                                }
+                                if (aBuffer.getLength())
+                                {
+                                    AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
+                                    if (eHashUsed == PASSHASH_XL)
+                                    {
+                                        AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+                                                     ScPassHashHelper::getHashURI(PASSHASH_XL));
+                                        AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2,
+                                                     ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+                                    }
+                                    else if (eHashUsed == PASSHASH_SHA1)
+                                        AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+                                                     ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+
+                                }
+                            }
                             }
-                            if (aBuffer.getLength())
-                                AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear());
                         }
                         rtl::OUString sPrintRanges;
                         table::CellRangeAddress aColumnHeaderRange;
@@ -1747,6 +1799,20 @@ void ScXMLExport::_ExportContent()
                         else if (!pDoc->IsPrintEntireSheet(static_cast<SCTAB>(nTable)))
                             AddAttribute( XML_NAMESPACE_TABLE, XML_PRINT, XML_FALSE);
                         SvXMLElementExport aElemT(*this, sElemTab, sal_True, sal_True);
+
+                    if (pProtect && pProtect->isProtected())
+                    {
+                        if (pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS))
+                            AddAttribute(XML_NAMESPACE_TABLE, XML_SELECT_PROTECTED_CELLS, XML_TRUE);
+                        if (pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS))
+                            AddAttribute(XML_NAMESPACE_TABLE, XML_SELECT_UNPROTECTED_CELLS, XML_TRUE);
+
+                        rtl::OUString aElemName = GetNamespaceMap().GetQNameByKey(
+                            XML_NAMESPACE_TABLE, GetXMLToken(XML_TABLE_PROTECTION));
+
+                        SvXMLElementExport aElemProtected(*this, aElemName, true, true);
+                    }
+
                         CheckAttrList();
 
                         if ( pDoc && pDoc->GetSheetEvents( static_cast<SCTAB>(nTable) ) &&
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index 511c321..16bdcad 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -637,6 +637,7 @@ const SvXMLTokenMap& ScXMLImport::GetTableElemTokenMap()
             { XML_NAMESPACE_TABLE,	XML_TABLE_HEADER_COLUMNS,		XML_TOK_TABLE_HEADER_COLS	},
             { XML_NAMESPACE_TABLE,	XML_TABLE_COLUMNS,				XML_TOK_TABLE_COLS			},
             { XML_NAMESPACE_TABLE,	XML_TABLE_COLUMN,				XML_TOK_TABLE_COL			},
+            { XML_NAMESPACE_TABLE,  XML_TABLE_PROTECTION,           XML_TOK_TABLE_PROTECTION    },
             { XML_NAMESPACE_TABLE,	XML_TABLE_ROW_GROUP,			XML_TOK_TABLE_ROW_GROUP		},
             { XML_NAMESPACE_TABLE,	XML_TABLE_HEADER_ROWS,			XML_TOK_TABLE_HEADER_ROWS	},
             { XML_NAMESPACE_TABLE,	XML_TABLE_ROWS, 				XML_TOK_TABLE_ROWS			},
@@ -656,6 +657,22 @@ const SvXMLTokenMap& ScXMLImport::GetTableElemTokenMap()
     return *pTableElemTokenMap;
 }
 
+const SvXMLTokenMap& ScXMLImport::GetTableProtectionAttrTokenMap()
+{
+    if (!pTableProtectionElemTokenMap)
+    {
+        static __FAR_DATA SvXMLTokenMapEntry aTableProtectionTokenMap[] =
+        {
+            { XML_NAMESPACE_TABLE, XML_SELECT_PROTECTED_CELLS,      XML_TOK_TABLE_SELECT_PROTECTED_CELLS    },
+            { XML_NAMESPACE_TABLE, XML_SELECT_UNPROTECTED_CELLS,    XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS  },
+            XML_TOKEN_MAP_END
+        };
+        pTableProtectionElemTokenMap = new SvXMLTokenMap(aTableProtectionTokenMap);
+    }
+
+    return *pTableProtectionElemTokenMap;
+}
+
 const SvXMLTokenMap& ScXMLImport::GetTableRowsElemTokenMap()
 {
     if( !pTableRowsElemTokenMap )
@@ -702,9 +719,11 @@ const SvXMLTokenMap& ScXMLImport::GetTableAttrTokenMap()
         {
             { XML_NAMESPACE_TABLE,     XML_NAME,           XML_TOK_TABLE_NAME          },
             { XML_NAMESPACE_TABLE,     XML_STYLE_NAME,     XML_TOK_TABLE_STYLE_NAME    },
-            { XML_NAMESPACE_TABLE,     XML_PROTECTED,      XML_TOK_TABLE_PROTECTION    },
+            { XML_NAMESPACE_TABLE, XML_PROTECTED,                   XML_TOK_TABLE_PROTECTED         },
             { XML_NAMESPACE_TABLE,     XML_PRINT_RANGES,   XML_TOK_TABLE_PRINT_RANGES  },
             { XML_NAMESPACE_TABLE,     XML_PROTECTION_KEY, XML_TOK_TABLE_PASSWORD      },
+            { XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM, XML_TOK_TABLE_PASSHASH      },
+            { XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2, XML_TOK_TABLE_PASSHASH_2  },
             { XML_NAMESPACE_TABLE,     XML_PRINT,          XML_TOK_TABLE_PRINT         },
             XML_TOKEN_MAP_END
         };
@@ -1664,6 +1683,7 @@ ScXMLImport::ScXMLImport(
     pLabelRangesElemTokenMap( 0 ),
     pLabelRangeAttrTokenMap( 0 ),
     pTableElemTokenMap( 0 ),
+    pTableProtectionElemTokenMap(NULL),
     pTableRowsElemTokenMap( 0 ),
     pTableColsElemTokenMap( 0 ),
     pTableScenarioAttrTokenMap( 0 ),
@@ -1788,6 +1808,7 @@ ScXMLImport::~ScXMLImport() throw()
     delete pLabelRangesElemTokenMap;
     delete pLabelRangeAttrTokenMap;
     delete pTableElemTokenMap;
+    delete pTableProtectionElemTokenMap;
     delete pTableRowsElemTokenMap;
     delete pTableColsElemTokenMap;
     delete pTableAttrTokenMap;
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index 4831d32..7ef0e65 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -169,6 +169,7 @@ enum ScXMLTableTokens
     XML_TOK_TABLE_COL,
     XML_TOK_TABLE_ROW_GROUP,
     XML_TOK_TABLE_HEADER_ROWS,
+    XML_TOK_TABLE_PROTECTION,
     XML_TOK_TABLE_ROWS,
     XML_TOK_TABLE_ROW,
     XML_TOK_TABLE_SOURCE,
@@ -179,6 +180,12 @@ enum ScXMLTableTokens
     XML_TOK_TABLE_EVENT_LISTENERS_EXT
 };
 
+enum ScXMLTokenProtectionTokens
+{
+    XML_TOK_TABLE_SELECT_PROTECTED_CELLS,
+    XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS
+};
+
 enum ScXMLTableRowsTokens
 {
     XML_TOK_TABLE_ROWS_ROW_GROUP,
@@ -199,9 +206,11 @@ enum ScXMLTableAttrTokens
 {
     XML_TOK_TABLE_NAME,
     XML_TOK_TABLE_STYLE_NAME,
-    XML_TOK_TABLE_PROTECTION,
+    XML_TOK_TABLE_PROTECTED,
     XML_TOK_TABLE_PRINT_RANGES,
     XML_TOK_TABLE_PASSWORD,
+    XML_TOK_TABLE_PASSHASH,
+    XML_TOK_TABLE_PASSHASH_2,
     XML_TOK_TABLE_PRINT
 };
 
@@ -699,6 +708,7 @@ class ScXMLImport: public SvXMLImport
     SvXMLTokenMap			*pLabelRangesElemTokenMap;
     SvXMLTokenMap			*pLabelRangeAttrTokenMap;
     SvXMLTokenMap			*pTableElemTokenMap;
+    SvXMLTokenMap           *pTableProtectionElemTokenMap;
     SvXMLTokenMap			*pTableRowsElemTokenMap;
     SvXMLTokenMap			*pTableColsElemTokenMap;
     SvXMLTokenMap			*pTableScenarioAttrTokenMap;
@@ -863,6 +873,7 @@ public:
     const SvXMLTokenMap& GetLabelRangesElemTokenMap();
     const SvXMLTokenMap& GetLabelRangeAttrTokenMap();
     const SvXMLTokenMap& GetTableElemTokenMap();
+    const SvXMLTokenMap& GetTableProtectionAttrTokenMap();
     const SvXMLTokenMap& GetTableRowsElemTokenMap();
     const SvXMLTokenMap& GetTableColsElemTokenMap();
     const SvXMLTokenMap& GetTableAttrTokenMap();
diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx
index bde6633..6eb7861 100644
--- a/sc/source/filter/xml/xmlsubti.cxx
+++ b/sc/source/filter/xml/xmlsubti.cxx
@@ -148,6 +148,15 @@ void ScMyTableData::SetChangedCols(const sal_Int32 nValue)
 
 /*******************************************************************************************************************************/
 
+ScXMLTabProtectionData::ScXMLTabProtectionData() :
+    meHash1(PASSHASH_SHA1),
+    meHash2(PASSHASH_UNSPECIFIED),
+    mbProtected(false),
+    mbSelectProtectedCells(true),
+    mbSelectUnprotectedCells(true)
+{
+}
+
 ScMyTables::ScMyTables(ScXMLImport& rTempImport)
     : rImport(rTempImport),
     aResizeShapes(rTempImport),
@@ -173,7 +182,7 @@ ScMyTables::~ScMyTables()
 }
 
 void ScMyTables::NewSheet(const rtl::OUString& sTableName, const rtl::OUString& sStyleName,
-                        const sal_Bool bTempProtection, const rtl::OUString& sTempPassword)
+                          const ScXMLTabProtectionData& rProtectData)
 {
     if (rImport.GetModel().is())
     {
@@ -189,8 +198,7 @@ void ScMyTables::NewSheet(const rtl::OUString& sTableName, const rtl::OUString&
         }
         ++nCurrentSheet;
 
-        bProtection = bTempProtection;
-        sPassword = sTempPassword;
+        maProtectionData = rProtectData;
         uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( rImport.GetModel(), uno::UNO_QUERY );
         if ( xSpreadDoc.is() )
         {
@@ -654,13 +662,16 @@ void ScMyTables::DeleteTable()
         aMatrixRangeList.clear();
     }
 
-    if (rImport.GetDocument() && bProtection)
+    if (rImport.GetDocument() && maProtectionData.mbProtected)
     {
-        uno::Sequence<sal_Int8> aPass;
-        SvXMLUnitConverter::decodeBase64(aPass, sPassword);
+        uno::Sequence<sal_Int8> aHash;
+        SvXMLUnitConverter::decodeBase64(aHash, maProtectionData.maPassword);
+
         auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
-        pProtect->setProtected(bProtection);
-        pProtect->setPasswordHash(aPass, PASSHASH_OOO);
+        pProtect->setProtected(maProtectionData.mbProtected);
+        pProtect->setPasswordHash(aHash, maProtectionData.meHash1, maProtectionData.meHash2);
+        pProtect->setOption(ScTableProtection::SELECT_LOCKED_CELLS,   maProtectionData.mbSelectProtectedCells);
+        pProtect->setOption(ScTableProtection::SELECT_UNLOCKED_CELLS, maProtectionData.mbSelectUnprotectedCells);
         rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), pProtect.get());
     }
 
diff --git a/sc/source/filter/xml/xmlsubti.hxx b/sc/source/filter/xml/xmlsubti.hxx
index 3abb885..19623ef 100644
--- a/sc/source/filter/xml/xmlsubti.hxx
+++ b/sc/source/filter/xml/xmlsubti.hxx
@@ -40,6 +40,7 @@
 #include <list>
 #include "XMLTableShapeResizer.hxx"
 #include "formula/grammar.hxx"
+#include "tabprotection.hxx"
 
 class ScXMLImport;
 
@@ -106,6 +107,18 @@ struct ScMatrixRange
     }
 };
 
+struct ScXMLTabProtectionData
+{
+    ::rtl::OUString maPassword;
+    ScPasswordHash  meHash1;
+    ScPasswordHash  meHash2;
+    bool            mbProtected;
+    bool            mbSelectProtectedCells;
+    bool            mbSelectUnprotectedCells;
+
+    ScXMLTabProtectionData();
+};
+
 class ScMyTables
 {
 private:
@@ -120,8 +133,8 @@ private:
     ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > xDrawPage;
     ::com::sun::star::uno::Reference < ::com::sun::star::drawing::XShapes > xShapes;
     rtl::OUString						sCurrentSheetName;
-    rtl::OUString						sPassword;
     std::vector<ScMyTableData*>			aTableVec;
+    ScXMLTabProtectionData              maProtectionData;
     ScMyMatrixRangeList                 aMatrixRangeList;
     com::sun::star::table::CellAddress	aRealCellPos;
     sal_Int32							nCurrentColStylePos;
@@ -129,7 +142,6 @@ private:
     sal_Int16							nCurrentXShapes;
     sal_Int32							nTableCount;
     sal_Int32							nCurrentSheet;
-    sal_Bool							bProtection;
 
     sal_Bool 							IsMerged (const com::sun::star::uno::Reference <com::sun::star::table::XCellRange>& xCellRange,
                                                 const sal_Int32 nCol, const sal_Int32 nRow,
@@ -144,7 +156,7 @@ public:
                                         ScMyTables(ScXMLImport& rImport);
                                         ~ScMyTables();
     void   								NewSheet(const rtl::OUString& sTableName, const rtl::OUString& sStyleName,
-                                                const sal_Bool bProtection, const rtl::OUString& sPassword);
+                                                 const ScXMLTabProtectionData& rProtectData);
     void								AddRow();
     void								SetRowStyle(const rtl::OUString& rCellStyleName);
     void								AddColumn(sal_Bool bIsCovered);
@@ -155,6 +167,7 @@ public:
     com::sun::star::table::CellAddress	GetRealCellPos();
     void								AddColCount(sal_Int32 nTempColCount);
     void								AddColStyle(const sal_Int32 nRepeat, const rtl::OUString& rCellStyleName);
+    ScXMLTabProtectionData&             GetCurrentProtectionData() { return maProtectionData; }
     rtl::OUString						GetCurrentSheetName() const { return sCurrentSheetName; }
     sal_Int32							GetCurrentSheet() const { return nCurrentSheet; }
     sal_Int32							GetCurrentColumn() const { return aTableVec[nTableCount - 1]->GetColCount(); }
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
index aa3f343..430a303 100644
--- a/sc/source/filter/xml/xmltabi.cxx
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -63,6 +63,9 @@
 
 using namespace com::sun::star;
 using namespace xmloff::token;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::xml::sax::XAttributeList;
+using ::rtl::OUString;
 
 /** 
  * Determine whether this table is an external reference cache from its 
@@ -161,10 +164,9 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
 
     if (!bTempIsSubTable)
     {
-        sal_Bool bProtection(sal_False);
+        ScXMLTabProtectionData aProtectData;
         rtl::OUString sName;
         rtl::OUString sStyleName;
-        rtl::OUString sPassword;
         sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
         const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableAttrTokenMap();
         for( sal_Int16 i=0; i < nAttrCount; ++i )
@@ -183,15 +185,21 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
                 case XML_TOK_TABLE_STYLE_NAME:
                         sStyleName = sValue;
                     break;
-                case XML_TOK_TABLE_PROTECTION:
-                        bProtection = IsXMLToken(sValue, XML_TRUE);
-                    break;
+                case XML_TOK_TABLE_PROTECTED:
+                    aProtectData.mbProtected = IsXMLToken(sValue, XML_TRUE);
+                break;
                 case XML_TOK_TABLE_PRINT_RANGES:
                         sPrintRanges = sValue;
                     break;
                 case XML_TOK_TABLE_PASSWORD:
-                        sPassword = sValue;
-                    break;
+                    aProtectData.maPassword = sValue;
+                break;
+                case XML_TOK_TABLE_PASSHASH:
+                    aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI(sValue);
+                break;
+                case XML_TOK_TABLE_PASSHASH_2:
+                    aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI(sValue);
+                break;
                 case XML_TOK_TABLE_PRINT:
                     {
                         if (IsXMLToken(sValue, XML_FALSE))
@@ -219,7 +227,7 @@ ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
         else
         {
             // This is a regular table.
-            GetScImport().GetTables().NewSheet(sName, sStyleName, bProtection, sPassword);
+            GetScImport().GetTables().NewSheet(sName, sStyleName, aProtectData);
         }
     }
     else
@@ -287,6 +295,9 @@ SvXMLImportContext *ScXMLTableContext::CreateChildContext( USHORT nPrefix,
             pContext = new ScXMLTableColContext( GetScImport(), nPrefix,
                                                       rLName, xAttrList );
         break;
+    case XML_TOK_TABLE_PROTECTION:
+        pContext = new ScXMLTableProtectionContext( GetScImport(), nPrefix, rLName, xAttrList );
+        break;
     case XML_TOK_TABLE_ROW_GROUP:
         pContext = new ScXMLTableRowsContext( GetScImport(), nPrefix,
                                                    rLName, xAttrList,
@@ -420,3 +431,61 @@ void ScXMLTableContext::EndElement()
     GetScImport().UnlockSolarMutex();
 }
 
+// ============================================================================
+
+ScXMLImport& ScXMLTableProtectionContext::GetScImport()
+{
+    return static_cast<ScXMLImport&>(GetImport());
+}
+
+ScXMLTableProtectionContext::ScXMLTableProtectionContext(
+    ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+    const Reference<XAttributeList>& xAttrList ) :
+    SvXMLImportContext( rImport, nPrefix, rLName )
+{
+    const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetTableProtectionAttrTokenMap();
+    bool bSelectProtectedCells = false;
+    bool bSelectUnprotectedCells = false;
+
+    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+
+    for (sal_Int16 i = 0; i < nAttrCount; ++i)
+    {
+        const OUString& aAttrName = xAttrList->getNameByIndex(i);
+        const OUString aValue = xAttrList->getValueByIndex(i);
+
+        OUString aLocalName;
+        USHORT nLocalPrefix = GetScImport().GetNamespaceMap().GetKeyByAttrName(
+            aAttrName, &aLocalName);
+
+        switch (rAttrTokenMap.Get(nLocalPrefix, aLocalName))
+        {
+            case XML_TOK_TABLE_SELECT_PROTECTED_CELLS:
+                bSelectProtectedCells = IsXMLToken(aValue, XML_TRUE);
+            break;
+            case XML_TOK_TABLE_SELECT_UNPROTECTED_CELLS:
+                bSelectUnprotectedCells = IsXMLToken(aValue, XML_TRUE);
+            break;
+            default:
+                ;
+        }
+    }
+
+    ScXMLTabProtectionData& rProtectData = GetScImport().GetTables().GetCurrentProtectionData();
+    rProtectData.mbSelectProtectedCells   = bSelectProtectedCells;
+    rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
+}
+
+ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
+{
+}
+
+SvXMLImportContext* ScXMLTableProtectionContext::CreateChildContext(
+    USHORT /*nPrefix*/, const OUString& /*rLocalName*/, const Reference<XAttributeList>& /*xAttrList*/ )
+{
+    return NULL;
+}
+
+void ScXMLTableProtectionContext::EndElement()
+{
+}
diff --git a/sc/source/filter/xml/xmltabi.hxx b/sc/source/filter/xml/xmltabi.hxx
index 8dd3b3e..411ce7c 100644
--- a/sc/source/filter/xml/xmltabi.hxx
+++ b/sc/source/filter/xml/xmltabi.hxx
@@ -75,4 +75,26 @@ public:
     virtual void EndElement();
 };
 
+// ============================================================================
+
+class ScXMLTableProtectionContext : public SvXMLImportContext
+{
+    ScXMLImport& GetScImport();
+
+public:
+    ScXMLTableProtectionContext( ScXMLImport& rImport, USHORT nPrefix,
+                        const ::rtl::OUString& rLName,
+                        const ::com::sun::star::uno::Reference<
+                                 ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+    virtual ~ScXMLTableProtectionContext();
+
+    virtual SvXMLImportContext *CreateChildContext( USHORT nPrefix,
+                                     const ::rtl::OUString& rLocalName,
+                                     const ::com::sun::star::uno::Reference<
+                                        ::com::sun::star::xml::sax::XAttributeList>& xAttrList );
+
+    virtual void EndElement();
+};
+
 #endif
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 6247f17..ee7c15d 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -1549,9 +1549,14 @@ BOOL __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium )
 
 #if ENABLE_SHEET_PROTECTION
     ScTabViewShell* pViewShell = GetBestViewShell();
-    if (pViewShell && ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_OOO))
+    bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA1);
+    if (bNeedsRehash)
+        // legacy xls hash double-hashed by SHA1 is also supported.
+        bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
+
+    if (pViewShell && bNeedsRehash)
     {
-        if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_OOO))
+        if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1))
             // password re-type cancelled.  Don't save the document.
             return false;
     }
diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx
index 02a7c01..0f237de 100644
--- a/sc/source/ui/miscdlgs/retypepassdlg.cxx
+++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx
@@ -77,7 +77,7 @@ ScRetypePassDlg::ScRetypePassDlg(Window* pParent) :
 
     mpDocItem(static_cast<ScDocProtection*>(NULL)),
     mnCurScrollPos(0),
-    meDesiredHash(PASSHASH_OOO)
+    meDesiredHash(PASSHASH_SHA1)
 {
     Init();
 }


More information about the ooo-build-commit mailing list