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 <[email protected]> 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 <[email protected]> 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() _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
