sw/CppunitTest_sw_htmlexport.mk           |    4 
 sw/qa/extras/htmlexport/data/URLs.odt     |binary
 sw/qa/extras/htmlexport/data/external.png |binary
 sw/qa/extras/htmlexport/htmlexport.cxx    |  221 ++++++++++++++++++++++++++++++
 sw/source/filter/html/css1atr.cxx         |    6 
 sw/source/filter/html/htmlflywriter.cxx   |   25 +--
 sw/source/filter/html/htmlforw.cxx        |    6 
 sw/source/filter/html/htmlplug.cxx        |   10 -
 sw/source/filter/html/wrthtml.cxx         |   35 ++++
 sw/source/filter/html/wrthtml.hxx         |    7 
 10 files changed, 286 insertions(+), 28 deletions(-)

New commits:
commit 4be345abd678babcbb989db1e7a16021ad1da562
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Jul 26 23:04:34 2024 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Jul 27 02:03:15 2024 +0200

    HTML/ReqIF export: introduce RelativeOwnObjectURL filter option
    
    When the use cases require use of absolute URLs at export (Options->
    Load/Save->General, Save URLs relative to file system and Save URLs
    relative to internet), the fles generated from the document itself
    (e.g., images that aren't embedded into HTML/ReqIF itself) may still
    need to be referenced relatively.
    
    This introduces the export filter option, named RelativeOwnObjectURL,
    that overrides the general export settings specifically for these
    self-generated objects.
    
    Change-Id: I09aeb931db5712271a40c683370316783507775a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171083
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sw/CppunitTest_sw_htmlexport.mk b/sw/CppunitTest_sw_htmlexport.mk
index e456673def7f..43a5ca56d041 100644
--- a/sw/CppunitTest_sw_htmlexport.mk
+++ b/sw/CppunitTest_sw_htmlexport.mk
@@ -61,6 +61,10 @@ $(eval $(call gb_CppunitTest_use_api,sw_htmlexport,\
 $(eval $(call gb_CppunitTest_use_ure,sw_htmlexport))
 $(eval $(call gb_CppunitTest_use_vcl,sw_htmlexport))
 
+$(eval $(call gb_CppunitTest_use_custom_headers,sw_htmlexport,\
+    officecfg/registry \
+))
+
 $(eval $(call gb_CppunitTest_use_rdb,sw_htmlexport,services))
 
 $(eval $(call gb_CppunitTest_use_configuration,sw_htmlexport))
diff --git a/sw/qa/extras/htmlexport/data/URLs.odt 
b/sw/qa/extras/htmlexport/data/URLs.odt
new file mode 100644
index 000000000000..fd3593113f31
Binary files /dev/null and b/sw/qa/extras/htmlexport/data/URLs.odt differ
diff --git a/sw/qa/extras/htmlexport/data/external.png 
b/sw/qa/extras/htmlexport/data/external.png
new file mode 100644
index 000000000000..6ed2b8afc0af
Binary files /dev/null and b/sw/qa/extras/htmlexport/data/external.png differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx 
b/sw/qa/extras/htmlexport/htmlexport.cxx
index a7878823f63b..b0976c5a764f 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -27,11 +27,14 @@
 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
 #include <com/sun/star/view/XSelectionSupplier.hpp>
 
+#include <officecfg/Office/Common.hxx>
+
 #include <test/htmltesttools.hxx>
 #include <tools/urlobj.hxx>
 #include <svtools/rtfkeywd.hxx>
 #include <comphelper/propertyvalue.hxx>
 #include <comphelper/propertysequence.hxx>
+#include <comphelper/scopeguard.hxx>
 #include <svtools/parrtf.hxx>
 #include <rtl/strbuf.hxx>
 #include <svtools/rtftoken.h>
@@ -3168,6 +3171,224 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testHTML_161979)
     CPPUNIT_ASSERT(numNonTransparent < size.Height() * size.Width());
 }
 
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testReqIF_exportAbsoluteURLs_ownRelative)
+{
+    auto pBatch(comphelper::ConfigurationChanges::create());
+    Resetter resetter([
+        bInternetPreviousValue = 
officecfg::Office::Common::Save::URL::Internet::get(),
+        bFileSystemPreviousValue = 
officecfg::Office::Common::Save::URL::FileSystem::get(), pBatch
+    ]() {
+        
officecfg::Office::Common::Save::URL::Internet::set(bInternetPreviousValue, 
pBatch);
+        
officecfg::Office::Common::Save::URL::FileSystem::set(bFileSystemPreviousValue, 
pBatch);
+        return pBatch->commit();
+    });
+    // Set saving absolute URLs
+    officecfg::Office::Common::Save::URL::Internet::set(false, pBatch);
+    officecfg::Office::Common::Save::URL::FileSystem::set(false, pBatch);
+    pBatch->commit();
+
+    createSwDoc("URLs.odt");
+    // Export to ReqIF, using absolute URLs
+    saveWithParams({
+        comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML 
(StarWriter)"_ustr),
+        comphelper::makePropertyValue(u"FilterOptions"_ustr, 
u"xhtmlns=reqif-xhtml"_ustr),
+        comphelper::makePropertyValue(u"ExportImagesAsOLE"_ustr, true),
+        comphelper::makePropertyValue(u"RelativeOwnObjectURL"_ustr, true),
+    });
+    xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
+
+    // HTTP URL: must be absolute
+    assertXPath(pXmlDoc, "//reqif-xhtml:p[1]/reqif-xhtml:a"_ostr, "href"_ostr,
+                u"http://www.example.org/"_ustr);
+    // file URL: must be absolute
+    assertXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a"_ostr, "href"_ostr,
+                createFileURL(u"NonExistingPath/NonExistingFile.html"));
+    // form URL: must be absolute
+    assertXPath(pXmlDoc, "//reqif-xhtml:form"_ostr, "action"_ostr,
+                u"https://www.example.org/submit"_ustr);
+    // linked image exported as object: generated, must be relative
+    OUString url = getXPath(pXmlDoc, 
"//reqif-xhtml:p[3]/reqif-xhtml:object"_ostr, "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its original image URL: must be absolute
+    assertXPath(pXmlDoc, 
"//reqif-xhtml:p[3]/reqif-xhtml:object/reqif-xhtml:object"_ostr,
+                "data"_ostr, createFileURL(u"external.png"));
+    // embedded image exported as object: generated, must be relative
+    url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object"_ostr, 
"data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its image URL: generated, must be relative
+    url = getXPath(pXmlDoc, 
"//reqif-xhtml:p[4]/reqif-xhtml:object/reqif-xhtml:object"_ostr,
+                   "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+    // unordered list with image bullet - it gets embedded as base64 data
+    OUString style = getXPath(pXmlDoc, "//reqif-xhtml:ul"_ostr, "style"_ostr);
+    CPPUNIT_ASSERT(style.indexOf("list-style-image: 
url(data:image/png;base64,") != -1);
+    // an as-char frame, exported as a whole to an object, must be relative
+    url = getXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object"_ostr, 
"data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its file hyperlink must be absolute
+    assertXPath(pXmlDoc, 
"//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a"_ostr, "href"_ostr,
+                createFileURL(u"foo/bar"));
+    // its image URL: generated, must be relative
+    url = getXPath(pXmlDoc,
+                   
"//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a/reqif-xhtml:object"_ostr,
+                   "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testReqIF_exportRelativeURLs)
+{
+    CPPUNIT_ASSERT(officecfg::Office::Common::Save::URL::Internet::get());
+    CPPUNIT_ASSERT(officecfg::Office::Common::Save::URL::FileSystem::get());
+
+    createSwDoc("URLs.odt");
+    // Export to ReqIF, using relative URLs (the default)
+    saveWithParams({
+        comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML 
(StarWriter)"_ustr),
+        comphelper::makePropertyValue(u"FilterOptions"_ustr, 
u"xhtmlns=reqif-xhtml"_ustr),
+        comphelper::makePropertyValue(u"ExportImagesAsOLE"_ustr, true),
+    });
+    xmlDocUniquePtr pXmlDoc = WrapReqifFromTempFile();
+
+    // HTTP URL: must be absolute
+    assertXPath(pXmlDoc, "//reqif-xhtml:p[1]/reqif-xhtml:a"_ostr, "href"_ostr,
+                u"http://www.example.org/"_ustr);
+    // file URL: must be relative
+    OUString url = getXPath(pXmlDoc, "//reqif-xhtml:p[2]/reqif-xhtml:a"_ostr, 
"href"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("NonExistingPath/NonExistingFile.html"));
+    // form URL: must be absolute
+    assertXPath(pXmlDoc, "//reqif-xhtml:form"_ostr, "action"_ostr,
+                u"https://www.example.org/submit"_ustr);
+    // linked image exported as object: generated, must be relative
+    url = getXPath(pXmlDoc, "//reqif-xhtml:p[3]/reqif-xhtml:object"_ostr, 
"data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its original image URL: must be relative
+    url = getXPath(pXmlDoc, 
"//reqif-xhtml:p[3]/reqif-xhtml:object/reqif-xhtml:object"_ostr,
+                   "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("external.png"));
+    // embedded image exported as object: generated, must be relative
+    url = getXPath(pXmlDoc, "//reqif-xhtml:p[4]/reqif-xhtml:object"_ostr, 
"data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its image URL: generated, must be relative
+    url = getXPath(pXmlDoc, 
"//reqif-xhtml:p[4]/reqif-xhtml:object/reqif-xhtml:object"_ostr,
+                   "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+    // unordered list with image bullet - it gets embedded as base64 data
+    OUString style = getXPath(pXmlDoc, "//reqif-xhtml:ul"_ostr, "style"_ostr);
+    CPPUNIT_ASSERT(style.indexOf("list-style-image: 
url(data:image/png;base64,") != -1);
+    // an as-char frame, exported as a whole to an object, must be relative
+    url = getXPath(pXmlDoc, "//reqif-xhtml:p[5]/reqif-xhtml:object"_ostr, 
"data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".ole"));
+    // its file hyperlink must be relative
+    url = getXPath(pXmlDoc, 
"//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a"_ostr,
+                   "href"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("foo/bar"));
+    // its image URL: generated, must be relative
+    url = getXPath(pXmlDoc,
+                   
"//reqif-xhtml:p[5]/reqif-xhtml:object/reqif-xhtml:a/reqif-xhtml:object"_ostr,
+                   "data"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, 
testHTML_exportAbsoluteURLs_ownRelative)
+{
+    auto pBatch(comphelper::ConfigurationChanges::create());
+    Resetter resetter([
+        bInternetPreviousValue = 
officecfg::Office::Common::Save::URL::Internet::get(),
+        bFileSystemPreviousValue = 
officecfg::Office::Common::Save::URL::FileSystem::get(), pBatch
+    ]() {
+        
officecfg::Office::Common::Save::URL::Internet::set(bInternetPreviousValue, 
pBatch);
+        
officecfg::Office::Common::Save::URL::FileSystem::set(bFileSystemPreviousValue, 
pBatch);
+        return pBatch->commit();
+    });
+    // Set saving absolute URLs
+    officecfg::Office::Common::Save::URL::Internet::set(false, pBatch);
+    officecfg::Office::Common::Save::URL::FileSystem::set(false, pBatch);
+    pBatch->commit();
+
+    createSwDoc("URLs.odt");
+    // Export to HTML, using absolute URLs
+    saveWithParams({
+        comphelper::makePropertyValue(u"FilterName"_ustr, u"HTML 
(StarWriter)"_ustr),
+        comphelper::makePropertyValue(u"RelativeOwnObjectURL"_ustr, true),
+    });
+    htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
+
+    // HTTP URL: must be absolute
+    assertXPath(pHtmlDoc, "//p[1]/a"_ostr, "href"_ostr, 
u"http://www.example.org/"_ustr);
+    // file URL: must be absolute
+    assertXPath(pHtmlDoc, "//p[2]/a"_ostr, "href"_ostr,
+                createFileURL(u"NonExistingPath/NonExistingFile.html"));
+    // form URL: must be absolute
+    assertXPath(pHtmlDoc, "//form"_ostr, "action"_ostr, 
u"https://www.example.org/submit"_ustr);
+    // linked image: must be absolute
+    assertXPath(pHtmlDoc, "//p[3]/img"_ostr, "src"_ostr, 
createFileURL(u"external.png"));
+    // embedded image: generated, must be relative
+    OUString url = getXPath(pHtmlDoc, "//p[4]/img"_ostr, "src"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+    // unordered list with image bullet - it gets embedded as base64 data
+    OUString style = getXPath(pHtmlDoc, "//ul"_ostr, "style"_ostr);
+    CPPUNIT_ASSERT(style.indexOf("list-style-image: 
url(data:image/png;base64,") != -1);
+    // image-in-frame file hyperlink must be absolute; FIXME: 
HTMLOutFuncs::Out_ImageMap
+    // assertXPath(pHtmlDoc, "//p[5]/map/area"_ostr, "href"_ostr, 
createFileURL(u"foo/bar"));
+    // its image URL: generated, must be relative
+    url = getXPath(pHtmlDoc, "//p[5]/img"_ostr, "src"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".gif"));
+}
+
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_exportRelativeURLs)
+{
+    CPPUNIT_ASSERT(officecfg::Office::Common::Save::URL::Internet::get());
+    CPPUNIT_ASSERT(officecfg::Office::Common::Save::URL::FileSystem::get());
+
+    createSwDoc("URLs.odt");
+    // Export to HTML, using relative URLs (the default)
+    ExportToHTML();
+    htmlDocUniquePtr pHtmlDoc = parseHtml(maTempFile);
+
+    // HTTP URL: must be absolute
+    assertXPath(pHtmlDoc, "//p[1]/a"_ostr, "href"_ostr, 
u"http://www.example.org/"_ustr);
+    // file URL: must be relative
+    OUString url = getXPath(pHtmlDoc, "//p[2]/a"_ostr, "href"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("NonExistingPath/NonExistingFile.html"));
+    // form URL: must be absolute
+    assertXPath(pHtmlDoc, "//form"_ostr, "action"_ostr, 
u"https://www.example.org/submit"_ustr);
+    // linked image: must be relative
+    url = getXPath(pHtmlDoc, "//p[3]/img"_ostr, "src"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("external.png"));
+    // embedded image: generated, must be relative
+    url = getXPath(pHtmlDoc, "//p[4]/img"_ostr, "src"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".png"));
+    // unordered list with image bullet - it gets embedded as base64 data
+    OUString style = getXPath(pHtmlDoc, "//ul"_ostr, "style"_ostr);
+    CPPUNIT_ASSERT(style.indexOf("list-style-image: 
url(data:image/png;base64,") != -1);
+    // image-in-frame file hyperlink must be relative
+    url = getXPath(pHtmlDoc, "//p[5]/map/area"_ostr, "href"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith("foo/bar"));
+    // its image URL: generated, must be relative
+    url = getXPath(pHtmlDoc, "//p[5]/img"_ostr, "src"_ostr);
+    CPPUNIT_ASSERT(!url.startsWith("file:"));
+    CPPUNIT_ASSERT(url.endsWith(".gif"));
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/html/css1atr.cxx 
b/sw/source/filter/html/css1atr.cxx
index cfd4e9e50fb9..20706f93d690 100644
--- a/sw/source/filter/html/css1atr.cxx
+++ b/sw/source/filter/html/css1atr.cxx
@@ -3050,6 +3050,7 @@ static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& 
rWrt, const SfxPoolItem& rH
     const Color & rColor = static_cast<const SvxBrushItem &>(rHt).GetColor();
     OUString aLink = pGraphicName ? *pGraphicName
                             : static_cast<const SvxBrushItem 
&>(rHt).GetGraphicLink();
+    bool bOwn = false;
     SvxGraphicPosition ePos = static_cast<const SvxBrushItem 
&>(rHt).GetGraphicPos();
     if( sw::Css1Background::Page == nMode && !rWrt.mbEmbedImages )
     {
@@ -3089,7 +3090,7 @@ static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& 
rWrt, const SfxPoolItem& rH
     else if( !pGraphicName && rWrt.m_bCfgCpyLinkedGrfs )
     {
         OUString aGraphicAsLink = aLink;
-        rWrt.CopyLocalFileToINet( aGraphicAsLink );
+        bOwn = rWrt.CopyLocalFileToINet( aGraphicAsLink );
         aLink = aGraphicAsLink;
     }
     // In tables we only export something if there is a Graphic
@@ -3188,8 +3189,7 @@ static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& 
rWrt, const SfxPoolItem& rH
             else
             {
                 sOut += OStringToOUString(sCSS1_url, 
RTL_TEXTENCODING_ASCII_US)+
-                     "(" +  
URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
-                             aLink) + ")";
+                     "(" +  rWrt.normalizeURL(aLink, bOwn) + ")";
             }
 
             if( !pRepeat.empty() )
diff --git a/sw/source/filter/html/htmlflywriter.cxx 
b/sw/source/filter/html/htmlflywriter.cxx
index ddab7d00cf2f..a98aab4d429f 100644
--- a/sw/source/filter/html/htmlflywriter.cxx
+++ b/sw/source/filter/html/htmlflywriter.cxx
@@ -1234,7 +1234,8 @@ SwHTMLWriter& OutHTML_ImageStart( HtmlWriter& rHtml, 
SwHTMLWriter& rWrt, const S
                        const Size &rRealSize, HtmlFrmOpts nFrameOpts,
                        const char *pMarkType,
                        const ImageMap *pAltImgMap,
-                       const OUString& rMimeType )
+                       const OUString& rMimeType,
+                       bool bOwn)
 {
     // <object data="..."> instead of <img src="...">
     bool bReplacement = (nFrameOpts & HtmlFrmOpts::Replacement) || 
rWrt.mbReqIF;
@@ -1250,8 +1251,8 @@ SwHTMLWriter& OutHTML_ImageStart( HtmlWriter& rHtml, 
SwHTMLWriter& rWrt, const S
     }
 
     OUString aGraphicURL( rGraphicURL );
-    if( !rWrt.mbEmbedImages && 
!HTMLOutFuncs::PrivateURLToInternalImg(aGraphicURL) && !rWrt.mpTempBaseURL )
-        aGraphicURL = URIHelper::simpleNormalizedMakeRelative( 
rWrt.GetBaseURL(), aGraphicURL);
+    if (!rWrt.mbEmbedImages)
+        aGraphicURL = rWrt.normalizeURL(aGraphicURL, bOwn);
 
     const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
 
@@ -1496,6 +1497,7 @@ SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt,
 {
     OUString aGraphicInBase64;
     OUString aLink;
+    bool bOwn = false;
     if( pBrush )
     {
         aLink = pBrush->GetGraphicLink();
@@ -1510,11 +1512,11 @@ SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt,
                 }
             }
         }
-        else if(!aLink.isEmpty())
+        else
         {
             if( rWrt.m_bCfgCpyLinkedGrfs )
             {
-                rWrt.CopyLocalFileToINet( aLink );
+                bOwn = rWrt.CopyLocalFileToINet(aLink);
             }
 
         }
@@ -1525,8 +1527,7 @@ SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt,
     }
     if(!aLink.isEmpty())
     {
-        if( !HTMLOutFuncs::PrivateURLToInternalImg(aLink) )
-            aLink = URIHelper::simpleNormalizedMakeRelative( 
rWrt.GetBaseURL(), aLink);
+        aLink = rWrt.normalizeURL(aLink, bOwn);
     }
 
     OStringBuffer sOut;
@@ -1787,7 +1788,7 @@ static void OutHTML_ImageOLEStart(SwHTMLWriter& rWrt, 
const Graphic& rGraphic,
         SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed");
 
     // Refer to this data.
-    aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), 
aFileName);
+    aFileName = rWrt.normalizeURL(aFileName, true);
     rWrt.Strm().WriteOString(
         Concat2View("<" + rWrt.GetNamespace() + 
OOO_STRING_SVTOOLS_HTML_object));
     rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + 
"\""));
@@ -1884,7 +1885,7 @@ static SwHTMLWriter & OutHTML_FrameFormatAsImage( 
SwHTMLWriter& rWrt, const SwFr
     HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
     OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, GraphicURL, aGraphic, 
rFrameFormat.GetName(), aSz,
                     HtmlFrmOpts::GenImgMask, "frame",
-                    aIMap.GetIMapObjectCount() ? &aIMap : nullptr, aMimeType );
+                    aIMap.GetIMapObjectCount() ? &aIMap : nullptr, aMimeType, 
true);
 
     GfxLink aLink = aGraphic.GetGfxLink();
     if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng)
@@ -1928,6 +1929,7 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( 
SwHTMLWriter& rWrt, const SwFra
 
     OUString aGraphicURL;
     OUString aMimeType;
+    bool bOwn = false;
     if(!rWrt.mbEmbedImages)
     {
         const SwMirrorGrf& rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
@@ -2012,12 +2014,13 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( 
SwHTMLWriter& rWrt, const SwFra
             aGraphicURL = URIHelper::SmartRel2Abs(
                 INetURLObject(rWrt.GetBaseURL()), aGraphicURL,
                 URIHelper::GetMaybeFileHdl() );
+            bOwn = true;
         }
         else
         {
             pGrfNd->GetFileFilterNms( &aGraphicURL, nullptr );
             if( rWrt.m_bCfgCpyLinkedGrfs )
-                rWrt.CopyLocalFileToINet( aGraphicURL );
+                bOwn = rWrt.CopyLocalFileToINet(aGraphicURL);
         }
 
     }
@@ -2029,7 +2032,7 @@ static SwHTMLWriter& OutHTML_FrameFormatGrfNode( 
SwHTMLWriter& rWrt, const SwFra
 
     HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
     OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic, 
pGrfNd->GetTitle(),
-                  pGrfNd->GetTwipSize(), nFrameFlags, "graphic", nullptr, 
aMimeType );
+                  pGrfNd->GetTwipSize(), nFrameFlags, "graphic", nullptr, 
aMimeType, bOwn );
 
     GfxLink aLink = aGraphic.GetGfxLink();
     if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng)
diff --git a/sw/source/filter/html/htmlforw.cxx 
b/sw/source/filter/html/htmlforw.cxx
index c020d1632612..2d7aa7200b0f 100644
--- a/sw/source/filter/html/htmlforw.cxx
+++ b/sw/source/filter/html/htmlforw.cxx
@@ -467,8 +467,7 @@ void SwHTMLWriter::OutForm( bool bOn,
         {
             sOut += " " OOO_STRING_SVTOOLS_HTML_O_action "=\"";
             Strm().WriteOString( sOut );
-            OUString aURL
-                = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), *s);
+            OUString aURL = normalizeURL(*s, false);
             HTMLOutFuncs::Out_String( Strm(), aURL );
             sOut = "\""_ostr;
         }
@@ -967,8 +966,7 @@ SwHTMLWriter& OutHTML_DrawFrameFormatAsControl( 
SwHTMLWriter& rWrt,
                 sOut += " " OOO_STRING_SVTOOLS_HTML_O_src "=\"";
                 rWrt.Strm().WriteOString( sOut );
 
-                HTMLOutFuncs::Out_String( rWrt.Strm(),
-                            URIHelper::simpleNormalizedMakeRelative( 
rWrt.GetBaseURL(), *s) );
+                HTMLOutFuncs::Out_String(rWrt.Strm(), rWrt.normalizeURL(*s, 
false));
                 sOut = "\""_ostr;
             }
         }
diff --git a/sw/source/filter/html/htmlplug.cxx 
b/sw/source/filter/html/htmlplug.cxx
index 720a9a929647..3e594bbf8b43 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -1259,8 +1259,7 @@ SwHTMLWriter& OutHTML_FrameFormatOLENode( SwHTMLWriter& 
rWrt, const SwFrameForma
         aAny = xSet->getPropertyValue(u"PluginURL"_ustr);
         if( (aAny >>= aStr) && !aStr.isEmpty() )
         {
-            aURL = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(),
-                      aStr);
+            aURL = rWrt.normalizeURL(aStr, false);
         }
 
         if( !aURL.isEmpty() )
@@ -1308,7 +1307,7 @@ SwHTMLWriter& OutHTML_FrameFormatOLENode( SwHTMLWriter& 
rWrt, const SwFrameForma
         aAny = xSet->getPropertyValue(u"AppletCodeBase"_ustr);
         if( (aAny >>= aCd) && !aCd.isEmpty() )
         {
-            OUString sCodeBase( 
URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aCd) );
+            OUString sCodeBase(rWrt.normalizeURL(aCd, false));
             if( !sCodeBase.isEmpty() )
             {
                 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\"");
@@ -1524,13 +1523,14 @@ static void OutHTMLGraphic(SwHTMLWriter& rWrt, const 
SwFrameFormat& rFrameFormat
         nFlags |= HtmlFrmOpts::Replacement;
     HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace);
     OutHTML_ImageStart(aHtml, rWrt, rFrameFormat, aGraphicURL, rGraphic, 
pOLENd->GetTitle(),
-                       pOLENd->GetTwipSize(), nFlags, "ole", nullptr, 
aMimeType);
+                       pOLENd->GetTwipSize(), nFlags, "ole", nullptr, 
aMimeType, true);
     OutHTML_ImageEnd(aHtml, rWrt);
 }
 
 static void OutHTMLStartObject(SwHTMLWriter& rWrt, const OUString& rFileName, 
const OUString& rFileType)
 {
-    OUString aFileName = 
URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), rFileName);
+    // OutHTMLStartObject is only for own objects
+    OUString aFileName = rWrt.normalizeURL(rFileName, true);
 
     if (rWrt.IsLFPossible())
         rWrt.OutNewLine();
diff --git a/sw/source/filter/html/wrthtml.cxx 
b/sw/source/filter/html/wrthtml.cxx
index 58360ff40527..f77b5154cdee 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -362,6 +362,17 @@ void SwHTMLWriter::SetupFilterFromPropertyValues(
         it->second >>= bVal;
         m_bPreserveSpacesOnWrite = bVal;
     }
+
+    it = aStoreMap.find(u"RelativeOwnObjectURL"_ustr);
+    if (it != aStoreMap.end())
+    {
+        // URLs for images / objects created by export (from the document 
information) will be
+        // relative, regardless of 
org.openoffice.Office.Common/Save/URL/Internet and
+        // org.openoffice.Office.Common/Save/URL/FileSystem settings
+        bool bVal = false;
+        it->second >>= bVal;
+        m_bRelativeURLsForOwnObjects = bVal;
+    }
 }
 
 ErrCode SwHTMLWriter::WriteStream()
@@ -770,7 +781,7 @@ static void lcl_html_OutSectionStartTag( SwHTMLWriter& 
rHTMLWrt,
         OUString aFilter( aFName.getToken(0, sfx2::cTokenSeparator, nIdx) );
         OUString aSection( aFName.getToken(0, sfx2::cTokenSeparator, nIdx) );
 
-        OUString aEncURL( 
URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aURL ) );
+        OUString aEncURL(rHTMLWrt.normalizeURL(aURL, false));
         sal_Unicode cDelim = 255U;
         bool bURLContainsDelim = (-1 != aEncURL.indexOf( cDelim ) );
 
@@ -1384,7 +1395,7 @@ OUString SwHTMLWriter::convertHyperlinkHRefValue(const 
OUString& rURL)
         if (!aURL.HasError())
             sURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
     }
-    return URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL );
+    return normalizeURL(sURL, false);
 }
 
 void SwHTMLWriter::OutHyperlinkHRefValue( const OUString& rURL )
@@ -1425,11 +1436,12 @@ void SwHTMLWriter::OutBackground( const SvxBrushItem 
*pBrushItem, bool bGraphic
     }
     else
     {
+        bool bOwn = false;
         if( m_bCfgCpyLinkedGrfs )
         {
-            CopyLocalFileToINet( GraphicURL );
+            bOwn = CopyLocalFileToINet(GraphicURL);
         }
-        OUString s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), 
GraphicURL));
+        OUString s(normalizeURL(GraphicURL, bOwn));
         Strm().WriteOString(" " OOO_STRING_SVTOOLS_HTML_O_background "=\"" );
         HTMLOutFuncs::Out_String( Strm(), s );
         Strm().WriteOString("\"");
@@ -1608,6 +1620,21 @@ OString SwHTMLWriter::GetNamespace() const
     return maNamespace + ":";
 }
 
+OUString SwHTMLWriter::normalizeURL(const OUString& url, bool own) const
+{
+    OUString ret(url);
+    if (HTMLOutFuncs::PrivateURLToInternalImg(ret))
+        return ret;
+    OUString base;
+    if (!mpTempBaseURL)
+        base = GetBaseURL();
+    else if (own && m_bRelativeURLsForOwnObjects && GetOrigFileName())
+        base = *GetOrigFileName();
+    if (!base.isEmpty())
+        ret = URIHelper::simpleNormalizedMakeRelative(base, ret);
+    return ret;
+}
+
 // Structure caches the current data of the writer to output a
 // other part of the document, like e.g. header/footer
 HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, SwNodeOffset nStt,
diff --git a/sw/source/filter/html/wrthtml.hxx 
b/sw/source/filter/html/wrthtml.hxx
index aac06fbf8868..0b518a29c448 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -282,6 +282,8 @@ class SwHTMLWriter : public Writer
     bool m_bLFPossible = false; // a line break can be inserted
     bool m_bSpacePreserve = false; // Using xml::space="preserve", or 
"white-space: pre-wrap" style
     bool m_bPreserveSpacesOnWrite = false; // If export should use 
m_bSpacePreserve
+    // If "Save URLs relative to *" is ignored for self-generated images / 
objects
+    bool m_bRelativeURLsForOwnObjects = false;
 
     sal_uInt16 OutHeaderAttrs();
     const SwPageDesc *MakeHeader( sal_uInt16& rHeaderAtrs );
@@ -629,6 +631,8 @@ public:
     bool IsSpacePreserve() const { return m_bSpacePreserve; }
     void SetSpacePreserve(bool val) { m_bSpacePreserve = val; }
     bool IsPreserveSpacesOnWritePrefSet() const { return 
m_bPreserveSpacesOnWrite; }
+
+    OUString normalizeURL(const OUString& url, bool own) const;
 };
 
 inline bool SwHTMLWriter::IsCSS1Source( sal_uInt16 n ) const
@@ -706,7 +710,8 @@ SwHTMLWriter& OutHTML_ImageStart( HtmlWriter& rHtml, 
SwHTMLWriter&, const SwFram
                        const Size& rRealSize, HtmlFrmOpts nFrameOpts,
                        const char *pMarkType,
                        const ImageMap *pGenImgMap,
-                       const OUString& rMimeType = {} );
+                       const OUString& rMimeType,
+                       bool bOwn = false );
 SwHTMLWriter& OutHTML_ImageEnd( HtmlWriter& rHtml, SwHTMLWriter& );
 
 SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt, const char *pTag,

Reply via email to