summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/core/xmlfilterbase.hxx2
-rw-r--r--oox/source/core/xmlfilterbase.cxx50
-rw-r--r--sc/qa/unit/data/xlsx/open-as-read-only.xlsxbin0 -> 5211 bytes
-rw-r--r--sc/qa/unit/subsequent_export-test.cxx12
-rw-r--r--sc/source/filter/excel/excdoc.cxx2
-rw-r--r--sd/qa/unit/data/pptx/open-as-read-only.pptxbin0 -> 21569 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx12
-rw-r--r--sd/source/filter/eppt/pptx-epptooxml.cxx14
-rw-r--r--sfx2/source/doc/objstor.cxx27
-rw-r--r--sw/qa/extras/ooxmlexport/data/open-as-read-only.docxbin0 -> 4594 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport11.cxx7
-rw-r--r--sw/source/filter/ww8/docxexport.cxx4
12 files changed, 111 insertions, 19 deletions
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
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/open-as-read-only.xlsx
Binary files 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
--- /dev/null
+++ b/sd/qa/unit/data/pptx/open-as-read-only.pptx
Binary files 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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/open-as-read-only.docx
Binary files 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()