[Libreoffice-commits] core.git: include/oox oox/source sc/source sd/source sfx2/source sw/source

László Németh nemeth at numbertext.org
Thu Jun 28 14:35:19 UTC 2018


 include/oox/core/xmlfilterbase.hxx       |    2 -
 oox/source/core/xmlfilterbase.cxx        |   50 +++++++++++++++++++++----------
 sc/source/filter/excel/excdoc.cxx        |    2 -
 sd/source/filter/eppt/pptx-epptooxml.cxx |   14 ++++++++
 sfx2/source/doc/objstor.cxx              |   27 ++++++++++++++++
 sw/source/filter/ww8/docxexport.cxx      |    4 +-
 6 files changed, 80 insertions(+), 19 deletions(-)

New commits:
commit 9a5c56a9c4e04589b0a6bb710573922e459d9685
Author: László Németh <nemeth at numbertext.org>
Date:   Wed Jun 20 16:28:13 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.
    
    Change-Id: Ie279c0670090d075103384cfa44ff1c2a2898216
    Reviewed-on: https://gerrit.libreoffice.org/56180
    Tested-by: Jenkins
    Reviewed-by: László Németh <nemeth at numbertext.org>

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/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/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx
index 59da0d6932c4..212821d7b56b 100644
--- a/sd/source/filter/eppt/pptx-epptooxml.cxx
+++ b/sd/source/filter/eppt/pptx-epptooxml.cxx
@@ -362,7 +362,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 9bc418f8f53a..f0fbca97941c 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -2248,6 +2248,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/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 9355677fed3c..c3bf421ef793 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -886,14 +886,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