[Libreoffice-commits] core.git: Branch 'libreoffice-6-1' - include/oox oox/source sc/qa sc/source sd/qa sd/source sfx2/source sw/qa sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Jul 18 13:40:21 UTC 2018


 include/oox/core/xmlfilterbase.hxx                   |    2 
 oox/source/core/xmlfilterbase.cxx                    |   50 +++++++++++++------
 sc/qa/unit/data/xlsx/open-as-read-only.xlsx          |binary
 sc/qa/unit/subsequent_export-test.cxx                |   12 ++++
 sc/source/filter/excel/excdoc.cxx                    |    2 
 sd/qa/unit/data/pptx/open-as-read-only.pptx          |binary
 sd/qa/unit/export-tests-ooxml2.cxx                   |   12 ++++
 sd/source/filter/eppt/pptx-epptooxml.cxx             |   14 ++++-
 sfx2/source/doc/objstor.cxx                          |   27 ++++++++++
 sw/qa/extras/ooxmlexport/data/open-as-read-only.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport11.cxx           |    7 ++
 sw/source/filter/ww8/docxexport.cxx                  |    4 +
 12 files changed, 111 insertions(+), 19 deletions(-)

New commits:
commit 61aaefd8e902f86f5f7347efdb56686638149133
Author:     László Németh <nemeth at numbertext.org>
AuthorDate: Wed Jun 20 16:28:13 2018 +0200
Commit:     Miklos Vajna <vmiklos at collabora.co.uk>
CommitDate: Wed Jul 18 15:39:57 2018 +0200

    tdf#107690 OOXML import/export of setting "Open as read-only"
    
    Import custom document property _MarkAsFinal as LoadReadonly
    setting, export LoadReadonly as _MarkAsFinal in DOCX, XLSX
    and PPTX documents.
    
    Before this fix, LibreOffice opened read-only OOXML documents
    as editable, also saved and exported _MarkAsFinal=true silently,
    resulting unintented read-only warning info bar in MSO.
    
    This commit improves interoperability a lot, because this is a
    basic document protection of MSO, recommended on its UI.
    
    Note: LoadReadonly (on File->Properties...->Security, property
    "Open file read-only") doesn't show "Edit read-only" info bar
    from commit 630186ff4e0eba7317e542f8c3eca39ebd068721,
    but it's still possible to switch on editing by Edit->Edit Mode.
    MSO shows info bar for _MarkAsFinal. (There is an advantage to
    hide the info bar in LibreOffice in a mixed environment,
    to avoid overwriting of press-ready MSO files by LibreOffice.)
    
    Note 2: Other differences of LoadReadonly in LO and _MarkAsFinal
    in MSO: (1) Switching on editing doesn't remove the LoadReadonly
    property automatically in LO. (2) Saving with LoadReadonly doesn't
    switch off editing of the actual (still opened) document in LO.
    
    (cherry picked from commit 9a5c56a9c4e04589b0a6bb710573922e459d9685
    and bbdb6cb8ed0d77eeb2e413b38f29d2084bd8257b (unit tests))
    
    Change-Id: I79897605e1fabe0708cce0b0c6216c152b201fc9
    Reviewed-on: https://gerrit.libreoffice.org/56752
    Tested-by: Jenkins
    Reviewed-by: László Németh <nemeth at numbertext.org>
    Tested-by: László Németh <nemeth at numbertext.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/include/oox/core/xmlfilterbase.hxx b/include/oox/core/xmlfilterbase.hxx
index ffe0c5bc45e3..e2be8d14f9c8 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -224,7 +224,7 @@ public:
 
         @param xProperties  The document properties to export.
      */
-    void exportDocumentProperties( const css::uno::Reference< css::document::XDocumentProperties >& xProperties );
+    void exportDocumentProperties( const css::uno::Reference< css::document::XDocumentProperties >& xProperties, bool bSecurityOptOpenReadOnly );
 
     /** Write the customXml entries we are preserving (xlsx and pptx only). */
     void exportCustomFragments();
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index 57a752489960..5168d81fb7fb 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -750,13 +750,31 @@ writeAppProperties( XmlFilterBase& rSelf, const Reference< XDocumentProperties >
 }
 
 static void
-writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentProperties >& xProperties )
+writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentProperties >& xProperties, bool bSecurityOptOpenReadOnly )
 {
     uno::Reference<beans::XPropertyAccess> xUserDefinedProperties( xProperties->getUserDefinedProperties(), uno::UNO_QUERY );
     Sequence< PropertyValue > aprop( xUserDefinedProperties->getPropertyValues() );
     sal_Int32 nbCustomProperties = aprop.getLength();
     // tdf#89791 : if no custom properties, no need to add docProps/custom.x
-    if (!nbCustomProperties)
+    // tdf#107690: except the case of read-only documents, because that
+    // is handled by the _MarkAsFinal custom property in MSO.
+    if (!nbCustomProperties && !bSecurityOptOpenReadOnly)
+        return;
+
+    std::vector<PropertyValue> aprop2;
+    for ( sal_Int32 n = 0; n < nbCustomProperties; ++n )
+        aprop2.push_back(aprop[n]);
+
+    if (bSecurityOptOpenReadOnly)
+    {
+        PropertyValue aPropertyValue;
+        // MSO custom property for read-only documents
+        aPropertyValue.Name = "_MarkAsFinal";
+        aPropertyValue.Value <<= true;
+        aprop2.push_back(aPropertyValue);
+    }
+
+    if (!aprop2.size())
         return;
 
     rSelf.addRelation(
@@ -770,11 +788,12 @@ writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentPropertie
             FSNS( XML_xmlns, XML_vt ),  OUStringToOString(rSelf.getNamespaceURL(OOX_NS(officeDocPropsVT)), RTL_TEXTENCODING_UTF8).getStr(),
             FSEND );
 
-    for ( sal_Int32 n = 0; n < nbCustomProperties; ++n )
+    auto aIt = aprop2.begin();
+    for ( size_t n = 0; n < aprop2.size(); ++n )
     {
-        if ( !aprop[n].Name.isEmpty() )
+        if ( !aIt->Name.isEmpty() )
         {
-            OString aName = OUStringToOString( aprop[n].Name, RTL_TEXTENCODING_ASCII_US );
+            OString aName = OUStringToOString( aIt->Name, RTL_TEXTENCODING_ASCII_US );
             // pid starts from 2 not from 1 as MS supports pid from 2
             pAppProps->startElement( XML_property ,
                 XML_fmtid,  "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
@@ -782,18 +801,18 @@ writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentPropertie
                 XML_name,   aName,
                 FSEND);
 
-            switch ( aprop[n].Value.getValueTypeClass() )
+            switch ( aIt->Value.getValueTypeClass() )
             {
                 case TypeClass_STRING:
                 {
                     OUString aValue;
-                    aprop[n].Value >>= aValue;
-                     writeElement( pAppProps, FSNS( XML_vt, XML_lpwstr ), aValue );
+                    aIt->Value >>= aValue;
+                    writeElement( pAppProps, FSNS( XML_vt, XML_lpwstr ), aValue );
                 }
                 break;
                 case TypeClass_BOOLEAN:
                 {
-                    bool val = *o3tl::forceAccess<bool>(aprop[n].Value);
+                    bool val = *o3tl::forceAccess<bool>(aIt->Value);
                     writeElement( pAppProps, FSNS( XML_vt, XML_bool ), val ? 1 : 0);
                 }
                 break;
@@ -803,23 +822,23 @@ writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentPropertie
                     util::Date aDate;
                     util::Duration aDuration;
                     util::DateTime aDateTime;
-                    if ( ( aprop[n].Value ) >>= num )
+                    if ( ( aIt->Value ) >>= num )
                     {
                         writeElement( pAppProps, FSNS( XML_vt, XML_i4 ), num );
                     }
-                    else if ( ( aprop[n].Value ) >>= aDate )
+                    else if ( ( aIt->Value ) >>= aDate )
                     {
                         aDateTime = util::DateTime( 0, 0 , 0, 0, aDate.Year, aDate.Month, aDate.Day, true );
                         writeElement( pAppProps, FSNS( XML_vt, XML_filetime ), aDateTime);
                     }
-                    else if ( ( aprop[n].Value ) >>= aDuration )
+                    else if ( ( aIt->Value ) >>= aDuration )
                     {
                         OUStringBuffer buf;
                         ::sax::Converter::convertDuration( buf, aDuration );
                         OUString aDurationStr = buf.makeStringAndClear();
                         writeElement( pAppProps, FSNS( XML_vt, XML_lpwstr ), aDurationStr );
                     }
-                    else if ( ( aprop[n].Value ) >>= aDateTime )
+                    else if ( ( aIt->Value ) >>= aDateTime )
                             writeElement( pAppProps, FSNS( XML_vt, XML_filetime ), aDateTime );
                     else
                         //no other options
@@ -829,17 +848,18 @@ writeCustomProperties( XmlFilterBase& rSelf, const Reference< XDocumentPropertie
             }
             pAppProps->endElement( XML_property );
         }
+        ++aIt;
     }
     pAppProps->endElement( XML_Properties );
 }
 
-void XmlFilterBase::exportDocumentProperties( const Reference< XDocumentProperties >& xProperties )
+void XmlFilterBase::exportDocumentProperties( const Reference< XDocumentProperties >& xProperties, bool bSecurityOptOpenReadOnly )
 {
     if( xProperties.is() )
     {
         writeCoreProperties( *this, xProperties );
         writeAppProperties( *this, xProperties );
-        writeCustomProperties( *this, xProperties );
+        writeCustomProperties( *this, xProperties, bSecurityOptOpenReadOnly );
     }
 }
 
diff --git a/sc/qa/unit/data/xlsx/open-as-read-only.xlsx b/sc/qa/unit/data/xlsx/open-as-read-only.xlsx
new file mode 100644
index 000000000000..e871a95d3997
Binary files /dev/null and b/sc/qa/unit/data/xlsx/open-as-read-only.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 5e65134fbfbe..e7440a249da8 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -204,6 +204,7 @@ public:
 
     void testHiddenRepeatedRowsODS();
     void testHyperlinkTargetFrameODS();
+    void testOpenDocumentAsReadOnly();
 
     CPPUNIT_TEST_SUITE(ScExportTest);
     CPPUNIT_TEST(test);
@@ -309,6 +310,7 @@ public:
 
     CPPUNIT_TEST(testHiddenRepeatedRowsODS);
     CPPUNIT_TEST(testHyperlinkTargetFrameODS);
+    CPPUNIT_TEST(testOpenDocumentAsReadOnly);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -3994,6 +3996,16 @@ void ScExportTest::testHyperlinkTargetFrameODS()
     CPPUNIT_ASSERT_EQUAL(OUString("_blank"), aTargetFrameExport);
 }
 
+void ScExportTest::testOpenDocumentAsReadOnly()
+{
+    ScDocShellRef xDocSh = loadDoc("open-as-read-only.", FORMAT_XLSX);
+    CPPUNIT_ASSERT(xDocSh->IsSecurityOptOpenReadOnly());
+    ScDocShellRef xDocSh2 = saveAndReload(xDocSh.get(), FORMAT_XLSX);
+    CPPUNIT_ASSERT(xDocSh2->IsSecurityOptOpenReadOnly());
+    xDocSh->DoClose();
+    xDocSh2->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx
index e2b30c261837..891919fdc7e7 100644
--- a/sc/source/filter/excel/excdoc.cxx
+++ b/sc/source/filter/excel/excdoc.cxx
@@ -828,7 +828,7 @@ 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);
+    rStrm.exportDocumentProperties(xDocProps, pDocShell->IsSecurityOptOpenReadOnly());
     rStrm.exportCustomFragments();
 
     sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
diff --git a/sd/qa/unit/data/pptx/open-as-read-only.pptx b/sd/qa/unit/data/pptx/open-as-read-only.pptx
new file mode 100644
index 000000000000..57a4d32de7f4
Binary files /dev/null and b/sd/qa/unit/data/pptx/open-as-read-only.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index c0b23ac38cdd..92258796d507 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -143,6 +143,7 @@ public:
     void testTdf90627();
     void testTdf104786();
     void testTdf104789();
+    void testOpenDocumentAsReadOnly();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -209,6 +210,7 @@ public:
     CPPUNIT_TEST(testTdf90627);
     CPPUNIT_TEST(testTdf104786);
     CPPUNIT_TEST(testTdf104789);
+    CPPUNIT_TEST(testOpenDocumentAsReadOnly);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1677,6 +1679,16 @@ void SdOOXMLExportTest2::testTdf104789()
     xDocShRef->DoClose();
 }
 
+void SdOOXMLExportTest2::testOpenDocumentAsReadOnly()
+{
+    ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/pptx/open-as-read-only.pptx"), PPTX);
+    CPPUNIT_ASSERT(xDocShRef->IsSecurityOptOpenReadOnly());
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    CPPUNIT_ASSERT(xDocShRef->IsSecurityOptOpenReadOnly());
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 13dd072460f0..d90ea3a60d7b 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -357,7 +357,19 @@ void PowerPointExport::writeDocumentProperties()
     uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
 
     if (xDocProps.is())
-        exportDocumentProperties(xDocProps);
+    {
+        bool bSecurityOptOpenReadOnly = false;
+        uno::Reference< lang::XMultiServiceFactory > xFactory(mXModel, uno::UNO_QUERY);
+        uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+        try
+        {
+            xSettings->getPropertyValue("LoadReadonly") >>= bSecurityOptOpenReadOnly;
+        }
+        catch( Exception& )
+        {
+        }
+        exportDocumentProperties(xDocProps, bSecurityOptOpenReadOnly);
+    }
 
     exportCustomFragments();
 }
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 7f34e6a9ca96..716455cda9ae 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -2247,6 +2247,33 @@ bool SfxObjectShell::ImportFrom(SfxMedium& rMedium,
                     }
                 }
             }
+
+            // tdf#107690 import custom document property _MarkAsFinal as SecurityOptOpenReadonly
+            // (before this fix, LibreOffice opened read-only OOXML documents as editable,
+            // also saved and exported _MarkAsFinal=true silently, resulting unintented read-only
+            // warning info bar in MSO)
+            uno::Reference< document::XDocumentPropertiesSupplier > xPropSupplier(GetModel(), uno::UNO_QUERY_THROW);
+            uno::Reference<document::XDocumentProperties> xDocProps = xPropSupplier->getDocumentProperties() ;
+            uno::Reference<beans::XPropertyContainer> xPropertyContainer = xDocProps->getUserDefinedProperties();
+            if (xPropertyContainer.is())
+            {
+                uno::Reference<beans::XPropertySet> xPropertySet(xPropertyContainer, uno::UNO_QUERY);
+                if (xPropertySet.is())
+                {
+                    uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
+                    if (xPropertySetInfo.is() && xPropertySetInfo->hasPropertyByName("_MarkAsFinal"))
+                    {
+                        if (xPropertySet->getPropertyValue("_MarkAsFinal").get<bool>())
+                        {
+                            uno::Reference< lang::XMultiServiceFactory > xFactory(GetModel(), uno::UNO_QUERY);
+                            uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
+                            xSettings->setPropertyValue("LoadReadonly", uno::makeAny(true));
+                        }
+                        xPropertyContainer->removeProperty("_MarkAsFinal");
+                    }
+                }
+            }
+
             return bRtn;
         }
         catch (const packages::zip::ZipIOException&)
diff --git a/sw/qa/extras/ooxmlexport/data/open-as-read-only.docx b/sw/qa/extras/ooxmlexport/data/open-as-read-only.docx
new file mode 100644
index 000000000000..057c67ff6dfe
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/open-as-read-only.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 9882bb943f7b..f27c88facc67 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -394,6 +394,13 @@ DECLARE_OOXMLEXPORT_TEST(testTdf107969, "tdf107969.docx")
     // SAXParseException: '[word/document.xml line 2]: Extra content at the end of the document', Stream 'word/document.xml'.
 }
 
+DECLARE_OOXMLEXPORT_TEST(testOpenDocumentAsReadOnly, "open-as-read-only.docx")
+{
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    CPPUNIT_ASSERT(pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 68a04ba937d7..6199cbf94acd 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -887,14 +887,16 @@ void DocxExport::WriteProperties( )
     // Write the core properties
     SwDocShell* pDocShell( m_pDoc->GetDocShell( ) );
     uno::Reference<document::XDocumentProperties> xDocProps;
+    bool bSecurityOptOpenReadOnly = false;
     if ( pDocShell )
     {
         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
                pDocShell->GetModel( ), uno::UNO_QUERY );
         xDocProps = xDPS->getDocumentProperties();
+        bSecurityOptOpenReadOnly = pDocShell->IsSecurityOptOpenReadOnly();
     }
 
-    m_pFilter->exportDocumentProperties( xDocProps );
+    m_pFilter->exportDocumentProperties( xDocProps, bSecurityOptOpenReadOnly );
 }
 
 void DocxExport::WriteSettings()


More information about the Libreoffice-commits mailing list