summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2023-11-01 00:37:19 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2023-11-01 10:24:21 +0100
commit9f1289f1e3c9b4a5f2be7a7187877db6b5015973 (patch)
tree4e042a908529f291db9321d1849de83b82d548bc /tools
parentd8326f1f54b2f4644b52fbfa7106eeeae6e5bb7b (diff)
tdf#157820: handle \\?\ prefixes in INetURLObject
They are already handled in osl file URL functions. Change-Id: Id0c224bdb79963e7ce52abde57bf05b0a6a81ff5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158741 Reviewed-by: Stephan Bergmann <sbergman@redhat.com> Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/qa/cppunit/test_urlobj.cxx20
-rw-r--r--tools/source/fsys/urlobj.cxx94
2 files changed, 97 insertions, 17 deletions
diff --git a/tools/qa/cppunit/test_urlobj.cxx b/tools/qa/cppunit/test_urlobj.cxx
index 2c8ae1a36a25..fff77e41f5e7 100644
--- a/tools/qa/cppunit/test_urlobj.cxx
+++ b/tools/qa/cppunit/test_urlobj.cxx
@@ -332,6 +332,26 @@ namespace tools_urlobj
CPPUNIT_ASSERT_EQUAL(OUString(""), obj.GetHost());
CPPUNIT_ASSERT_EQUAL(OUString("80a0/foo"), obj.GetURLPath());
}
+ {
+ // Test Windows \\?\C:... long path scheme
+ INetURLObject base(u"file:///C:/foo"); // set up base path
+ bool bWasAbsolute = false;
+ INetURLObject obj
+ = base.smartRel2Abs(u"\\\\?\\D:\\bar\\baz.ext"_ustr, bWasAbsolute);
+ CPPUNIT_ASSERT(bWasAbsolute);
+ CPPUNIT_ASSERT_EQUAL(u"file:///D:/bar/baz.ext"_ustr,
+ obj.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
+ {
+ // Test Windows \\?\UNC\Server... long path scheme
+ INetURLObject base(u"file://ServerFoo/fooShare"); // set up base path
+ bool bWasAbsolute = false;
+ INetURLObject obj = base.smartRel2Abs(
+ u"\\\\?\\UNC\\ServerBar\\barShare\\baz.ext"_ustr, bWasAbsolute);
+ CPPUNIT_ASSERT(bWasAbsolute);
+ CPPUNIT_ASSERT_EQUAL(u"file://ServerBar/barShare/baz.ext"_ustr,
+ obj.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
}
// Change the following lines only, if you add, remove or rename
diff --git a/tools/source/fsys/urlobj.cxx b/tools/source/fsys/urlobj.cxx
index 3c54eea3d664..a97af83bad81 100644
--- a/tools/source/fsys/urlobj.cxx
+++ b/tools/source/fsys/urlobj.cxx
@@ -809,6 +809,17 @@ bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef,
eMechanism = EncodeMechanism::All;
nFragmentDelimiter = 0x80000000;
}
+ else if (eStyle & FSysStyle::Dos
+ && pEnd - p1 >= 6
+ && p1[0] == '\\' && p1[1] == '\\' && p1[2] == '?' && p1[3] == '\\'
+ && rtl::isAsciiAlpha(p1[4])
+ && p1[5] == ':'
+ && (pEnd - p1 == 6 || p1[6] == '/' || p1[6] == '\\'))
+ {
+ m_eScheme = INetProtocol::File; // 8th, 9th
+ eMechanism = EncodeMechanism::All;
+ nFragmentDelimiter = 0x80000000;
+ }
else if (pEnd - p1 >= 2 && p1[0] == '/' && p1[1] == '/')
{
p1 += 2;
@@ -828,6 +839,14 @@ bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef,
&& p1[1] == '\\')
{
p1 += 2;
+ if (pEnd - p1 >= 6 && p1[0] == '?' && p1[1] == '\\' && p1[5] == '\\'
+ && rtl::toAsciiLowerCase(p1[2]) == 'u'
+ && rtl::toAsciiLowerCase(p1[3]) == 'n'
+ && rtl::toAsciiLowerCase(p1[4]) == 'c')
+ {
+ p1 += 6; // "\\?\UNC\Servername\..."
+ }
+
sal_Int32 n = rtl_ustr_indexOfChar_WithLength(
p1, pEnd - p1, '\\');
sal_Unicode const * pe = n == -1 ? pEnd : p1 + n;
@@ -1161,6 +1180,16 @@ bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef,
&& pPos[1] == '\\')
{
sal_Unicode const * p1 = pPos + 2;
+ sal_Unicode const * pHostPortTentativeBegin = p1;
+ if (pEnd - p1 >= 6 && p1[0] == '?' && p1[1] == '\\' && p1[5] == '\\'
+ && rtl::toAsciiLowerCase(p1[2]) == 'u'
+ && rtl::toAsciiLowerCase(p1[3]) == 'n'
+ && rtl::toAsciiLowerCase(p1[4]) == 'c')
+ {
+ p1 += 6; // "\\?\UNC\Servername\..."
+ pHostPortTentativeBegin = p1;
+ }
+
sal_Unicode const * pe = p1;
while (pe < pEnd && *pe != '\\' &&
*pe != nFragmentDelimiter)
@@ -1175,7 +1204,7 @@ bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef,
)
{
m_aAbsURIRef.append("//");
- pHostPortBegin = pPos + 2;
+ pHostPortBegin = pHostPortTentativeBegin;
pHostPortEnd = pe;
pPos = pe;
nSegmentDelimiter = '\\';
@@ -1193,18 +1222,26 @@ bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef,
// becomes
// "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
// replacing "\" by "/" within <*path>
- if (eStyle & FSysStyle::Dos
- && pEnd - pPos >= 2
- && rtl::isAsciiAlpha(pPos[0])
- && pPos[1] == ':'
- && (pEnd - pPos == 2
- || pPos[2] == '/'
- || pPos[2] == '\\'))
+ if (eStyle & FSysStyle::Dos)
{
- m_aAbsURIRef.append("//");
- nAltSegmentDelimiter = '\\';
- bSkippedInitialSlash = true;
- break;
+ sal_Unicode const* p1 = pPos;
+ if (pEnd - p1 >= 4 && p1[0] == '\\' && p1[1] == '\\' && p1[2] == '?'
+ && p1[3] == '\\')
+ p1 += 4; // "\\?\c:\..."
+
+ if (pEnd - p1 >= 2
+ && rtl::isAsciiAlpha(p1[0])
+ && p1[1] == ':'
+ && (pEnd - p1 == 2
+ || p1[2] == '/'
+ || p1[2] == '\\'))
+ {
+ pPos = p1;
+ m_aAbsURIRef.append("//");
+ nAltSegmentDelimiter = '\\';
+ bSkippedInitialSlash = true;
+ break;
+ }
}
// 9th Production (any):
@@ -1581,12 +1618,35 @@ bool INetURLObject::convertRelToAbs(OUString const & rTheRelURIRef,
q += 2;
sal_Int32 n = rtl_ustr_indexOfChar_WithLength(
q, pEnd - q, '\\');
- sal_Unicode const * qe = n == -1 ? pEnd : q + n;
- if (parseHostOrNetBiosName(
- q, qe, EncodeMechanism::All, RTL_TEXTENCODING_DONTKNOW,
- true, nullptr))
+ if (n == 1 && q[0] == '?')
{
- bFSys = true; // 1st
+ // "\\?\c:\..." or "\\?\UNC\servername\..."
+ q += 2;
+ if (pEnd - q >= 2
+ && rtl::isAsciiAlpha(q[0])
+ && q[1] == ':'
+ && (pEnd - q == 2 || q[2] == '/' || q[2] == '\\'))
+ {
+ bFSys = true; // 2nd, 3rd
+ }
+ else if (pEnd - q >= 4
+ && q[3] == '\\'
+ && rtl::toAsciiLowerCase(q[0]) == 'u'
+ && rtl::toAsciiLowerCase(q[1]) == 'n'
+ && rtl::toAsciiLowerCase(q[2]) == 'c')
+ {
+ q += 4; // Check if it's 1st below
+ }
+ }
+ if (!bFSys)
+ {
+ sal_Unicode const * qe = n == -1 ? pEnd : q + n;
+ if (parseHostOrNetBiosName(
+ q, qe, EncodeMechanism::All, RTL_TEXTENCODING_DONTKNOW,
+ true, nullptr))
+ {
+ bFSys = true; // 1st
+ }
}
}
if (bFSys)