sw/qa/extras/ooxmlexport/ooxmlexport12.cxx   |   10 +
 sw/qa/extras/ooxmlexport/ooxmlexport16.cxx   |    6 -
 sw/source/filter/ww8/docxattributeoutput.cxx |  147 ++++++++++++++++++---------
 3 files changed, 108 insertions(+), 55 deletions(-)

New commits:
commit 64dcedcf7c073d1819794d68a33651b14877e1b5
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Thu Mar 10 11:00:36 2022 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Mar 10 19:14:04 2022 +0100

    tdf#147760 tdf#142902 DOCX export: anonymize date and moveFromRangeStart
    
    Anonymization exported a zeroed w:date in change tracking
    and commenting elements w:ins, w:del, w:moveFrom, w:moveTo,
    w:cellIns, w:cellDel, w:comment, w:moveFromRangeStart and
    w:moveToRangeStart instead of simply skipping it, according
    to OOXML.
    
    Also don't export w:date, if the imported DOCX was anonymized
    by Word's Document Inspector, i.e. it doesn't contain w:date.
    
    Fix also missing anonymization of author and date of
    moveFromRangeStart and moveToRangeStart elements.
    
    Follow-up to commit 2c51746997478ad5d0e7cc64aa6489769c473d43
    "tdf#146171 DOCX: fix loss of change tracking, if no date",
    commit 9e1e88ad5cf2dc0e9b188c60930445652a6c7519
    "tdf#145720 DOCX export: fix loss of tracked moving" and
    commit ded2452a52d21131347a0dc2e25c8161f20fcfad
    "tdf#142902 DOCX export: remove personal info of comments and changes".
    
    Change-Id: If79402e4723886ceab3b4b9c24e83793f87cd513
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131317
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
index c568f7228a7b..5d1af7159fcf 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
@@ -1222,10 +1222,12 @@ DECLARE_OOXMLEXPORT_TEST(testTdf145720, 
"tdf104797.docx")
                     u"Tekijä");
         assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:moveTo/w:moveToRangeStart", "author",
                     u"Tekijä");
-        assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[1]/w:moveFrom/w:moveFromRangeStart", "date",
-                    "1970-01-01T00:00:00Z");
-        assertXPath(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:moveTo/w:moveToRangeStart", "date",
-                    "1970-01-01T00:00:00Z");
+        // no date (anonymized change)
+        // This failed, date was exported as w:date="0-00-00T00:00:00Z", and 
later "1970-01-01T00:00:00Z"
+        assertXPathNoAttribute(pXmlDoc, 
"/w:document/w:body/w:p[1]/w:moveFrom/w:moveFromRangeStart",
+                               "date");
+        assertXPathNoAttribute(pXmlDoc, 
"/w:document/w:body/w:p[2]/w:moveTo/w:moveToRangeStart",
+                               "date");
     }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index 543a7580bd79..b1637cfa3ad1 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -651,6 +651,7 @@ CPPUNIT_TEST_FIXTURE(Test, 
testTdf146171_invalid_change_date)
     // false alarm? during ODF roundtrip:
     // 'Error: "1970-01-01" does not satisfy the "dateTime" type'
     // disable and check only the conversion of the invalid (zeroed) change 
date
+    // 0000-00-00T00:00:00Z, resulting loss of change tracking during ODF 
roundtrip
     // reload("writer8", "tdf146171.odt");
     reload("Office Open XML Text", "tdf146171.docx");
 
@@ -659,8 +660,9 @@ CPPUNIT_TEST_FIXTURE(Test, 
testTdf146171_invalid_change_date)
     assertXPath(pXmlDoc, "//w:ins", 4);
     // This was 0
     assertXPath(pXmlDoc, "//w:del", 1);
-    // This was 0000-00-00T00:00:00Z, resulting loss of change tracking during 
ODF roundtrip
-    assertXPath(pXmlDoc, "//w:del", "date", "1970-01-01T00:00:00Z");
+    // no date (anonymized change)
+    // This failed, date was exported as w:date="1970-01-01T00:00:00Z" before 
fixing tdf#147760
+    assertXPathNoAttribute(pXmlDoc, "//w:del", "date");
 }
 
 DECLARE_OOXMLEXPORT_TEST(testTdf139580, "tdf139580.odt")
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index a0fd9fd0f995..11e890706e7a 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1914,16 +1914,32 @@ void 
DocxAttributeOutput::DoWriteBookmarkTagEnd(sal_Int32 const nId)
 void DocxAttributeOutput::DoWriteMoveRangeTagStart(const OString & 
bookmarkName,
     bool bFrom, const SwRedlineData* pRedlineData)
 {
-    const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( 
pRedlineData->GetAuthor() ) );
-    OString aDate( DateTimeToOString( pRedlineData->GetTimeStamp() ) );
+    bool bRemovePersonalInfo = SvtSecurityOptions::IsOptionSet(
+        SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo );
 
-    m_pSerializer->singleElementNS(XML_w, bFrom
+    const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( 
pRedlineData->GetAuthor() ) );
+    const DateTime aDateTime = pRedlineData->GetTimeStamp();
+    bool bNoDate = bRemovePersonalInfo ||
+        ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
+    if ( bNoDate )
+        m_pSerializer->singleElementNS(XML_w, bFrom
                 ? XML_moveFromRangeStart
                 : XML_moveToRangeStart,
-        FSNS(XML_w, XML_id), OString::number(m_nNextBookmarkId),
-        FSNS(XML_w, XML_author ), OUStringToOString(rAuthor, 
RTL_TEXTENCODING_UTF8),
-        FSNS(XML_w, XML_date ), aDate,
-        FSNS(XML_w, XML_name), bookmarkName);
+            FSNS(XML_w, XML_id), OString::number(m_nNextBookmarkId),
+            FSNS(XML_w, XML_author ), bRemovePersonalInfo
+                    ? "Author" + OString::number( 
GetExport().GetInfoID(rAuthor) )
+                    : OUStringToOString(rAuthor, RTL_TEXTENCODING_UTF8),
+            FSNS(XML_w, XML_name), bookmarkName);
+    else
+        m_pSerializer->singleElementNS(XML_w, bFrom
+                ? XML_moveFromRangeStart
+                : XML_moveToRangeStart,
+            FSNS(XML_w, XML_id), OString::number(m_nNextBookmarkId),
+            FSNS(XML_w, XML_author ), bRemovePersonalInfo
+                    ? "Author" + OString::number( 
GetExport().GetInfoID(rAuthor) )
+                    : OUStringToOString(rAuthor, RTL_TEXTENCODING_UTF8),
+            FSNS(XML_w, XML_date ), DateTimeToOString( aDateTime ),
+            FSNS(XML_w, XML_name), bookmarkName);
 }
 
 void DocxAttributeOutput::DoWriteMoveRangeTagEnd(sal_Int32 const nId, bool 
bFrom)
@@ -3486,9 +3502,9 @@ void DocxAttributeOutput::Redline( const SwRedlineData* 
pRedlineData)
 
     OString aId( OString::number( pRedlineData->GetSeqNo() ) );
     const OUString &rAuthor( SW_MOD()->GetRedlineAuthor( 
pRedlineData->GetAuthor() ) );
-    OString aDate( DateTimeToOString( bRemovePersonalInfo
-            ? DateTime(Date( 1, 1, 1970 )) // Epoch time
-            : pRedlineData->GetTimeStamp() ) );
+    const DateTime aDateTime = pRedlineData->GetTimeStamp();
+    bool bNoDate = bRemovePersonalInfo ||
+        ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
 
     switch( pRedlineData->GetType() )
     {
@@ -3499,12 +3515,19 @@ void DocxAttributeOutput::Redline( const SwRedlineData* 
pRedlineData)
         break;
 
     case RedlineType::Format:
-        m_pSerializer->startElementNS( XML_w, XML_rPrChange,
+        if ( bNoDate )
+            m_pSerializer->startElementNS( XML_w, XML_rPrChange,
+                FSNS( XML_w, XML_id ), aId,
+                FSNS( XML_w, XML_author ), bRemovePersonalInfo
+                    ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
+                    : rAuthor );
+        else
+            m_pSerializer->startElementNS( XML_w, XML_rPrChange,
                 FSNS( XML_w, XML_id ), aId,
                 FSNS( XML_w, XML_author ), bRemovePersonalInfo
                     ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
                     : rAuthor,
-                FSNS( XML_w, XML_date ), aDate );
+                FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ) );
 
         // Check if there is any extra data stored in the redline object
         if (pRedlineData->GetExtraData())
@@ -3538,12 +3561,19 @@ void DocxAttributeOutput::Redline( const SwRedlineData* 
pRedlineData)
         break;
 
     case RedlineType::ParagraphFormat:
-        m_pSerializer->startElementNS( XML_w, XML_pPrChange,
+        if ( bNoDate )
+            m_pSerializer->startElementNS( XML_w, XML_pPrChange,
+                FSNS( XML_w, XML_id ), aId,
+                FSNS( XML_w, XML_author ), bRemovePersonalInfo
+                    ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
+                    : rAuthor );
+        else
+            m_pSerializer->startElementNS( XML_w, XML_pPrChange,
                 FSNS( XML_w, XML_id ), aId,
                 FSNS( XML_w, XML_author ), bRemovePersonalInfo
                     ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
                     : rAuthor,
-                FSNS( XML_w, XML_date ), aDate );
+                FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ) );
 
         // Check if there is any extra data stored in the redline object
         if (pRedlineData->GetExtraData())
@@ -3624,27 +3654,29 @@ void DocxAttributeOutput::StartRedline( const 
SwRedlineData * pRedlineData )
                         ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
                         : rAuthor, RTL_TEXTENCODING_UTF8 ) );
 
-    OString aDate( DateTimeToOString( bRemovePersonalInfo
-            ? DateTime(Date( 1, 1, 1970 )) // Epoch time
-            : pRedlineData->GetTimeStamp() ) );
-
+    const DateTime aDateTime = pRedlineData->GetTimeStamp();
+    bool bNoDate = bRemovePersonalInfo ||
+        ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
     bool bMoved = pRedlineData->IsMoved();
     switch ( pRedlineData->GetType() )
     {
         case RedlineType::Insert:
-            m_pSerializer->startElementNS( XML_w, bMoved ? XML_moveTo : 
XML_ins,
-                    FSNS( XML_w, XML_id ), aId,
-                    FSNS( XML_w, XML_author ), aAuthor,
-                    FSNS( XML_w, XML_date ), aDate );
-            break;
-
         case RedlineType::Delete:
-            m_pSerializer->startElementNS( XML_w, bMoved ? XML_moveFrom : 
XML_del,
+        {
+            sal_Int32 eElement = RedlineType::Insert == pRedlineData->GetType()
+                ? ( bMoved ? XML_moveTo : XML_ins )
+                : ( bMoved ? XML_moveFrom : XML_del );
+            if ( bNoDate )
+                m_pSerializer->startElementNS( XML_w, eElement,
+                    FSNS( XML_w, XML_id ), aId,
+                    FSNS( XML_w, XML_author ), aAuthor );
+            else
+                m_pSerializer->startElementNS( XML_w, eElement,
                     FSNS( XML_w, XML_id ), aId,
                     FSNS( XML_w, XML_author ), aAuthor,
-                    FSNS( XML_w, XML_date ), aDate );
+                    FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ) );
             break;
-
+        }
         case RedlineType::Format:
             SAL_INFO("sw.ww8", "TODO DocxAttributeOutput::StartRedline()" );
             break;
@@ -4745,15 +4777,21 @@ void DocxAttributeOutput::TableRowRedline( 
ww8::WW8TableNodeInfoInner::Pointer_t
                         ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
                         : rAuthor, RTL_TEXTENCODING_UTF8 ) );
 
-        OString aDate( DateTimeToOString( bRemovePersonalInfo
-                    ? DateTime(Date( 1, 1, 1970 )) // Epoch time
-                    : aRedlineData.GetTimeStamp() ) );
+        const DateTime aDateTime = aRedlineData.GetTimeStamp();
+        bool bNoDate = bRemovePersonalInfo ||
+            ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
 
-        m_pSerializer->singleElementNS( XML_w,
+        if ( bNoDate )
+            m_pSerializer->singleElementNS( XML_w,
+                            RedlineType::Delete == pRedline->GetType() ? 
XML_del : XML_ins,
+                            FSNS( XML_w, XML_id ), aId,
+                            FSNS( XML_w, XML_author ), aAuthor );
+        else
+            m_pSerializer->singleElementNS( XML_w,
                             RedlineType::Delete == pRedline->GetType() ? 
XML_del : XML_ins,
                             FSNS( XML_w, XML_id ), aId,
                             FSNS( XML_w, XML_author ), aAuthor,
-                            FSNS( XML_w, XML_date ), aDate );
+                            FSNS( XML_w, XML_date ), DateTimeToOString( 
aDateTime ) );
         return;
     }
 }
@@ -4787,20 +4825,21 @@ void DocxAttributeOutput::TableCellRedline( 
ww8::WW8TableNodeInfoInner::Pointer_
                         ? "Author" + OUString::number( 
GetExport().GetInfoID(rAuthor) )
                         : rAuthor, RTL_TEXTENCODING_UTF8 ) );
 
-                    OString aDate( DateTimeToOString( bRemovePersonalInfo
-                            ? DateTime(Date( 1, 1, 1970 )) // Epoch time
-                            : aRedlineData.GetTimeStamp() ) );
-
-                    if (nRedlineType == RedlineType::TableCellInsert)
-                        m_pSerializer->singleElementNS( XML_w, XML_cellIns,
+                    sal_Int32 nElement = nRedlineType == 
RedlineType::TableCellInsert
+                        ? XML_cellIns
+                        : XML_cellDel;
+                    const DateTime aDateTime = aRedlineData.GetTimeStamp();
+                    bool bNoDate = bRemovePersonalInfo || ( 
aDateTime.GetYear() == 1970 &&
+                                        aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
+                    if ( bNoDate )
+                        m_pSerializer->singleElementNS( XML_w, nElement,
                             FSNS( XML_w, XML_id ), aId,
-                            FSNS( XML_w, XML_author ), aAuthor,
-                            FSNS( XML_w, XML_date ), aDate );
-                    else if (nRedlineType == RedlineType::TableCellDelete)
-                        m_pSerializer->singleElementNS( XML_w, XML_cellDel,
+                            FSNS( XML_w, XML_author ), aAuthor );
+                    else
+                        m_pSerializer->singleElementNS( XML_w, nElement,
                             FSNS( XML_w, XML_id ), aId,
                             FSNS( XML_w, XML_author ), aAuthor,
-                            FSNS( XML_w, XML_date ), aDate );
+                            FSNS( XML_w, XML_date ), DateTimeToOString( 
aDateTime ) );
                 }
                 break;
                 default: break;
@@ -8499,14 +8538,24 @@ DocxAttributeOutput::hasResolved 
DocxAttributeOutput::WritePostitFields()
     for (auto& [f, data] : m_postitFields)
     {
         OString idstr = OString::number(data.id);
-        m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, XML_id 
), idstr,
-            FSNS( XML_w, XML_author ), bRemovePersonalInfo
+        const DateTime aDateTime = f->GetDateTime();
+        bool bNoDate = bRemovePersonalInfo ||
+            ( aDateTime.GetYear() == 1970 && aDateTime.GetMonth() == 1 && 
aDateTime.GetDay() == 1 );
+        if ( bNoDate )
+            m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, 
XML_id ), idstr,
+                FSNS( XML_w, XML_author ), bRemovePersonalInfo
+                     ? "Author" + OUString::number( 
GetExport().GetInfoID(f->GetPar1()) )
+                     : f->GetPar1(),
+                FSNS( XML_w, XML_initials ), bRemovePersonalInfo
+                     ? OUString::number( 
GetExport().GetInfoID(f->GetInitials()) )
+                     : f->GetInitials() );
+        else
+            m_pSerializer->startElementNS( XML_w, XML_comment, FSNS( XML_w, 
XML_id ), idstr,
+                FSNS( XML_w, XML_author ), bRemovePersonalInfo
                      ? "Author" + OUString::number( 
GetExport().GetInfoID(f->GetPar1()) )
                      : f->GetPar1(),
-            FSNS( XML_w, XML_date ), DateTimeToOString( bRemovePersonalInfo
-                     ? util::DateTime() // "no date" time
-                     : f->GetDateTime() ),
-            FSNS( XML_w, XML_initials ), bRemovePersonalInfo
+                FSNS( XML_w, XML_date ), DateTimeToOString( aDateTime ),
+                FSNS( XML_w, XML_initials ), bRemovePersonalInfo
                      ? OUString::number( 
GetExport().GetInfoID(f->GetInitials()) )
                      : f->GetInitials() );
 

Reply via email to