From 107a20ee079ae852b3b33412f234aab2dc35168f Mon Sep 17 00:00:00 2001 From: Attila Szűcs Date: Fri, 11 Dec 2020 18:51:10 +0100 Subject: tdf#138824 tdf#137937 XLSX export: fix parent directory path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parent directory paths (../) removed by XclExpHyperlink::BuildFileName() resulted broken external reference. Note: on Linux, now this fix creates a working, but still fragile path relative to the root directory. Co-authored-by: Tibor Nagy (NISZ) Change-Id: I9401d75d1fba0194d4ff509d9b7305969b8804e2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107603 Tested-by: László Németh Reviewed-by: László Németh --- .../childDir/tdf138824_linkToParentDirectory.ods | Bin 0 -> 11436 bytes sc/qa/unit/data/ods/tdf138824_externalSource.ods | Bin 0 -> 10762 bytes sc/qa/unit/subsequent_export-test.cxx | 52 +++++++++++++++++++-- sc/source/filter/excel/xelink.cxx | 11 +++-- 4 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 sc/qa/unit/data/ods/childDir/tdf138824_linkToParentDirectory.ods create mode 100644 sc/qa/unit/data/ods/tdf138824_externalSource.ods (limited to 'sc') diff --git a/sc/qa/unit/data/ods/childDir/tdf138824_linkToParentDirectory.ods b/sc/qa/unit/data/ods/childDir/tdf138824_linkToParentDirectory.ods new file mode 100644 index 000000000000..2f0c6d2f93cb Binary files /dev/null and b/sc/qa/unit/data/ods/childDir/tdf138824_linkToParentDirectory.ods differ diff --git a/sc/qa/unit/data/ods/tdf138824_externalSource.ods b/sc/qa/unit/data/ods/tdf138824_externalSource.ods new file mode 100644 index 000000000000..59228e390e4d Binary files /dev/null and b/sc/qa/unit/data/ods/tdf138824_externalSource.ods differ diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index ce6083a591c2..6e776339cb4d 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -269,6 +269,7 @@ public: void testTdf76047_externalLink(); void testTdf87973_externalLinkSkipUnuseds(); void testTdf138741_externalLinkSkipUnusedsCrash(); + void testTdf138824_linkToParentDirectory(); void testTdf129969(); void testTdf84874(); void testTdf136721_paper_size(); @@ -442,6 +443,7 @@ public: CPPUNIT_TEST(testTdf76047_externalLink); CPPUNIT_TEST(testTdf87973_externalLinkSkipUnuseds); CPPUNIT_TEST(testTdf138741_externalLinkSkipUnusedsCrash); + CPPUNIT_TEST(testTdf138824_linkToParentDirectory); CPPUNIT_TEST(testTdf129969); CPPUNIT_TEST(testTdf84874); CPPUNIT_TEST(testTdf136721_paper_size); @@ -5561,7 +5563,7 @@ void ScExportTest::testTdf87973_externalLinkSkipUnuseds() ScDocument& rDoc = pShell->GetDocument(); // change external link to: 87973_externalSource.ods - OUString aFormula, bFormula; + OUString aFormula, aFormula2; rDoc.GetFormula(3, 1, 0, aFormula); auto nIdxOfFilename = aFormula.indexOf("tdf132105_external.ods"); aFormula = aFormula.replaceAt(nIdxOfFilename, 22, "87973_externalSource.ods"); @@ -5583,9 +5585,9 @@ void ScExportTest::testTdf87973_externalLinkSkipUnuseds() // check if the new filename is present in the link (and not replaced by '[2]') ScDocument& rDoc2 = pDocSh->GetDocument(); - rDoc2.GetFormula(3, 1, 0, bFormula); - CPPUNIT_ASSERT(bFormula.indexOf("tdf132105_external.ods") < 0); - CPPUNIT_ASSERT(bFormula.indexOf("87973_externalSource.ods") > 0); + rDoc2.GetFormula(3, 1, 0, aFormula2); + CPPUNIT_ASSERT(aFormula2.indexOf("tdf132105_external.ods") < 0); + CPPUNIT_ASSERT(aFormula2.indexOf("87973_externalSource.ods") >= 0); pDocSh->DoClose(); } @@ -5601,6 +5603,48 @@ void ScExportTest::testTdf138741_externalLinkSkipUnusedsCrash() xShell->DoClose(); } +void ScExportTest::testTdf138824_linkToParentDirectory() +{ + ScDocShellRef xShell = loadDoc("childDir/tdf138824_linkToParentDirectory.", FORMAT_ODS); + CPPUNIT_ASSERT(xShell.is()); + + ScDocument& rDoc = xShell->GetDocument(); + + // saveAndReload save the file to a temporary directory + // the link must be changed to point to that parent directory + utl::TempFile aTempFile; + auto aTempFilename = aTempFile.GetURL(); + auto nIdxOfTmpFile = aTempFilename.lastIndexOf('/'); + nIdxOfTmpFile = aTempFilename.lastIndexOf('/', nIdxOfTmpFile); + aTempFilename = aTempFilename.copy(0, nIdxOfTmpFile + 1); + + // change external link to tmp directory + OUString aFormula; + rDoc.GetFormula(3, 1, 0, aFormula); + auto nIdxOfFilename = aFormula.indexOf("tdf138824_externalSource.ods"); + auto nIdxOfFile = aFormula.indexOf("file"); + + aFormula = aFormula.replaceAt(nIdxOfFile, nIdxOfFilename - nIdxOfFile, aTempFilename); + rDoc.SetFormula(ScAddress(3, 1, 0), aFormula, formula::FormulaGrammar::GRAM_NATIVE_UI); + + ScDocShellRef xDocSh = saveAndReload(&(*xShell), FORMAT_XLSX); + CPPUNIT_ASSERT(xDocSh.is()); + + std::shared_ptr pXPathFile + = ScBootstrapFixture::exportTo(&(*xDocSh), FORMAT_XLSX); + xmlDocUniquePtr pDoc = XPathHelper::parseExport( + pXPathFile, m_xSFactory, "xl/externalLinks/_rels/externalLink1.xml.rels"); + CPPUNIT_ASSERT(pDoc); + + // it should be "../tdf138824_externalSource.ods" but because of an other bug, + // on linux some other directory names may added into the middle + OUString aValue = getXPath(pDoc, "/r:Relationships/r:Relationship", "Target"); + CPPUNIT_ASSERT_EQUAL(0, static_cast(aValue.indexOf("../"))); + CPPUNIT_ASSERT(aValue.indexOf("/tdf138824_externalSource.ods") > 0); + + xDocSh->DoClose(); +} + void ScExportTest::testTdf129969() { ScDocShellRef xShell = loadDoc("external_hyperlink.", FORMAT_ODS); diff --git a/sc/source/filter/excel/xelink.cxx b/sc/source/filter/excel/xelink.cxx index c84cd6364dc4..2b42606f30ea 100644 --- a/sc/source/filter/excel/xelink.cxx +++ b/sc/source/filter/excel/xelink.cxx @@ -1681,10 +1681,15 @@ void XclExpSupbook::SaveXml( XclExpXmlStream& rStrm ) // Add relation for this stream, e.g. xl/externalLinks/_rels/externalLink1.xml.rels sal_uInt16 nLevel = 0; bool bRel = true; + + // BuildFileName delete ../ and convert them to nLevel + // but addrelation needs ../ instead of nLevel, so we have to convert it back + OUString sFile = XclExpHyperlink::BuildFileName(nLevel, bRel, maUrl, GetRoot(), true); + while (nLevel-- > 0) + sFile = "../" + sFile; + OUString sId = rStrm.addRelation( pExternalLink->getOutputStream(), - oox::getRelationship(Relationship::EXTERNALLINKPATH), - XclExpHyperlink::BuildFileName( nLevel, bRel, maUrl, GetRoot(), true), - true ); + oox::getRelationship(Relationship::EXTERNALLINKPATH), sFile, true ); pExternalLink->startElement( XML_externalLink, XML_xmlns, rStrm.getNamespaceURL(OOX_NS(xls)).toUtf8()); -- cgit