tdf#138824 tdf#137937 XLSX export: fix parent directory path
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 <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
(cherry picked from commit 107a20ee079ae852b3b33412f234aab2dc35168f)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108006
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
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 0000000..2f0c6d2
--- /dev/null
+++ b/sc/qa/unit/data/ods/childDir/tdf138824_linkToParentDirectory.ods
Binary files 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 0000000..59228e3
--- /dev/null
+++ b/sc/qa/unit/data/ods/tdf138824_externalSource.ods
Binary files differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 35d349f..e173f85 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -274,6 +274,7 @@ public:
void testTdf76047_externalLink();
void testTdf87973_externalLinkSkipUnuseds();
void testTdf138741_externalLinkSkipUnusedsCrash();
void testTdf138824_linkToParentDirectory();
void testTdf129969();
void testTdf84874();
void testTdf136721_paper_size();
@@ -449,6 +450,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);
@@ -5624,7 +5626,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");
@@ -5646,9 +5648,9 @@ void ScExportTest::testTdf87973_externalLinkSkipUnuseds()
// check if the 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();
}
@@ -5664,6 +5666,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<utl::TempFile> 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<int>(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 affc984..cd5d570 100644
--- a/sc/source/filter/excel/xelink.cxx
+++ b/sc/source/filter/excel/xelink.cxx
@@ -1680,10 +1680,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());