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;

Reply via email to