summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/svl/PasswordHelper.hxx7
-rw-r--r--sc/CppunitTest_sc_subsequent_export_test.mk2
-rw-r--r--sc/inc/tabprotection.hxx2
-rw-r--r--sc/qa/unit/data/fods/protection-key1.fods20
-rw-r--r--sc/qa/unit/data/fods/protection-key2.fods20
-rw-r--r--sc/qa/unit/data/fods/protection-key3.fods20
-rw-r--r--sc/qa/unit/data/fods/protection-key4.fods20
-rw-r--r--sc/qa/unit/data/fods/protection-key5.fods20
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx118
-rw-r--r--sc/source/core/data/tabprotection.cxx27
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx25
-rw-r--r--sc/source/ui/docshell/docsh.cxx4
-rw-r--r--svl/source/misc/PasswordHelper.cxx52
-rw-r--r--sw/CppunitTest_sw_odfexport.mk1
-rw-r--r--sw/qa/extras/odfexport/data/protection-key.fodt48
-rw-r--r--sw/qa/extras/odfexport/odfexport.cxx32
-rw-r--r--xmloff/source/text/XMLSectionExport.cxx8
17 files changed, 416 insertions, 10 deletions
diff --git a/include/svl/PasswordHelper.hxx b/include/svl/PasswordHelper.hxx
index ca048ed85924..a71f2ca7c172 100644
--- a/include/svl/PasswordHelper.hxx
+++ b/include/svl/PasswordHelper.hxx
@@ -33,10 +33,15 @@ public:
SVL_DLLPUBLIC static void GetHashPassword(css::uno::Sequence <sal_Int8>& rPassHash, const sal_Char* pPass, sal_uInt32 nLen);
SVL_DLLPUBLIC static void GetHashPassword(css::uno::Sequence<sal_Int8>& rPassHash, const OUString& sPass);
+ SVL_DLLPUBLIC static void GetHashPasswordSHA1UTF8(css::uno::Sequence<sal_Int8>& rPassHash, const OUString& sPass);
+ SVL_DLLPUBLIC static void GetHashPasswordSHA256(css::uno::Sequence<sal_Int8>& rPassHash, const OUString& sPass);
/**
Use this method to compare a given string with another given Hash value.
This is necessary, because in older versions exists different hashes of the same string. They were endian dependent.
- We need this to handle old files. This method will compare against big and little endian. See #101326#
+ We need this to handle old files. This method will compare against big and
+ little endian UTF-16.
+ tdf#115483: also check 2 different new ways of hashing that were added in
+ ODF 1.2, requiring UTF-8 encoding.
*/
SVL_DLLPUBLIC static bool CompareHashPassword(const css::uno::Sequence<sal_Int8>& rOldPassHash, const OUString& sNewPass);
};
diff --git a/sc/CppunitTest_sc_subsequent_export_test.mk b/sc/CppunitTest_sc_subsequent_export_test.mk
index b97423e27f89..cf6125f6ef04 100644
--- a/sc/CppunitTest_sc_subsequent_export_test.mk
+++ b/sc/CppunitTest_sc_subsequent_export_test.mk
@@ -72,6 +72,8 @@ $(eval $(call gb_CppunitTest_use_components,sc_subsequent_export_test,\
embeddedobj/util/embobj \
eventattacher/source/evtatt \
filter/source/config/cache/filterconfig1 \
+ filter/source/odfflatxml/odfflatxml \
+ filter/source/xmlfilteradaptor/xmlfa \
forms/util/frm \
framework/util/fwk \
i18npool/source/search/i18nsearch \
diff --git a/sc/inc/tabprotection.hxx b/sc/inc/tabprotection.hxx
index 61e0d605e6a8..3f2fc7b4e189 100644
--- a/sc/inc/tabprotection.hxx
+++ b/sc/inc/tabprotection.hxx
@@ -33,6 +33,8 @@ class ScTableProtectionImpl;
enum ScPasswordHash
{
PASSHASH_SHA1 = 0,
+ PASSHASH_SHA1_UTF8, // tdf#115483 this is UTF8, previous one is wrong UTF16
+ PASSHASH_SHA256,
PASSHASH_XL,
PASSHASH_UNSPECIFIED
};
diff --git a/sc/qa/unit/data/fods/protection-key1.fods b/sc/qa/unit/data/fods/protection-key1.fods
new file mode 100644
index 000000000000..e15f1e459919
--- /dev/null
+++ b/sc/qa/unit/data/fods/protection-key1.fods
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:body>
+
+ <!-- UTF-16 LE, bad SHA1 -->
+ <office:spreadsheet table:structure-protected="true" table:protection-key="vbnhxyBKtPHCA1wB21zG1Oha8ZA=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
+ <table:tracked-changes/>
+ <table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
+
+ <table:table table:name="Sheet1" table:protected="true" table:protection-key="vbnhxyBKtPHCA1wB21zG1Oha8ZA=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
+ <loext:table-protection loext:select-protected-cells="true" loext:select-unprotected-cells="true"/>
+ <table:table-row>
+ <table:table-cell/>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document>
diff --git a/sc/qa/unit/data/fods/protection-key2.fods b/sc/qa/unit/data/fods/protection-key2.fods
new file mode 100644
index 000000000000..b719a195b202
--- /dev/null
+++ b/sc/qa/unit/data/fods/protection-key2.fods
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:body>
+
+ <!-- UTF-8, good SHA1 -->
+ <office:spreadsheet table:structure-protected="true" table:protection-key="nLHas0RIwepGDaH4c2hpyIUvIS8=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
+ <table:tracked-changes/>
+ <table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
+
+ <table:table table:name="Sheet1" table:protected="true" table:protection-key="nLHas0RIwepGDaH4c2hpyIUvIS8=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
+ <loext:table-protection loext:select-protected-cells="true" loext:select-unprotected-cells="true"/>
+ <table:table-row>
+ <table:table-cell/>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document>
diff --git a/sc/qa/unit/data/fods/protection-key3.fods b/sc/qa/unit/data/fods/protection-key3.fods
new file mode 100644
index 000000000000..31c149fee0f6
--- /dev/null
+++ b/sc/qa/unit/data/fods/protection-key3.fods
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:body>
+
+ <!-- UTF-8, SHA256, ODF 1.2 URI -->
+ <office:spreadsheet table:structure-protected="true" table:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha256">
+ <table:tracked-changes/>
+ <table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
+
+ <table:table table:name="Sheet1" table:protected="true" table:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" table:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha256">
+ <loext:table-protection loext:select-protected-cells="true" loext:select-unprotected-cells="true"/>
+ <table:table-row>
+ <table:table-cell/>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document>
diff --git a/sc/qa/unit/data/fods/protection-key4.fods b/sc/qa/unit/data/fods/protection-key4.fods
new file mode 100644
index 000000000000..667a9e9b2525
--- /dev/null
+++ b/sc/qa/unit/data/fods/protection-key4.fods
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:body>
+
+ <!-- UTF-8, SHA256, W3C URI -->
+ <office:spreadsheet table:structure-protected="true" table:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" table:protection-key-digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256">
+ <table:tracked-changes/>
+ <table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
+
+ <table:table table:name="Sheet1" table:protected="true" table:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" table:protection-key-digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256">
+ <loext:table-protection loext:select-protected-cells="true" loext:select-unprotected-cells="true"/>
+ <table:table-row>
+ <table:table-cell/>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document>
diff --git a/sc/qa/unit/data/fods/protection-key5.fods b/sc/qa/unit/data/fods/protection-key5.fods
new file mode 100644
index 000000000000..b5dfcc83dd92
--- /dev/null
+++ b/sc/qa/unit/data/fods/protection-key5.fods
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.spreadsheet">
+ <office:body>
+
+ <!-- Excel hash + SHA1 -->
+ <office:spreadsheet table:structure-protected="true" table:protection-key="OX3WkEe79fv1PE+FUmfOLdwVoqI=" table:protection-key-digest-algorithm="http://docs.oasis-open.org/office/ns/table/legacy-hash-excel" loext:protection-key-digest-algorithm-2="http://www.w3.org/2000/09/xmldsig#sha1">
+ <table:tracked-changes/>
+ <table:calculation-settings table:automatic-find-labels="false" table:use-regular-expressions="false" table:use-wildcards="true"/>
+
+ <table:table table:name="Sheet1" table:style-name="ta1" table:protected="true" table:protection-key="OX3WkEe79fv1PE+FUmfOLdwVoqI=" table:protection-key-digest-algorithm="http://docs.oasis-open.org/office/ns/table/legacy-hash-excel" loext:protection-key-digest-algorithm-2="http://www.w3.org/2000/09/xmldsig#sha1">
+ <loext:table-protection loext:select-protected-cells="true" loext:select-unprotected-cells="true"/>
+ <table:table-row>
+ <table:table-cell/>
+ </table:table-row>
+ </table:table>
+ <table:named-expressions/>
+ </office:spreadsheet>
+ </office:body>
+</office:document>
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 6865897d0318..2bf2cb8d8fd0 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -96,6 +96,11 @@ public:
void testConditionalFormatExportODS();
void testConditionalFormatExportXLSX();
void testTdf99856_dataValidationTest();
+ void testProtectionKeyODS_UTF16LErtlSHA1();
+ void testProtectionKeyODS_UTF8SHA1();
+ void testProtectionKeyODS_UTF8SHA256ODF12();
+ void testProtectionKeyODS_UTF8SHA256W3C();
+ void testProtectionKeyODS_XL_SHA1();
void testColorScaleExportODS();
void testColorScaleExportXLSX();
void testDataBarExportODS();
@@ -206,6 +211,11 @@ public:
CPPUNIT_TEST(testConditionalFormatExportODS);
CPPUNIT_TEST(testConditionalFormatExportXLSX);
CPPUNIT_TEST(testTdf99856_dataValidationTest);
+ CPPUNIT_TEST(testProtectionKeyODS_UTF16LErtlSHA1);
+ CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA1);
+ CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256ODF12);
+ CPPUNIT_TEST(testProtectionKeyODS_UTF8SHA256W3C);
+ CPPUNIT_TEST(testProtectionKeyODS_XL_SHA1);
CPPUNIT_TEST(testColorScaleExportODS);
CPPUNIT_TEST(testColorScaleExportXLSX);
CPPUNIT_TEST(testDataBarExportODS);
@@ -328,7 +338,8 @@ void ScExportTest::registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx)
{ BAD_CAST("xdr"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing") },
{ BAD_CAST("x"), BAD_CAST("http://schemas.openxmlformats.org/spreadsheetml/2006/main") },
{ BAD_CAST("r"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/relationships") },
- { BAD_CAST("number"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") }
+ { BAD_CAST("number"), BAD_CAST("urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0") },
+ { BAD_CAST("loext"), BAD_CAST("urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0") },
};
for(size_t i = 0; i < SAL_N_ELEMENTS(aNamespaces); ++i)
{
@@ -495,6 +506,111 @@ void ScExportTest::testTdf99856_dataValidationTest()
xDocSh->DoClose();
}
+void ScExportTest::testProtectionKeyODS_UTF16LErtlSHA1()
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ ScDocShellRef xShell = loadDoc("protection-key1.", FORMAT_FODS);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell.is());
+
+ ScDocument& rDoc = xShell->GetDocument();
+ ScDocProtection *const pDocProt(rDoc.GetDocProtection());
+ CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
+ ScTableProtection *const pTabProt(rDoc.GetTabProtection(0));
+ CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_ODS);
+ xmlDocPtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
+ assertXPath(pXmlDoc, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
+ assertXPath(pXmlDoc, "//table:table[@table:protected='true' and @table:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
+}
+
+void ScExportTest::testProtectionKeyODS_UTF8SHA1()
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ ScDocShellRef xShell = loadDoc("protection-key2.", FORMAT_FODS);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell.is());
+
+ ScDocument& rDoc = xShell->GetDocument();
+ ScDocProtection *const pDocProt(rDoc.GetDocProtection());
+ CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
+ ScTableProtection *const pTabProt(rDoc.GetTabProtection(0));
+ CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_ODS);
+ xmlDocPtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
+ assertXPath(pXmlDoc, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
+ assertXPath(pXmlDoc, "//table:table[@table:protected='true' and @table:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha1']");
+}
+
+void ScExportTest::testProtectionKeyODS_UTF8SHA256ODF12()
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ ScDocShellRef xShell = loadDoc("protection-key3.", FORMAT_FODS);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell.is());
+
+ ScDocument& rDoc = xShell->GetDocument();
+ ScDocProtection *const pDocProt(rDoc.GetDocProtection());
+ CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
+ ScTableProtection *const pTabProt(rDoc.GetTabProtection(0));
+ CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_ODS);
+ xmlDocPtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
+ assertXPath(pXmlDoc, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
+ assertXPath(pXmlDoc, "//table:table[@table:protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
+}
+
+void ScExportTest::testProtectionKeyODS_UTF8SHA256W3C()
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ ScDocShellRef xShell = loadDoc("protection-key4.", FORMAT_FODS);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell.is());
+
+ ScDocument& rDoc = xShell->GetDocument();
+ ScDocProtection *const pDocProt(rDoc.GetDocProtection());
+ CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
+ ScTableProtection *const pTabProt(rDoc.GetTabProtection(0));
+ CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_ODS);
+ xmlDocPtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
+ assertXPath(pXmlDoc, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
+ assertXPath(pXmlDoc, "//table:table[@table:protected='true' and @table:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=' and @table:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256']");
+}
+
+void ScExportTest::testProtectionKeyODS_XL_SHA1()
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ ScDocShellRef xShell = loadDoc("protection-key5.", FORMAT_FODS);
+ CPPUNIT_ASSERT_MESSAGE("Failed to load doc", xShell.is());
+
+ ScDocument& rDoc = xShell->GetDocument();
+ ScDocProtection *const pDocProt(rDoc.GetDocProtection());
+ CPPUNIT_ASSERT(pDocProt->verifyPassword(password));
+ ScTableProtection *const pTabProt(rDoc.GetTabProtection(0));
+ CPPUNIT_ASSERT(pTabProt->verifyPassword(password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ std::shared_ptr<utl::TempFile> pXPathFile = ScBootstrapFixture::exportTo(&(*xShell), FORMAT_ODS);
+ xmlDocPtr pXmlDoc = XPathHelper::parseExport(pXPathFile, m_xSFactory, "content.xml");
+ assertXPath(pXmlDoc, "//office:spreadsheet[@table:structure-protected='true' and @table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and @table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/legacy-hash-excel' and @loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
+ assertXPath(pXmlDoc, "//table:table[@table:protected='true' and @table:protection-key='OX3WkEe79fv1PE+FUmfOLdwVoqI=' and @table:protection-key-digest-algorithm='http://docs.oasis-open.org/office/ns/table/legacy-hash-excel' and @loext:protection-key-digest-algorithm-2='http://www.w3.org/2000/09/xmldsig#sha1']");
+}
+
void ScExportTest::testColorScaleExportODS()
{
ScDocShellRef xShell = loadDoc("colorscale.", FORMAT_ODS);
diff --git a/sc/source/core/data/tabprotection.cxx b/sc/source/core/data/tabprotection.cxx
index 21a3f686a44f..9a4a8bdde26d 100644
--- a/sc/source/core/data/tabprotection.cxx
+++ b/sc/source/core/data/tabprotection.cxx
@@ -28,6 +28,8 @@
#define DEBUG_TAB_PROTECTION 0
#define URI_SHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
+#define URI_SHA256_ODF12 "http://www.w3.org/2000/09/xmldsig#sha256"
+#define URI_SHA256_W3C "http://www.w3.org/2001/04/xmlenc#sha256"
#define URI_XLS_LEGACY "http://docs.oasis-open.org/office/ns/table/legacy-hash-excel"
using namespace ::com::sun::star;
@@ -62,6 +64,8 @@ OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
{
switch (eHash)
{
+ case PASSHASH_SHA256:
+ return OUString(URI_SHA256_ODF12);
case PASSHASH_SHA1:
return OUString(URI_SHA1);
case PASSHASH_XL:
@@ -75,6 +79,8 @@ OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
ScPasswordHash ScPassHashHelper::getHashTypeFromURI(const OUString& rURI)
{
+ if (rURI == URI_SHA256_ODF12 || rURI == URI_SHA256_W3C)
+ return PASSHASH_SHA256;
if ( rURI == URI_SHA1 )
return PASSHASH_SHA1;
else if ( rURI == URI_XLS_LEGACY )
@@ -140,6 +146,12 @@ Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const OUString& aPassText
case PASSHASH_SHA1:
SvPasswordHelper::GetHashPassword(aHash, aPassText);
break;
+ case PASSHASH_SHA1_UTF8:
+ SvPasswordHelper::GetHashPasswordSHA1UTF8(aHash, aPassText);
+ break;
+ case PASSHASH_SHA256:
+ SvPasswordHelper::GetHashPasswordSHA256(aHash, aPassText);
+ break;
default:
;
}
@@ -320,7 +332,20 @@ bool ScTableProtectionImpl::verifyPassword(const OUString& aPassText) const
printf("\n");
#endif
- return aHash == maPassHash;
+ if (aHash == maPassHash)
+ {
+ return true;
+ }
+
+ // tdf#115483 compat hack for ODF 1.2; for now UTF8-SHA1 passwords are only
+ // verified, not generated
+ if (meHash1 == PASSHASH_SHA1 && meHash2 == PASSHASH_UNSPECIFIED)
+ {
+ Sequence<sal_Int8> const aHash2 = hashPassword(aPassText, PASSHASH_SHA1_UTF8);
+ return aHash2 == maPassHash;
+ }
+
+ return false;
}
bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index e9c6a22916f4..9c09a1ee0eb0 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -1702,6 +1702,11 @@ void ScXMLExport::SetBodyAttributes()
aPassHash = p->getPasswordHash(PASSHASH_SHA1);
eHashUsed = PASSHASH_SHA1;
}
+ else if (p->hasPasswordHash(PASSHASH_SHA256))
+ {
+ aPassHash = p->getPasswordHash(PASSHASH_SHA256);
+ eHashUsed = PASSHASH_SHA256;
+ }
else if (p->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
{
aPassHash = p->getPasswordHash(PASSHASH_XL, PASSHASH_SHA1);
@@ -1723,8 +1728,15 @@ void ScXMLExport::SetBodyAttributes()
ScPassHashHelper::getHashURI(PASSHASH_SHA1));
}
else if (eHashUsed == PASSHASH_SHA1)
+ {
AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+ }
+ else if (eHashUsed == PASSHASH_SHA256)
+ {
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+ ScPassHashHelper::getHashURI(PASSHASH_SHA256));
+ }
}
}
}
@@ -2840,6 +2852,12 @@ void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpre
pProtect->getPasswordHash(PASSHASH_SHA1));
eHashUsed = PASSHASH_SHA1;
}
+ else if (pProtect->hasPasswordHash(PASSHASH_SHA256))
+ {
+ ::sax::Converter::encodeBase64(aBuffer,
+ pProtect->getPasswordHash(PASSHASH_SHA256));
+ eHashUsed = PASSHASH_SHA256;
+ }
else if (pProtect->hasPasswordHash(PASSHASH_XL, PASSHASH_SHA1))
{
// Double-hash this by SHA1 on top of the legacy xls hash.
@@ -2861,8 +2879,15 @@ void ScXMLExport::WriteTable(sal_Int32 nTable, const uno::Reference<sheet::XSpre
ScPassHashHelper::getHashURI(PASSHASH_SHA1));
}
else if (eHashUsed == PASSHASH_SHA1)
+ {
AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
ScPassHashHelper::getHashURI(PASSHASH_SHA1));
+ }
+ else if (eHashUsed == PASSHASH_SHA256)
+ {
+ AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+ ScPassHashHelper::getHashURI(PASSHASH_SHA256));
+ }
}
}
}
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 607cf964cdf9..1e56605c1d78 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -1714,6 +1714,10 @@ bool ScDocShell::SaveAs( SfxMedium& rMedium )
if (bNeedsRehash)
// legacy xls hash double-hashed by SHA1 is also supported.
bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
+ if (bNeedsRehash)
+ { // SHA256 explicitly supported in ODF 1.2, implicitly in ODF 1.1
+ bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA256);
+ }
if (pViewShell && bNeedsRehash)
{
diff --git a/svl/source/misc/PasswordHelper.cxx b/svl/source/misc/PasswordHelper.cxx
index 00558f6a1630..48aa165507ee 100644
--- a/svl/source/misc/PasswordHelper.cxx
+++ b/svl/source/misc/PasswordHelper.cxx
@@ -19,11 +19,32 @@
#include <svl/PasswordHelper.hxx>
+#include <comphelper/hash.hxx>
#include <rtl/digest.h>
#include <memory>
using namespace com::sun::star;
+void SvPasswordHelper::GetHashPasswordSHA256(uno::Sequence<sal_Int8>& rPassHash, OUString const& rPassword)
+{
+ OString const tmp(OUStringToOString(rPassword, RTL_TEXTENCODING_UTF8));
+ ::std::vector<unsigned char> const hash(::comphelper::Hash::calculateHash(
+ reinterpret_cast<unsigned char const*>(tmp.getStr()), tmp.getLength(),
+ ::comphelper::HashType::SHA256));
+ rPassHash.realloc(hash.size());
+ ::std::copy(hash.begin(), hash.end(), rPassHash.begin());
+}
+
+void SvPasswordHelper::GetHashPasswordSHA1UTF8(uno::Sequence<sal_Int8>& rPassHash, OUString const& rPassword)
+{
+ OString const tmp(OUStringToOString(rPassword, RTL_TEXTENCODING_UTF8));
+ ::std::vector<unsigned char> const hash(::comphelper::Hash::calculateHash(
+ reinterpret_cast<unsigned char const*>(tmp.getStr()), tmp.getLength(),
+ ::comphelper::HashType::SHA1));
+ rPassHash.realloc(hash.size());
+ ::std::copy(hash.begin(), hash.end(), rPassHash.begin());
+}
+
void SvPasswordHelper::GetHashPassword(uno::Sequence<sal_Int8>& rPassHash, const sal_Char* pPass, sal_uInt32 nLen)
{
rPassHash.realloc(RTL_DIGEST_LENGTH_SHA1);
@@ -74,14 +95,31 @@ bool SvPasswordHelper::CompareHashPassword(const uno::Sequence<sal_Int8>& rOldPa
{
bool bResult = false;
- uno::Sequence<sal_Int8> aNewPass(RTL_DIGEST_LENGTH_SHA1);
- GetHashPasswordLittleEndian(aNewPass, sNewPass);
- if (aNewPass == rOldPassHash)
- bResult = true;
- else
+ if (rOldPassHash.getLength() == RTL_DIGEST_LENGTH_SHA1)
+ {
+ uno::Sequence<sal_Int8> aNewPass(RTL_DIGEST_LENGTH_SHA1);
+ GetHashPasswordSHA1UTF8(aNewPass, sNewPass);
+ if (aNewPass == rOldPassHash)
+ {
+ bResult = true;
+ }
+ else
+ {
+ GetHashPasswordLittleEndian(aNewPass, sNewPass);
+ if (aNewPass == rOldPassHash)
+ bResult = true;
+ else
+ {
+ GetHashPasswordBigEndian(aNewPass, sNewPass);
+ bResult = (aNewPass == rOldPassHash);
+ }
+ }
+ }
+ else if (rOldPassHash.getLength() == 32)
{
- GetHashPasswordBigEndian(aNewPass, sNewPass);
- bResult = (aNewPass == rOldPassHash);
+ uno::Sequence<sal_Int8> aNewPass;
+ GetHashPasswordSHA256(aNewPass, sNewPass);
+ bResult = aNewPass == rOldPassHash;
}
return bResult;
diff --git a/sw/CppunitTest_sw_odfexport.mk b/sw/CppunitTest_sw_odfexport.mk
index da931c3f3006..8fb2228d84a3 100644
--- a/sw/CppunitTest_sw_odfexport.mk
+++ b/sw/CppunitTest_sw_odfexport.mk
@@ -21,6 +21,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_odfexport, \
cppuhelper \
sal \
sfx \
+ svl \
sw \
test \
tl \
diff --git a/sw/qa/extras/odfexport/data/protection-key.fodt b/sw/qa/extras/odfexport/data/protection-key.fodt
new file mode 100644
index 000000000000..cd4cde9623a4
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/protection-key.fodt
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
+
+ <office:styles>
+
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+
+ </office:styles>
+ <office:automatic-styles>
+
+ <style:style style:name="Sect" style:family="section">
+ <style:section-properties style:editable="false">
+ <style:columns fo:column-count="1" fo:column-gap="0cm"/>
+ </style:section-properties>
+ </style:style>
+
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+
+ <!-- UTF-16 LE, bad SHA1 -->
+ <text:section text:style-name="Sect" text:name="Section0" text:protected="true" text:protection-key="vbnhxyBKtPHCA1wB21zG1Oha8ZA=">
+ <text:p text:style-name="Standard"/>
+ </text:section>
+
+ <!-- echo -n $(echo -n 1012345678901234567890123456789012345678901234567890 | sha1sum | cut -f 1 -d ' ') | xxd -r -p | base64 -->
+ <!-- UTF-8, good SHA1 -->
+ <text:section text:style-name="Sect" text:name="Section1" text:protected="true" text:protection-key="nLHas0RIwepGDaH4c2hpyIUvIS8=">
+ <text:p text:style-name="Standard"/>
+ </text:section>
+
+ <!-- echo -n $(echo -n 1012345678901234567890123456789012345678901234567890 | sha256sum | cut -f 1 -d ' ') | xxd -r -p | base64 -->
+ <!-- UTF-8, SHA256, ODF 1.2 URI -->
+ <text:section text:style-name="Sect" text:name="Section2" text:protected="true" text:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" text:protection-key-digest-algorithm="http://www.w3.org/2000/09/xmldsig#sha256">
+ <text:p text:style-name="Standard"/>
+ </text:section>
+
+ <!-- UTF-8, SHA256, W3C URI -->
+ <text:section text:style-name="Sect" text:name="Section3" text:protected="true" text:protection-key="1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=" text:protection-key-digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256">
+ <text:p text:style-name="Standard"/>
+ </text:section>
+
+ <text:p text:style-name="Standard"/>
+ </office:text>
+ </office:body>
+</office:document>
+
diff --git a/sw/qa/extras/odfexport/odfexport.cxx b/sw/qa/extras/odfexport/odfexport.cxx
index 14bd0bc2bc0e..4051d31349d5 100644
--- a/sw/qa/extras/odfexport/odfexport.cxx
+++ b/sw/qa/extras/odfexport/odfexport.cxx
@@ -36,6 +36,7 @@
#include <comphelper/fileformat.h>
#include <comphelper/propertysequence.hxx>
#include <unotools/streamwrap.hxx>
+#include <svl/PasswordHelper.hxx>
#include <docufld.hxx> // for SwHiddenTextField::ParseIfFieldDefinition() method call
class Test : public SwModelTestBase
@@ -856,6 +857,37 @@ DECLARE_ODFEXPORT_TEST(testCharacterBorder, "charborder.odt")
}
}
+DECLARE_ODFEXPORT_TEST(testProtectionKey, "protection-key.fodt")
+{
+ OUString const password("1012345678901234567890123456789012345678901234567890");
+
+ // check 1 invalid OOo legacy password and 3 valid ODF 1.2 passwords
+ uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xSect0(xSections->getByIndex(0), uno::UNO_QUERY);
+ uno::Sequence<sal_Int8> const key0(getProperty<uno::Sequence<sal_Int8>>(xSect0, "ProtectionKey"));
+ CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key0, password));
+ uno::Reference<beans::XPropertySet> xSect1(xSections->getByIndex(1), uno::UNO_QUERY);
+ uno::Sequence<sal_Int8> const key1(getProperty<uno::Sequence<sal_Int8>>(xSect1, "ProtectionKey"));
+ CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key1, password));
+ uno::Reference<beans::XPropertySet> xSect2(xSections->getByIndex(2), uno::UNO_QUERY);
+ uno::Sequence<sal_Int8> const key2(getProperty<uno::Sequence<sal_Int8>>(xSect1, "ProtectionKey"));
+ CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key2, password));
+ uno::Reference<beans::XPropertySet> xSect3(xSections->getByIndex(3), uno::UNO_QUERY);
+ uno::Sequence<sal_Int8> const key3(getProperty<uno::Sequence<sal_Int8>>(xSect1, "ProtectionKey"));
+ CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key3, password));
+
+ // we can't assume that the user entered the password; check that we
+ // round-trip the password as-is
+ if (xmlDocPtr pXmlDoc = parseExport("content.xml"))
+ {
+ assertXPath(pXmlDoc, "//text:section[@text:name='Section0' and @text:protected='true' and @text:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=']");
+ assertXPath(pXmlDoc, "//text:section[@text:name='Section1' and @text:protected='true' and @text:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=']");
+ assertXPath(pXmlDoc, "//text:section[@text:name='Section2' and @text:protected='true' and @text:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256' and @text:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=']");
+ assertXPath(pXmlDoc, "//text:section[@text:name='Section3' and @text:protected='true' and @text:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256' and @text:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=']");
+ }
+}
+
DECLARE_ODFEXPORT_TEST(testFdo43807, "fdo43807.odt")
{
uno::Reference<beans::XPropertySet> xSet(getParagraph(1), uno::UNO_QUERY);
diff --git a/xmloff/source/text/XMLSectionExport.cxx b/xmloff/source/text/XMLSectionExport.cxx
index e6a6875244c2..46189a119ca7 100644
--- a/xmloff/source/text/XMLSectionExport.cxx
+++ b/xmloff/source/text/XMLSectionExport.cxx
@@ -398,8 +398,16 @@ void XMLSectionExport::ExportRegularSectionStart(
{
OUStringBuffer aBuffer;
::sax::Converter::encodeBase64(aBuffer, aPassword);
+ // in ODF 1.0/1.1 the algorithm was left unspecified so we can write anything
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY,
aBuffer.makeStringAndClear());
+ if (aPassword.getLength() == 32 && GetExport().getDefaultVersion() >= SvtSaveOptions::ODFVER_012)
+ {
+ // attribute exists in ODF 1.2 or later; default is SHA1 so no need to write that
+ GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM,
+ // write the URL from ODF 1.2, not the W3C one
+ "http://www.w3.org/2000/09/xmldsig#sha256");
+ }
}
// export element