summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2022-03-10 11:00:36 +0100
committerLászló Németh <nemeth@numbertext.org>2022-03-10 19:14:04 +0100
commit64dcedcf7c073d1819794d68a33651b14877e1b5 (patch)
tree6e1c505ff798c511f8b16f0466f03400b3e1e4f1
parentf79ebdeaaacd08328142eedf048f77e11b035801 (diff)
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 <nemeth@numbertext.org>
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport12.cxx10
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport16.cxx6
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx147
3 files changed, 108 insertions, 55 deletions
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() );