summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cui/source/dialogs/hlinettp.cxx8
-rw-r--r--framework/qa/cppunit/services.cxx24
-rw-r--r--sw/qa/uitest/writer_tests3/hyperlinkdialog.py21
-rw-r--r--tools/qa/cppunit/test_urlobj.cxx27
-rw-r--r--tools/source/fsys/urlobj.cxx30
5 files changed, 101 insertions, 9 deletions
diff --git a/cui/source/dialogs/hlinettp.cxx b/cui/source/dialogs/hlinettp.cxx
index c26420d5703a..3a0f431acc17 100644
--- a/cui/source/dialogs/hlinettp.cxx
+++ b/cui/source/dialogs/hlinettp.cxx
@@ -158,13 +158,7 @@ OUString SvxHyperlinkInternetTp::CreateAbsoluteURL() const
// erase leading and trailing whitespaces
OUString aStrURL(m_xCbbTarget->get_active_text().trim());
- INetURLObject aURL(aStrURL);
-
- if( aURL.GetProtocol() == INetProtocol::NotValid )
- {
- aURL.SetSmartProtocol( GetSmartProtocolFromButtons() );
- aURL.SetSmartURL(aStrURL);
- }
+ INetURLObject aURL(aStrURL, GetSmartProtocolFromButtons());
// username and password for ftp-url
if( aURL.GetProtocol() == INetProtocol::Ftp && !m_xEdLogin->get_text().isEmpty() )
diff --git a/framework/qa/cppunit/services.cxx b/framework/qa/cppunit/services.cxx
index c75ce9f65633..873ea5938e4c 100644
--- a/framework/qa/cppunit/services.cxx
+++ b/framework/qa/cppunit/services.cxx
@@ -14,6 +14,7 @@
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/FrameSearchFlag.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
#include <comphelper/propertyvalue.hxx>
#include <salhelper/thread.hxx>
@@ -126,6 +127,29 @@ CPPUNIT_TEST_FIXTURE(Test, testLoadComponentFromURL)
xThread->join();
}
}
+
+CPPUNIT_TEST_FIXTURE(Test, testURLTransformer_parseSmart)
+{
+ // Without the accompanying fix in place, this test would have failed with
+ // "www.example.com:" treated as scheme, "/8080/foo/" as path, "bar?q=baz"
+ // as name, and "F" as fragment.
+
+ css::util::URL aURL;
+ aURL.Complete = "www.example.com:8080/foo/bar?q=baz#F";
+ css::uno::Reference xParser(css::util::URLTransformer::create(mxComponentContext));
+ CPPUNIT_ASSERT(xParser->parseSmart(aURL, "http:"));
+ CPPUNIT_ASSERT_EQUAL(OUString("http://www.example.com:8080/foo/bar?q=baz#F"), aURL.Complete);
+ CPPUNIT_ASSERT_EQUAL(OUString("http://www.example.com:8080/foo/bar"), aURL.Main);
+ CPPUNIT_ASSERT_EQUAL(OUString("http://"), aURL.Protocol);
+ CPPUNIT_ASSERT(aURL.User.isEmpty());
+ CPPUNIT_ASSERT(aURL.Password.isEmpty());
+ CPPUNIT_ASSERT_EQUAL(OUString("www.example.com"), aURL.Server);
+ CPPUNIT_ASSERT_EQUAL(sal_Int16(8080), aURL.Port);
+ CPPUNIT_ASSERT_EQUAL(OUString("/foo/"), aURL.Path);
+ CPPUNIT_ASSERT_EQUAL(OUString("bar"), aURL.Name);
+ CPPUNIT_ASSERT_EQUAL(OUString("q=baz"), aURL.Arguments);
+ CPPUNIT_ASSERT_EQUAL(OUString("F"), aURL.Mark);
+}
}
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/uitest/writer_tests3/hyperlinkdialog.py b/sw/qa/uitest/writer_tests3/hyperlinkdialog.py
index c20a39b48f2a..c737f33ad1b8 100644
--- a/sw/qa/uitest/writer_tests3/hyperlinkdialog.py
+++ b/sw/qa/uitest/writer_tests3/hyperlinkdialog.py
@@ -72,6 +72,27 @@ class HyperlinkDialog(UITestCase):
self.assertEqual(get_state_as_dict(xedit)["SelectedText"], "link")
+ def test_insert_hyperlink_without_scheme(self):
+
+ with self.ui_test.create_doc_in_start_center("writer"):
+ xMainWindow = self.xUITest.getTopFocusWindow()
+
+ with self.ui_test.execute_dialog_through_command(".uno:HyperlinkDialog") as xDialog:
+
+ # insert link
+ xtab=xDialog.getChild("tabcontrol")
+ select_pos(xtab, "0")
+
+ xtarget = xDialog.getChild("target")
+ xtarget.executeAction("TYPE", mkPropertyValues({"TEXT": "www.libreoffice.org:80"}))
+
+ # Check that the link is added with http scheme
+ xMainWindow = self.xUITest.getTopFocusWindow()
+ xedit = xMainWindow.getChild("writer_edit")
+ xedit.executeAction("SELECT", mkPropertyValues({"START_POS": "0", "END_POS": "29"}))
+ self.assertEqual(get_state_as_dict(xedit)["SelectedText"], "http://www.libreoffice.org:80")
+
+
def test_tdf141166(self):
# Skip this test for --with-help=html and --with-help=online, as that would fail with a
# DialogNotExecutedException("did not execute a dialog for a blocking action") thrown from
diff --git a/tools/qa/cppunit/test_urlobj.cxx b/tools/qa/cppunit/test_urlobj.cxx
index ec64b5d66777..abcd2fe1417b 100644
--- a/tools/qa/cppunit/test_urlobj.cxx
+++ b/tools/qa/cppunit/test_urlobj.cxx
@@ -319,6 +319,32 @@ namespace tools_urlobj
obj.GetMainURL(INetURLObject::DecodeMechanism::NONE));
}
+ void testParseSmart()
+ {
+ {
+ // host:port must not be misinterpreted as scheme:path
+ INetURLObject obj("example.com:8080/foo", INetProtocol::Http);
+ CPPUNIT_ASSERT(!obj.HasError());
+ CPPUNIT_ASSERT_EQUAL(OUString("http://example.com:8080/foo"),
+ obj.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ CPPUNIT_ASSERT_EQUAL(INetProtocol::Http, obj.GetProtocol());
+ CPPUNIT_ASSERT_EQUAL(OUString("example.com"), obj.GetHost());
+ CPPUNIT_ASSERT_EQUAL(sal_uInt32(8080), obj.GetPort());
+ CPPUNIT_ASSERT_EQUAL(OUString("/foo"), obj.GetURLPath());
+ }
+ {
+ // port may only contain decimal digits, so this must be treated as unknown scheme
+ INetURLObject obj("example.com:80a0/foo", INetProtocol::Http);
+ CPPUNIT_ASSERT(!obj.HasError());
+ CPPUNIT_ASSERT_EQUAL(OUString("example.com:80a0/foo"),
+ obj.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ CPPUNIT_ASSERT_EQUAL(INetProtocol::Generic, obj.GetProtocol());
+ CPPUNIT_ASSERT(obj.isSchemeEqualTo(u"example.com"));
+ CPPUNIT_ASSERT_EQUAL(OUString(""), obj.GetHost());
+ CPPUNIT_ASSERT_EQUAL(OUString("80a0/foo"), obj.GetURLPath());
+ }
+ }
+
// Change the following lines only, if you add, remove or rename
// member functions of the current class,
// because these macros are need by auto register mechanism.
@@ -335,6 +361,7 @@ namespace tools_urlobj
CPPUNIT_TEST( testSetExtension );
CPPUNIT_TEST( testChangeScheme );
CPPUNIT_TEST( testTd146382 );
+ CPPUNIT_TEST( testParseSmart );
CPPUNIT_TEST_SUITE_END( );
}; // class createPool
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index 49d0500cabb0..1b171ad2ed8e 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -869,8 +869,34 @@ bool INetURLObject::setAbsURIRef(OUString const & rTheAbsURIRef,
aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter);
if (!aSynScheme.isEmpty())
{
- m_eScheme = INetProtocol::Generic;
- pPos = p1;
+ if (bSmart && m_eSmartScheme != m_eScheme && p1 != pEnd && rtl::isAsciiDigit(*p1))
+ {
+ // rTheAbsURIRef doesn't define a known scheme (handled by the "if (pPrefix)"
+ // branch above); but a known scheme is defined in m_eSmartScheme. If this
+ // scheme may have a port in authority component, then avoid misinterpreting
+ // URLs like www.foo.bar:123/baz as using unknown "www.foo.bar" scheme with
+ // 123/baz rootless path. For now, do not try to handle possible colons in
+ // user information, require such ambiguous URLs to have explicit scheme part.
+ // Also ignore possibility of empty port.
+ const SchemeInfo& rInfo = getSchemeInfo(m_eSmartScheme);
+ if (rInfo.m_bAuthority && rInfo.m_bPort)
+ {
+ // Make sure that all characters from colon to [/?#] or to EOL are digits.
+ // Or maybe make it simple, and just assume that "xyz:1..." is more likely
+ // to be host "xyz" and port "1...", than scheme "xyz" and path "1..."?
+ sal_Unicode const* p2 = p1 + 1;
+ while (p2 != pEnd && rtl::isAsciiDigit(*p2))
+ ++p2;
+ if (p2 == pEnd || *p2 == '/' || *p2 == '?' || *p2 == '#')
+ m_eScheme = m_eSmartScheme;
+ }
+ }
+
+ if (m_eScheme == INetProtocol::NotValid)
+ {
+ m_eScheme = INetProtocol::Generic;
+ pPos = p1;
+ }
}
}