diff options
author | László Németh <nemeth@numbertext.org> | 2018-06-20 16:28:13 +0200 |
---|---|---|
committer | László Németh <nemeth@numbertext.org> | 2018-06-28 16:34:52 +0200 |
commit | 9a5c56a9c4e04589b0a6bb710573922e459d9685 (patch) | |
tree | ce22578a4ca4992bdf64c18f1012dd515540ebfa /oox | |
parent | 9c368751f6fbc50209e621182c3415ef4c4db29d (diff) |
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@numbertext.org>
Diffstat (limited to 'oox')
-rw-r--r-- | oox/source/core/xmlfilterbase.cxx | 50 |
1 files changed, 35 insertions, 15 deletions
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 ); } } |