oox/source/export/drawingml.cxx    |   65 ++++++++++++++++++++++++++++++++-----
 sd/qa/unit/data/pptx/tdf54037.pptx |binary
 sd/qa/unit/export-tests-ooxml1.cxx |   22 ++++++++++++
 3 files changed, 79 insertions(+), 8 deletions(-)

New commits:
commit e0a4f7e28bbfc589ca66893a65845b05c57481e2
Author:     Tibor Nagy <nagy.tib...@nisz.hu>
AuthorDate: Thu Apr 29 17:26:59 2021 +0200
Commit:     Balazs Varga <varga.bala...@nisz.hu>
CommitDate: Thu Oct 21 09:41:56 2021 +0200

    tdf#54037 PPTX export: fix internal hyperlinks
    
    exported as external by accident: after reloading the bad
    export, clicking on the hyperlink opened the same file
    in another document, because the exported link contained
    also the full file name reference instead of the slide name,
    according to the OOXML Relationship TargetMode="External".
    
    Change-Id: I08cf1537cd307b0b6f51ba1c3f61d89e220d44fd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114891
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>
    (cherry picked from commit 3a24211a1d49f33ca52e4fb2c927d50304f005df)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123858
    Tested-by: Balazs Varga <varga.bala...@nisz.hu>
    Reviewed-by: Balazs Varga <varga.bala...@nisz.hu>

diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 4970cea7a29a..76e4302c3d0f 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -93,6 +93,10 @@
 #include <com/sun/star/xml/dom/XNodeList.hpp>
 #include <com/sun/star/xml/sax/Writer.hpp>
 #include <com/sun/star/xml/sax/XSAXSerializable.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/frame/XModel.hpp>
 
 #include <comphelper/random.hxx>
 #include <comphelper/seqstream.hxx>
@@ -156,9 +160,12 @@ OUString URLTransformer::getTransformedString(const 
OUString& rString) const
     return rString;
 }
 
-bool URLTransformer::isExternalURL(const OUString& /*rURL*/) const
+bool URLTransformer::isExternalURL(const OUString& rURL) const
 {
-    return true;
+    bool bExternal = true;
+    if (rURL.startsWith("#"))
+        bExternal = false;
+    return bExternal;
 }
 
 static css::uno::Any getLineDash( const 
css::uno::Reference<css::frame::XModel>& xModel, const OUString& rDashName )
@@ -1840,6 +1847,29 @@ void DrawingML::WriteShapeTransformation( const 
Reference< XShape >& rXShape, sa
             bFlipHWrite, bFlipVWrite, ExportRotateClockwisify(nRotation + 
nCameraRotation), IsGroupShape( rXShape ));
 }
 
+static OUString lcl_GetTarget(const css::uno::Reference<css::frame::XModel>& 
xModel, OUString& rURL)
+{
+    Reference<drawing::XDrawPagesSupplier> xDPS(xModel, uno::UNO_QUERY_THROW);
+    Reference<drawing::XDrawPages> xDrawPages(xDPS->getDrawPages(), 
uno::UNO_SET_THROW);
+    sal_uInt32 nPageCount = xDrawPages->getCount();
+    OUString sTarget;
+
+    for (sal_uInt32 i = 0; i < nPageCount; ++i)
+    {
+        Reference<XDrawPage> xDrawPage;
+        xDrawPages->getByIndex(i) >>= xDrawPage;
+        Reference<container::XNamed> xNamed(xDrawPage, UNO_QUERY_THROW);
+        OUString sSlideName = "#" + xNamed->getName();
+        if (rURL == sSlideName)
+        {
+            sTarget = "slide" + OUString::number(i + 1) + ".xml";
+            break;
+        }
+    }
+
+    return sTarget;
+}
+
 void DrawingML::WriteRunProperties( const Reference< XPropertySet >& rRun, 
bool bIsField, sal_Int32 nElement,
                                     bool bCheckDirect,bool& 
rbOverridingCharHeight, sal_Int32& rnCharHeight,
                                     sal_Int16 nScriptType, const Reference< 
XPropertySet >& rXShapePropSet)
@@ -2175,15 +2205,34 @@ void DrawingML::WriteRunProperties( const Reference< 
XPropertySet >& rRun, bool
         OUString sURL;
 
         mAny >>= sURL;
-        if( !sURL.isEmpty() ) {
-            OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
-                                  
oox::getRelationship(Relationship::HYPERLINK),
-                                  sURL, true );
+        if (!sURL.isEmpty())
+        {
+            if (!sURL.match("#action?jump="))
+            {
+                bool bExtURL = URLTransformer().isExternalURL(sURL);
+                sURL = bExtURL ? sURL : lcl_GetTarget(GetFB()->getModel(), 
sURL);
+
+                OUString sRelId
+                    = mpFB->addRelation(mpFS->getOutputStream(),
+                                        bExtURL ? 
oox::getRelationship(Relationship::HYPERLINK)
+                                                : 
oox::getRelationship(Relationship::SLIDE),
+                                        sURL, bExtURL);
 
-            mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), 
sRelId);
+                if (bExtURL)
+                    mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, 
XML_id), sRelId);
+                else
+                    mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, 
XML_id), sRelId,
+                                          XML_action, 
"ppaction://hlinksldjump");
+            }
+            else
+            {
+                sal_Int32 nIndex = sURL.indexOf('=');
+                OUString aDestination(sURL.copy(nIndex + 1));
+                mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, 
XML_id), "", XML_action,
+                                      "ppaction://hlinkshowjump?jump=" + 
aDestination);
+            }
         }
     }
-
     mpFS->endElementNS( XML_a, nElement );
 }
 
diff --git a/sd/qa/unit/data/pptx/tdf54037.pptx 
b/sd/qa/unit/data/pptx/tdf54037.pptx
new file mode 100644
index 000000000000..a6120619c48f
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf54037.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx 
b/sd/qa/unit/export-tests-ooxml1.cxx
index a6b0c428aff1..a2d287ac73dd 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -54,6 +54,7 @@ using namespace css;
 class SdOOXMLExportTest1 : public SdModelTestBaseXML
 {
 public:
+    void testTdf54037();
     void testFdo90607();
     void testTdf127237();
     void testBnc887230();
@@ -107,6 +108,7 @@ public:
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest1);
 
+    CPPUNIT_TEST(testTdf54037);
     CPPUNIT_TEST(testFdo90607);
     CPPUNIT_TEST(testTdf127237);
     CPPUNIT_TEST(testBnc887230);
@@ -210,6 +212,26 @@ void checkFontAttributes( const SdrTextObj* pObj, 
ItemValue nVal)
 
 }
 
+void SdOOXMLExportTest1::testTdf54037()
+{
+    sd::DrawDocShellRef xDocShRef = loadURL( 
m_directories.getURLFromSrc(u"/sd/qa/unit/data/pptx/tdf54037.pptx"), PPTX );
+    utl::TempFile tempFile;
+    xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+    xDocShRef->DoClose();
+
+    xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml");
+    xmlDocUniquePtr pRelsDoc = parseExport(tempFile, 
"ppt/slides/_rels/slide1.xml.rels");
+
+    assertXPath(pXmlDoc, 
"/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p[1]/a:r/a:rPr/a:hlinkClick",
+                "action", "ppaction://hlinksldjump");
+
+    assertXPath(pXmlDoc, 
"/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p[2]/a:r/a:rPr/a:hlinkClick",
+                "action", "ppaction://hlinkshowjump?jump=nextslide");
+
+    assertXPath(pRelsDoc, "/rels:Relationships/rels:Relationship[@Id='rId1']", 
"Target",
+                "slide2.xml");
+}
+
 void SdOOXMLExportTest1::testTdf127237()
 {
     sd::DrawDocShellRef xDocShRef = loadURL( 
m_directories.getURLFromSrc("/sd/qa/unit/data/pptx/tdf127237.pptx"), PPTX );

Reply via email to