sd/qa/unit/data/pptx/pres-with-notes.pptx |binary sd/qa/unit/export-tests-ooxml4.cxx | 35 ++++++++++++++++++++++++++++++ sd/source/filter/eppt/epptooxml.hxx | 4 +++ sd/source/filter/eppt/pptx-epptooxml.cxx | 32 +++++++++++++++++++++++---- sw/source/core/crsr/swcrsr.cxx | 15 ++++++++++++ 5 files changed, 80 insertions(+), 6 deletions(-)
New commits: commit 76e9c0d24dc423cf65d885143810a5af7ec6598d Author: Samuel Mehrbrodt <[email protected]> AuthorDate: Thu Jun 13 15:09:13 2024 +0200 Commit: Xisco Fauli <[email protected]> CommitDate: Fri Jun 21 12:44:25 2024 +0200 pptx: Don't export notes author/date when in privacy mode Change-Id: Ia2f20b05b043d45df090f2843a4d365c692770fd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168813 Reviewed-by: Samuel Mehrbrodt <[email protected]> Tested-by: Jenkins Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168987 diff --git a/sd/qa/unit/data/pptx/pres-with-notes.pptx b/sd/qa/unit/data/pptx/pres-with-notes.pptx new file mode 100644 index 000000000000..25f9692a2a1c Binary files /dev/null and b/sd/qa/unit/data/pptx/pres-with-notes.pptx differ diff --git a/sd/qa/unit/export-tests-ooxml4.cxx b/sd/qa/unit/export-tests-ooxml4.cxx index 63af283d664f..0e11eb581bf0 100644 --- a/sd/qa/unit/export-tests-ooxml4.cxx +++ b/sd/qa/unit/export-tests-ooxml4.cxx @@ -14,6 +14,7 @@ #include <editeng/editobj.hxx> #include <editeng/numitem.hxx> #include <docmodel/uno/UnoGradientTools.hxx> +#include <officecfg/Office/Common.hxx> #include <svx/xlineit0.hxx> #include <svx/xlndsit.hxx> @@ -1095,6 +1096,40 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTdf102261_testParaTabStopDefaultDis } } +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testNotesAuthorDate) +{ + createSdImpressDoc("pptx/pres-with-notes.pptx"); + + auto pBatch(comphelper::ConfigurationChanges::create()); + // 1. Remove all personal info, but keep note info + officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::set(true, pBatch); + officecfg::Office::Common::Security::Scripting::KeepNoteAuthorDateInfoOnSaving::set(true, + pBatch); + pBatch->commit(); + + saveAndReload(u"Impress Office Open XML"_ustr); + + xmlDocUniquePtr pXml = parseExport(u"ppt/commentAuthors.xml"_ustr); + assertXPath(pXml, "/p:cmAuthorLst/p:cmAuthor[@id=0]"_ostr, "name"_ostr, "Hans Wurst"); + assertXPath(pXml, "/p:cmAuthorLst/p:cmAuthor[@id=1]"_ostr, "name"_ostr, "Max Muster"); + + pXml = parseExport(u"ppt/comments/comment1.xml"_ustr); + assertXPath(pXml, "/p:cmLst/p:cm"_ostr, "dt"_ostr, "2024-06-13T12:03:08.000000000"); + + // 2. Remove all personal info + officecfg::Office::Common::Security::Scripting::KeepNoteAuthorDateInfoOnSaving::set(false, + pBatch); + pBatch->commit(); + saveAndReload(u"Impress Office Open XML"_ustr); + + pXml = parseExport(u"ppt/commentAuthors.xml"_ustr); + assertXPath(pXml, "/p:cmAuthorLst/p:cmAuthor[@id=0]"_ostr, "name"_ostr, "Author1"); + assertXPath(pXml, "/p:cmAuthorLst/p:cmAuthor[@id=1]"_ostr, "name"_ostr, "Author2"); + + pXml = parseExport(u"ppt/comments/comment1.xml"_ustr); + assertXPathNoAttribute(pXml, "/p:cmLst/p:cm"_ostr, "dt"_ostr); +} + CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest4, testTableCellVerticalPropertyRoundtrip) { createSdImpressDoc("pptx/tcPr-vert-roundtrip.pptx"); diff --git a/sd/source/filter/eppt/epptooxml.hxx b/sd/source/filter/eppt/epptooxml.hxx index c187c90c721c..9646afb865d8 100644 --- a/sd/source/filter/eppt/epptooxml.hxx +++ b/sd/source/filter/eppt/epptooxml.hxx @@ -22,6 +22,7 @@ #include <oox/core/xmlfilterbase.hxx> #include <oox/vml/vmldrawing.hxx> #include <oox/export/shapes.hxx> +#include <unotools/securityoptions.hxx> #include "epptbase.hxx" using ::sax_fastparser::FSHelperPtr; @@ -139,6 +140,7 @@ private: ::sax_fastparser::FSHelperPtr mPresentationFS; LayoutInfo mLayoutInfo[OOXML_LAYOUT_SIZE]; + std::unique_ptr<SvtSecurityMapPersonalInfo> mpAuthorIDs; // map authors to remove personal info std::vector< ::sax_fastparser::FSHelperPtr > mpSlidesFSArray; sal_Int32 mnLayoutFileIdMax; @@ -158,6 +160,8 @@ private: /// Map of placeholder indexes for Master placeholders std::unordered_map< css::uno::Reference<css::drawing::XShape>, sal_Int32 > maPlaceholderShapeToIndexMap; + // Get author id to remove personal info + size_t GetInfoID( const OUString sPersonalInfo ) const { return mpAuthorIDs->GetInfoID(sPersonalInfo); } struct AuthorComments { sal_Int32 nId; sal_Int32 nLastIndex; diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index 2d9e51e40fa5..728682f955d6 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -34,6 +34,7 @@ #include <sal/log.hxx> #include <tools/UnitConversion.hxx> #include <tools/datetime.hxx> +#include <unotools/securityoptions.hxx> #include <com/sun/star/animations/TransitionType.hpp> #include <com/sun/star/animations/TransitionSubType.hpp> #include <com/sun/star/beans/XPropertySetInfo.hpp> @@ -342,6 +343,7 @@ ShapeExport& PowerPointShapeExport::WriteUnknownShape(const Reference< XShape >& PowerPointExport::PowerPointExport(const Reference< XComponentContext >& rContext, const uno::Sequence<uno::Any>& rArguments) : XmlFilterBase(rContext) + , mpAuthorIDs( new SvtSecurityMapPersonalInfo ) , mnLayoutFileIdMax(1) , mnSlideIdMax(1 << 8) , mnSlideMasterIdMax(1U << 31) @@ -1166,6 +1168,12 @@ bool PowerPointExport::WriteComments(sal_uInt32 nPageNum) if (xAnnotationEnumeration->hasMoreElements()) { + bool bRemoveCommentAuthorDates + = SvtSecurityOptions::IsOptionSet( + SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo) + && !SvtSecurityOptions::IsOptionSet( + SvtSecurityOptions::EOption::DocWarnKeepNoteAuthorDateInfo); + FSHelperPtr pFS = openFragmentStreamWithSerializer( "ppt/comments/comment" + OUString::number(nPageNum + 1) + ".xml", u"application/vnd.openxmlformats-officedocument.presentationml.comments+xml"_ustr); @@ -1180,16 +1188,30 @@ bool PowerPointExport::WriteComments(sal_uInt32 nPageNum) RealPoint2D aRealPoint2D(xAnnotation->getPosition()); Reference< XText > xText(xAnnotation->getTextRange()); sal_Int32 nLastIndex; - sal_Int32 nId = GetAuthorIdAndLastIndex(xAnnotation->getAuthor(), nLastIndex); + OUString sAuthor(bRemoveCommentAuthorDates + ? "Author" + + OUString::number(GetInfoID(xAnnotation->getAuthor())) + : xAnnotation->getAuthor()); + sal_Int32 nId = GetAuthorIdAndLastIndex(sAuthor, nLastIndex); char cDateTime[sizeof("-32768-65535-65535T65535:65535:65535.4294967295")]; // reserve enough space for hypothetical max length snprintf(cDateTime, sizeof cDateTime, "%02" SAL_PRIdINT32 "-%02" SAL_PRIuUINT32 "-%02" SAL_PRIuUINT32 "T%02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ".%09" SAL_PRIuUINT32, sal_Int32(aDateTime.Year), sal_uInt32(aDateTime.Month), sal_uInt32(aDateTime.Day), sal_uInt32(aDateTime.Hours), sal_uInt32(aDateTime.Minutes), sal_uInt32(aDateTime.Seconds), aDateTime.NanoSeconds); - pFS->startElementNS(XML_p, XML_cm, - XML_authorId, OString::number(nId), - XML_dt, cDateTime, - XML_idx, OString::number(nLastIndex)); + util::DateTime aEmptyDate; + if (bRemoveCommentAuthorDates || aDateTime == aEmptyDate) + { + pFS->startElementNS(XML_p, XML_cm, + XML_authorId, OString::number(nId), + XML_idx, OString::number(nLastIndex)); + } + else + { + pFS->startElementNS(XML_p, XML_cm, + XML_authorId, OString::number(nId), + XML_dt, cDateTime, + XML_idx, OString::number(nLastIndex)); + } pFS->singleElementNS(XML_p, XML_pos, XML_x, OString::number(std::round(convertMm100ToMasterUnit(aRealPoint2D.X * 100))), commit 0b29618ebc6fcfcaecb634ce51a5a5da6cee1216 Author: László Németh <[email protected]> AuthorDate: Fri Jun 14 23:21:00 2024 +0200 Commit: Xisco Fauli <[email protected]> CommitDate: Fri Jun 21 12:44:14 2024 +0200 tdf#161563 sw: show "No Break" context menu only on a whole word It's possible to set CharNoHyphenation on shorter character sequences, than a word, but the result is not correct (use soft hyphens for alternative hyphenation within words), so limit "No Break" menu item only for selected words. (Not completely, because only Point() is checked for word boundary yet, not also Mark().) If no selection, cursor position must be within the hyphenated word (where "No Break" applied for the whole word automatically). This fixes also the assert in SwTextFrame::IsInHyphenatedWord(), when multiple nodes were selected. Follow-up to commit 2f0c7d5691acd4010443856788a54b0abc03098b "tdf#161563 tdf#161565 sw: add No Break to word context menu & visualize". Change-Id: I41b64e6a2eb0daf08f488420fc1eaba2045a28db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168898 Reviewed-by: László Németh <[email protected]> Tested-by: Jenkins (cherry picked from commit 41916d9fb045654fa19b4eac90a3099550a890f7) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168889 Reviewed-by: Xisco Fauli <[email protected]> diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx index 3a986d37ddc0..2405aaf63eff 100644 --- a/sw/source/core/crsr/swcrsr.cxx +++ b/sw/source/core/crsr/swcrsr.cxx @@ -2370,6 +2370,19 @@ void SwCursor::RestoreSavePos() bool SwCursor::IsInHyphenatedWord(SwRootFrame const& rLayout) const { + // skip, if the selected text contains multiple nodes, long text or space, + // or not in word starting or word ending positions + if ( HasMark() && ( GetPoint()->GetNode() != GetMark()->GetNode() || + abs(GetPoint()->GetContentIndex() - GetMark()->GetContentIndex()) > 100 || + GetText().indexOf(' ') > -1 || + !( IsStartWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) || + IsEndWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) ) ) ) + return false; + + // skip, if no selection and the cursor is not in a word + if ( !HasMark() && !IsInWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, &rLayout) ) + return false; + bool bRet = false; Point aPt; std::pair<Point, bool> const tmp(aPt, true); @@ -2377,7 +2390,7 @@ bool SwCursor::IsInHyphenatedWord(SwRootFrame const& rLayout) const &rLayout, GetPoint(), &tmp); if( pFrame && pFrame->IsTextFrame() ) { - SwPaM aPam( *GetPoint(), *GetMark() ); + SwPaM aPam( *GetPoint() ); bRet = static_cast<SwTextFrame const*>(pFrame)->IsInHyphenatedWord( &aPam, HasMark() ); } return bRet;
