sc/inc/unonames.hxx                       |    1 
 sc/qa/uitest/calc_tests9/tdf118938.py     |   49 ++++++++++++++++++++++++++++++
 sc/qa/uitest/data/tdf118938.xlsx          |binary
 sc/source/filter/excel/excdoc.cxx         |   11 ++++++
 sc/source/filter/oox/workbooksettings.cxx |   11 +-----
 sc/source/ui/unoobj/confuno.cxx           |   13 +++++++
 sfx2/source/view/viewfrm.cxx              |    7 +++-
 7 files changed, 81 insertions(+), 11 deletions(-)

New commits:
commit c082158018148be01476d5bc82c1cd71ea6541df
Author:     Tünde Tóth <toth.tu...@nisz.hu>
AuthorDate: Tue Aug 31 12:08:39 2021 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Wed Sep 1 11:29:08 2021 +0200

    tdf#118938 XLSX import/export: fix permission for editing
    
    The password for editing wasn't asked, also wasn't
    exported in XLSX documents. Now it's exported in Calc
    using the following steps, also verified before editing:
    
    - In File->Save As, choose Excel 2007–365 (.xlsx) format;
    
    - enable checkbox "Save with password" and click Save;
    
    - in the dialog "Set password", click on "Options" and enable
      checkbox "Open file read-only", and enter a password
      for editing (i.e. skip the password for opening).
    
    Note: Excel 2016 doesn't ask password for editing, but
    Office 365 does. Passwords created in Excel haven't been
    supported, yet. Also passwords with diacritics aren't
    interoperable.
    
    Note: saving the file under a different path is still
    allowed both in Calc and Excel without asking the password
    for editing.
    
    Change-Id: Ic00d7c5a785e04d270a182a4087ea922d7d92979
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121371
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx
index 56936063f74c..36ab650e918b 100644
--- a/sc/inc/unonames.hxx
+++ b/sc/inc/unonames.hxx
@@ -666,6 +666,7 @@
 // Security options
 #define SC_UNO_LOADREADONLY         "LoadReadonly"
 #define SC_UNO_MODIFYPASSWORDINFO   "ModifyPasswordInfo"
+#define SC_UNO_MODIFYPASSWORDHASH   "ModifyPasswordHash"
 
 // FormulaParser
 #define SC_UNO_COMPILEENGLISH       "CompileEnglish"
diff --git a/sc/qa/uitest/calc_tests9/tdf118938.py 
b/sc/qa/uitest/calc_tests9/tdf118938.py
new file mode 100644
index 000000000000..7444f65780ea
--- /dev/null
+++ b/sc/qa/uitest/calc_tests9/tdf118938.py
@@ -0,0 +1,49 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_url_for_data_file
+from libreoffice.uno.propertyvalue import mkPropertyValues
+
+#Bug 118938 - FILESAVE to Microsoft Excel 2007-2013 XML (.xlsx) files as 
read-only
+#             with additional password protection for editing not working 
(Calc)
+
+class tdf118938(UITestCase):
+    def test_tdf118938(self):
+        with self.ui_test.load_file(get_url_for_data_file("tdf118938.xlsx")):
+            #The document was created in Calc after this fix.
+            calcDoc = self.xUITest.getTopFocusWindow()
+            gridwin = calcDoc.getChild("grid_window")
+
+            incorrectPass = False;
+
+            try:
+                self.xUITest.executeDialog(".uno:EditDoc")
+                xDialog = self.xUITest.getTopFocusWindow();
+                xPassword = xDialog.getChild("newpassEntry")
+                xPassword.executeAction("TYPE", mkPropertyValues({"TEXT": 
"a"}))
+                xOKBtn = xDialog.getChild("ok")
+                self.ui_test.close_dialog_through_button(xOKBtn)
+
+                try:
+                    xWarnDialog = self.xUITest.getTopFocusWindow()
+                    xOK = xWarnDialog.getChild("ok")
+                    self.ui_test.close_dialog_through_button(xOK)
+
+                    xDialog2 = self.xUITest.getTopFocusWindow();
+                    xCancelBtn = xDialog2.getChild("cancel")
+                    self.ui_test.close_dialog_through_button(xCancelBtn)
+
+                    incorrectPass = True;
+                except:
+                    pass
+            except:
+                assert False, "The password dialog hasn't appeared."
+
+            if incorrectPass:
+                assert False, "Incorrect password."
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sc/qa/uitest/data/tdf118938.xlsx b/sc/qa/uitest/data/tdf118938.xlsx
new file mode 100644
index 000000000000..5e571f9f2475
Binary files /dev/null and b/sc/qa/uitest/data/tdf118938.xlsx differ
diff --git a/sc/source/filter/excel/excdoc.cxx 
b/sc/source/filter/excel/excdoc.cxx
index ebc5a69f937a..1f43caaf73f9 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -806,7 +806,11 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm )
     uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 
pDocShell->GetModel(), uno::UNO_QUERY_THROW );
     uno::Reference<document::XDocumentProperties> xDocProps = 
xDPS->getDocumentProperties();
 
-    rStrm.exportDocumentProperties(xDocProps, 
pDocShell->IsSecurityOptOpenReadOnly());
+    sal_uInt32 nWriteProtHash = pDocShell->GetModifyPasswordHash();
+    OUString sUserName = GetUserName();
+    bool bHasPassword = nWriteProtHash && !sUserName.isEmpty();
+    rStrm.exportDocumentProperties(xDocProps,
+                                   pDocShell->IsSecurityOptOpenReadOnly() && 
!bHasPassword);
     rStrm.exportCustomFragments();
 
     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
@@ -821,6 +825,11 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm )
             // OOXTODO: XML_rupBuild
     );
 
+    if (bHasPassword)
+        rWorkbook->singleElement(XML_fileSharing,
+                XML_userName, sUserName,
+                XML_reservationPassword, OString::number(nWriteProtHash, 
16).getStr());
+
     if( !maTableList.IsEmpty() )
     {
         InitializeSave();
diff --git a/sc/source/filter/oox/workbooksettings.cxx 
b/sc/source/filter/oox/workbooksettings.cxx
index 19967601cd30..a7ab887bf967 100644
--- a/sc/source/filter/oox/workbooksettings.cxx
+++ b/sc/source/filter/oox/workbooksettings.cxx
@@ -210,15 +210,8 @@ void WorkbookSettings::finalizeImport()
         if (maFileSharing.mbRecommendReadOnly || 
!maFileSharing.maHashValue.isEmpty())
             aSettingsProp.setProperty( PROP_LoadReadonly, true );
 
-        /* TODO: setting ModifyPasswordHash was commented out with commit
-         * 1a842832cd174d5ccfd832fdb94c93ae42e8eacc of which the filter
-         * fragment parts meanwhile contain PASSWORDTOMODIFY again, also for
-         * calc_OOXML.xcu, but setting the property doesn't raise a dialog. If
-         * it worked, a Sequence<PropertyValue> should be used for
-         * algorithmName,hashValue,... see also
-         * SfxObjectShell::SetModifyPasswordInfo() */
-//        if( maFileSharing.mnPasswordHash != 0 )
-//            aSettingsProp.setProperty( PROP_ModifyPasswordHash, static_cast< 
sal_Int32 >( maFileSharing.mnPasswordHash ) );
+        if( maFileSharing.mnPasswordHash != 0 )
+            aSettingsProp.setProperty( PROP_ModifyPasswordHash, static_cast< 
sal_Int32 >( maFileSharing.mnPasswordHash ) );
     }
     catch( Exception& )
     {
diff --git a/sc/source/ui/unoobj/confuno.cxx b/sc/source/ui/unoobj/confuno.cxx
index d7ead11acdd4..f148b9abed8f 100644
--- a/sc/source/ui/unoobj/confuno.cxx
+++ b/sc/source/ui/unoobj/confuno.cxx
@@ -83,6 +83,7 @@ static const SfxItemPropertyMapEntry* 
lcl_GetConfigPropertyMap()
         {u"" SC_UNO_LOADREADONLY, 0,  cppu::UnoType<bool>::get(),              
0, 0},
         {u"" SC_UNO_SHAREDOC,     0,  cppu::UnoType<bool>::get(),              
0, 0},
         {u"" SC_UNO_MODIFYPASSWORDINFO, 0,  cppu::UnoType<uno::Sequence< 
beans::PropertyValue >>::get(),              0, 0},
+        {u"" SC_UNO_MODIFYPASSWORDHASH, 0,  cppu::UnoType<sal_Int32>::get(),   
0, 0},
         {u"" SC_UNO_EMBED_FONTS,               0,  cppu::UnoType<bool>::get(), 
0, 0},
         {u"" SC_UNO_EMBED_ONLY_USED_FONTS,     0,  cppu::UnoType<bool>::get(), 
0, 0},
         {u"" SC_UNO_EMBED_FONT_SCRIPT_LATIN,   0,  cppu::UnoType<bool>::get(), 
0, 0},
@@ -337,6 +338,16 @@ void SAL_CALL ScDocumentConfiguration::setPropertyValue(
             throw beans::PropertyVetoException(
                 "The hash is not allowed to be changed now!" );
     }
+    else if (aPropertyName == SC_UNO_MODIFYPASSWORDHASH)
+    {
+        sal_Int32 nHash;
+        if (!(aValue >>= nHash))
+            throw lang::IllegalArgumentException("Value of type sal_Int32 
expected!",
+                                                 
uno::Reference<uno::XInterface>(), 2);
+
+        if (!pDocShell->SetModifyPasswordHash(nHash))
+            throw beans::PropertyVetoException("The hash is not allowed to be 
changed now!");
+    }
     else if (aPropertyName == SC_UNO_EMBED_FONTS)
     {
         bool bVal = aValue.has<bool>() && aValue.get<bool>();
@@ -537,6 +548,8 @@ uno::Any SAL_CALL 
ScDocumentConfiguration::getPropertyValue( const OUString& aPr
     }
     else if ( aPropertyName == SC_UNO_MODIFYPASSWORDINFO )
         aRet <<= pDocShell->GetModifyPasswordInfo();
+    else if (aPropertyName == SC_UNO_MODIFYPASSWORDHASH)
+        aRet <<= pDocShell->GetModifyPasswordHash();
     else if (aPropertyName == SC_UNO_EMBED_FONTS)
         aRet <<= rDoc.IsEmbedFonts();
     else if (aPropertyName == SC_UNO_EMBED_ONLY_USED_FONTS)
diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx
index ada11bea9930..4ba5bc852834 100644
--- a/sfx2/source/view/viewfrm.cxx
+++ b/sfx2/source/view/viewfrm.cxx
@@ -352,6 +352,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
 
             StreamMode nOpenMode;
             bool bNeedsReload = false;
+            bool bPasswordEntered = false;
             if ( !pSh->IsReadOnly() )
             {
                 // Save and reload Readonly
@@ -388,6 +389,7 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                     }
 
                     pSh->SetModifyPasswordEntered();
+                    bPasswordEntered = true;
                 }
 
                 nOpenMode = pSh->IsOriginallyReadOnlyMedium() ? 
SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
@@ -439,8 +441,11 @@ void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq )
                                                                          
aPhysObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
             bool bIsWebDAV = aMedObj.isAnyKnownWebDAVScheme();
 
+            // tdf#118938 Reload the document when the user enters the editing 
password,
+            //            even if the physical name isn't different to the 
logical name.
             if ( ( !bNeedsReload && ( ( aMedObj.GetProtocol() == 
INetProtocol::File &&
-                                        aMedObj.getFSysPath( FSysStyle::Detect 
) != aPhysObj.getFSysPath( FSysStyle::Detect ) &&
+                                        ( aMedObj.getFSysPath( 
FSysStyle::Detect ) != aPhysObj.getFSysPath( FSysStyle::Detect )
+                                          || bPasswordEntered ) &&
                                         !bPhysObjIsYounger )
                                       || ( bIsWebDAV && !bPhysObjIsYounger )
                                       || ( pMed->IsRemote() && !bIsWebDAV ) ) )

Reply via email to