oox/source/core/xmlfilterbase.cxx                    |  126 +++++++++++++++----
 oox/source/docprop/docprophandler.cxx                |   51 +++++--
 sw/qa/extras/ooxmlexport/data/custom-properties.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport2.cxx            |   51 +++++--
 4 files changed, 175 insertions(+), 53 deletions(-)

New commits:
commit a87af93ff874a55b81e55b46b63798fde4cefc4f
Author:     Bartosz Kosiorek <gan...@poczta.onet.pl>
AuthorDate: Thu Oct 15 19:57:45 2020 +0200
Commit:     Bartosz Kosiorek <gan...@poczta.onet.pl>
CommitDate: Thu Oct 22 14:42:27 2020 +0200

    tdf#103987 Avoid duplication of the Custom Properties during OOXML export
    
    The MS Office is case insensitive for Properties.
    As a result properties names: ContentType and contentType
    are treated as the same properties.
    Additionally some Core and Extended File Properties does not exist
    in LibreOffice standard.
    
    To resolve that such properties are stored in LibreOffice Custom File 
Properties.
    For example:
     - category
     - contentStatus
     - contentType
     - identifier
     - version
    
    Unfortunately if user specify Custom Property which differ only with case,
    there will be conflict. To solve that the properties were renamed to be 
unique:
     - OOXMLCorePropertiesCategory
     - OOXMLCorePropertiesContentStatus
     - OOXMLCorePropertiesContentType
     - OOXMLCorePropertiesIdentifier
     - OOXMLCorePropertiesVersion
    
    Additionally if internal property have default value, then the value will
    not be imported into Custom File Property.
    During export to OOXML (eg. docx) The values which are already stored
    in Core or Extended File Properties, are not stored
    into Custom File Properties to avoid duplication.
    
    Change-Id: Ifc2b88ab74aa41d12ba968fff199062ce8dc96ee
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104384
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>
    Reviewed-by: Bartosz Kosiorek <gan...@poczta.onet.pl>

diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index 43f4e573229a..259e0bf2e406 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -640,17 +640,44 @@ writeCoreProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentProperties
         FSNS(XML_xmlns, XML_dcmitype), rSelf.getNamespaceURL(OOX_NS(dcmiType)),
         FSNS(XML_xmlns, XML_xsi),      rSelf.getNamespaceURL(OOX_NS(xsi)));
 
-#ifdef OOXTODO
-    writeElement( pCoreProps, FSNS( XML_cp, XML_category ),         "category" 
);
-    writeElement( pCoreProps, FSNS( XML_cp, XML_contentStatus ),    "status" );
-    writeElement( pCoreProps, FSNS( XML_cp, XML_contentType ),      
"contentType" );
-#endif  /* def OOXTODO */
+    uno::Reference<beans::XPropertyAccess> 
xUserDefinedProperties(xProperties->getUserDefinedProperties(), uno::UNO_QUERY);
+    comphelper::SequenceAsHashMap 
aUserDefinedProperties(xUserDefinedProperties->getPropertyValues());
+    comphelper::SequenceAsHashMap::iterator it;
+
+    it = aUserDefinedProperties.find("OOXMLCorePropertyCategory");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pCoreProps, FSNS( XML_cp, XML_category ), aValue );
+    }
+
+    it = aUserDefinedProperties.find("OOXMLCorePropertyContentStatus");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pCoreProps, FSNS( XML_cp, XML_contentStatus ), 
aValue );
+    }
+
+    it = aUserDefinedProperties.find("OOXMLCorePropertyContentType");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pCoreProps, FSNS( XML_cp, XML_contentType ), aValue 
);
+    }
     writeElement( pCoreProps, FSNS( XML_dcterms, XML_created ),     
xProperties->getCreationDate() );
     writeElement( pCoreProps, FSNS( XML_dc, XML_creator ),          
xProperties->getAuthor() );
     writeElement( pCoreProps, FSNS( XML_dc, XML_description ),      
xProperties->getDescription() );
-#ifdef OOXTODO
-    writeElement( pCoreProps, FSNS( XML_dc, XML_identifier ),       "ident" );
-#endif  /* def OOXTODO */
+
+    it = aUserDefinedProperties.find("OOXMLCorePropertyIdentifier");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pCoreProps, FSNS( XML_dc, XML_identifier ), aValue );
+    }
     writeElement( pCoreProps, FSNS( XML_cp, XML_keywords ),         
xProperties->getKeywords() );
     writeElement( pCoreProps, FSNS( XML_dc, XML_language ),         
LanguageTag( xProperties->getLanguage()) );
     writeElement( pCoreProps, FSNS( XML_cp, XML_lastModifiedBy ),   
xProperties->getModifiedBy() );
@@ -659,9 +686,14 @@ writeCoreProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentProperties
     writeElement( pCoreProps, FSNS( XML_cp, XML_revision ),         
xProperties->getEditingCycles() );
     writeElement( pCoreProps, FSNS( XML_dc, XML_subject ),          
xProperties->getSubject() );
     writeElement( pCoreProps, FSNS( XML_dc, XML_title ),            
xProperties->getTitle() );
-#ifdef OOXTODO
-    writeElement( pCoreProps, FSNS( XML_cp, XML_version ),          "version" 
);
-#endif  /* def OOXTODO */
+
+    it = aUserDefinedProperties.find("OOXMLCorePropertyVersion");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pCoreProps, FSNS( XML_cp, XML_version ), aValue );
+    }
 
     pCoreProps->endElementNS( XML_cp, XML_coreProperties );
 }
@@ -679,9 +711,21 @@ writeAppProperties( XmlFilterBase& rSelf, const Reference< 
XDocumentProperties >
             XML_xmlns,               
rSelf.getNamespaceURL(OOX_NS(officeExtPr)),
             FSNS(XML_xmlns, XML_vt), 
rSelf.getNamespaceURL(OOX_NS(officeDocPropsVT)));
 
+    uno::Reference<beans::XPropertyAccess> 
xUserDefinedProperties(xProperties->getUserDefinedProperties(), uno::UNO_QUERY);
+    comphelper::SequenceAsHashMap 
aUserDefinedProperties(xUserDefinedProperties->getPropertyValues());
+    comphelper::SequenceAsHashMap::iterator it;
+
     writeElement( pAppProps, XML_Template,              
xProperties->getTemplateName() );
+
+    it = aUserDefinedProperties.find("Manager");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pAppProps, XML_Manager,       aValue );
+    }
+
 #ifdef OOXTODO
-    writeElement( pAppProps, XML_Manager,               "manager" );
     writeElement( pAppProps, XML_PresentationFormat,    "presentation format" 
);
     writeElement( pAppProps, XML_Lines,                 "lines" );
     writeElement( pAppProps, XML_Slides,                "slides" );
@@ -697,19 +741,37 @@ writeAppProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentProperties >
     writeElement( pAppProps, XML_TitlesOfParts,         "titles of parts" );
     writeElement( pAppProps, XML_LinksUpToDate,         "links up-to-date" );
     writeElement( pAppProps, XML_SharedDoc,             "shared doc" );
-    writeElement( pAppProps, XML_HyperlinkBase,         "hyperlink base" );
     writeElement( pAppProps, XML_HLinks,                "hlinks" );
     writeElement( pAppProps, XML_HyperlinksChanged,     "hyperlinks changed" );
     writeElement( pAppProps, XML_DigSig,                "digital signature" );
 #endif  /* def OOXTODO */
     writeElement( pAppProps, XML_Application,           
utl::DocInfoHelper::GetGeneratorString() );
-#ifdef OOXTODO
-    writeElement( pAppProps, XML_AppVersion,            "app version" );
-    writeElement( pAppProps, XML_DocSecurity,           "doc security" );
-#endif  /* def OOXTODO */
+
+    it = aUserDefinedProperties.find("HyperlinkBase");
+    if (it != aUserDefinedProperties.end())
+    {
+        OUString aValue;
+        if (it->second >>= aValue)
+            writeElement( pAppProps, XML_HyperlinkBase, aValue );
+    }
+    // AppVersion specifies the version of the application which produced 
document
+    // It is strictly connected with MS Office versions:
+    //     * 12:  [Office 2007]  [LO < 7.0]
+    //     * 14:  [Office 2010]
+    //     * 15:  [Office 2013/2016/2019]  [LO >= 7.0]
+    // The LibreOffice is application on 2013/2016/2019 level
+    writeElement( pAppProps, XML_AppVersion, "15.0000" );
+
+    // OOXTODO Calculate DocSecurity value based on security (password, 
read-only etc.)
+    it = aUserDefinedProperties.find("DocSecurity");
+    if (it != aUserDefinedProperties.end())
+    {
+        sal_Int32 nValue;
+        if (it->second >>= nValue)
+            writeElement( pAppProps, XML_DocSecurity, nValue );
+    }
 
     comphelper::SequenceAsHashMap aStats = 
xProperties->getDocumentStatistics();
-    comphelper::SequenceAsHashMap::iterator it;
     sal_Int32 nValue = 0;
 
     it = aStats.find("PageCount");
@@ -747,8 +809,6 @@ writeAppProperties( XmlFilterBase& rSelf, const Reference< 
XDocumentProperties >
                 writeElement(pAppProps, XML_Paragraphs, nValue);
     }
 
-    uno::Reference<beans::XPropertyAccess> 
xUserDefinedProperties(xProperties->getUserDefinedProperties(), uno::UNO_QUERY);
-    comphelper::SequenceAsHashMap 
aUserDefinedProperties(xUserDefinedProperties->getPropertyValues());
     it = aUserDefinedProperties.find("Company");
     if (it != aUserDefinedProperties.end())
     {
@@ -797,6 +857,19 @@ writeCustomProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentPropertie
         if ( !rProp.Name.isEmpty() )
         {
             OString aName = OUStringToOString( rProp.Name, 
RTL_TEXTENCODING_ASCII_US );
+            // Skip storing these values in Custom Properties as it will be 
stored in Core/Extended Properties
+            if (( aName == "OOXMLCorePropertyCategory" ) || // stored in 
cp:category
+                ( aName == "OOXMLCorePropertyContentStatus" ) || // stored in 
cp:contentStatus
+                ( aName == "OOXMLCorePropertyContentType" ) || // stored in 
cp:contentType
+                ( aName == "OOXMLCorePropertyIdentifier" ) || // stored in 
dc:identifier
+                ( aName == "OOXMLCorePropertyVersion" ) || // stored in 
cp:version
+                ( aName == "HyperlinkBase" ) || // stored in Extended File 
Properties
+                ( aName == "AppVersion" ) || // stored in Extended File 
Properties
+                ( aName == "DocSecurity" ) || // stored in Extended File 
Properties
+                ( aName == "Manager" ) || // stored in Extended File Properties
+                ( aName == "Company" )) // stored in Extended File Properties
+                continue;
+
             // pid starts from 2 not from 1 as MS supports pid from 2
             pAppProps->startElement( XML_property ,
                 XML_fmtid,  "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}",
@@ -818,16 +891,25 @@ writeCustomProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentPropertie
                     writeElement( pAppProps, FSNS( XML_vt, XML_bool ), val ? 1 
: 0);
                 }
                 break;
+                case TypeClass_DOUBLE:
+                {
+                    double num = {}; // spurious -Werror=maybe-uninitialized
+                    if ( rProp.Value >>= num )
+                    {
+                        // r8 - 8-byte real number
+                        writeElement( pAppProps, FSNS( XML_vt, XML_r8 ), 
OUString::number(num) );
+                    }
+                }
+                break;
                 default:
                 {
-                    double num;
+                    double num = {}; // spurious -Werror=maybe-uninitialized
                     util::Date aDate;
                     util::Duration aDuration;
                     util::DateTime aDateTime;
                     if ( rProp.Value >>= num )
                     {
                         // i4 - 4-byte signed integer
-                        // r8 - 8-byte real number
                         writeElement( pAppProps, FSNS( XML_vt, XML_i4 ), num );
                     }
                     else if ( rProp.Value >>= aDate )
diff --git a/oox/source/docprop/docprophandler.cxx 
b/oox/source/docprop/docprophandler.cxx
index e26db66b12c6..07f9b4c0dc72 100644
--- a/oox/source/docprop/docprophandler.cxx
+++ b/oox/source/docprop/docprophandler.cxx
@@ -414,27 +414,27 @@ void SAL_CALL OOXMLDocPropHandler::characters( const 
OUString& aChars )
                 switch( m_nBlock )
                 {
                 case COREPR_TOKEN( category ):
-                    m_aCustomPropertyName = "category";
+                    m_aCustomPropertyName = "OOXMLCorePropertyCategory";
                     AddCustomProperty( uno::makeAny( aChars ) ); // the 
property has string type
                     break;
 
                 case COREPR_TOKEN( contentStatus ):
-                    m_aCustomPropertyName = "contentStatus";
+                    m_aCustomPropertyName = "OOXMLCorePropertyContentStatus";
                     AddCustomProperty( uno::makeAny( aChars ) ); // the 
property has string type
                     break;
 
                 case COREPR_TOKEN( contentType ):
-                    m_aCustomPropertyName = "contentType";
+                    m_aCustomPropertyName = "OOXMLCorePropertyContentType";
                     AddCustomProperty( uno::makeAny( aChars ) ); // the 
property has string type
                     break;
 
-                case COREPR_TOKEN( identifier ):
-                    m_aCustomPropertyName = "identifier";
+                case DC_TOKEN( identifier ):
+                    m_aCustomPropertyName = "OOXMLCorePropertyIdentifier";
                     AddCustomProperty( uno::makeAny( aChars ) ); // the 
property has string type
                     break;
 
                 case COREPR_TOKEN( version ):
-                    m_aCustomPropertyName = "version";
+                    m_aCustomPropertyName = "OOXMLCorePropertyVersion";
                     AddCustomProperty( uno::makeAny( aChars ) ); // the 
property has string type
                     break;
 
@@ -537,47 +537,68 @@ void SAL_CALL OOXMLDocPropHandler::characters( const 
OUString& aChars )
 
                 case EXTPR_TOKEN( HyperlinksChanged ):
                     m_aCustomPropertyName = "HyperlinksChanged";
-                    AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); 
// the property has boolean type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toBoolean() )
+                        AddCustomProperty( uno::makeAny( aChars.toBoolean() ) 
); // the property has boolean type
                     break;
 
                 case EXTPR_TOKEN( LinksUpToDate ):
                     m_aCustomPropertyName = "LinksUpToDate";
-                    AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); 
// the property has boolean type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toBoolean() )
+                        AddCustomProperty( uno::makeAny( aChars.toBoolean() ) 
); // the property has boolean type
                     break;
 
                 case EXTPR_TOKEN( ScaleCrop ):
                     m_aCustomPropertyName = "ScaleCrop";
-                    AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); 
// the property has boolean type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toBoolean() )
+                        AddCustomProperty( uno::makeAny( aChars.toBoolean() ) 
); // the property has boolean type
                     break;
 
                 case EXTPR_TOKEN( SharedDoc ):
                     m_aCustomPropertyName = "ShareDoc";
-                    AddCustomProperty( uno::makeAny( aChars.toBoolean() ) ); 
// the property has boolean type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toBoolean() )
+                        AddCustomProperty( uno::makeAny( aChars.toBoolean() ) 
); // the property has boolean type
                     break;
 
                 case EXTPR_TOKEN( DocSecurity ):
                     m_aCustomPropertyName = "DocSecurity";
-                    AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // 
the property has sal_Int32 type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    // OOXTODO Instead of storing value, enable security
+                    // 1 - password protected, 2 - recommended read-only
+                    // 4 - enforced read-only, 8 - locked for annotation
+                    if ( aChars.toInt32() != 0 )
+                        AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); 
// the property has sal_Int32 type
                     break;
 
                 case EXTPR_TOKEN( HiddenSlides ):
                     m_aCustomPropertyName = "HiddenSlides";
-                    AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // 
the property has sal_Int32 type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toInt32() != 0 )
+                        AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); 
// the property has sal_Int32 type
                     break;
 
                 case EXTPR_TOKEN( MMClips ):
                     m_aCustomPropertyName = "MMClips";
-                    AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // 
the property has sal_Int32 type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toInt32() != 0 )
+                        AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); 
// the property has sal_Int32 type
                     break;
 
                 case EXTPR_TOKEN( Notes ):
                     m_aCustomPropertyName = "Notes";
-                    AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // 
the property has sal_Int32 type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toInt32() != 0 )
+                        AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); 
// the property has sal_Int32 type
                     break;
 
                 case EXTPR_TOKEN( Slides ):
                     m_aCustomPropertyName = "Slides";
-                    AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); // 
the property has sal_Int32 type
+                    // tdf#103987 Don't create custom property if the value is 
default
+                    if ( aChars.toInt32() != 0 )
+                        AddCustomProperty( uno::makeAny( aChars.toInt32() ) ); 
// the property has sal_Int32 type
                     break;
 
                 case EXTPR_TOKEN( AppVersion ):
diff --git a/sw/qa/extras/ooxmlexport/data/custom-properties.docx 
b/sw/qa/extras/ooxmlexport/data/custom-properties.docx
index 33cce91f7ec4..4d104cb26824 100644
Binary files a/sw/qa/extras/ooxmlexport/data/custom-properties.docx and 
b/sw/qa/extras/ooxmlexport/data/custom-properties.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
index a77d41b64094..6906989d645b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
@@ -86,42 +86,57 @@ DECLARE_OOXMLEXPORT_TEST(testPageGraphicBackground, 
"page-graphic-background.odt
 }
 
 
-DECLARE_OOXMLEXPORT_TEST(testCustomProperties, "custom-properties.docx")
+DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testCustomProperties, 
"custom-properties.docx")
 {
-    // tdf#133377 FILESAVE XLSX: Make sure the custom/core/application file 
properties
-    // are stored correctly after roundtrip to .docx
+    // tdf#133377  tdf#103987 FILESAVE XLSX: Make sure the 
custom/core/application
+    // file properties are stored correctly after roundtrip to .docx
 
     // Extended file properties - specific to Office package,
     // eg. docx - Number of Pages, pptx - Number of Slides
     xmlDocUniquePtr pXmlDoc = parseExport("docProps/app.xml");
-    if (!pXmlDoc)
-        return;
-
     assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Paragraphs", "1");
     //assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Lines", "1");
     assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Pages", "1");
     assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Words", "3");
-    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Characters", "21");
-    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:CharactersWithSpaces", 
"23");
+    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Characters", "22");
+    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:CharactersWithSpaces", 
"24");
     assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Company", "hhhhkompany");
+    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:Manager", "ffffmenadzer");
+    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:HyperlinkBase", 
"gggghiperlink");
+    //assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:DocSecurity", "2");
+    assertXPathContent(pXmlDoc, 
"/extended-properties:Properties/extended-properties:AppVersion", "15.0000");
 
     // Custom file properties - defined by user
     xmlDocUniquePtr pCustomXml = parseExport("docProps/custom.xml");
-    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[12]",
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property", 8);
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[1]",
                 "name", "testDateProperty");
-    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[12]/vt:filetime",
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[1]/vt:filetime",
                        "1982-04-19T10:00:00Z");
-    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[14]",
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[3]",
                 "name", "testNegativeNumberProperty");
-    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[14]/vt:i4",
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[3]/vt:r8",
                        "-100");
-    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[17]",
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[4]",
+                "name", "testNumberProperty");
+    //assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[4]/vt:i4",
+    //                   "256");
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[5]",
+                "name", "testRealNumberProperty");
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[5]/vt:r8",
+                       "-128.1");
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[6]",
                 "name", "testTextProperty");
-    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[17]/vt:lpwstr",
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[6]/vt:lpwstr",
                        "testPropertyValue");
-    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[18]",
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[7]",
                 "name", "testYesNoProperty");
-    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[18]/vt:bool",
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[7]/vt:bool",
+                       "1");
+    // Hidden Custom File Property. With Final set, MS Office notifies 
recipients that the document is final, and sets the document to read-only.
+    assertXPath(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[8]",
+                "name", "_MarkAsFinal");
+    assertXPathContent(pCustomXml, 
"/custom-properties:Properties/custom-properties:property[8]/vt:bool",
                        "1");
 
     // Core file properties - common for all packages (eg. creation date, 
modify date)
@@ -130,6 +145,10 @@ DECLARE_OOXMLEXPORT_TEST(testCustomProperties, 
"custom-properties.docx")
     assertXPathContent(pXmlDoc, "/cp:coreProperties/dc:description", 
"cccckomentarzglowny");
     assertXPathContent(pXmlDoc, "/cp:coreProperties/cp:lastPrinted", 
"2020-10-15T07:42:00Z");
     assertXPathContent(pXmlDoc, "/cp:coreProperties/dcterms:created", 
"2020-10-14T16:23:00Z");
+    assertXPathContent(pXmlDoc, "/cp:coreProperties/cp:category", 
"eeeetokategoria");
+    assertXPathContent(pXmlDoc, "/cp:coreProperties/cp:version", 
"xxxxversion");
+    assertXPathContent(pXmlDoc, "/cp:coreProperties/cp:contentStatus", 
"ddddstatusnieznany");
+    assertXPathContent(pXmlDoc, "/cp:coreProperties/dc:identifier", 
"zzzzidentifier");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testZoom, "zoom.docx")
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to