/src/libreoffice/tools/source/fsys/urlobj.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <sal/config.h> |
21 | | |
22 | | #include <tools/urlobj.hxx> |
23 | | #include <tools/debug.hxx> |
24 | | #include <tools/inetmime.hxx> |
25 | | #include <tools/stream.hxx> |
26 | | #include <com/sun/star/uno/Reference.hxx> |
27 | | #include <com/sun/star/util/XStringWidth.hpp> |
28 | | #include <o3tl/enumarray.hxx> |
29 | | #include <osl/diagnose.h> |
30 | | #include <osl/file.hxx> |
31 | | #include <rtl/character.hxx> |
32 | | #include <rtl/string.h> |
33 | | #include <rtl/textenc.h> |
34 | | #include <rtl/ustring.hxx> |
35 | | #include <sal/log.hxx> |
36 | | #include <sal/types.h> |
37 | | |
38 | | #include <algorithm> |
39 | | #include <cassert> |
40 | | #include <limits> |
41 | | #include <memory> |
42 | | #include <string_view> |
43 | | |
44 | | #include <string.h> |
45 | | |
46 | | #include <com/sun/star/uno/Sequence.hxx> |
47 | | #include <comphelper/base64.hxx> |
48 | | #include <comphelper/string.hxx> |
49 | | |
50 | | using namespace css; |
51 | | |
52 | | // INetURLObject |
53 | | |
54 | | /* The URI grammar (using RFC 2234 conventions). |
55 | | |
56 | | Constructs of the form |
57 | | {reference <rule1> using rule2} |
58 | | stand for a rule matching the given rule1 specified in the given reference, |
59 | | encoded to URI syntax using rule2 (as specified in this URI grammar). |
60 | | |
61 | | |
62 | | ; RFC 1738, RFC 2396, RFC 2732, private |
63 | | login = [user [":" password] "@"] hostport |
64 | | user = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~") |
65 | | password = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ";" / "=" / "_" / "~") |
66 | | hostport = host [":" port] |
67 | | host = incomplete-hostname / hostname / IPv4address / IPv6reference |
68 | | incomplete-hostname = *(domainlabel ".") domainlabel |
69 | | hostname = *(domainlabel ".") toplabel ["."] |
70 | | domainlabel = alphanum [*(alphanum / "-") alphanum] |
71 | | toplabel = ALPHA [*(alphanum / "-") alphanum] |
72 | | IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT |
73 | | IPv6reference = "[" hexpart [":" IPv4address] "]" |
74 | | hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) |
75 | | hexseq = hex4 *(":" hex4) |
76 | | hex4 = 1*4HEXDIG |
77 | | port = *DIGIT |
78 | | escaped = "%" HEXDIG HEXDIG |
79 | | reserved = "$" / "&" / "+" / "," / "/" / ":" / ";" / "=" / "?" / "@" / "[" / "]" |
80 | | mark = "!" / "'" / "(" / ")" / "*" / "-" / "." / "_" / "~" |
81 | | alphanum = ALPHA / DIGIT |
82 | | unreserved = alphanum / mark |
83 | | uric = escaped / reserved / unreserved |
84 | | pchar = escaped / unreserved / "$" / "&" / "+" / "," / ":" / "=" / "@" |
85 | | |
86 | | |
87 | | ; RFC 1738, RFC 2396 |
88 | | ftp-url = "FTP://" login ["/" segment *("/" segment) [";TYPE=" ("A" / "D" / "I")]] |
89 | | segment = *pchar |
90 | | |
91 | | |
92 | | ; RFC 1738, RFC 2396 |
93 | | http-url = "HTTP://" hostport ["/" segment *("/" segment) ["?" *uric]] |
94 | | segment = *(pchar / ";") |
95 | | |
96 | | |
97 | | ; RFC 1738, RFC 2396, <http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q188997&> |
98 | | file-url = "FILE://" [host / "LOCALHOST" / netbios-name] ["/" segment *("/" segment)] |
99 | | segment = *pchar |
100 | | netbios-name = 1*{<alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "^" / "_" / "{" / "}" / "~"> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "_" / "~")} |
101 | | |
102 | | |
103 | | ; RFC 2368, RFC 2396 |
104 | | mailto-url = "MAILTO:" [to] [headers] |
105 | | to = {RFC 822 <#mailbox> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} |
106 | | headers = "?" header *("&" header) |
107 | | header = hname "=" hvalue |
108 | | hname = {RFC 822 <field-name> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} / "BODY" |
109 | | hvalue = {RFC 822 <field-body> using *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} |
110 | | |
111 | | |
112 | | ; private (see RFC 1738, RFC 2396) |
113 | | vnd-sun-star-webdav-url = "VND.SUN.STAR.WEBDAV://" hostport ["/" segment *("/" segment) ["?" *uric]] |
114 | | segment = *(pchar / ";") |
115 | | |
116 | | |
117 | | ; private |
118 | | private-url = "PRIVATE:" path ["?" *uric] |
119 | | path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") |
120 | | |
121 | | |
122 | | ; private |
123 | | vnd-sun-star-help-url = "VND.SUN.STAR.HELP://" name *("/" segment) ["?" *uric] |
124 | | name = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") |
125 | | segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") |
126 | | |
127 | | |
128 | | ; private |
129 | | https-url = "HTTPS://" hostport ["/" segment *("/" segment) ["?" *uric]] |
130 | | segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") |
131 | | |
132 | | |
133 | | ; private |
134 | | macro-url = "MACRO:" path ["?" *uric] |
135 | | path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") |
136 | | |
137 | | |
138 | | ; private |
139 | | javascript-url = "JAVASCRIPT:" *uric |
140 | | |
141 | | |
142 | | ; RFC 2397 |
143 | | data-url = "DATA:" [mediatype] [";BASE64"] "," *uric |
144 | | mediatype = [type "/" subtype] *(";" attribute "=" value) |
145 | | type = {RFC 2045 <type> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} |
146 | | subtype = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} |
147 | | attribute = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} |
148 | | value = {RFC 2045 <subtype> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")} |
149 | | |
150 | | |
151 | | ; RFC 2392, RFC 2396 |
152 | | cid-url = "CID:" {RFC 822 <addr-spec> using *uric} |
153 | | |
154 | | |
155 | | ; private |
156 | | vnd-sun-star-hier-url = "VND.SUN.STAR.HIER:" ["//"reg_name] *("/" *pchar) |
157 | | reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") |
158 | | |
159 | | |
160 | | ; private |
161 | | uno-url = ".UNO:" path ["?" *uric] |
162 | | path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") |
163 | | |
164 | | |
165 | | ; private |
166 | | component-url = ".COMPONENT:" path ["?" *uric] |
167 | | path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~") |
168 | | |
169 | | |
170 | | ; private |
171 | | vnd-sun-star-pkg-url = "VND.SUN.STAR.PKG://" reg_name *("/" *pchar) ["?" *uric] |
172 | | reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~") |
173 | | |
174 | | |
175 | | ; RFC 2255 |
176 | | ldap-url = "LDAP://" [hostport] ["/" [dn ["?" [attrdesct *("," attrdesc)] ["?" ["base" / "one" / "sub"] ["?" [filter] ["?" extension *("," extension)]]]]]] |
177 | | dn = {RFC 2253 <distinguishedName> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} |
178 | | attrdesc = {RFC 2251 <AttributeDescription> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} |
179 | | filter = {RFC 2254 <filter> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} |
180 | | extension = ["!"] ["X-"] extoken ["=" exvalue] |
181 | | extoken = {RFC 2252 <oid> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")} |
182 | | exvalue = {RFC 2251 <LDAPString> using *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")} |
183 | | |
184 | | |
185 | | ; private |
186 | | db-url = "DB:" *uric |
187 | | |
188 | | |
189 | | ; private |
190 | | vnd-sun-star-cmd-url = "VND.SUN.STAR.CMD:" opaque_part |
191 | | opaque_part = uric_no_slash *uric |
192 | | uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," |
193 | | |
194 | | |
195 | | ; RFC 1738 |
196 | | telnet-url = "TELNET://" login ["/"] |
197 | | |
198 | | |
199 | | ; private |
200 | | vnd-sun-star-expand-url = "VND.SUN.STAR.EXPAND:" opaque_part |
201 | | opaque_part = uric_no_slash *uric |
202 | | uric_no_slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," |
203 | | |
204 | | |
205 | | ; private |
206 | | vnd-sun-star-tdoc-url = "VND.SUN.STAR.TDOC:/" segment *("/" segment) |
207 | | segment = *pchar |
208 | | |
209 | | |
210 | | ; private |
211 | | unknown-url = scheme ":" 1*uric |
212 | | scheme = ALPHA *(alphanum / "+" / "-" / ".") |
213 | | |
214 | | |
215 | | ; private (http://ubiqx.org/cifs/Appendix-D.html): |
216 | | smb-url = "SMB://" login ["/" segment *("/" segment) ["?" *uric]] |
217 | | segment = *(pchar / ";") |
218 | | */ |
219 | | |
220 | | sal_Int32 INetURLObject::SubString::clear() |
221 | 24.3M | { |
222 | 24.3M | sal_Int32 nDelta = -m_nLength; |
223 | 24.3M | m_nBegin = -1; |
224 | 24.3M | m_nLength = 0; |
225 | 24.3M | return nDelta; |
226 | 24.3M | } |
227 | | |
228 | | sal_Int32 INetURLObject::SubString::set(OUStringBuffer & rString, |
229 | | std::u16string_view rSubString) |
230 | 707k | { |
231 | 707k | sal_Int32 nDelta = rSubString.size() - m_nLength; |
232 | | |
233 | 707k | rString.remove(m_nBegin, m_nLength); |
234 | 707k | rString.insert(m_nBegin, rSubString); |
235 | | |
236 | 707k | m_nLength = rSubString.size(); |
237 | 707k | return nDelta; |
238 | 707k | } |
239 | | |
240 | | sal_Int32 INetURLObject::SubString::set(OUString & rString, |
241 | | std::u16string_view rSubString) |
242 | 0 | { |
243 | 0 | sal_Int32 nDelta = rSubString.size() - m_nLength; |
244 | |
|
245 | 0 | rString = OUString::Concat(rString.subView(0, m_nBegin)) + |
246 | 0 | rSubString + rString.subView(m_nBegin + m_nLength); |
247 | |
|
248 | 0 | m_nLength = rSubString.size(); |
249 | 0 | return nDelta; |
250 | 0 | } |
251 | | |
252 | | sal_Int32 INetURLObject::SubString::set(OUStringBuffer & rString, |
253 | | std::u16string_view rSubString, |
254 | | sal_Int32 nTheBegin) |
255 | 682k | { |
256 | 682k | m_nBegin = nTheBegin; |
257 | 682k | return set(rString, rSubString); |
258 | 682k | } |
259 | | |
260 | | inline void INetURLObject::SubString::operator +=(sal_Int32 nDelta) |
261 | 386k | { |
262 | 386k | if (isPresent()) |
263 | 147k | m_nBegin = m_nBegin + nDelta; |
264 | 386k | } |
265 | | |
266 | | int INetURLObject::SubString::compare(SubString const & rOther, |
267 | | OUStringBuffer const & rThisString, |
268 | | OUStringBuffer const & rOtherString) const |
269 | 0 | { |
270 | 0 | sal_Int32 len = std::min(m_nLength, rOther.m_nLength); |
271 | 0 | sal_Unicode const * p1 = rThisString.getStr() + m_nBegin; |
272 | 0 | sal_Unicode const * end = p1 + len; |
273 | 0 | sal_Unicode const * p2 = rOtherString.getStr() + rOther.m_nBegin; |
274 | 0 | while (p1 != end) { |
275 | 0 | if (*p1 < *p2) { |
276 | 0 | return -1; |
277 | 0 | } else if (*p1 > *p2) { |
278 | 0 | return 1; |
279 | 0 | } |
280 | 0 | ++p1; |
281 | 0 | ++p2; |
282 | 0 | } |
283 | 0 | return m_nLength < rOther.m_nLength ? -1 |
284 | 0 | : m_nLength > rOther.m_nLength ? 1 |
285 | 0 | : 0; |
286 | 0 | } |
287 | | |
288 | | struct INetURLObject::SchemeInfo |
289 | | { |
290 | | OUString m_sScheme; |
291 | | OUString m_aPrefix; |
292 | | bool m_bAuthority; |
293 | | bool m_bUser; |
294 | | bool m_bAuth; |
295 | | bool m_bPassword; |
296 | | bool m_bHost; |
297 | | bool m_bPort; |
298 | | bool m_bHierarchical; |
299 | | bool m_bQuery; |
300 | | }; |
301 | | |
302 | | struct INetURLObject::PrefixInfo |
303 | | { |
304 | | enum class Kind { Official, Internal, External }; // order is important! |
305 | | |
306 | | OUString m_aPrefix; |
307 | | OUString m_aTranslatedPrefix; |
308 | | INetProtocol m_eScheme; |
309 | | Kind m_eKind; |
310 | | }; |
311 | | |
312 | | // static |
313 | | inline INetURLObject::SchemeInfo const & |
314 | | INetURLObject::getSchemeInfo(INetProtocol eTheScheme) |
315 | 11.7M | { |
316 | 11.7M | static constexpr OUString EMPTY = u""_ustr; |
317 | 11.7M | static constexpr OUString FTP = u"ftp"_ustr; |
318 | 11.7M | static constexpr OUString HTTP = u"http"_ustr; |
319 | 11.7M | static constexpr OUString FILE1 = u"file"_ustr; // because FILE is already defined |
320 | 11.7M | static constexpr OUString MAILTO = u"mailto"_ustr; |
321 | 11.7M | static constexpr OUString VND_WEBDAV = u"vnd.sun.star.webdav"_ustr; |
322 | 11.7M | static constexpr OUString PRIVATE = u"private"_ustr; |
323 | 11.7M | static constexpr OUString VND_HELP = u"vnd.sun.star.help"_ustr; |
324 | 11.7M | static constexpr OUString HTTPS = u"https"_ustr; |
325 | 11.7M | static constexpr OUString MACRO = u"macro"_ustr; |
326 | 11.7M | static constexpr OUString JAVASCRIPT = u"javascript"_ustr; |
327 | 11.7M | static constexpr OUString DATA = u"data"_ustr; |
328 | 11.7M | static constexpr OUString CID = u"cid"_ustr; |
329 | 11.7M | static constexpr OUString VND_HIER = u"vnd.sun.star.hier"_ustr; |
330 | 11.7M | static constexpr OUString UNO = u".uno"_ustr; |
331 | 11.7M | static constexpr OUString COMPONENT = u".component"_ustr; |
332 | 11.7M | static constexpr OUString VND_PKG = u"vnd.sun.star.pkg"_ustr; |
333 | 11.7M | static constexpr OUString LDAP = u"ldap"_ustr; |
334 | 11.7M | static constexpr OUString DB = u"db"_ustr; |
335 | 11.7M | static constexpr OUString VND_CMD = u"vnd.sun.star.cmd"_ustr; |
336 | 11.7M | static constexpr OUString TELNET = u"telnet"_ustr; |
337 | 11.7M | static constexpr OUString VND_EXPAND = u"vnd.sun.star.expand"_ustr; |
338 | 11.7M | static constexpr OUString VND_TDOC = u"vnd.sun.star.tdoc"_ustr; |
339 | 11.7M | static constexpr OUString SMB = u"smb"_ustr; |
340 | 11.7M | static constexpr OUString HID = u"hid"_ustr; |
341 | 11.7M | static constexpr OUString SFTP = u"sftp"_ustr; |
342 | 11.7M | static constexpr OUString VND_CMIS = u"vnd.libreoffice.cmis"_ustr; |
343 | | |
344 | 11.7M | static o3tl::enumarray<INetProtocol, SchemeInfo> constexpr map = { |
345 | | // [-loplugin:redundantfcast]: |
346 | 11.7M | SchemeInfo{ |
347 | 11.7M | EMPTY, u""_ustr, false, false, false, false, false, false, false, false}, |
348 | 11.7M | SchemeInfo{ |
349 | 11.7M | FTP, u"ftp://"_ustr, true, true, false, true, true, true, true, |
350 | 11.7M | false}, |
351 | 11.7M | SchemeInfo{ |
352 | 11.7M | HTTP, u"http://"_ustr, true, false, false, false, true, true, true, |
353 | 11.7M | true}, |
354 | 11.7M | SchemeInfo{ |
355 | 11.7M | FILE1, u"file://"_ustr, true, false, false, false, true, false, true, |
356 | 11.7M | false}, |
357 | 11.7M | SchemeInfo{ |
358 | 11.7M | MAILTO, u"mailto:"_ustr, false, false, false, false, false, false, |
359 | 11.7M | false, true}, |
360 | 11.7M | SchemeInfo{ |
361 | 11.7M | VND_WEBDAV, u"vnd.sun.star.webdav://"_ustr, true, false, |
362 | 11.7M | false, false, true, true, true, true}, |
363 | 11.7M | SchemeInfo{ |
364 | 11.7M | PRIVATE, u"private:"_ustr, false, false, false, false, false, false, |
365 | 11.7M | false, true}, |
366 | 11.7M | SchemeInfo{ |
367 | 11.7M | VND_HELP, u"vnd.sun.star.help://"_ustr, true, false, false, |
368 | 11.7M | false, false, false, true, true}, |
369 | 11.7M | SchemeInfo{ |
370 | 11.7M | HTTPS, u"https://"_ustr, true, false, false, false, true, true, |
371 | 11.7M | true, true}, |
372 | 11.7M | SchemeInfo{ |
373 | 11.7M | MACRO, u"macro:"_ustr, false, false, false, false, false, false, |
374 | 11.7M | false, true}, |
375 | 11.7M | SchemeInfo{ |
376 | 11.7M | JAVASCRIPT, u"javascript:"_ustr, false, false, false, false, false, |
377 | 11.7M | false, false, false}, |
378 | 11.7M | SchemeInfo{ |
379 | 11.7M | DATA, u"data:"_ustr, false, false, false, false, false, false, false, |
380 | 11.7M | false}, |
381 | 11.7M | SchemeInfo{ |
382 | 11.7M | CID, u"cid:"_ustr, false, false, false, false, false, false, false, |
383 | 11.7M | false}, |
384 | 11.7M | SchemeInfo{ |
385 | 11.7M | VND_HIER, u"vnd.sun.star.hier:"_ustr, true, false, false, |
386 | 11.7M | false, false, false, true, false}, |
387 | 11.7M | SchemeInfo{ |
388 | 11.7M | UNO, u".uno:"_ustr, false, false, false, false, false, false, false, |
389 | 11.7M | true}, |
390 | 11.7M | SchemeInfo{ |
391 | 11.7M | COMPONENT, u".component:"_ustr, false, false, false, false, false, |
392 | 11.7M | false, false, true}, |
393 | 11.7M | SchemeInfo{ |
394 | 11.7M | VND_PKG, u"vnd.sun.star.pkg://"_ustr, true, false, false, |
395 | 11.7M | false, false, false, true, true}, |
396 | 11.7M | SchemeInfo{ |
397 | 11.7M | LDAP, u"ldap://"_ustr, true, false, false, false, true, true, |
398 | 11.7M | false, true}, |
399 | 11.7M | SchemeInfo{ |
400 | 11.7M | DB, u"db:"_ustr, false, false, false, false, false, false, false, |
401 | 11.7M | false}, |
402 | 11.7M | SchemeInfo{ |
403 | 11.7M | VND_CMD, u"vnd.sun.star.cmd:"_ustr, false, false, false, |
404 | 11.7M | false, false, false, false, false}, |
405 | 11.7M | SchemeInfo{ |
406 | 11.7M | TELNET, u"telnet://"_ustr, true, true, false, true, true, true, |
407 | 11.7M | true, false}, |
408 | 11.7M | SchemeInfo{ |
409 | 11.7M | VND_EXPAND, u"vnd.sun.star.expand:"_ustr, false, false, |
410 | 11.7M | false, false, false, false, false, false}, |
411 | 11.7M | SchemeInfo{ |
412 | 11.7M | VND_TDOC, u"vnd.sun.star.tdoc:"_ustr, false, false, false, |
413 | 11.7M | false, false, false, true, false}, |
414 | 11.7M | SchemeInfo{ |
415 | 11.7M | EMPTY, u""_ustr, false, false, false, false, true, true, true, false }, |
416 | 11.7M | SchemeInfo{ |
417 | 11.7M | SMB, u"smb://"_ustr, true, true, false, true, true, true, true, |
418 | 11.7M | true}, |
419 | 11.7M | SchemeInfo{ |
420 | 11.7M | HID, u"hid:"_ustr, false, false, false, false, false, false, false, |
421 | 11.7M | true}, |
422 | 11.7M | SchemeInfo{ |
423 | 11.7M | SFTP, u"sftp://"_ustr, true, true, false, true, true, true, true, |
424 | 11.7M | true}, |
425 | 11.7M | SchemeInfo{ |
426 | 11.7M | VND_CMIS, u"vnd.libreoffice.cmis://"_ustr, true, true, |
427 | 11.7M | false, false, true, false, true, true} }; |
428 | 11.7M | return map[eTheScheme]; |
429 | 11.7M | }; |
430 | | |
431 | | inline INetURLObject::SchemeInfo const & INetURLObject::getSchemeInfo() const |
432 | 11.7M | { |
433 | 11.7M | return getSchemeInfo(m_eScheme); |
434 | 11.7M | } |
435 | | |
436 | | namespace { |
437 | | |
438 | | sal_Unicode getHexDigit(sal_uInt32 nWeight) |
439 | 65.2M | { |
440 | 65.2M | assert(nWeight < 16); |
441 | 65.2M | static const sal_Unicode aDigits[16] |
442 | 65.2M | = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', |
443 | 65.2M | 'D', 'E', 'F' }; |
444 | 65.2M | return aDigits[nWeight]; |
445 | 65.2M | } |
446 | | |
447 | | } |
448 | | |
449 | | // static |
450 | | inline void INetURLObject::appendEscape(OUStringBuffer & rTheText, |
451 | | sal_uInt32 nOctet) |
452 | 32.6M | { |
453 | 32.6M | rTheText.append( '%' ); |
454 | 32.6M | rTheText.append( getHexDigit(nOctet >> 4) ); |
455 | 32.6M | rTheText.append( getHexDigit(nOctet & 15) ); |
456 | 32.6M | } |
457 | | |
458 | | namespace { |
459 | | |
460 | | enum |
461 | | { |
462 | | PA = INetURLObject::PART_USER_PASSWORD, |
463 | | PD = INetURLObject::PART_FPATH, |
464 | | PE = INetURLObject::PART_AUTHORITY, |
465 | | PF = INetURLObject::PART_REL_SEGMENT_EXTRA, |
466 | | PG = INetURLObject::PART_URIC, |
467 | | PH = INetURLObject::PART_HTTP_PATH, |
468 | | PI = INetURLObject::PART_MESSAGE_ID_PATH, |
469 | | PJ = INetURLObject::PART_MAILTO, |
470 | | PK = INetURLObject::PART_PATH_BEFORE_QUERY, |
471 | | PL = INetURLObject::PART_PCHAR, |
472 | | PM = INetURLObject::PART_VISIBLE, |
473 | | PN = INetURLObject::PART_VISIBLE_NONSPECIAL, |
474 | | PO = INetURLObject::PART_UNO_PARAM_VALUE, |
475 | | PP = INetURLObject::PART_UNAMBIGUOUS, |
476 | | PQ = INetURLObject::PART_URIC_NO_SLASH, |
477 | | PR = INetURLObject::PART_HTTP_QUERY, |
478 | | }; |
479 | | |
480 | | sal_uInt32 const aMustEncodeMap[128] |
481 | | = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
482 | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
483 | | /* */ PP, |
484 | | /* ! */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
485 | | /* " */ PM+PN +PP, |
486 | | /* # */ PM, |
487 | | /* $ */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
488 | | /* % */ PM, |
489 | | /* & */ PA +PD+PE+PF+PG+PH+PI +PK+PL+PM+PN+PO +PQ+PR, |
490 | | /* ' */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
491 | | /* ( */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
492 | | /* ) */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
493 | | /* * */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
494 | | /* + */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO +PQ+PR, |
495 | | /* , */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN +PQ+PR, |
496 | | /* - */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
497 | | /* . */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
498 | | /* / */ +PD +PG+PH+PI+PJ+PK +PM+PN+PO, |
499 | | /* 0 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
500 | | /* 1 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
501 | | /* 2 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
502 | | /* 3 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
503 | | /* 4 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
504 | | /* 5 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
505 | | /* 6 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
506 | | /* 7 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
507 | | /* 8 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
508 | | /* 9 */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
509 | | /* : */ +PD+PE +PG+PH+PI+PJ+PK+PL+PM+PN+PO +PQ+PR, |
510 | | /* ; */ PA +PE+PF+PG+PH+PI+PJ+PK +PM +PQ+PR, |
511 | | /* < */ +PI +PM+PN +PP, |
512 | | /* = */ PA +PD+PE+PF+PG+PH +PK+PL+PM+PN +PQ+PR, |
513 | | /* > */ +PI +PM+PN +PP, |
514 | | /* ? */ +PG +PM +PO +PQ, |
515 | | /* @ */ +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
516 | | /* A */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
517 | | /* B */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
518 | | /* C */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
519 | | /* D */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
520 | | /* E */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
521 | | /* F */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
522 | | /* G */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
523 | | /* H */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
524 | | /* I */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
525 | | /* J */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
526 | | /* K */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
527 | | /* L */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
528 | | /* M */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
529 | | /* N */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
530 | | /* O */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
531 | | /* P */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
532 | | /* Q */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
533 | | /* R */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
534 | | /* S */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
535 | | /* T */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
536 | | /* U */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
537 | | /* V */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
538 | | /* W */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
539 | | /* X */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
540 | | /* Y */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
541 | | /* Z */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
542 | | /* [ */ PG +PM+PN+PO, |
543 | | /* \ */ +PM+PN +PP, |
544 | | /* ] */ PG +PM+PN+PO, |
545 | | /* ^ */ PM+PN +PP, |
546 | | /* _ */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
547 | | /* ` */ PM+PN +PP, |
548 | | /* a */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
549 | | /* b */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
550 | | /* c */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
551 | | /* d */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
552 | | /* e */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
553 | | /* f */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
554 | | /* g */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
555 | | /* h */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
556 | | /* i */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
557 | | /* j */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
558 | | /* k */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
559 | | /* l */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
560 | | /* m */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
561 | | /* n */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
562 | | /* o */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
563 | | /* p */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
564 | | /* q */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
565 | | /* r */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
566 | | /* s */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
567 | | /* t */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
568 | | /* u */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
569 | | /* v */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
570 | | /* w */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
571 | | /* x */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
572 | | /* y */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
573 | | /* z */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ+PR, |
574 | | /* { */ PM+PN +PP, |
575 | | /* | */ +PM+PN +PP, |
576 | | /* } */ PM+PN +PP, |
577 | | /* ~ */ PA +PD+PE+PF+PG+PH+PI+PJ+PK+PL+PM+PN+PO+PP+PQ, |
578 | | 0 }; |
579 | | |
580 | | bool mustEncode(sal_uInt32 nUTF32, INetURLObject::Part ePart) |
581 | 43.6M | { |
582 | 43.6M | return !rtl::isAscii(nUTF32) || !(aMustEncodeMap[nUTF32] & ePart); |
583 | 43.6M | } |
584 | | |
585 | | } |
586 | | |
587 | | void INetURLObject::setInvalid() |
588 | 3.04M | { |
589 | 3.04M | m_aAbsURIRef.setLength(0); |
590 | 3.04M | m_eScheme = INetProtocol::NotValid; |
591 | 3.04M | m_aScheme.clear(); |
592 | 3.04M | m_aUser.clear(); |
593 | 3.04M | m_aAuth.clear(); |
594 | 3.04M | m_aHost.clear(); |
595 | 3.04M | m_aPort.clear(); |
596 | 3.04M | m_aPath.clear(); |
597 | 3.04M | m_aQuery.clear(); |
598 | 3.04M | m_aFragment.clear(); |
599 | 3.04M | } |
600 | | |
601 | | namespace { |
602 | | |
603 | | std::unique_ptr<SvMemoryStream> memoryStream( |
604 | | void const * data, sal_Int32 length) |
605 | 33.1k | { |
606 | 33.1k | std::unique_ptr<char[]> b( |
607 | 33.1k | new char[length]); |
608 | 33.1k | memcpy(b.get(), data, length); |
609 | 33.1k | std::unique_ptr<SvMemoryStream> s( |
610 | 33.1k | new SvMemoryStream(b.get(), length, StreamMode::READ)); |
611 | 33.1k | s->ObjectOwnsMemory(true); |
612 | | // coverity[leaked_storage : FALSE] - belongs to SvMemoryStream s at this point |
613 | 33.1k | b.release(); |
614 | 33.1k | return s; |
615 | 33.1k | } |
616 | | |
617 | | } |
618 | | |
619 | | std::unique_ptr<SvMemoryStream> INetURLObject::getData() const |
620 | 38.4k | { |
621 | 38.4k | if( GetProtocol() != INetProtocol::Data ) |
622 | 0 | { |
623 | 0 | return nullptr; |
624 | 0 | } |
625 | | |
626 | 38.4k | OUString sURLPath = GetURLPath( DecodeMechanism::WithCharset, RTL_TEXTENCODING_ISO_8859_1 ); |
627 | 38.4k | sal_Unicode const * pSkippedMediatype = INetMIME::scanContentType( sURLPath ); |
628 | 38.4k | sal_Int32 nCharactersSkipped = pSkippedMediatype == nullptr |
629 | 38.4k | ? 0 : pSkippedMediatype-sURLPath.getStr(); |
630 | 38.4k | if (sURLPath.match(",", nCharactersSkipped)) |
631 | 29.9k | { |
632 | 29.9k | nCharactersSkipped += strlen(","); |
633 | 29.9k | OString sURLEncodedData( |
634 | 29.9k | sURLPath.getStr() + nCharactersSkipped, |
635 | 29.9k | sURLPath.getLength() - nCharactersSkipped, |
636 | 29.9k | RTL_TEXTENCODING_ISO_8859_1, OUSTRING_TO_OSTRING_CVTFLAGS); |
637 | 29.9k | return memoryStream( |
638 | 29.9k | sURLEncodedData.getStr(), sURLEncodedData.getLength()); |
639 | 29.9k | } |
640 | 8.49k | else if (sURLPath.matchIgnoreAsciiCase(";base64,", nCharactersSkipped)) |
641 | 3.93k | { |
642 | 3.93k | nCharactersSkipped += strlen(";base64,"); |
643 | 3.93k | std::u16string_view sBase64Data = sURLPath.subView( nCharactersSkipped ); |
644 | 3.93k | css::uno::Sequence< sal_Int8 > aDecodedData; |
645 | 3.93k | if (comphelper::Base64::decodeSomeChars(aDecodedData, sBase64Data) |
646 | 3.93k | == sBase64Data.size()) |
647 | 3.20k | { |
648 | 3.20k | return memoryStream( |
649 | 3.20k | aDecodedData.getArray(), aDecodedData.getLength()); |
650 | 3.20k | } |
651 | 3.93k | } |
652 | 5.29k | return nullptr; |
653 | 38.4k | } |
654 | | |
655 | | namespace { |
656 | | |
657 | | FSysStyle guessFSysStyleByCounting(sal_Unicode const * pBegin, |
658 | | sal_Unicode const * pEnd, |
659 | | FSysStyle eStyle) |
660 | 297k | { |
661 | 297k | DBG_ASSERT(eStyle |
662 | 297k | & (FSysStyle::Unix |
663 | 297k | | FSysStyle::Dos), |
664 | 297k | "guessFSysStyleByCounting(): Bad style"); |
665 | 297k | DBG_ASSERT(std::numeric_limits< sal_Int32 >::min() < pBegin - pEnd |
666 | 297k | && pEnd - pBegin <= std::numeric_limits< sal_Int32 >::max(), |
667 | 297k | "guessFSysStyleByCounting(): Too big"); |
668 | 297k | sal_Int32 nSlashCount |
669 | 297k | = (eStyle & FSysStyle::Unix) ? |
670 | 297k | 0 : std::numeric_limits< sal_Int32 >::min(); |
671 | 297k | sal_Int32 nBackslashCount |
672 | 297k | = (eStyle & FSysStyle::Dos) ? |
673 | 297k | 0 : std::numeric_limits< sal_Int32 >::min(); |
674 | 2.33M | while (pBegin != pEnd) |
675 | 2.03M | switch (*pBegin++) |
676 | 2.03M | { |
677 | 158k | case '/': |
678 | 158k | ++nSlashCount; |
679 | 158k | break; |
680 | | |
681 | 92.6k | case '\\': |
682 | 92.6k | ++nBackslashCount; |
683 | 92.6k | break; |
684 | 2.03M | } |
685 | 297k | return nSlashCount >= nBackslashCount ? |
686 | 261k | FSysStyle::Unix : FSysStyle::Dos; |
687 | 297k | } |
688 | | |
689 | | OUString parseScheme( |
690 | | sal_Unicode const ** begin, sal_Unicode const * end, |
691 | | sal_uInt32 fragmentDelimiter) |
692 | 1.19M | { |
693 | 1.19M | sal_Unicode const * p = *begin; |
694 | 1.19M | if (p != end && rtl::isAsciiAlpha(*p)) { |
695 | 1.17M | do { |
696 | 1.17M | ++p; |
697 | 1.17M | } while (p != end |
698 | 1.09M | && (rtl::isAsciiAlphanumeric(*p) || *p == '+' || *p == '-' |
699 | 306k | || *p == '.')); |
700 | | // #i34835# To avoid problems with Windows file paths like "C:\foo", |
701 | | // do not accept generic schemes that are only one character long: |
702 | 292k | if (end - p > 1 && p[0] == ':' && p[1] != fragmentDelimiter |
703 | 21.0k | && p - *begin >= 2) |
704 | 16.7k | { |
705 | 16.7k | OUString scheme( |
706 | 16.7k | OUString(*begin, p - *begin).toAsciiLowerCase()); |
707 | 16.7k | *begin = p + 1; |
708 | 16.7k | return scheme; |
709 | 16.7k | } |
710 | 292k | } |
711 | 1.17M | return OUString(); |
712 | 1.19M | } |
713 | | |
714 | | } |
715 | | |
716 | | bool INetURLObject::setAbsURIRef(std::u16string_view rTheAbsURIRef, |
717 | | EncodeMechanism eMechanism, |
718 | | rtl_TextEncoding eCharset, |
719 | | bool bSmart, |
720 | | FSysStyle eStyle) |
721 | 2.34M | { |
722 | 2.34M | sal_Unicode const * pPos = rTheAbsURIRef.data(); |
723 | 2.34M | sal_Unicode const * pEnd = pPos + rTheAbsURIRef.size(); |
724 | | |
725 | 2.34M | setInvalid(); |
726 | | |
727 | 2.34M | sal_uInt32 nFragmentDelimiter = '#'; |
728 | | |
729 | 2.34M | m_aAbsURIRef.setLength(0); |
730 | | |
731 | | // Parse <scheme>: |
732 | 2.34M | sal_Unicode const * p = pPos; |
733 | 2.34M | PrefixInfo const * pPrefix = getPrefix(p, pEnd); |
734 | 2.34M | if (pPrefix) |
735 | 1.51M | { |
736 | 1.51M | pPos = p; |
737 | 1.51M | m_eScheme = pPrefix->m_eScheme; |
738 | | |
739 | 1.51M | const OUString & rTemp = pPrefix->m_eKind >= PrefixInfo::Kind::External ? |
740 | 0 | pPrefix->m_aTranslatedPrefix : |
741 | 1.51M | pPrefix->m_aPrefix; |
742 | 1.51M | m_aAbsURIRef.append(rTemp); |
743 | 1.51M | m_aScheme = SubString( 0, rTemp.indexOf(':') ); |
744 | 1.51M | } |
745 | 838k | else |
746 | 838k | { |
747 | 838k | if (bSmart) |
748 | 211k | { |
749 | | // For scheme detection, the first (if any) of the following |
750 | | // productions that matches the input string (and for which the |
751 | | // appropriate style bit is set in eStyle, if applicable) |
752 | | // determines the scheme. The productions use the auxiliary rules |
753 | | |
754 | | // domain = label *("." label) |
755 | | // label = alphanum [*(alphanum / "-") alphanum] |
756 | | // alphanum = ALPHA / DIGIT |
757 | | // IPv6reference = "[" IPv6address "]" |
758 | | // IPv6address = hexpart [":" IPv4address] |
759 | | // IPv4address = 1*3DIGIT 3("." 1*3DIGIT) |
760 | | // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) |
761 | | // hexseq = hex4 *(":" hex4) |
762 | | // hex4 = 1*4HEXDIG |
763 | | // UCS4 = <any UCS4 character> |
764 | | |
765 | | // 1st Production (known scheme; handled by the "if (pPrefix)" branch above): |
766 | | // <one of the known schemes, ignoring case> ":" *UCS4 |
767 | | // 2nd Production (mailto): |
768 | | // domain "@" domain |
769 | | // 3rd Production (ftp): |
770 | | // "FTP" 2*("." label) ["/" *UCS4] |
771 | | // 4th Production (http): |
772 | | // label 2*("." label) ["/" *UCS4] |
773 | | // 5th Production (file): |
774 | | // "//" (domain / IPv6reference) ["/" *UCS4] |
775 | | // 6th Production (Unix file): |
776 | | // "/" *UCS4 |
777 | | // 7th Production (UNC file; FSysStyle::Dos only): |
778 | | // "\\" domain ["\" *UCS4] |
779 | | // 8th Production (Unix-like DOS file; FSysStyle::Dos only): |
780 | | // ALPHA ":" ["/" *UCS4] |
781 | | // 9th Production (DOS file; FSysStyle::Dos only): |
782 | | // ALPHA ":" ["\" *UCS4] |
783 | | // 10th Production (any scheme; handled by the "m_eScheme = INetProtocol::Generic;" code |
784 | | // after this else branch): |
785 | | // <any scheme> ":" *UCS4 |
786 | | |
787 | | // For the 'non URL' file productions 6--9, the interpretation of |
788 | | // the input as a (degenerate) URI is turned off, i.e., escape |
789 | | // sequences and fragments are never detected as such, but are |
790 | | // taken as literal characters. |
791 | | |
792 | 211k | sal_Unicode const * p1 = pPos; |
793 | 211k | if (eStyle & FSysStyle::Dos |
794 | 211k | && pEnd - p1 >= 2 |
795 | 194k | && rtl::isAsciiAlpha(p1[0]) |
796 | 120k | && p1[1] == ':' |
797 | 3.01k | && (pEnd - p1 == 2 || p1[2] == '/' || p1[2] == '\\')) |
798 | 2.74k | { |
799 | 2.74k | m_eScheme = INetProtocol::File; // 8th, 9th |
800 | 2.74k | eMechanism = EncodeMechanism::All; |
801 | 2.74k | nFragmentDelimiter = 0x80000000; |
802 | 2.74k | } |
803 | 208k | else if (eStyle & FSysStyle::Dos |
804 | 208k | && pEnd - p1 >= 6 |
805 | 183k | && p1[0] == '\\' && p1[1] == '\\' && p1[2] == '?' && p1[3] == '\\' |
806 | 7.39k | && rtl::isAsciiAlpha(p1[4]) |
807 | 6.66k | && p1[5] == ':' |
808 | 1.79k | && (pEnd - p1 == 6 || p1[6] == '/' || p1[6] == '\\')) |
809 | 1.45k | { |
810 | 1.45k | m_eScheme = INetProtocol::File; // 8th, 9th |
811 | 1.45k | eMechanism = EncodeMechanism::All; |
812 | 1.45k | nFragmentDelimiter = 0x80000000; |
813 | 1.45k | } |
814 | 207k | else if (pEnd - p1 >= 2 && p1[0] == '/' && p1[1] == '/') |
815 | 8.02k | { |
816 | 8.02k | p1 += 2; |
817 | 8.02k | if ((scanDomain(p1, pEnd) > 0 || scanIPv6reference(p1, pEnd)) |
818 | 3.36k | && (p1 == pEnd || *p1 == '/')) |
819 | 1.92k | m_eScheme = INetProtocol::File; // 5th |
820 | 8.02k | } |
821 | 199k | else if (p1 != pEnd && *p1 == '/') |
822 | 20.2k | { |
823 | 20.2k | m_eScheme = INetProtocol::File; // 6th |
824 | 20.2k | eMechanism = EncodeMechanism::All; |
825 | 20.2k | nFragmentDelimiter = 0x80000000; |
826 | 20.2k | } |
827 | 178k | else if (eStyle & FSysStyle::Dos |
828 | 178k | && pEnd - p1 >= 2 |
829 | 163k | && p1[0] == '\\' |
830 | 28.6k | && p1[1] == '\\') |
831 | 28.2k | { |
832 | 28.2k | p1 += 2; |
833 | 28.2k | if (pEnd - p1 >= 6 && p1[0] == '?' && p1[1] == '\\' && p1[5] == '\\' |
834 | 3.98k | && rtl::toAsciiLowerCase(p1[2]) == 'u' |
835 | 3.02k | && rtl::toAsciiLowerCase(p1[3]) == 'n' |
836 | 2.51k | && rtl::toAsciiLowerCase(p1[4]) == 'c') |
837 | 1.95k | { |
838 | 1.95k | p1 += 6; // "\\?\UNC\Servername\..." |
839 | 1.95k | } |
840 | | |
841 | 28.2k | sal_Int32 n = rtl_ustr_indexOfChar_WithLength( |
842 | 28.2k | p1, pEnd - p1, '\\'); |
843 | 28.2k | sal_Unicode const * pe = n == -1 ? pEnd : p1 + n; |
844 | 28.2k | if ( |
845 | 28.2k | parseHostOrNetBiosName( |
846 | 28.2k | p1, pe, EncodeMechanism::All, RTL_TEXTENCODING_DONTKNOW, |
847 | 28.2k | true, nullptr) || |
848 | 8.85k | (scanDomain(p1, pe) > 0 && p1 == pe) |
849 | 28.2k | ) |
850 | 19.4k | { |
851 | 19.4k | m_eScheme = INetProtocol::File; // 7th |
852 | 19.4k | eMechanism = EncodeMechanism::All; |
853 | 19.4k | nFragmentDelimiter = 0x80000000; |
854 | 19.4k | } |
855 | 28.2k | } |
856 | 150k | else |
857 | 150k | { |
858 | 150k | sal_Unicode const * pDomainEnd = p1; |
859 | 150k | sal_uInt32 nLabels = scanDomain(pDomainEnd, pEnd); |
860 | 150k | if (nLabels > 0 && pDomainEnd != pEnd && *pDomainEnd == '@') |
861 | 1.15k | { |
862 | 1.15k | ++pDomainEnd; |
863 | 1.15k | if (scanDomain(pDomainEnd, pEnd) > 0 |
864 | 827 | && pDomainEnd == pEnd) |
865 | 452 | m_eScheme = INetProtocol::Mailto; // 2nd |
866 | 1.15k | } |
867 | 149k | else if (nLabels >= 3 |
868 | 1.79k | && (pDomainEnd == pEnd || *pDomainEnd == '/')) |
869 | 1.16k | m_eScheme |
870 | 1.16k | = pDomainEnd - p1 >= 4 |
871 | 1.16k | && (p1[0] == 'f' || p1[0] == 'F') |
872 | 569 | && (p1[1] == 't' || p1[1] == 'T') |
873 | 164 | && (p1[2] == 'p' || p1[2] == 'P') |
874 | 80 | && p1[3] == '.' ? |
875 | 1.16k | INetProtocol::Ftp : INetProtocol::Http; // 3rd, 4th |
876 | 150k | } |
877 | 211k | } |
878 | | |
879 | 838k | OUString aSynScheme; |
880 | 838k | if (m_eScheme == INetProtocol::NotValid) { |
881 | 790k | sal_Unicode const * p1 = pPos; |
882 | 790k | aSynScheme = parseScheme(&p1, pEnd, nFragmentDelimiter); |
883 | 790k | if (!aSynScheme.isEmpty()) |
884 | 13.7k | { |
885 | 13.7k | if (bSmart && m_eSmartScheme != m_eScheme && p1 != pEnd && rtl::isAsciiDigit(*p1)) |
886 | 2.79k | { |
887 | | // rTheAbsURIRef doesn't define a known scheme (handled by the "if (pPrefix)" |
888 | | // branch above); but a known scheme is defined in m_eSmartScheme. If this |
889 | | // scheme may have a port in authority component, then avoid misinterpreting |
890 | | // URLs like www.foo.bar:123/baz as using unknown "www.foo.bar" scheme with |
891 | | // 123/baz rootless path. For now, do not try to handle possible colons in |
892 | | // user information, require such ambiguous URLs to have explicit scheme part. |
893 | | // Also ignore possibility of empty port. |
894 | 2.79k | const SchemeInfo& rInfo = getSchemeInfo(m_eSmartScheme); |
895 | 2.79k | if (rInfo.m_bAuthority && rInfo.m_bPort) |
896 | 2.79k | { |
897 | | // Make sure that all characters from colon to [/?#] or to EOL are digits. |
898 | | // Or maybe make it simple, and just assume that "xyz:1..." is more likely |
899 | | // to be host "xyz" and port "1...", than scheme "xyz" and path "1..."? |
900 | 2.79k | sal_Unicode const* p2 = p1 + 1; |
901 | 8.01k | while (p2 != pEnd && rtl::isAsciiDigit(*p2)) |
902 | 5.22k | ++p2; |
903 | 2.79k | if (p2 == pEnd || *p2 == '/' || *p2 == '?' || *p2 == '#') |
904 | 856 | m_eScheme = m_eSmartScheme; |
905 | 2.79k | } |
906 | 2.79k | } |
907 | | |
908 | 13.7k | if (m_eScheme == INetProtocol::NotValid) |
909 | 12.8k | { |
910 | 12.8k | m_eScheme = INetProtocol::Generic; |
911 | 12.8k | pPos = p1; |
912 | 12.8k | } |
913 | 13.7k | } |
914 | 790k | } |
915 | | |
916 | 838k | if (bSmart && m_eScheme == INetProtocol::NotValid && pPos != pEnd |
917 | 159k | && *pPos != nFragmentDelimiter) |
918 | 159k | { |
919 | 159k | m_eScheme = m_eSmartScheme; |
920 | 159k | } |
921 | | |
922 | 838k | if (m_eScheme == INetProtocol::NotValid) |
923 | 617k | { |
924 | 617k | setInvalid(); |
925 | 617k | return false; |
926 | 617k | } |
927 | | |
928 | 220k | if (m_eScheme != INetProtocol::Generic) { |
929 | 208k | aSynScheme = getSchemeInfo().m_sScheme; |
930 | 208k | } |
931 | 220k | m_aScheme.set(m_aAbsURIRef, aSynScheme, m_aAbsURIRef.getLength()); |
932 | 220k | m_aAbsURIRef.append(':'); |
933 | 220k | } |
934 | | |
935 | 1.73M | sal_uInt32 nSegmentDelimiter = '/'; |
936 | 1.73M | sal_uInt32 nAltSegmentDelimiter = 0x80000000; |
937 | 1.73M | bool bSkippedInitialSlash = false; |
938 | | |
939 | | // Parse //<user>;AUTH=<auth>@<host>:<port> or |
940 | | // //<user>:<password>@<host>:<port> or |
941 | | // //<reg_name> |
942 | 1.73M | if (getSchemeInfo().m_bAuthority) |
943 | 1.56M | { |
944 | 1.56M | sal_Unicode const * pUserInfoBegin = nullptr; |
945 | 1.56M | sal_Unicode const * pUserInfoEnd = nullptr; |
946 | 1.56M | sal_Unicode const * pHostPortBegin = nullptr; |
947 | 1.56M | sal_Unicode const * pHostPortEnd = nullptr; |
948 | | |
949 | 1.56M | switch (m_eScheme) |
950 | 1.56M | { |
951 | 0 | case INetProtocol::VndSunStarHelp: |
952 | 0 | { |
953 | 0 | if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/') |
954 | 0 | { |
955 | 0 | setInvalid(); |
956 | 0 | return false; |
957 | 0 | } |
958 | 0 | m_aAbsURIRef.append("//"); |
959 | 0 | OUStringBuffer aSynAuthority; |
960 | 0 | while (pPos < pEnd |
961 | 0 | && *pPos != '/' && *pPos != '?' |
962 | 0 | && *pPos != nFragmentDelimiter) |
963 | 0 | { |
964 | 0 | EscapeType eEscapeType; |
965 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
966 | 0 | eMechanism, |
967 | 0 | eCharset, eEscapeType); |
968 | 0 | appendUCS4(aSynAuthority, nUTF32, eEscapeType, |
969 | 0 | PART_AUTHORITY, eCharset, false); |
970 | 0 | } |
971 | 0 | m_aHost.set(m_aAbsURIRef, |
972 | 0 | aSynAuthority, |
973 | 0 | m_aAbsURIRef.getLength()); |
974 | | // misusing m_aHost to store the authority |
975 | 0 | break; |
976 | 0 | } |
977 | | |
978 | 0 | case INetProtocol::VndSunStarHier: |
979 | 0 | { |
980 | 0 | if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') |
981 | 0 | { |
982 | 0 | pPos += 2; |
983 | 0 | m_aAbsURIRef.append("//"); |
984 | 0 | OUStringBuffer aSynAuthority; |
985 | 0 | while (pPos < pEnd |
986 | 0 | && *pPos != '/' && *pPos != '?' |
987 | 0 | && *pPos != nFragmentDelimiter) |
988 | 0 | { |
989 | 0 | EscapeType eEscapeType; |
990 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, |
991 | 0 | pEnd, |
992 | 0 | eMechanism, |
993 | 0 | eCharset, |
994 | 0 | eEscapeType); |
995 | 0 | appendUCS4(aSynAuthority, |
996 | 0 | nUTF32, |
997 | 0 | eEscapeType, |
998 | 0 | PART_AUTHORITY, |
999 | 0 | eCharset, |
1000 | 0 | false); |
1001 | 0 | } |
1002 | 0 | if (aSynAuthority.isEmpty()) |
1003 | 0 | { |
1004 | 0 | setInvalid(); |
1005 | 0 | return false; |
1006 | 0 | } |
1007 | 0 | m_aHost.set(m_aAbsURIRef, |
1008 | 0 | aSynAuthority, |
1009 | 0 | m_aAbsURIRef.getLength()); |
1010 | | // misusing m_aHost to store the authority |
1011 | 0 | } |
1012 | 0 | break; |
1013 | 0 | } |
1014 | | |
1015 | 45 | case INetProtocol::VndSunStarPkg: |
1016 | 45 | case INetProtocol::Cmis: |
1017 | 45 | { |
1018 | 45 | if (pEnd - pPos < 2 || *pPos++ != '/' || *pPos++ != '/') |
1019 | 0 | { |
1020 | 0 | setInvalid(); |
1021 | 0 | return false; |
1022 | 0 | } |
1023 | 45 | m_aAbsURIRef.append("//"); |
1024 | 45 | OUStringBuffer aSynUser(128); |
1025 | | |
1026 | 45 | bool bHasUser = false; |
1027 | 1.26k | while (pPos < pEnd && *pPos != '@' |
1028 | 1.21k | && *pPos != '/' && *pPos != '?' |
1029 | 1.21k | && *pPos != nFragmentDelimiter) |
1030 | 1.21k | { |
1031 | 1.21k | EscapeType eEscapeType; |
1032 | 1.21k | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
1033 | 1.21k | eMechanism, |
1034 | 1.21k | eCharset, eEscapeType); |
1035 | 1.21k | appendUCS4(aSynUser, nUTF32, eEscapeType, |
1036 | 1.21k | PART_USER_PASSWORD, eCharset, false); |
1037 | | |
1038 | 1.21k | bHasUser = *pPos == '@'; |
1039 | 1.21k | } |
1040 | | |
1041 | 45 | OUStringBuffer aSynAuthority(64); |
1042 | 45 | if ( !bHasUser ) |
1043 | 45 | { |
1044 | 45 | aSynAuthority = std::move(aSynUser); |
1045 | 45 | } |
1046 | 0 | else |
1047 | 0 | { |
1048 | 0 | m_aUser.set(m_aAbsURIRef, |
1049 | 0 | aSynUser, |
1050 | 0 | m_aAbsURIRef.getLength()); |
1051 | 0 | m_aAbsURIRef.append("@"); |
1052 | 0 | ++pPos; |
1053 | |
|
1054 | 0 | while (pPos < pEnd |
1055 | 0 | && *pPos != '/' && *pPos != '?' |
1056 | 0 | && *pPos != nFragmentDelimiter) |
1057 | 0 | { |
1058 | 0 | EscapeType eEscapeType; |
1059 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
1060 | 0 | eMechanism, |
1061 | 0 | eCharset, eEscapeType); |
1062 | 0 | appendUCS4(aSynAuthority, nUTF32, eEscapeType, |
1063 | 0 | PART_AUTHORITY, eCharset, false); |
1064 | 0 | } |
1065 | 0 | } |
1066 | 45 | if (aSynAuthority.isEmpty()) |
1067 | 0 | { |
1068 | 0 | setInvalid(); |
1069 | 0 | return false; |
1070 | 0 | } |
1071 | 45 | m_aHost.set(m_aAbsURIRef, |
1072 | 45 | aSynAuthority, |
1073 | 45 | m_aAbsURIRef.getLength()); |
1074 | | // misusing m_aHost to store the authority |
1075 | 45 | break; |
1076 | 45 | } |
1077 | | |
1078 | 1.11M | case INetProtocol::File: |
1079 | 1.11M | if (bSmart) |
1080 | 557k | { |
1081 | | // The first of the following seven productions that |
1082 | | // matches the rest of the input string (and for which the |
1083 | | // appropriate style bit is set in eStyle, if applicable) |
1084 | | // determines the used notation. The productions use the |
1085 | | // auxiliary rules |
1086 | | |
1087 | | // domain = label *("." label) |
1088 | | // label = alphanum [*(alphanum / "-") alphanum] |
1089 | | // alphanum = ALPHA / DIGIT |
1090 | | // IPv6reference = "[" IPv6address "]" |
1091 | | // IPv6address = hexpart [":" IPv4address] |
1092 | | // IPv4address = 1*3DIGIT 3("." 1*3DIGIT) |
1093 | | // hexpart = (hexseq ["::" [hexseq]]) / ("::" [hexseq]) |
1094 | | // hexseq = hex4 *(":" hex4) |
1095 | | // hex4 = 1*4HEXDIG |
1096 | | // path = <any UCS4 character except "#"> |
1097 | | // UCS4 = <any UCS4 character> |
1098 | | |
1099 | | // 1st Production (URL): |
1100 | | // "//" [domain / IPv6reference] ["/" *path] |
1101 | | // ["#" *UCS4] |
1102 | | // becomes |
1103 | | // "file://" domain "/" *path ["#" *UCS4] |
1104 | 557k | if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') |
1105 | 505k | { |
1106 | 505k | sal_Unicode const * p1 = pPos + 2; |
1107 | 589k | while (p1 != pEnd && *p1 != '/' && |
1108 | 83.4k | *p1 != nFragmentDelimiter) |
1109 | 83.4k | { |
1110 | 83.4k | ++p1; |
1111 | 83.4k | } |
1112 | 505k | if (parseHostOrNetBiosName( |
1113 | 505k | pPos + 2, p1, EncodeMechanism::All, |
1114 | 505k | RTL_TEXTENCODING_DONTKNOW, true, nullptr)) |
1115 | 502k | { |
1116 | 502k | m_aAbsURIRef.append("//"); |
1117 | 502k | pHostPortBegin = pPos + 2; |
1118 | 502k | pHostPortEnd = p1; |
1119 | 502k | pPos = p1; |
1120 | 502k | break; |
1121 | 502k | } |
1122 | 505k | } |
1123 | | |
1124 | | // 2nd Production (MS IE generated 1; FSysStyle::Dos only): |
1125 | | // "//" ALPHA ":" ["/" *path] ["#" *UCS4] |
1126 | | // becomes |
1127 | | // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] |
1128 | | // replacing "\" by "/" within <*path> |
1129 | | // 3rd Production (MS IE generated 2; FSysStyle::Dos only): |
1130 | | // "//" ALPHA ":" ["\" *path] ["#" *UCS4] |
1131 | | // becomes |
1132 | | // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] |
1133 | | // replacing "\" by "/" within <*path> |
1134 | | // 4th Production (miscounted slashes): |
1135 | | // "//" *path ["#" *UCS4] |
1136 | | // becomes |
1137 | | // "file:///" *path ["#" *UCS4] |
1138 | 55.4k | if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') |
1139 | 3.71k | { |
1140 | 3.71k | m_aAbsURIRef.append("//"); |
1141 | 3.71k | pPos += 2; |
1142 | 3.71k | bSkippedInitialSlash = true; |
1143 | 3.71k | if ((eStyle & FSysStyle::Dos) |
1144 | 3.71k | && pEnd - pPos >= 2 |
1145 | 3.67k | && rtl::isAsciiAlpha(pPos[0]) |
1146 | 1.05k | && pPos[1] == ':' |
1147 | 883 | && (pEnd - pPos == 2 |
1148 | 757 | || pPos[2] == '/' || pPos[2] == '\\')) |
1149 | 158 | nAltSegmentDelimiter = '\\'; |
1150 | 3.71k | break; |
1151 | 3.71k | } |
1152 | | |
1153 | | // 5th Production (Unix): |
1154 | | // "/" *path ["#" *UCS4] |
1155 | | // becomes |
1156 | | // "file:///" *path ["#" *UCS4] |
1157 | 51.7k | if (pPos < pEnd && *pPos == '/') |
1158 | 20.3k | { |
1159 | 20.3k | m_aAbsURIRef.append("//"); |
1160 | 20.3k | break; |
1161 | 20.3k | } |
1162 | | |
1163 | | // 6th Production (UNC; FSysStyle::Dos only): |
1164 | | // "\\" domain ["\" *path] ["#" *UCS4] |
1165 | | // becomes |
1166 | | // "file://" domain "/" *path ["#" *UCS4] |
1167 | | // replacing "\" by "/" within <*path> |
1168 | 31.4k | if (eStyle & FSysStyle::Dos |
1169 | 31.4k | && pEnd - pPos >= 2 |
1170 | 29.8k | && pPos[0] == '\\' |
1171 | 23.4k | && pPos[1] == '\\') |
1172 | 23.2k | { |
1173 | 23.2k | sal_Unicode const * p1 = pPos + 2; |
1174 | 23.2k | sal_Unicode const * pHostPortTentativeBegin = p1; |
1175 | 23.2k | if (pEnd - p1 >= 6 && p1[0] == '?' && p1[1] == '\\' && p1[5] == '\\' |
1176 | 1.05k | && rtl::toAsciiLowerCase(p1[2]) == 'u' |
1177 | 794 | && rtl::toAsciiLowerCase(p1[3]) == 'n' |
1178 | 426 | && rtl::toAsciiLowerCase(p1[4]) == 'c') |
1179 | 323 | { |
1180 | 323 | p1 += 6; // "\\?\UNC\Servername\..." |
1181 | 323 | pHostPortTentativeBegin = p1; |
1182 | 323 | } |
1183 | | |
1184 | 23.2k | sal_Unicode const * pe = p1; |
1185 | 251k | while (pe < pEnd && *pe != '\\' && |
1186 | 229k | *pe != nFragmentDelimiter) |
1187 | 228k | { |
1188 | 228k | ++pe; |
1189 | 228k | } |
1190 | 23.2k | if ( |
1191 | 23.2k | parseHostOrNetBiosName( |
1192 | 23.2k | p1, pe, EncodeMechanism::All, |
1193 | 23.2k | RTL_TEXTENCODING_DONTKNOW, true, nullptr) || |
1194 | 3.45k | (scanDomain(p1, pe) > 0 && p1 == pe) |
1195 | 23.2k | ) |
1196 | 19.8k | { |
1197 | 19.8k | m_aAbsURIRef.append("//"); |
1198 | 19.8k | pHostPortBegin = pHostPortTentativeBegin; |
1199 | 19.8k | pHostPortEnd = pe; |
1200 | 19.8k | pPos = pe; |
1201 | 19.8k | nSegmentDelimiter = '\\'; |
1202 | 19.8k | break; |
1203 | 19.8k | } |
1204 | 23.2k | } |
1205 | | |
1206 | | // 7th Production (Unix-like DOS; FSysStyle::Dos only): |
1207 | | // ALPHA ":" ["/" *path] ["#" *UCS4] |
1208 | | // becomes |
1209 | | // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] |
1210 | | // replacing "\" by "/" within <*path> |
1211 | | // 8th Production (DOS; FSysStyle::Dos only): |
1212 | | // ALPHA ":" ["\" *path] ["#" *UCS4] |
1213 | | // becomes |
1214 | | // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4] |
1215 | | // replacing "\" by "/" within <*path> |
1216 | 11.6k | if (eStyle & FSysStyle::Dos) |
1217 | 11.6k | { |
1218 | 11.6k | sal_Unicode const* p1 = pPos; |
1219 | 11.6k | if (pEnd - p1 >= 4 && p1[0] == '\\' && p1[1] == '\\' && p1[2] == '?' |
1220 | 1.72k | && p1[3] == '\\') |
1221 | 1.60k | p1 += 4; // "\\?\c:\..." |
1222 | | |
1223 | 11.6k | if (pEnd - p1 >= 2 |
1224 | 10.0k | && rtl::isAsciiAlpha(p1[0]) |
1225 | 7.11k | && p1[1] == ':' |
1226 | 4.35k | && (pEnd - p1 == 2 |
1227 | 3.47k | || p1[2] == '/' |
1228 | 1.84k | || p1[2] == '\\')) |
1229 | 4.19k | { |
1230 | 4.19k | pPos = p1; |
1231 | 4.19k | m_aAbsURIRef.append("//"); |
1232 | 4.19k | nAltSegmentDelimiter = '\\'; |
1233 | 4.19k | bSkippedInitialSlash = true; |
1234 | 4.19k | break; |
1235 | 4.19k | } |
1236 | 11.6k | } |
1237 | | |
1238 | | // 9th Production (any): |
1239 | | // *path ["#" *UCS4] |
1240 | | // becomes |
1241 | | // "file:///" *path ["#" *UCS4] |
1242 | | // replacing the delimiter by "/" within <*path>. The |
1243 | | // delimiter is that character from the set { "/", "\"} |
1244 | | // which appears most often in <*path> (if FSysStyle::Unix |
1245 | | // is not among the style bits, "/" is removed from the |
1246 | | // set; if FSysStyle::Dos is not among the style bits, "\" is |
1247 | | // removed from the set). If two or |
1248 | | // more characters appear the same number of times, the |
1249 | | // character mentioned first in that set is chosen. If |
1250 | | // the first character of <*path> is the delimiter, that |
1251 | | // character is not copied |
1252 | 7.43k | if (eStyle & (FSysStyle::Unix | FSysStyle::Dos)) |
1253 | 7.43k | { |
1254 | 7.43k | m_aAbsURIRef.append("//"); |
1255 | 7.43k | switch (guessFSysStyleByCounting(pPos, pEnd, eStyle)) |
1256 | 7.43k | { |
1257 | 5.22k | case FSysStyle::Unix: |
1258 | 5.22k | nSegmentDelimiter = '/'; |
1259 | 5.22k | break; |
1260 | | |
1261 | 2.20k | case FSysStyle::Dos: |
1262 | 2.20k | nSegmentDelimiter = '\\'; |
1263 | 2.20k | break; |
1264 | | |
1265 | 0 | default: |
1266 | 0 | OSL_FAIL( |
1267 | 0 | "INetURLObject::setAbsURIRef():" |
1268 | 0 | " Bad guessFSysStyleByCounting"); |
1269 | 0 | break; |
1270 | 7.43k | } |
1271 | 7.43k | bSkippedInitialSlash |
1272 | 7.43k | = pPos != pEnd && *pPos != nSegmentDelimiter; |
1273 | 7.43k | break; |
1274 | 7.43k | } |
1275 | 7.43k | } |
1276 | 562k | [[fallthrough]]; |
1277 | 1.00M | default: |
1278 | 1.00M | { |
1279 | | // For INetProtocol::File, allow an empty authority ("//") to be |
1280 | | // missing if the following path starts with an explicit "/" |
1281 | | // (Java is notorious in generating such file URLs, so be |
1282 | | // liberal here): |
1283 | 1.00M | if (pEnd - pPos >= 2 && pPos[0] == '/' && pPos[1] == '/') |
1284 | 839k | pPos += 2; |
1285 | 166k | else if (!bSmart |
1286 | 17.8k | && !(m_eScheme == INetProtocol::File |
1287 | 11.1k | && pPos != pEnd && *pPos == '/')) |
1288 | 10.0k | { |
1289 | 10.0k | setInvalid(); |
1290 | 10.0k | return false; |
1291 | 10.0k | } |
1292 | 996k | m_aAbsURIRef.append("//"); |
1293 | | |
1294 | 996k | sal_Unicode const * pAuthority = pPos; |
1295 | 996k | sal_uInt32 c = getSchemeInfo().m_bQuery ? '?' : 0x80000000; |
1296 | 6.65M | while (pPos < pEnd && *pPos != '/' && *pPos != c |
1297 | 5.73M | && *pPos != nFragmentDelimiter) |
1298 | 5.65M | ++pPos; |
1299 | 996k | if (getSchemeInfo().m_bUser) |
1300 | 59.6k | if (getSchemeInfo().m_bHost) |
1301 | 59.6k | { |
1302 | 59.6k | sal_Unicode const * p1 = pAuthority; |
1303 | 920k | while (p1 < pPos && *p1 != '@') |
1304 | 861k | ++p1; |
1305 | 59.6k | if (p1 == pPos) |
1306 | 41.4k | { |
1307 | 41.4k | pHostPortBegin = pAuthority; |
1308 | 41.4k | pHostPortEnd = pPos; |
1309 | 41.4k | } |
1310 | 18.1k | else |
1311 | 18.1k | { |
1312 | 18.1k | pUserInfoBegin = pAuthority; |
1313 | 18.1k | pUserInfoEnd = p1; |
1314 | 18.1k | pHostPortBegin = p1 + 1; |
1315 | 18.1k | pHostPortEnd = pPos; |
1316 | 18.1k | } |
1317 | 59.6k | } |
1318 | 0 | else |
1319 | 0 | { |
1320 | 0 | pUserInfoBegin = pAuthority; |
1321 | 0 | pUserInfoEnd = pPos; |
1322 | 0 | } |
1323 | 936k | else if (getSchemeInfo().m_bHost) |
1324 | 936k | { |
1325 | 936k | pHostPortBegin = pAuthority; |
1326 | 936k | pHostPortEnd = pPos; |
1327 | 936k | } |
1328 | 0 | else if (pPos != pAuthority) |
1329 | 0 | { |
1330 | 0 | setInvalid(); |
1331 | 0 | return false; |
1332 | 0 | } |
1333 | 996k | break; |
1334 | 996k | } |
1335 | 1.56M | } |
1336 | | |
1337 | 1.55M | if (pUserInfoBegin) |
1338 | 18.1k | { |
1339 | 18.1k | Part ePart = PART_USER_PASSWORD; |
1340 | 18.1k | bool bSupportsPassword = getSchemeInfo().m_bPassword; |
1341 | 18.1k | bool bSupportsAuth |
1342 | 18.1k | = !bSupportsPassword && getSchemeInfo().m_bAuth; |
1343 | 18.1k | bool bHasAuth = false; |
1344 | 18.1k | OUStringBuffer aSynUser; |
1345 | 18.1k | sal_Unicode const * p1 = pUserInfoBegin; |
1346 | 168k | while (p1 < pUserInfoEnd) |
1347 | 167k | { |
1348 | 167k | EscapeType eEscapeType; |
1349 | 167k | sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, |
1350 | 167k | eMechanism, eCharset, eEscapeType); |
1351 | 167k | if (eEscapeType == EscapeType::NONE) |
1352 | 164k | { |
1353 | 164k | if (nUTF32 == ':' && bSupportsPassword) |
1354 | 16.7k | { |
1355 | 16.7k | bHasAuth = true; |
1356 | 16.7k | break; |
1357 | 16.7k | } |
1358 | 147k | else if (nUTF32 == ';' && bSupportsAuth |
1359 | 0 | && pUserInfoEnd - p1 |
1360 | 0 | > RTL_CONSTASCII_LENGTH("auth=") |
1361 | 0 | && INetMIME::equalIgnoreCase( |
1362 | 0 | p1, |
1363 | 0 | p1 + RTL_CONSTASCII_LENGTH("auth="), |
1364 | 0 | "auth=")) |
1365 | 0 | { |
1366 | 0 | p1 += RTL_CONSTASCII_LENGTH("auth="); |
1367 | 0 | bHasAuth = true; |
1368 | 0 | break; |
1369 | 0 | } |
1370 | 164k | } |
1371 | 150k | appendUCS4(aSynUser, nUTF32, eEscapeType, ePart, |
1372 | 150k | eCharset, false); |
1373 | 150k | } |
1374 | 18.1k | m_aUser.set(m_aAbsURIRef, aSynUser, m_aAbsURIRef.getLength()); |
1375 | 18.1k | if (bHasAuth) |
1376 | 16.7k | { |
1377 | 16.7k | if (bSupportsPassword) |
1378 | 16.7k | { |
1379 | 16.7k | m_aAbsURIRef.append(':'); |
1380 | 16.7k | OUStringBuffer aSynAuth; |
1381 | 296k | while (p1 < pUserInfoEnd) |
1382 | 280k | { |
1383 | 280k | EscapeType eEscapeType; |
1384 | 280k | sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, |
1385 | 280k | eMechanism, eCharset, |
1386 | 280k | eEscapeType); |
1387 | 280k | appendUCS4(aSynAuth, nUTF32, eEscapeType, |
1388 | 280k | ePart, eCharset, false); |
1389 | 280k | } |
1390 | 16.7k | m_aAuth.set(m_aAbsURIRef, aSynAuth, m_aAbsURIRef.getLength()); |
1391 | 16.7k | } |
1392 | 0 | else |
1393 | 0 | { |
1394 | 0 | m_aAbsURIRef.append(";AUTH="); |
1395 | 0 | OUStringBuffer aSynAuth; |
1396 | 0 | while (p1 < pUserInfoEnd) |
1397 | 0 | { |
1398 | 0 | EscapeType eEscapeType; |
1399 | 0 | sal_uInt32 nUTF32 = getUTF32(p1, pUserInfoEnd, |
1400 | 0 | eMechanism, eCharset, |
1401 | 0 | eEscapeType); |
1402 | 0 | if (!INetMIME::isIMAPAtomChar(nUTF32)) |
1403 | 0 | { |
1404 | 0 | setInvalid(); |
1405 | 0 | return false; |
1406 | 0 | } |
1407 | 0 | appendUCS4(aSynAuth, nUTF32, eEscapeType, |
1408 | 0 | ePart, eCharset, false); |
1409 | 0 | } |
1410 | 0 | m_aAuth.set(m_aAbsURIRef, aSynAuth, m_aAbsURIRef.getLength()); |
1411 | 0 | } |
1412 | 16.7k | } |
1413 | 18.1k | if (pHostPortBegin) |
1414 | 18.1k | m_aAbsURIRef.append('@'); |
1415 | 18.1k | } |
1416 | | |
1417 | 1.55M | if (pHostPortBegin) |
1418 | 1.51M | { |
1419 | 1.51M | sal_Unicode const * pPort = pHostPortEnd; |
1420 | 1.51M | if ( getSchemeInfo().m_bPort && pHostPortBegin < pHostPortEnd ) |
1421 | 435k | { |
1422 | 435k | sal_Unicode const * p1 = pHostPortEnd - 1; |
1423 | 644k | while (p1 > pHostPortBegin && rtl::isAsciiDigit(*p1)) |
1424 | 209k | --p1; |
1425 | 435k | if (*p1 == ':') |
1426 | 8.16k | pPort = p1; |
1427 | 435k | } |
1428 | 1.51M | bool bNetBiosName = false; |
1429 | 1.51M | switch (m_eScheme) |
1430 | 1.51M | { |
1431 | 1.08M | case INetProtocol::File: |
1432 | | // If the host equals "LOCALHOST" (unencoded and ignoring |
1433 | | // case), turn it into an empty host: |
1434 | 1.08M | if (INetMIME::equalIgnoreCase(pHostPortBegin, pPort, |
1435 | 1.08M | "localhost")) |
1436 | 0 | pHostPortBegin = pPort; |
1437 | 1.08M | bNetBiosName = true; |
1438 | 1.08M | break; |
1439 | | |
1440 | 300 | case INetProtocol::Ldap: |
1441 | 2.99k | case INetProtocol::Smb: |
1442 | 2.99k | if (pHostPortBegin == pPort && pPort != pHostPortEnd) |
1443 | 1.24k | { |
1444 | 1.24k | setInvalid(); |
1445 | 1.24k | return false; |
1446 | 1.24k | } |
1447 | 1.75k | break; |
1448 | 434k | default: |
1449 | 434k | if (pHostPortBegin == pPort) |
1450 | 1.88k | { |
1451 | 1.88k | setInvalid(); |
1452 | 1.88k | return false; |
1453 | 1.88k | } |
1454 | 432k | break; |
1455 | 1.51M | } |
1456 | 1.51M | sal_Int32 nLenBeforeHost = m_aAbsURIRef.getLength(); |
1457 | 1.51M | if (!parseHostOrNetBiosName( |
1458 | 1.51M | pHostPortBegin, pPort, eMechanism, eCharset, |
1459 | 1.51M | bNetBiosName, &m_aAbsURIRef)) |
1460 | 60.1k | { |
1461 | 60.1k | setInvalid(); |
1462 | 60.1k | return false; |
1463 | 60.1k | } |
1464 | 1.45M | m_aHost = SubString(nLenBeforeHost, m_aAbsURIRef.getLength() - nLenBeforeHost); |
1465 | 1.45M | if (pPort != pHostPortEnd) |
1466 | 6.02k | { |
1467 | 6.02k | m_aAbsURIRef.append(':'); |
1468 | 6.02k | m_aPort.set(m_aAbsURIRef, |
1469 | 6.02k | std::u16string_view{pPort + 1, static_cast<size_t>(pHostPortEnd - (pPort + 1))}, |
1470 | 6.02k | m_aAbsURIRef.getLength()); |
1471 | 6.02k | } |
1472 | 1.45M | } |
1473 | 1.55M | } |
1474 | | |
1475 | | // Parse <path> |
1476 | 1.65M | sal_Int32 nBeforePathLength = m_aAbsURIRef.getLength(); |
1477 | 1.65M | if (!parsePath(m_eScheme, &pPos, pEnd, eMechanism, eCharset, |
1478 | 1.65M | bSkippedInitialSlash, nSegmentDelimiter, |
1479 | 1.65M | nAltSegmentDelimiter, |
1480 | 1.65M | getSchemeInfo().m_bQuery ? '?' : 0x80000000, |
1481 | 1.65M | nFragmentDelimiter, m_aAbsURIRef)) |
1482 | 591 | { |
1483 | 591 | setInvalid(); |
1484 | 591 | return false; |
1485 | 591 | } |
1486 | 1.65M | m_aPath = SubString(nBeforePathLength, m_aAbsURIRef.getLength() - nBeforePathLength); |
1487 | | |
1488 | | // Parse ?<query> |
1489 | 1.65M | if (getSchemeInfo().m_bQuery && pPos < pEnd && *pPos == '?') |
1490 | 64.3k | { |
1491 | 64.3k | m_aAbsURIRef.append('?'); |
1492 | 64.3k | OUStringBuffer aSynQuery; |
1493 | 3.70M | for (++pPos; pPos < pEnd && *pPos != nFragmentDelimiter;) |
1494 | 3.64M | { |
1495 | 3.64M | EscapeType eEscapeType; |
1496 | 3.64M | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
1497 | 3.64M | eMechanism, eCharset, eEscapeType); |
1498 | 3.64M | appendUCS4(aSynQuery, nUTF32, eEscapeType, |
1499 | 3.64M | PART_URIC, eCharset, true); |
1500 | 3.64M | } |
1501 | 64.3k | m_aQuery.set(m_aAbsURIRef, aSynQuery, m_aAbsURIRef.getLength()); |
1502 | 64.3k | } |
1503 | | |
1504 | | // Parse #<fragment> |
1505 | 1.65M | if (pPos < pEnd && *pPos == nFragmentDelimiter) |
1506 | 243k | { |
1507 | 243k | m_aAbsURIRef.append(sal_Unicode(nFragmentDelimiter)); |
1508 | 243k | OUStringBuffer aSynFragment; |
1509 | 16.0M | for (++pPos; pPos < pEnd;) |
1510 | 15.8M | { |
1511 | 15.8M | EscapeType eEscapeType; |
1512 | 15.8M | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
1513 | 15.8M | eMechanism, eCharset, eEscapeType); |
1514 | 15.8M | appendUCS4(aSynFragment, nUTF32, eEscapeType, PART_URIC, |
1515 | 15.8M | eCharset, true); |
1516 | 15.8M | } |
1517 | 243k | m_aFragment.set(m_aAbsURIRef, aSynFragment, m_aAbsURIRef.getLength()); |
1518 | 243k | } |
1519 | | |
1520 | 1.65M | if (pPos != pEnd) |
1521 | 0 | { |
1522 | 0 | setInvalid(); |
1523 | 0 | return false; |
1524 | 0 | } |
1525 | | |
1526 | 1.65M | return true; |
1527 | 1.65M | } |
1528 | | |
1529 | 0 | void INetURLObject::changeScheme(INetProtocol eTargetScheme) { |
1530 | 0 | sal_Int32 oldSchemeLen = 0; |
1531 | 0 | const OUString& rOldSchemeName = getSchemeInfo().m_sScheme; |
1532 | 0 | if (m_eScheme == INetProtocol::Generic) |
1533 | 0 | oldSchemeLen = m_aScheme.getLength(); |
1534 | 0 | else |
1535 | 0 | oldSchemeLen = rOldSchemeName.getLength(); |
1536 | 0 | m_eScheme=eTargetScheme; |
1537 | 0 | const OUString& rNewSchemeName = getSchemeInfo().m_sScheme; |
1538 | 0 | sal_Int32 newSchemeLen = rNewSchemeName.getLength(); |
1539 | 0 | m_aAbsURIRef.remove(0, oldSchemeLen); |
1540 | 0 | m_aAbsURIRef.insert(0, rNewSchemeName); |
1541 | 0 | sal_Int32 delta=newSchemeLen-oldSchemeLen; |
1542 | 0 | m_aUser+=delta; |
1543 | 0 | m_aAuth+=delta; |
1544 | 0 | m_aHost+=delta; |
1545 | 0 | m_aPort+=delta; |
1546 | 0 | m_aPath+=delta; |
1547 | 0 | m_aQuery+=delta; |
1548 | 0 | m_aFragment+=delta; |
1549 | 0 | } |
1550 | | |
1551 | | bool INetURLObject::convertRelToAbs(OUString const & rTheRelURIRef, |
1552 | | INetURLObject & rTheAbsURIRef, |
1553 | | bool & rWasAbsolute, |
1554 | | EncodeMechanism eMechanism, |
1555 | | rtl_TextEncoding eCharset, |
1556 | | bool bIgnoreFragment, bool bSmart, |
1557 | | bool bRelativeNonURIs, FSysStyle eStyle) |
1558 | | const |
1559 | 543k | { |
1560 | 543k | sal_Unicode const * p = rTheRelURIRef.getStr(); |
1561 | 543k | sal_Unicode const * pEnd = p + rTheRelURIRef.getLength(); |
1562 | | |
1563 | 543k | sal_Unicode const * pPrefixBegin = p; |
1564 | 543k | PrefixInfo const * pPrefix = getPrefix(pPrefixBegin, pEnd); |
1565 | 543k | bool hasScheme = pPrefix != nullptr; |
1566 | 543k | if (!hasScheme) { |
1567 | 403k | pPrefixBegin = p; |
1568 | 403k | hasScheme = !parseScheme(&pPrefixBegin, pEnd, '#').isEmpty(); |
1569 | 403k | } |
1570 | | |
1571 | 543k | sal_uInt32 nSegmentDelimiter = '/'; |
1572 | 543k | sal_uInt32 nQueryDelimiter |
1573 | 543k | = !bSmart || getSchemeInfo().m_bQuery ? '?' : 0x80000000; |
1574 | 543k | sal_uInt32 nFragmentDelimiter = '#'; |
1575 | 543k | Part ePart = PART_VISIBLE; |
1576 | | |
1577 | 543k | if (!hasScheme && bSmart) |
1578 | 313k | { |
1579 | | // If the input matches any of the following productions (for which |
1580 | | // the appropriate style bit is set in eStyle), it is assumed to be an |
1581 | | // absolute file system path, rather than a relative URI reference. |
1582 | | // (This is only a subset of the productions used for scheme detection |
1583 | | // in INetURLObject::setAbsURIRef(), because most of those productions |
1584 | | // interfere with the syntax of relative URI references.) The |
1585 | | // productions use the auxiliary rules |
1586 | | |
1587 | | // domain = label *("." label) |
1588 | | // label = alphanum [*(alphanum / "-") alphanum] |
1589 | | // alphanum = ALPHA / DIGIT |
1590 | | // UCS4 = <any UCS4 character> |
1591 | | |
1592 | | // 1st Production (UNC file; FSysStyle::Dos only): |
1593 | | // "\\" domain ["\" *UCS4] |
1594 | | // 2nd Production (Unix-like DOS file; FSysStyle::Dos only): |
1595 | | // ALPHA ":" ["/" *UCS4] |
1596 | | // 3rd Production (DOS file; FSysStyle::Dos only): |
1597 | | // ALPHA ":" ["\" *UCS4] |
1598 | 313k | if (eStyle & FSysStyle::Dos) |
1599 | 313k | { |
1600 | 313k | bool bFSys = false; |
1601 | 313k | sal_Unicode const * q = p; |
1602 | 313k | if (pEnd - q >= 2 |
1603 | 213k | && rtl::isAsciiAlpha(q[0]) |
1604 | 24.8k | && q[1] == ':' |
1605 | 4.05k | && (pEnd - q == 2 || q[2] == '/' || q[2] == '\\')) |
1606 | 2.09k | bFSys = true; // 2nd, 3rd |
1607 | 311k | else if (pEnd - q >= 2 && q[0] == '\\' && q[1] == '\\') |
1608 | 45.1k | { |
1609 | 45.1k | q += 2; |
1610 | 45.1k | sal_Int32 n = rtl_ustr_indexOfChar_WithLength( |
1611 | 45.1k | q, pEnd - q, '\\'); |
1612 | 45.1k | if (n == 1 && q[0] == '?') |
1613 | 9.21k | { |
1614 | | // "\\?\c:\..." or "\\?\UNC\servername\..." |
1615 | 9.21k | q += 2; |
1616 | 9.21k | if (pEnd - q >= 2 |
1617 | 8.38k | && rtl::isAsciiAlpha(q[0]) |
1618 | 6.53k | && q[1] == ':' |
1619 | 1.79k | && (pEnd - q == 2 || q[2] == '/' || q[2] == '\\')) |
1620 | 1.45k | { |
1621 | 1.45k | bFSys = true; // 2nd, 3rd |
1622 | 1.45k | } |
1623 | 7.76k | else if (pEnd - q >= 4 |
1624 | 6.10k | && q[3] == '\\' |
1625 | 4.02k | && rtl::toAsciiLowerCase(q[0]) == 'u' |
1626 | 2.90k | && rtl::toAsciiLowerCase(q[1]) == 'n' |
1627 | 2.38k | && rtl::toAsciiLowerCase(q[2]) == 'c') |
1628 | 1.93k | { |
1629 | 1.93k | q += 4; // Check if it's 1st below |
1630 | 1.93k | } |
1631 | 9.21k | } |
1632 | 45.1k | if (!bFSys) |
1633 | 43.7k | { |
1634 | 43.7k | sal_Unicode const * qe = n == -1 ? pEnd : q + n; |
1635 | 43.7k | if (parseHostOrNetBiosName( |
1636 | 43.7k | q, qe, EncodeMechanism::All, RTL_TEXTENCODING_DONTKNOW, |
1637 | 43.7k | true, nullptr)) |
1638 | 24.5k | { |
1639 | 24.5k | bFSys = true; // 1st |
1640 | 24.5k | } |
1641 | 43.7k | } |
1642 | 45.1k | } |
1643 | 313k | if (bFSys) |
1644 | 28.1k | { |
1645 | 28.1k | INetURLObject aNewURI; |
1646 | 28.1k | aNewURI.setAbsURIRef(rTheRelURIRef, eMechanism, |
1647 | 28.1k | eCharset, true, eStyle); |
1648 | 28.1k | if (!aNewURI.HasError()) |
1649 | 22.0k | { |
1650 | 22.0k | rTheAbsURIRef = std::move(aNewURI); |
1651 | 22.0k | rWasAbsolute = true; |
1652 | 22.0k | return true; |
1653 | 22.0k | } |
1654 | 28.1k | } |
1655 | 313k | } |
1656 | | |
1657 | | // When the base URL is a file URL, accept relative file system paths |
1658 | | // using "\" or ":" as delimiter (and ignoring URI conventions for "%" |
1659 | | // and "#"), as well as relative URIs using "/" as delimiter: |
1660 | 291k | if (m_eScheme == INetProtocol::File) |
1661 | 290k | switch (guessFSysStyleByCounting(p, pEnd, eStyle)) |
1662 | 290k | { |
1663 | 255k | case FSysStyle::Unix: |
1664 | 255k | nSegmentDelimiter = '/'; |
1665 | 255k | break; |
1666 | | |
1667 | 34.1k | case FSysStyle::Dos: |
1668 | 34.1k | nSegmentDelimiter = '\\'; |
1669 | 34.1k | bRelativeNonURIs = true; |
1670 | 34.1k | break; |
1671 | | |
1672 | 0 | default: |
1673 | 0 | OSL_FAIL("INetURLObject::convertRelToAbs():" |
1674 | 0 | " Bad guessFSysStyleByCounting"); |
1675 | 0 | break; |
1676 | 290k | } |
1677 | | |
1678 | 291k | if (bRelativeNonURIs) |
1679 | 34.1k | { |
1680 | 34.1k | eMechanism = EncodeMechanism::All; |
1681 | 34.1k | nQueryDelimiter = 0x80000000; |
1682 | 34.1k | nFragmentDelimiter = 0x80000000; |
1683 | 34.1k | ePart = PART_VISIBLE_NONSPECIAL; |
1684 | 34.1k | } |
1685 | 291k | } |
1686 | | |
1687 | | // If the relative URI has the same scheme as the base URI, and that |
1688 | | // scheme is hierarchical, then ignore its presence in the relative |
1689 | | // URI in order to be backward compatible (cf. RFC 2396 section 5.2 |
1690 | | // step 3): |
1691 | 521k | if (pPrefix && pPrefix->m_eScheme == m_eScheme |
1692 | 83.5k | && getSchemeInfo().m_bHierarchical) |
1693 | 83.5k | { |
1694 | 83.5k | hasScheme = false; |
1695 | 417k | while (p != pEnd && *p++ != ':') ; |
1696 | 83.5k | } |
1697 | 521k | rWasAbsolute = hasScheme; |
1698 | | |
1699 | | // Fast solution for non-relative URIs: |
1700 | 521k | if (hasScheme) |
1701 | 59.5k | { |
1702 | 59.5k | INetURLObject aNewURI(rTheRelURIRef, eMechanism, eCharset); |
1703 | 59.5k | if (aNewURI.HasError()) |
1704 | 6.06k | { |
1705 | 6.06k | rWasAbsolute = false; |
1706 | 6.06k | return false; |
1707 | 6.06k | } |
1708 | | |
1709 | 53.4k | if (bIgnoreFragment) |
1710 | 0 | aNewURI.clearFragment(); |
1711 | 53.4k | rTheAbsURIRef = std::move(aNewURI); |
1712 | 53.4k | return true; |
1713 | 59.5k | } |
1714 | | |
1715 | 461k | enum State { STATE_AUTH, STATE_ABS_PATH, STATE_REL_PATH, STATE_FRAGMENT, |
1716 | 461k | STATE_DONE }; |
1717 | | |
1718 | 461k | OUStringBuffer aSynAbsURIRef(128); |
1719 | | // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme |
1720 | | // is empty ("") in that case, so take the scheme from m_aAbsURIRef |
1721 | 461k | if (m_eScheme != INetProtocol::Generic) |
1722 | 460k | { |
1723 | 460k | aSynAbsURIRef.append(getSchemeInfo().m_sScheme); |
1724 | 460k | } |
1725 | 717 | else |
1726 | 717 | { |
1727 | 717 | sal_Unicode const * pSchemeBegin |
1728 | 717 | = m_aAbsURIRef.getStr(); |
1729 | 717 | sal_Unicode const * pSchemeEnd = pSchemeBegin; |
1730 | 4.13k | while (pSchemeEnd[0] != ':') |
1731 | 3.41k | { |
1732 | 3.41k | ++pSchemeEnd; |
1733 | 3.41k | } |
1734 | 717 | aSynAbsURIRef.append(pSchemeBegin, pSchemeEnd - pSchemeBegin); |
1735 | 717 | } |
1736 | 461k | aSynAbsURIRef.append(':'); |
1737 | | |
1738 | 461k | State eState = STATE_AUTH; |
1739 | 461k | bool bSameDoc = true; |
1740 | | |
1741 | 461k | if (getSchemeInfo().m_bAuthority) |
1742 | 376k | { |
1743 | 376k | if (pEnd - p >= 2 && p[0] == '/' && p[1] == '/') |
1744 | 103k | { |
1745 | 103k | aSynAbsURIRef.append("//"); |
1746 | 103k | p += 2; |
1747 | 103k | eState = STATE_ABS_PATH; |
1748 | 103k | bSameDoc = false; |
1749 | 352k | while (p != pEnd) |
1750 | 333k | { |
1751 | 333k | EscapeType eEscapeType; |
1752 | 333k | sal_uInt32 nUTF32 |
1753 | 333k | = getUTF32(p, pEnd, eMechanism, |
1754 | 333k | eCharset, eEscapeType); |
1755 | 333k | if (eEscapeType == EscapeType::NONE) |
1756 | 332k | { |
1757 | 332k | if (nUTF32 == nSegmentDelimiter) |
1758 | 83.0k | break; |
1759 | 249k | else if (nUTF32 == nFragmentDelimiter) |
1760 | 1.04k | { |
1761 | 1.04k | eState = STATE_FRAGMENT; |
1762 | 1.04k | break; |
1763 | 1.04k | } |
1764 | 332k | } |
1765 | 248k | appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, |
1766 | 248k | PART_VISIBLE, eCharset, true); |
1767 | 248k | } |
1768 | 103k | } |
1769 | 273k | else |
1770 | 273k | { |
1771 | 273k | SubString aAuthority(getAuthority()); |
1772 | 273k | aSynAbsURIRef.append(m_aAbsURIRef.getStr() |
1773 | 273k | + aAuthority.getBegin(), |
1774 | 273k | aAuthority.getLength()); |
1775 | 273k | } |
1776 | 376k | } |
1777 | | |
1778 | 461k | if (eState == STATE_AUTH) |
1779 | 358k | { |
1780 | 358k | if (p == pEnd) |
1781 | 25.4k | eState = STATE_DONE; |
1782 | 332k | else if (*p == nFragmentDelimiter) |
1783 | 9.90k | { |
1784 | 9.90k | ++p; |
1785 | 9.90k | eState = STATE_FRAGMENT; |
1786 | 9.90k | } |
1787 | 323k | else if (*p == nSegmentDelimiter) |
1788 | 68.2k | { |
1789 | 68.2k | ++p; |
1790 | 68.2k | eState = STATE_ABS_PATH; |
1791 | 68.2k | bSameDoc = false; |
1792 | 68.2k | } |
1793 | 254k | else |
1794 | 254k | { |
1795 | 254k | eState = STATE_REL_PATH; |
1796 | 254k | bSameDoc = false; |
1797 | 254k | } |
1798 | 358k | } |
1799 | | |
1800 | 461k | if (eState == STATE_ABS_PATH) |
1801 | 170k | { |
1802 | 170k | aSynAbsURIRef.append('/'); |
1803 | 170k | eState = STATE_DONE; |
1804 | 1.52M | while (p != pEnd) |
1805 | 1.36M | { |
1806 | 1.36M | EscapeType eEscapeType; |
1807 | 1.36M | sal_uInt32 nUTF32 |
1808 | 1.36M | = getUTF32(p, pEnd, eMechanism, eCharset, eEscapeType); |
1809 | 1.36M | if (eEscapeType == EscapeType::NONE) |
1810 | 1.30M | { |
1811 | 1.30M | if (nUTF32 == nFragmentDelimiter) |
1812 | 10.8k | { |
1813 | 10.8k | eState = STATE_FRAGMENT; |
1814 | 10.8k | break; |
1815 | 10.8k | } |
1816 | 1.29M | else if (nUTF32 == nSegmentDelimiter) |
1817 | 140k | nUTF32 = '/'; |
1818 | 1.30M | } |
1819 | 1.35M | appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, ePart, |
1820 | 1.35M | eCharset, true); |
1821 | 1.35M | } |
1822 | 170k | } |
1823 | 291k | else if (eState == STATE_REL_PATH) |
1824 | 254k | { |
1825 | 254k | if (!getSchemeInfo().m_bHierarchical) |
1826 | 70.8k | { |
1827 | | // Detect cases where a relative input could not be made absolute |
1828 | | // because the given base URL is broken (most probably because it is |
1829 | | // empty): |
1830 | 70.8k | SAL_WARN_IF( |
1831 | 70.8k | HasError(), "tools.urlobj", |
1832 | 70.8k | "cannot make <" << rTheRelURIRef |
1833 | 70.8k | << "> absolute against broken base <" |
1834 | 70.8k | << GetMainURL(DecodeMechanism::NONE) << ">"); |
1835 | 70.8k | rWasAbsolute = false; |
1836 | 70.8k | return false; |
1837 | 70.8k | } |
1838 | | |
1839 | 183k | sal_Unicode const * pBasePathBegin |
1840 | 183k | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
1841 | 183k | sal_Unicode const * pBasePathEnd |
1842 | 183k | = pBasePathBegin + m_aPath.getLength(); |
1843 | 1.66M | while (pBasePathEnd != pBasePathBegin) |
1844 | 1.66M | if (*(--pBasePathEnd) == '/') |
1845 | 183k | { |
1846 | 183k | ++pBasePathEnd; |
1847 | 183k | break; |
1848 | 183k | } |
1849 | | |
1850 | 183k | sal_Int32 nPathBegin = aSynAbsURIRef.getLength(); |
1851 | 183k | aSynAbsURIRef.append(pBasePathBegin, pBasePathEnd - pBasePathBegin); |
1852 | 183k | DBG_ASSERT(aSynAbsURIRef.getLength() > nPathBegin |
1853 | 183k | && aSynAbsURIRef[aSynAbsURIRef.getLength() - 1] == '/', |
1854 | 183k | "INetURLObject::convertRelToAbs(): Bad base path"); |
1855 | | |
1856 | 385k | while (p != pEnd && *p != nQueryDelimiter && *p != nFragmentDelimiter) |
1857 | 201k | { |
1858 | 201k | if (*p == '.') |
1859 | 14.7k | { |
1860 | 14.7k | if (pEnd - p == 1 |
1861 | 11.8k | || p[1] == nSegmentDelimiter |
1862 | 10.8k | || p[1] == nQueryDelimiter |
1863 | 10.8k | || p[1] == nFragmentDelimiter) |
1864 | 4.18k | { |
1865 | 4.18k | ++p; |
1866 | 4.18k | if (p != pEnd && *p == nSegmentDelimiter) |
1867 | 1.00k | ++p; |
1868 | 4.18k | continue; |
1869 | 4.18k | } |
1870 | 10.5k | else if (pEnd - p >= 2 |
1871 | 10.5k | && p[1] == '.' |
1872 | 8.35k | && (pEnd - p == 2 |
1873 | 6.66k | || p[2] == nSegmentDelimiter |
1874 | 1.23k | || p[2] == nQueryDelimiter |
1875 | 1.23k | || p[2] == nFragmentDelimiter) |
1876 | 7.52k | && aSynAbsURIRef.getLength() - nPathBegin > 1) |
1877 | 6.06k | { |
1878 | 6.06k | p += 2; |
1879 | 6.06k | if (p != pEnd && *p == nSegmentDelimiter) |
1880 | 4.00k | ++p; |
1881 | | |
1882 | 6.06k | sal_Int32 i = aSynAbsURIRef.getLength() - 2; |
1883 | 39.4k | while (i > nPathBegin && aSynAbsURIRef[i] != '/') |
1884 | 33.4k | --i; |
1885 | 6.06k | aSynAbsURIRef.setLength(i + 1); |
1886 | 6.06k | DBG_ASSERT( |
1887 | 6.06k | aSynAbsURIRef.getLength() > nPathBegin |
1888 | 6.06k | && aSynAbsURIRef[aSynAbsURIRef.getLength() - 1] == '/', |
1889 | 6.06k | "INetURLObject::convertRelToAbs(): Bad base path"); |
1890 | 6.06k | continue; |
1891 | 6.06k | } |
1892 | 14.7k | } |
1893 | | |
1894 | 829k | while (p != pEnd |
1895 | 728k | && *p != nSegmentDelimiter |
1896 | 642k | && *p != nQueryDelimiter |
1897 | 642k | && *p != nFragmentDelimiter) |
1898 | 638k | { |
1899 | 638k | EscapeType eEscapeType; |
1900 | 638k | sal_uInt32 nUTF32 |
1901 | 638k | = getUTF32(p, pEnd, eMechanism, |
1902 | 638k | eCharset, eEscapeType); |
1903 | 638k | appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, ePart, |
1904 | 638k | eCharset, true); |
1905 | 638k | } |
1906 | 191k | if (p != pEnd && *p == nSegmentDelimiter) |
1907 | 86.1k | { |
1908 | 86.1k | aSynAbsURIRef.append('/'); |
1909 | 86.1k | ++p; |
1910 | 86.1k | } |
1911 | 191k | } |
1912 | | |
1913 | 185k | while (p != pEnd && *p != nFragmentDelimiter) |
1914 | 1.92k | { |
1915 | 1.92k | EscapeType eEscapeType; |
1916 | 1.92k | sal_uInt32 nUTF32 |
1917 | 1.92k | = getUTF32(p, pEnd, eMechanism, eCharset, eEscapeType); |
1918 | 1.92k | appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, ePart, |
1919 | 1.92k | eCharset, true); |
1920 | 1.92k | } |
1921 | | |
1922 | 183k | if (p == pEnd) |
1923 | 178k | eState = STATE_DONE; |
1924 | 5.16k | else |
1925 | 5.16k | { |
1926 | 5.16k | ++p; |
1927 | 5.16k | eState = STATE_FRAGMENT; |
1928 | 5.16k | } |
1929 | 183k | } |
1930 | 36.4k | else if (bSameDoc) |
1931 | 35.3k | { |
1932 | 35.3k | aSynAbsURIRef.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(), |
1933 | 35.3k | m_aPath.getLength()); |
1934 | 35.3k | if (m_aQuery.isPresent()) |
1935 | 0 | aSynAbsURIRef.append(m_aAbsURIRef.getStr() |
1936 | 0 | + m_aQuery.getBegin() - 1, |
1937 | 0 | m_aQuery.getLength() + 1); |
1938 | 35.3k | } |
1939 | | |
1940 | 390k | if (eState == STATE_FRAGMENT && !bIgnoreFragment) |
1941 | 26.9k | { |
1942 | 26.9k | aSynAbsURIRef.append('#'); |
1943 | 377k | while (p != pEnd) |
1944 | 350k | { |
1945 | 350k | EscapeType eEscapeType; |
1946 | 350k | sal_uInt32 nUTF32 |
1947 | 350k | = getUTF32(p, pEnd, eMechanism, eCharset, eEscapeType); |
1948 | 350k | appendUCS4(aSynAbsURIRef, nUTF32, eEscapeType, |
1949 | 350k | PART_VISIBLE, eCharset, true); |
1950 | 350k | } |
1951 | 26.9k | } |
1952 | | |
1953 | 390k | INetURLObject aNewURI(aSynAbsURIRef); |
1954 | 390k | if (aNewURI.HasError()) |
1955 | 31.9k | { |
1956 | | // Detect cases where a relative input could not be made absolute |
1957 | | // because the given base URL is broken (most probably because it is |
1958 | | // empty): |
1959 | 31.9k | SAL_WARN_IF( |
1960 | 31.9k | HasError(), "tools.urlobj", |
1961 | 31.9k | "cannot make <" << rTheRelURIRef |
1962 | 31.9k | << "> absolute against broken base <" << GetMainURL(DecodeMechanism::NONE) |
1963 | 31.9k | << ">"); |
1964 | 31.9k | rWasAbsolute = false; |
1965 | 31.9k | return false; |
1966 | 31.9k | } |
1967 | | |
1968 | 358k | rTheAbsURIRef = std::move(aNewURI); |
1969 | 358k | return true; |
1970 | 390k | } |
1971 | | |
1972 | | bool INetURLObject::convertAbsToRel(OUString const & rTheAbsURIRef, |
1973 | | OUString & rTheRelURIRef, |
1974 | | EncodeMechanism eEncodeMechanism, |
1975 | | DecodeMechanism eDecodeMechanism, |
1976 | | rtl_TextEncoding eCharset, |
1977 | | FSysStyle eStyle) const |
1978 | 0 | { |
1979 | | // Check for hierarchical base URL: |
1980 | 0 | if (!getSchemeInfo().m_bHierarchical) |
1981 | 0 | { |
1982 | 0 | rTheRelURIRef = decode(rTheAbsURIRef, eDecodeMechanism, eCharset); |
1983 | 0 | return false; |
1984 | 0 | } |
1985 | | |
1986 | | // Convert the input (absolute or relative URI ref) to an absolute URI |
1987 | | // ref: |
1988 | 0 | INetURLObject aSubject; |
1989 | 0 | bool bWasAbsolute; |
1990 | 0 | if (!convertRelToAbs(rTheAbsURIRef, aSubject, bWasAbsolute, |
1991 | 0 | eEncodeMechanism, eCharset, false, false, false, |
1992 | 0 | eStyle)) |
1993 | 0 | { |
1994 | 0 | rTheRelURIRef = decode(rTheAbsURIRef, eDecodeMechanism, eCharset); |
1995 | 0 | return false; |
1996 | 0 | } |
1997 | | |
1998 | | // Check for differing scheme or authority parts: |
1999 | 0 | if ((m_aScheme.compare( |
2000 | 0 | aSubject.m_aScheme, m_aAbsURIRef, aSubject.m_aAbsURIRef) |
2001 | 0 | != 0) |
2002 | 0 | || (m_aUser.compare( |
2003 | 0 | aSubject.m_aUser, m_aAbsURIRef, aSubject.m_aAbsURIRef) |
2004 | 0 | != 0) |
2005 | 0 | || (m_aAuth.compare( |
2006 | 0 | aSubject.m_aAuth, m_aAbsURIRef, aSubject.m_aAbsURIRef) |
2007 | 0 | != 0) |
2008 | 0 | || (m_aHost.compare( |
2009 | 0 | aSubject.m_aHost, m_aAbsURIRef, aSubject.m_aAbsURIRef) |
2010 | 0 | != 0) |
2011 | 0 | || (m_aPort.compare( |
2012 | 0 | aSubject.m_aPort, m_aAbsURIRef, aSubject.m_aAbsURIRef) |
2013 | 0 | != 0)) |
2014 | 0 | { |
2015 | 0 | rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); |
2016 | 0 | return false; |
2017 | 0 | } |
2018 | | |
2019 | 0 | sal_Unicode const * pBasePathBegin |
2020 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
2021 | 0 | sal_Unicode const * pBasePathEnd = pBasePathBegin + m_aPath.getLength(); |
2022 | 0 | sal_Unicode const * pSubjectPathBegin |
2023 | 0 | = aSubject.m_aAbsURIRef.getStr() + aSubject.m_aPath.getBegin(); |
2024 | 0 | sal_Unicode const * pSubjectPathEnd |
2025 | 0 | = pSubjectPathBegin + aSubject.m_aPath.getLength(); |
2026 | | |
2027 | | // Make nMatch point past the last matching slash, or past the end of the |
2028 | | // paths, in case they are equal: |
2029 | 0 | sal_Unicode const * pSlash = nullptr; |
2030 | 0 | sal_Unicode const * p1 = pBasePathBegin; |
2031 | 0 | sal_Unicode const * p2 = pSubjectPathBegin; |
2032 | 0 | for (;;) |
2033 | 0 | { |
2034 | 0 | if (p1 == pBasePathEnd || p2 == pSubjectPathEnd) |
2035 | 0 | { |
2036 | 0 | if (p1 == pBasePathEnd && p2 == pSubjectPathEnd) |
2037 | 0 | pSlash = p1; |
2038 | 0 | break; |
2039 | 0 | } |
2040 | | |
2041 | 0 | sal_Unicode c = *p1++; |
2042 | 0 | if (c != *p2++) |
2043 | 0 | break; |
2044 | 0 | if (c == '/') |
2045 | 0 | pSlash = p1; |
2046 | 0 | } |
2047 | 0 | if (!pSlash) |
2048 | 0 | { |
2049 | | // One of the paths does not start with '/': |
2050 | 0 | rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); |
2051 | 0 | return false; |
2052 | 0 | } |
2053 | 0 | sal_Int32 nMatch = pSlash - pBasePathBegin; |
2054 | | |
2055 | | // If the two URLs are DOS file URLs starting with different volumes |
2056 | | // (e.g., file:///a:/... and file:///b:/...), the subject is not made |
2057 | | // relative (it could be, but some people do not like that): |
2058 | 0 | if (m_eScheme == INetProtocol::File |
2059 | 0 | && nMatch <= 1 |
2060 | 0 | && hasDosVolume(eStyle) |
2061 | 0 | && aSubject.hasDosVolume(eStyle)) //TODO! ok to use eStyle for these? |
2062 | 0 | { |
2063 | 0 | rTheRelURIRef = aSubject.GetMainURL(eDecodeMechanism, eCharset); |
2064 | 0 | return false; |
2065 | 0 | } |
2066 | | |
2067 | | // For every slash in the base path after nMatch, a prefix of "../" is |
2068 | | // added to the new relative URL (if the common prefix of the two paths is |
2069 | | // only "/"---but see handling of file URLs above---, the complete subject |
2070 | | // path could go into the new relative URL instead, but some people don't |
2071 | | // like that): |
2072 | 0 | OUStringBuffer aSynRelURIRef; |
2073 | 0 | for (sal_Unicode const * p = pBasePathBegin + nMatch; p != pBasePathEnd; |
2074 | 0 | ++p) |
2075 | 0 | { |
2076 | 0 | if (*p == '/') |
2077 | 0 | aSynRelURIRef.append("../"); |
2078 | 0 | } |
2079 | | |
2080 | | // If the new relative URL would start with "//" (i.e., it would be |
2081 | | // mistaken for a relative URL starting with an authority part), or if the |
2082 | | // new relative URL would neither be empty nor start with <"/"> nor start |
2083 | | // with <1*rseg> (i.e., it could be mistaken for an absolute URL starting |
2084 | | // with a scheme part), then the new relative URL is prefixed with "./": |
2085 | 0 | if (aSynRelURIRef.isEmpty()) |
2086 | 0 | { |
2087 | 0 | if (pSubjectPathEnd - pSubjectPathBegin >= nMatch + 2 |
2088 | 0 | && pSubjectPathBegin[nMatch] == '/' |
2089 | 0 | && pSubjectPathBegin[nMatch + 1] == '/') |
2090 | 0 | { |
2091 | 0 | aSynRelURIRef.append("./"); |
2092 | 0 | } |
2093 | 0 | else |
2094 | 0 | { |
2095 | 0 | for (sal_Unicode const * p = pSubjectPathBegin + nMatch; |
2096 | 0 | p != pSubjectPathEnd && *p != '/'; ++p) |
2097 | 0 | { |
2098 | 0 | if (mustEncode(*p, PART_REL_SEGMENT_EXTRA)) |
2099 | 0 | { |
2100 | 0 | aSynRelURIRef.append("./"); |
2101 | 0 | break; |
2102 | 0 | } |
2103 | 0 | } |
2104 | 0 | } |
2105 | 0 | } |
2106 | | |
2107 | | // The remainder of the subject path, starting at nMatch, is appended to |
2108 | | // the new relative URL: |
2109 | 0 | aSynRelURIRef.append(decode(pSubjectPathBegin + nMatch, pSubjectPathEnd, |
2110 | 0 | eDecodeMechanism, eCharset)); |
2111 | | |
2112 | | // If the subject has defined query or fragment parts, they are appended |
2113 | | // to the new relative URL: |
2114 | 0 | if (aSubject.m_aQuery.isPresent()) |
2115 | 0 | { |
2116 | 0 | aSynRelURIRef.append("?" |
2117 | 0 | + aSubject.decode(aSubject.m_aQuery, eDecodeMechanism, eCharset)); |
2118 | 0 | } |
2119 | 0 | if (aSubject.m_aFragment.isPresent()) |
2120 | 0 | { |
2121 | 0 | aSynRelURIRef.append("#" |
2122 | 0 | + aSubject.decode(aSubject.m_aFragment, eDecodeMechanism, eCharset)); |
2123 | 0 | } |
2124 | |
|
2125 | 0 | rTheRelURIRef = aSynRelURIRef.makeStringAndClear(); |
2126 | 0 | return true; |
2127 | 0 | } |
2128 | | |
2129 | | // static |
2130 | | bool INetURLObject::convertIntToExt(std::u16string_view rTheIntURIRef, |
2131 | | OUString & rTheExtURIRef, |
2132 | | DecodeMechanism eDecodeMechanism, |
2133 | | rtl_TextEncoding eCharset) |
2134 | 0 | { |
2135 | 0 | OUStringBuffer aSynExtURIRef(256); |
2136 | 0 | encodeText(aSynExtURIRef, rTheIntURIRef, PART_VISIBLE, |
2137 | 0 | EncodeMechanism::NotCanonical, eCharset, true); |
2138 | 0 | sal_Unicode const * pBegin = aSynExtURIRef.getStr(); |
2139 | 0 | sal_Unicode const * pEnd = pBegin + aSynExtURIRef.getLength(); |
2140 | 0 | sal_Unicode const * p = pBegin; |
2141 | 0 | PrefixInfo const * pPrefix = getPrefix(p, pEnd); |
2142 | 0 | bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::Kind::Internal; |
2143 | 0 | if (bConvert) |
2144 | 0 | { |
2145 | 0 | comphelper::string::replaceAt(aSynExtURIRef, 0, p - pBegin, |
2146 | 0 | pPrefix->m_aTranslatedPrefix); |
2147 | 0 | } |
2148 | 0 | rTheExtURIRef = decode(aSynExtURIRef, eDecodeMechanism, eCharset); |
2149 | 0 | return bConvert; |
2150 | 0 | } |
2151 | | |
2152 | | // static |
2153 | | bool INetURLObject::convertExtToInt(std::u16string_view rTheExtURIRef, |
2154 | | OUString & rTheIntURIRef, |
2155 | | DecodeMechanism eDecodeMechanism, |
2156 | | rtl_TextEncoding eCharset) |
2157 | 0 | { |
2158 | 0 | OUStringBuffer aSynIntURIRef(256); |
2159 | 0 | encodeText(aSynIntURIRef, rTheExtURIRef, PART_VISIBLE, |
2160 | 0 | EncodeMechanism::NotCanonical, eCharset, true); |
2161 | 0 | sal_Unicode const * pBegin = aSynIntURIRef.getStr(); |
2162 | 0 | sal_Unicode const * pEnd = pBegin + aSynIntURIRef.getLength(); |
2163 | 0 | sal_Unicode const * p = pBegin; |
2164 | 0 | PrefixInfo const * pPrefix = getPrefix(p, pEnd); |
2165 | 0 | bool bConvert = pPrefix && pPrefix->m_eKind == PrefixInfo::Kind::External; |
2166 | 0 | if (bConvert) |
2167 | 0 | { |
2168 | 0 | comphelper::string::replaceAt(aSynIntURIRef, 0, p - pBegin, |
2169 | 0 | pPrefix->m_aTranslatedPrefix); |
2170 | 0 | } |
2171 | 0 | rTheIntURIRef = decode(aSynIntURIRef, eDecodeMechanism, eCharset); |
2172 | 0 | return bConvert; |
2173 | 0 | } |
2174 | | |
2175 | | // static |
2176 | | INetURLObject::PrefixInfo const * INetURLObject::getPrefix(sal_Unicode const *& rBegin, |
2177 | | sal_Unicode const * pEnd) |
2178 | 4.19M | { |
2179 | 4.19M | static PrefixInfo constexpr aMap[] |
2180 | 4.19M | { // dummy entry at front needed, because pLast may point here: |
2181 | 4.19M | { u""_ustr, u""_ustr, INetProtocol::NotValid, PrefixInfo::Kind::Internal }, |
2182 | 4.19M | { u".component:"_ustr, u"staroffice.component:"_ustr, INetProtocol::Component, |
2183 | 4.19M | PrefixInfo::Kind::Internal }, |
2184 | 4.19M | { u".uno:"_ustr, u"staroffice.uno:"_ustr, INetProtocol::Uno, |
2185 | 4.19M | PrefixInfo::Kind::Internal }, |
2186 | 4.19M | { u"cid:"_ustr, u""_ustr, INetProtocol::Cid, PrefixInfo::Kind::Official }, |
2187 | 4.19M | { u"data:"_ustr, u""_ustr, INetProtocol::Data, PrefixInfo::Kind::Official }, |
2188 | 4.19M | { u"db:"_ustr, u"staroffice.db:"_ustr, INetProtocol::Db, PrefixInfo::Kind::Internal }, |
2189 | 4.19M | { u"file:"_ustr, u""_ustr, INetProtocol::File, PrefixInfo::Kind::Official }, |
2190 | 4.19M | { u"ftp:"_ustr, u""_ustr, INetProtocol::Ftp, PrefixInfo::Kind::Official }, |
2191 | 4.19M | { u"hid:"_ustr, u"staroffice.hid:"_ustr, INetProtocol::Hid, |
2192 | 4.19M | PrefixInfo::Kind::Internal }, |
2193 | 4.19M | { u"http:"_ustr, u""_ustr, INetProtocol::Http, PrefixInfo::Kind::Official }, |
2194 | 4.19M | { u"https:"_ustr, u""_ustr, INetProtocol::Https, PrefixInfo::Kind::Official }, |
2195 | 4.19M | { u"javascript:"_ustr, u""_ustr, INetProtocol::Javascript, PrefixInfo::Kind::Official }, |
2196 | 4.19M | { u"ldap:"_ustr, u""_ustr, INetProtocol::Ldap, PrefixInfo::Kind::Official }, |
2197 | 4.19M | { u"macro:"_ustr, u"staroffice.macro:"_ustr, INetProtocol::Macro, |
2198 | 4.19M | PrefixInfo::Kind::Internal }, |
2199 | 4.19M | { u"mailto:"_ustr, u""_ustr, INetProtocol::Mailto, PrefixInfo::Kind::Official }, |
2200 | 4.19M | { u"private:"_ustr, u"staroffice.private:"_ustr, INetProtocol::PrivSoffice, |
2201 | 4.19M | PrefixInfo::Kind::Internal }, |
2202 | 4.19M | { u"private:factory/"_ustr, u"staroffice.factory:"_ustr, |
2203 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::Internal }, |
2204 | 4.19M | { u"private:helpid/"_ustr, u"staroffice.helpid:"_ustr, INetProtocol::PrivSoffice, |
2205 | 4.19M | PrefixInfo::Kind::Internal }, |
2206 | 4.19M | { u"private:java/"_ustr, u"staroffice.java:"_ustr, INetProtocol::PrivSoffice, |
2207 | 4.19M | PrefixInfo::Kind::Internal }, |
2208 | 4.19M | { u"private:searchfolder:"_ustr, u"staroffice.searchfolder:"_ustr, |
2209 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::Internal }, |
2210 | 4.19M | { u"private:trashcan:"_ustr, u"staroffice.trashcan:"_ustr, |
2211 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::Internal }, |
2212 | 4.19M | { u"sftp:"_ustr, u""_ustr, INetProtocol::Sftp, PrefixInfo::Kind::Official }, |
2213 | 4.19M | { u"smb:"_ustr, u""_ustr, INetProtocol::Smb, PrefixInfo::Kind::Official }, |
2214 | 4.19M | { u"staroffice.component:"_ustr, u".component:"_ustr, INetProtocol::Component, |
2215 | 4.19M | PrefixInfo::Kind::External }, |
2216 | 4.19M | { u"staroffice.db:"_ustr, u"db:"_ustr, INetProtocol::Db, PrefixInfo::Kind::External }, |
2217 | 4.19M | { u"staroffice.factory:"_ustr, u"private:factory/"_ustr, |
2218 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::External }, |
2219 | 4.19M | { u"staroffice.helpid:"_ustr, u"private:helpid/"_ustr, INetProtocol::PrivSoffice, |
2220 | 4.19M | PrefixInfo::Kind::External }, |
2221 | 4.19M | { u"staroffice.hid:"_ustr, u"hid:"_ustr, INetProtocol::Hid, |
2222 | 4.19M | PrefixInfo::Kind::External }, |
2223 | 4.19M | { u"staroffice.java:"_ustr, u"private:java/"_ustr, INetProtocol::PrivSoffice, |
2224 | 4.19M | PrefixInfo::Kind::External }, |
2225 | 4.19M | { u"staroffice.macro:"_ustr, u"macro:"_ustr, INetProtocol::Macro, |
2226 | 4.19M | PrefixInfo::Kind::External }, |
2227 | 4.19M | { u"staroffice.private:"_ustr, u"private:"_ustr, INetProtocol::PrivSoffice, |
2228 | 4.19M | PrefixInfo::Kind::External }, |
2229 | 4.19M | { u"staroffice.searchfolder:"_ustr, u"private:searchfolder:"_ustr, |
2230 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::External }, |
2231 | 4.19M | { u"staroffice.trashcan:"_ustr, u"private:trashcan:"_ustr, |
2232 | 4.19M | INetProtocol::PrivSoffice, PrefixInfo::Kind::External }, |
2233 | 4.19M | { u"staroffice.uno:"_ustr, u".uno:"_ustr, INetProtocol::Uno, |
2234 | 4.19M | PrefixInfo::Kind::External }, |
2235 | 4.19M | { u"staroffice:"_ustr, u"private:"_ustr, INetProtocol::PrivSoffice, |
2236 | 4.19M | PrefixInfo::Kind::External }, |
2237 | 4.19M | { u"telnet:"_ustr, u""_ustr, INetProtocol::Telnet, PrefixInfo::Kind::Official }, |
2238 | 4.19M | { u"vnd.libreoffice.cmis:"_ustr, u""_ustr, INetProtocol::Cmis, PrefixInfo::Kind::Internal }, |
2239 | 4.19M | { u"vnd.sun.star.cmd:"_ustr, u""_ustr, INetProtocol::VndSunStarCmd, |
2240 | 4.19M | PrefixInfo::Kind::Official }, |
2241 | 4.19M | { u"vnd.sun.star.expand:"_ustr, u""_ustr, INetProtocol::VndSunStarExpand, |
2242 | 4.19M | PrefixInfo::Kind::Official }, |
2243 | 4.19M | { u"vnd.sun.star.help:"_ustr, u""_ustr, INetProtocol::VndSunStarHelp, |
2244 | 4.19M | PrefixInfo::Kind::Official }, |
2245 | 4.19M | { u"vnd.sun.star.hier:"_ustr, u""_ustr, INetProtocol::VndSunStarHier, |
2246 | 4.19M | PrefixInfo::Kind::Official }, |
2247 | 4.19M | { u"vnd.sun.star.pkg:"_ustr, u""_ustr, INetProtocol::VndSunStarPkg, |
2248 | 4.19M | PrefixInfo::Kind::Official }, |
2249 | 4.19M | { u"vnd.sun.star.tdoc:"_ustr, u""_ustr, INetProtocol::VndSunStarTdoc, |
2250 | 4.19M | PrefixInfo::Kind::Official }, |
2251 | 4.19M | { u"vnd.sun.star.webdav:"_ustr, u""_ustr, INetProtocol::VndSunStarWebdav, |
2252 | 4.19M | PrefixInfo::Kind::Official } |
2253 | 4.19M | }; |
2254 | | /* This list needs to be sorted, or you'll introduce serious bugs */ |
2255 | | |
2256 | 4.19M | PrefixInfo const * pFirst = aMap + 1; |
2257 | 4.19M | PrefixInfo const * pLast = std::end(aMap) - 1; |
2258 | 4.19M | PrefixInfo const * pMatch = nullptr; |
2259 | 4.19M | sal_Unicode const * pMatched = rBegin; |
2260 | 4.19M | sal_Unicode const * p = rBegin; |
2261 | 4.19M | sal_Int32 i = 0; |
2262 | 10.7M | for (; pFirst < pLast; ++i) |
2263 | 7.61M | { |
2264 | 7.61M | assert(!pFirst->m_aPrefix.isEmpty() && "we start search after the dummy entry"); |
2265 | 7.61M | if (i == pFirst->m_aPrefix.getLength()) |
2266 | 68.9k | { |
2267 | 68.9k | pMatch = pFirst++; |
2268 | 68.9k | pMatched = p; |
2269 | 68.9k | } |
2270 | 7.61M | if (p >= pEnd) |
2271 | 1.04M | break; |
2272 | 6.57M | sal_uInt32 nChar = rtl::toAsciiLowerCase(*p++); |
2273 | 23.2M | while (pFirst <= pLast && static_cast<unsigned char>(pFirst->m_aPrefix[i]) < nChar) |
2274 | 16.6M | ++pFirst; |
2275 | 124M | while (pFirst <= pLast && static_cast<unsigned char>(pLast->m_aPrefix[i]) > nChar) |
2276 | 117M | --pLast; |
2277 | 6.57M | } |
2278 | 4.19M | if (pFirst == pLast) |
2279 | 1.93M | { |
2280 | 1.93M | sal_Unicode const * q = pFirst->m_aPrefix.getStr() + i; |
2281 | 6.35M | while (p < pEnd && *q != '\0' |
2282 | 4.55M | && rtl::toAsciiLowerCase(*p) == static_cast<unsigned char>(*q)) |
2283 | 4.41M | { |
2284 | 4.41M | ++p; |
2285 | 4.41M | ++q; |
2286 | 4.41M | } |
2287 | 1.93M | if (*q == '\0') |
2288 | 1.77M | { |
2289 | 1.77M | rBegin = p; |
2290 | 1.77M | return pFirst; |
2291 | 1.77M | } |
2292 | 1.93M | } |
2293 | 2.42M | rBegin = pMatched; |
2294 | 2.42M | return pMatch; |
2295 | 4.19M | } |
2296 | | |
2297 | | sal_Int32 INetURLObject::getAuthorityBegin() const |
2298 | 273k | { |
2299 | 273k | DBG_ASSERT(getSchemeInfo().m_bAuthority, |
2300 | 273k | "INetURLObject::getAuthority(): Bad scheme"); |
2301 | 273k | sal_Int32 nBegin; |
2302 | 273k | if (m_aUser.isPresent()) |
2303 | 0 | nBegin = m_aUser.getBegin(); |
2304 | 273k | else if (m_aHost.isPresent()) |
2305 | 273k | nBegin = m_aHost.getBegin(); |
2306 | 0 | else |
2307 | 0 | nBegin = m_aPath.getBegin(); |
2308 | 273k | nBegin -= RTL_CONSTASCII_LENGTH("//"); |
2309 | 273k | DBG_ASSERT(m_aAbsURIRef[nBegin] == '/' && m_aAbsURIRef[nBegin + 1] == '/', |
2310 | 273k | "INetURLObject::getAuthority(): Bad authority"); |
2311 | 273k | return nBegin; |
2312 | 273k | } |
2313 | | |
2314 | | INetURLObject::SubString INetURLObject::getAuthority() const |
2315 | 273k | { |
2316 | 273k | sal_Int32 nBegin = getAuthorityBegin(); |
2317 | 273k | sal_Int32 nEnd = m_aPort.isPresent() ? m_aPort.getEnd() : |
2318 | 273k | m_aHost.isPresent() ? m_aHost.getEnd() : |
2319 | 273k | m_aAuth.isPresent() ? m_aAuth.getEnd() : |
2320 | 0 | m_aUser.isPresent() ? m_aUser.getEnd() : |
2321 | 0 | nBegin + RTL_CONSTASCII_LENGTH("//"); |
2322 | 273k | return SubString(nBegin, nEnd - nBegin); |
2323 | 273k | } |
2324 | | |
2325 | | bool INetURLObject::setUser(std::u16string_view rTheUser, |
2326 | | rtl_TextEncoding eCharset) |
2327 | 0 | { |
2328 | 0 | if ( |
2329 | 0 | !getSchemeInfo().m_bUser |
2330 | 0 | ) |
2331 | 0 | { |
2332 | 0 | return false; |
2333 | 0 | } |
2334 | | |
2335 | 0 | OUStringBuffer aNewUser; |
2336 | 0 | encodeText(aNewUser, rTheUser, PART_USER_PASSWORD, |
2337 | 0 | EncodeMechanism::WasEncoded, eCharset, false); |
2338 | 0 | sal_Int32 nDelta; |
2339 | 0 | if (m_aUser.isPresent()) |
2340 | 0 | nDelta = m_aUser.set(m_aAbsURIRef, aNewUser); |
2341 | 0 | else if (m_aHost.isPresent()) |
2342 | 0 | { |
2343 | 0 | m_aAbsURIRef.insert(m_aHost.getBegin(), u'@'); |
2344 | 0 | nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aHost.getBegin()) + 1; |
2345 | 0 | } |
2346 | 0 | else if (getSchemeInfo().m_bHost) |
2347 | 0 | return false; |
2348 | 0 | else |
2349 | 0 | nDelta = m_aUser.set(m_aAbsURIRef, aNewUser, m_aPath.getBegin()); |
2350 | 0 | m_aAuth += nDelta; |
2351 | 0 | m_aHost += nDelta; |
2352 | 0 | m_aPort += nDelta; |
2353 | 0 | m_aPath += nDelta; |
2354 | 0 | m_aQuery += nDelta; |
2355 | 0 | m_aFragment += nDelta; |
2356 | 0 | return true; |
2357 | 0 | } |
2358 | | |
2359 | | namespace |
2360 | | { |
2361 | | void lcl_Erase(OUStringBuffer &rBuf, sal_Int32 index, sal_Int32 count) |
2362 | 67 | { |
2363 | 67 | OUString sTemp(rBuf.makeStringAndClear()); |
2364 | 67 | rBuf.append(sTemp.replaceAt(index, count, u"")); |
2365 | 67 | } |
2366 | | } |
2367 | | |
2368 | | bool INetURLObject::clearPassword() |
2369 | 11.8k | { |
2370 | 11.8k | if (!getSchemeInfo().m_bPassword) |
2371 | 11.8k | return false; |
2372 | 0 | if (m_aAuth.isPresent()) |
2373 | 0 | { |
2374 | 0 | lcl_Erase(m_aAbsURIRef, m_aAuth.getBegin() - 1, |
2375 | 0 | m_aAuth.getLength() + 1); |
2376 | 0 | sal_Int32 nDelta = m_aAuth.clear() - 1; |
2377 | 0 | m_aHost += nDelta; |
2378 | 0 | m_aPort += nDelta; |
2379 | 0 | m_aPath += nDelta; |
2380 | 0 | m_aQuery += nDelta; |
2381 | 0 | m_aFragment += nDelta; |
2382 | 0 | } |
2383 | 0 | return true; |
2384 | 11.8k | } |
2385 | | |
2386 | | bool INetURLObject::setPassword(std::u16string_view rThePassword, |
2387 | | rtl_TextEncoding eCharset) |
2388 | 0 | { |
2389 | 0 | if (!getSchemeInfo().m_bPassword) |
2390 | 0 | return false; |
2391 | 0 | OUStringBuffer aNewAuth; |
2392 | 0 | encodeText(aNewAuth, rThePassword, PART_USER_PASSWORD, |
2393 | 0 | EncodeMechanism::WasEncoded, eCharset, false); |
2394 | 0 | sal_Int32 nDelta; |
2395 | 0 | if (m_aAuth.isPresent()) |
2396 | 0 | nDelta = m_aAuth.set(m_aAbsURIRef, aNewAuth); |
2397 | 0 | else if (m_aUser.isPresent()) |
2398 | 0 | { |
2399 | 0 | m_aAbsURIRef.insert(m_aUser.getEnd(), u':'); |
2400 | 0 | nDelta |
2401 | 0 | = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aUser.getEnd() + 1) + 1; |
2402 | 0 | } |
2403 | 0 | else if (m_aHost.isPresent()) |
2404 | 0 | { |
2405 | 0 | m_aAbsURIRef.insert(m_aHost.getBegin(), ":@" ); |
2406 | 0 | m_aUser.set(m_aAbsURIRef, std::u16string_view{}, m_aHost.getBegin()); |
2407 | 0 | nDelta |
2408 | 0 | = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aHost.getBegin() + 1) + 2; |
2409 | 0 | } |
2410 | 0 | else if (getSchemeInfo().m_bHost) |
2411 | 0 | return false; |
2412 | 0 | else |
2413 | 0 | { |
2414 | 0 | m_aAbsURIRef.insert(m_aPath.getBegin(), u':'); |
2415 | 0 | m_aUser.set(m_aAbsURIRef, std::u16string_view{}, m_aPath.getBegin()); |
2416 | 0 | nDelta |
2417 | 0 | = m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aPath.getBegin() + 1) + 1; |
2418 | 0 | } |
2419 | 0 | m_aHost += nDelta; |
2420 | 0 | m_aPort += nDelta; |
2421 | 0 | m_aPath += nDelta; |
2422 | 0 | m_aQuery += nDelta; |
2423 | 0 | m_aFragment += nDelta; |
2424 | 0 | return true; |
2425 | 0 | } |
2426 | | |
2427 | | // static |
2428 | | bool INetURLObject::parseHost(sal_Unicode const *& rBegin, sal_Unicode const * pEnd, |
2429 | | OUStringBuffer* pCanonic) |
2430 | 576k | { |
2431 | | // RFC 2373 is inconsistent about how to write an IPv6 address in which an |
2432 | | // IPv4 address directly follows the abbreviating "::". The ABNF in |
2433 | | // Appendix B suggests ":::13.1.68.3", while an example in 2.2/3 explicitly |
2434 | | // mentions "::13:1.68.3". This algorithm accepts both variants: |
2435 | 576k | enum State { STATE_INITIAL, STATE_LABEL, STATE_LABEL_HYPHEN, |
2436 | 576k | STATE_LABEL_DOT, STATE_TOPLABEL, STATE_TOPLABEL_HYPHEN, |
2437 | 576k | STATE_TOPLABEL_DOT, STATE_IP4, STATE_IP4_DOT, STATE_IP6, |
2438 | 576k | STATE_IP6_COLON, STATE_IP6_2COLON, STATE_IP6_3COLON, |
2439 | 576k | STATE_IP6_HEXSEQ1, STATE_IP6_HEXSEQ1_COLON, |
2440 | 576k | STATE_IP6_HEXSEQ1_MAYBE_IP4, STATE_IP6_HEXSEQ2, |
2441 | 576k | STATE_IP6_HEXSEQ2_COLON, STATE_IP6_HEXSEQ2_MAYBE_IP4, |
2442 | 576k | STATE_IP6_IP4, STATE_IP6_IP4_DOT, STATE_IP6_DONE }; |
2443 | 576k | sal_uInt32 nNumber = 0; |
2444 | 576k | int nDigits = 0; |
2445 | 576k | int nOctets = 0; |
2446 | 576k | State eState = STATE_INITIAL; |
2447 | 576k | sal_Unicode const * p = rBegin; |
2448 | 576k | sal_Int32 nOriginalCanonicLength = pCanonic ? pCanonic->getLength() : 0; |
2449 | 4.70M | for (; p != pEnd; ++p) |
2450 | 4.24M | switch (eState) |
2451 | 4.24M | { |
2452 | 576k | case STATE_INITIAL: |
2453 | 576k | if (*p == '[') |
2454 | 58.0k | { |
2455 | 58.0k | if (pCanonic) |
2456 | 26.6k | pCanonic->append('['); |
2457 | 58.0k | eState = STATE_IP6; |
2458 | 58.0k | } |
2459 | 518k | else if (rtl::isAsciiAlpha(*p) || *p == '_') |
2460 | 431k | eState = STATE_TOPLABEL; |
2461 | 86.5k | else if (rtl::isAsciiDigit(*p)) |
2462 | 53.3k | { |
2463 | 53.3k | nNumber = INetMIME::getWeight(*p); |
2464 | 53.3k | nDigits = 1; |
2465 | 53.3k | nOctets = 1; |
2466 | 53.3k | eState = STATE_IP4; |
2467 | 53.3k | } |
2468 | 33.2k | else |
2469 | 33.2k | goto done; |
2470 | 542k | break; |
2471 | | |
2472 | 542k | case STATE_LABEL: |
2473 | 298k | if (*p == '.') |
2474 | 15.1k | eState = STATE_LABEL_DOT; |
2475 | 282k | else if (*p == '-') |
2476 | 13.3k | eState = STATE_LABEL_HYPHEN; |
2477 | 269k | else if (!rtl::isAsciiAlphanumeric(*p) && *p != '_') |
2478 | 10.1k | goto done; |
2479 | 287k | break; |
2480 | | |
2481 | 287k | case STATE_LABEL_HYPHEN: |
2482 | 24.5k | if (rtl::isAsciiAlphanumeric(*p) || *p == '_') |
2483 | 14.0k | eState = STATE_LABEL; |
2484 | 10.5k | else if (*p != '-') |
2485 | 2.42k | goto done; |
2486 | 22.1k | break; |
2487 | | |
2488 | 22.1k | case STATE_LABEL_DOT: |
2489 | 16.4k | if (rtl::isAsciiAlpha(*p) || *p == '_') |
2490 | 5.67k | eState = STATE_TOPLABEL; |
2491 | 10.7k | else if (rtl::isAsciiDigit(*p)) |
2492 | 6.91k | eState = STATE_LABEL; |
2493 | 3.84k | else |
2494 | 3.84k | goto done; |
2495 | 12.5k | break; |
2496 | | |
2497 | 2.47M | case STATE_TOPLABEL: |
2498 | 2.47M | if (*p == '.') |
2499 | 328k | eState = STATE_TOPLABEL_DOT; |
2500 | 2.14M | else if (*p == '-') |
2501 | 25.4k | eState = STATE_TOPLABEL_HYPHEN; |
2502 | 2.11M | else if (!rtl::isAsciiAlphanumeric(*p) && *p != '_') |
2503 | 22.5k | goto done; |
2504 | 2.45M | break; |
2505 | | |
2506 | 2.45M | case STATE_TOPLABEL_HYPHEN: |
2507 | 30.0k | if (rtl::isAsciiAlphanumeric(*p) || *p == '_') |
2508 | 21.4k | eState = STATE_TOPLABEL; |
2509 | 8.58k | else if (*p != '-') |
2510 | 1.70k | goto done; |
2511 | 28.3k | break; |
2512 | | |
2513 | 185k | case STATE_TOPLABEL_DOT: |
2514 | 185k | if (rtl::isAsciiAlpha(*p) || *p == '_') |
2515 | 178k | eState = STATE_TOPLABEL; |
2516 | 6.91k | else if (rtl::isAsciiDigit(*p)) |
2517 | 2.81k | eState = STATE_LABEL; |
2518 | 4.10k | else |
2519 | 4.10k | goto done; |
2520 | 180k | break; |
2521 | | |
2522 | 180k | case STATE_IP4: |
2523 | 119k | if (*p == '.') |
2524 | 28.0k | if (nOctets < 4) |
2525 | 25.8k | { |
2526 | 25.8k | if (pCanonic) |
2527 | 13.5k | { |
2528 | 13.5k | pCanonic->append(static_cast<sal_Int64>(nNumber)); |
2529 | 13.5k | pCanonic->append( '.' ); |
2530 | 13.5k | } |
2531 | 25.8k | ++nOctets; |
2532 | 25.8k | eState = STATE_IP4_DOT; |
2533 | 25.8k | } |
2534 | 2.18k | else |
2535 | 2.18k | eState = STATE_LABEL_DOT; |
2536 | 91.7k | else if (*p == '-') |
2537 | 6.63k | eState = STATE_LABEL_HYPHEN; |
2538 | 85.0k | else if (rtl::isAsciiAlpha(*p) || *p == '_') |
2539 | 12.3k | eState = STATE_LABEL; |
2540 | 72.7k | else if (rtl::isAsciiDigit(*p)) |
2541 | 58.6k | if (nDigits < 3) |
2542 | 50.5k | { |
2543 | 50.5k | nNumber = 10 * nNumber + INetMIME::getWeight(*p); |
2544 | 50.5k | ++nDigits; |
2545 | 50.5k | } |
2546 | 8.02k | else |
2547 | 8.02k | eState = STATE_LABEL; |
2548 | 14.1k | else |
2549 | 14.1k | goto done; |
2550 | 105k | break; |
2551 | | |
2552 | 105k | case STATE_IP4_DOT: |
2553 | 25.7k | if (rtl::isAsciiAlpha(*p) || *p == '_') |
2554 | 2.89k | eState = STATE_TOPLABEL; |
2555 | 22.8k | else if (rtl::isAsciiDigit(*p)) |
2556 | 21.9k | { |
2557 | 21.9k | nNumber = INetMIME::getWeight(*p); |
2558 | 21.9k | nDigits = 1; |
2559 | 21.9k | eState = STATE_IP4; |
2560 | 21.9k | } |
2561 | 914 | else |
2562 | 914 | goto done; |
2563 | 24.8k | break; |
2564 | | |
2565 | 57.9k | case STATE_IP6: |
2566 | 57.9k | if (*p == ':') |
2567 | 15.0k | eState = STATE_IP6_COLON; |
2568 | 42.8k | else if (rtl::isAsciiHexDigit(*p)) |
2569 | 40.7k | { |
2570 | 40.7k | nNumber = INetMIME::getHexWeight(*p); |
2571 | 40.7k | nDigits = 1; |
2572 | 40.7k | eState = STATE_IP6_HEXSEQ1; |
2573 | 40.7k | } |
2574 | 2.13k | else |
2575 | 2.13k | goto done; |
2576 | 55.7k | break; |
2577 | | |
2578 | 55.7k | case STATE_IP6_COLON: |
2579 | 14.9k | if (*p == ':') |
2580 | 14.3k | { |
2581 | 14.3k | if (pCanonic) |
2582 | 5.12k | pCanonic->append("::"); |
2583 | 14.3k | eState = STATE_IP6_2COLON; |
2584 | 14.3k | } |
2585 | 586 | else |
2586 | 586 | goto done; |
2587 | 14.3k | break; |
2588 | | |
2589 | 33.7k | case STATE_IP6_2COLON: |
2590 | 33.7k | if (*p == ']') |
2591 | 9.53k | eState = STATE_IP6_DONE; |
2592 | 24.2k | else if (*p == ':') |
2593 | 2.93k | { |
2594 | 2.93k | if (pCanonic) |
2595 | 1.99k | pCanonic->append(':'); |
2596 | 2.93k | eState = STATE_IP6_3COLON; |
2597 | 2.93k | } |
2598 | 21.2k | else if (rtl::isAsciiDigit(*p)) |
2599 | 10.0k | { |
2600 | 10.0k | nNumber = INetMIME::getWeight(*p); |
2601 | 10.0k | nDigits = 1; |
2602 | 10.0k | eState = STATE_IP6_HEXSEQ2_MAYBE_IP4; |
2603 | 10.0k | } |
2604 | 11.2k | else if (rtl::isAsciiHexDigit(*p)) |
2605 | 10.0k | { |
2606 | 10.0k | nNumber = INetMIME::getHexWeight(*p); |
2607 | 10.0k | nDigits = 1; |
2608 | 10.0k | eState = STATE_IP6_HEXSEQ2; |
2609 | 10.0k | } |
2610 | 1.20k | else |
2611 | 1.20k | goto done; |
2612 | 32.5k | break; |
2613 | | |
2614 | 32.5k | case STATE_IP6_3COLON: |
2615 | 2.79k | if (rtl::isAsciiDigit(*p)) |
2616 | 2.13k | { |
2617 | 2.13k | nNumber = INetMIME::getWeight(*p); |
2618 | 2.13k | nDigits = 1; |
2619 | 2.13k | nOctets = 1; |
2620 | 2.13k | eState = STATE_IP6_IP4; |
2621 | 2.13k | } |
2622 | 664 | else |
2623 | 664 | goto done; |
2624 | 2.13k | break; |
2625 | | |
2626 | 109k | case STATE_IP6_HEXSEQ1: |
2627 | 109k | if (*p == ']') |
2628 | 7.94k | { |
2629 | 7.94k | if (pCanonic) |
2630 | 3.22k | pCanonic->append( |
2631 | 3.22k | OUString::number(nNumber, 16)); |
2632 | 7.94k | eState = STATE_IP6_DONE; |
2633 | 7.94k | } |
2634 | 101k | else if (*p == ':') |
2635 | 53.4k | { |
2636 | 53.4k | if (pCanonic) |
2637 | 21.3k | { |
2638 | 21.3k | pCanonic->append( |
2639 | 21.3k | OUString::number(nNumber, 16)); |
2640 | 21.3k | pCanonic->append(':'); |
2641 | 21.3k | } |
2642 | 53.4k | eState = STATE_IP6_HEXSEQ1_COLON; |
2643 | 53.4k | } |
2644 | 47.6k | else if (rtl::isAsciiHexDigit(*p) && nDigits < 4) |
2645 | 43.0k | { |
2646 | 43.0k | assert(nNumber < 0xffff); |
2647 | 43.0k | nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); |
2648 | 43.0k | ++nDigits; |
2649 | 43.0k | } |
2650 | 4.62k | else |
2651 | 4.62k | goto done; |
2652 | 104k | break; |
2653 | | |
2654 | 104k | case STATE_IP6_HEXSEQ1_COLON: |
2655 | 69.9k | if (*p == ':') |
2656 | 19.3k | { |
2657 | 19.3k | if (pCanonic) |
2658 | 8.66k | pCanonic->append(':'); |
2659 | 19.3k | eState = STATE_IP6_2COLON; |
2660 | 19.3k | } |
2661 | 50.6k | else if (rtl::isAsciiDigit(*p)) |
2662 | 32.2k | { |
2663 | 32.2k | nNumber = INetMIME::getWeight(*p); |
2664 | 32.2k | nDigits = 1; |
2665 | 32.2k | eState = STATE_IP6_HEXSEQ1_MAYBE_IP4; |
2666 | 32.2k | } |
2667 | 18.3k | else if (rtl::isAsciiHexDigit(*p)) |
2668 | 16.8k | { |
2669 | 16.8k | nNumber = INetMIME::getHexWeight(*p); |
2670 | 16.8k | nDigits = 1; |
2671 | 16.8k | eState = STATE_IP6_HEXSEQ1; |
2672 | 16.8k | } |
2673 | 1.50k | else |
2674 | 1.50k | goto done; |
2675 | 68.4k | break; |
2676 | | |
2677 | 68.4k | case STATE_IP6_HEXSEQ1_MAYBE_IP4: |
2678 | 45.9k | if (*p == ']') |
2679 | 3.24k | { |
2680 | 3.24k | if (pCanonic) |
2681 | 1.44k | pCanonic->append( |
2682 | 1.44k | OUString::number(nNumber, 16)); |
2683 | 3.24k | eState = STATE_IP6_DONE; |
2684 | 3.24k | } |
2685 | 42.6k | else if (*p == ':') |
2686 | 16.5k | { |
2687 | 16.5k | if (pCanonic) |
2688 | 8.51k | { |
2689 | 8.51k | pCanonic->append( |
2690 | 8.51k | OUString::number(nNumber, 16)); |
2691 | 8.51k | pCanonic->append(':'); |
2692 | 8.51k | } |
2693 | 16.5k | eState = STATE_IP6_HEXSEQ1_COLON; |
2694 | 16.5k | } |
2695 | 26.1k | else if (*p == '.') |
2696 | 2.48k | { |
2697 | 2.48k | nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15) |
2698 | 2.48k | + (nNumber & 15); |
2699 | 2.48k | if (pCanonic) |
2700 | 816 | { |
2701 | 816 | pCanonic->append( |
2702 | 816 | OUString::number(nNumber)); |
2703 | 816 | pCanonic->append('.'); |
2704 | 816 | } |
2705 | 2.48k | nOctets = 2; |
2706 | 2.48k | eState = STATE_IP6_IP4_DOT; |
2707 | 2.48k | } |
2708 | 23.6k | else if (rtl::isAsciiDigit(*p) && nDigits < 3) |
2709 | 13.6k | { |
2710 | 13.6k | assert(nNumber < 0xfff); |
2711 | 13.6k | nNumber = 16 * nNumber + INetMIME::getWeight(*p); |
2712 | 13.6k | ++nDigits; |
2713 | 13.6k | } |
2714 | 10.0k | else if (rtl::isAsciiHexDigit(*p) && nDigits < 4) |
2715 | 8.60k | { |
2716 | 8.60k | nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); |
2717 | 8.60k | ++nDigits; |
2718 | 8.60k | eState = STATE_IP6_HEXSEQ1; |
2719 | 8.60k | } |
2720 | 1.39k | else |
2721 | 1.39k | goto done; |
2722 | 44.5k | break; |
2723 | | |
2724 | 73.8k | case STATE_IP6_HEXSEQ2: |
2725 | 73.8k | if (*p == ']') |
2726 | 8.94k | { |
2727 | 8.94k | if (pCanonic) |
2728 | 2.54k | pCanonic->append( |
2729 | 2.54k | OUString::number(nNumber, 16)); |
2730 | 8.94k | eState = STATE_IP6_DONE; |
2731 | 8.94k | } |
2732 | 64.9k | else if (*p == ':') |
2733 | 21.0k | { |
2734 | 21.0k | if (pCanonic) |
2735 | 7.29k | { |
2736 | 7.29k | pCanonic->append( |
2737 | 7.29k | OUString::number(nNumber, 16)); |
2738 | 7.29k | pCanonic->append(':'); |
2739 | 7.29k | } |
2740 | 21.0k | eState = STATE_IP6_HEXSEQ2_COLON; |
2741 | 21.0k | } |
2742 | 43.8k | else if (rtl::isAsciiHexDigit(*p) && nDigits < 4) |
2743 | 41.0k | { |
2744 | 41.0k | assert(nNumber < 0xffff); |
2745 | 41.0k | nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); |
2746 | 41.0k | ++nDigits; |
2747 | 41.0k | } |
2748 | 2.84k | else |
2749 | 2.84k | goto done; |
2750 | 71.0k | break; |
2751 | | |
2752 | 71.0k | case STATE_IP6_HEXSEQ2_COLON: |
2753 | 27.9k | if (rtl::isAsciiDigit(*p)) |
2754 | 11.6k | { |
2755 | 11.6k | nNumber = INetMIME::getWeight(*p); |
2756 | 11.6k | nDigits = 1; |
2757 | 11.6k | eState = STATE_IP6_HEXSEQ2_MAYBE_IP4; |
2758 | 11.6k | } |
2759 | 16.2k | else if (rtl::isAsciiHexDigit(*p)) |
2760 | 15.0k | { |
2761 | 15.0k | nNumber = INetMIME::getHexWeight(*p); |
2762 | 15.0k | nDigits = 1; |
2763 | 15.0k | eState = STATE_IP6_HEXSEQ2; |
2764 | 15.0k | } |
2765 | 1.25k | else |
2766 | 1.25k | goto done; |
2767 | 26.6k | break; |
2768 | | |
2769 | 32.3k | case STATE_IP6_HEXSEQ2_MAYBE_IP4: |
2770 | 32.3k | if (*p == ']') |
2771 | 3.23k | { |
2772 | 3.23k | if (pCanonic) |
2773 | 1.08k | pCanonic->append( |
2774 | 1.08k | OUString::number(nNumber, 16)); |
2775 | 3.23k | eState = STATE_IP6_DONE; |
2776 | 3.23k | } |
2777 | 29.0k | else if (*p == ':') |
2778 | 6.91k | { |
2779 | 6.91k | if (pCanonic) |
2780 | 3.00k | { |
2781 | 3.00k | pCanonic->append( |
2782 | 3.00k | OUString::number(nNumber, 16)); |
2783 | 3.00k | pCanonic->append(':'); |
2784 | 3.00k | } |
2785 | 6.91k | eState = STATE_IP6_HEXSEQ2_COLON; |
2786 | 6.91k | } |
2787 | 22.1k | else if (*p == '.') |
2788 | 2.02k | { |
2789 | 2.02k | nNumber = 100 * (nNumber >> 8) + 10 * (nNumber >> 4 & 15) |
2790 | 2.02k | + (nNumber & 15); |
2791 | 2.02k | if (pCanonic) |
2792 | 1.23k | { |
2793 | 1.23k | pCanonic->append( |
2794 | 1.23k | OUString::number(nNumber)); |
2795 | 1.23k | pCanonic->append('.'); |
2796 | 1.23k | } |
2797 | 2.02k | nOctets = 2; |
2798 | 2.02k | eState = STATE_IP6_IP4_DOT; |
2799 | 2.02k | } |
2800 | 20.1k | else if (rtl::isAsciiDigit(*p) && nDigits < 3) |
2801 | 10.7k | { |
2802 | 10.7k | assert(nNumber < 0xfff); |
2803 | 10.7k | nNumber = 16 * nNumber + INetMIME::getWeight(*p); |
2804 | 10.7k | ++nDigits; |
2805 | 10.7k | } |
2806 | 9.38k | else if (rtl::isAsciiHexDigit(*p) && nDigits < 4) |
2807 | 7.91k | { |
2808 | 7.91k | nNumber = 16 * nNumber + INetMIME::getHexWeight(*p); |
2809 | 7.91k | ++nDigits; |
2810 | 7.91k | eState = STATE_IP6_HEXSEQ2; |
2811 | 7.91k | } |
2812 | 1.47k | else |
2813 | 1.47k | goto done; |
2814 | 30.8k | break; |
2815 | | |
2816 | 30.8k | case STATE_IP6_IP4: |
2817 | 18.1k | if (*p == ']') |
2818 | 2.62k | if (nOctets == 4) |
2819 | 2.15k | { |
2820 | 2.15k | if (pCanonic) |
2821 | 924 | pCanonic->append( |
2822 | 924 | OUString::number(nNumber)); |
2823 | 2.15k | eState = STATE_IP6_DONE; |
2824 | 2.15k | } |
2825 | 471 | else |
2826 | 471 | goto done; |
2827 | 15.5k | else if (*p == '.') |
2828 | 7.82k | if (nOctets < 4) |
2829 | 7.53k | { |
2830 | 7.53k | if (pCanonic) |
2831 | 3.48k | { |
2832 | 3.48k | pCanonic->append( |
2833 | 3.48k | OUString::number(nNumber)); |
2834 | 3.48k | pCanonic->append('.'); |
2835 | 3.48k | } |
2836 | 7.53k | ++nOctets; |
2837 | 7.53k | eState = STATE_IP6_IP4_DOT; |
2838 | 7.53k | } |
2839 | 285 | else |
2840 | 285 | goto done; |
2841 | 7.74k | else if (rtl::isAsciiDigit(*p) && nDigits < 3) |
2842 | 5.88k | { |
2843 | 5.88k | assert(nNumber < 999); |
2844 | 5.88k | nNumber = 10 * nNumber + INetMIME::getWeight(*p); |
2845 | 5.88k | ++nDigits; |
2846 | 5.88k | } |
2847 | 1.86k | else |
2848 | 1.86k | goto done; |
2849 | 15.5k | break; |
2850 | | |
2851 | 15.5k | case STATE_IP6_IP4_DOT: |
2852 | 12.0k | if (rtl::isAsciiDigit(*p)) |
2853 | 10.2k | { |
2854 | 10.2k | nNumber = INetMIME::getWeight(*p); |
2855 | 10.2k | nDigits = 1; |
2856 | 10.2k | eState = STATE_IP6_IP4; |
2857 | 10.2k | } |
2858 | 1.77k | else |
2859 | 1.77k | goto done; |
2860 | 10.2k | break; |
2861 | | |
2862 | 10.2k | case STATE_IP6_DONE: |
2863 | 1.48k | goto done; |
2864 | 4.24M | } |
2865 | 576k | done: |
2866 | 576k | switch (eState) |
2867 | 576k | { |
2868 | 15.7k | case STATE_LABEL: |
2869 | 301k | case STATE_TOPLABEL: |
2870 | 448k | case STATE_TOPLABEL_DOT: |
2871 | 448k | if (pCanonic) |
2872 | 419k | { |
2873 | 419k | pCanonic->setLength(nOriginalCanonicLength); |
2874 | 419k | pCanonic->append(rBegin, p - rBegin); |
2875 | 419k | } |
2876 | 448k | rBegin = p; |
2877 | 448k | return true; |
2878 | | |
2879 | 20.2k | case STATE_IP4: |
2880 | 20.2k | if (nOctets == 4) |
2881 | 2.88k | { |
2882 | 2.88k | if (pCanonic) |
2883 | 1.52k | pCanonic->append( |
2884 | 1.52k | OUString::number(nNumber)); |
2885 | 2.88k | rBegin = p; |
2886 | 2.88k | return true; |
2887 | 2.88k | } |
2888 | 17.3k | if (pCanonic) |
2889 | 6.66k | pCanonic->setLength(nOriginalCanonicLength); |
2890 | 17.3k | return false; |
2891 | | |
2892 | 35.0k | case STATE_IP6_DONE: |
2893 | 35.0k | if (pCanonic) |
2894 | 11.5k | pCanonic->append(']'); |
2895 | 35.0k | rBegin = p; |
2896 | 35.0k | return true; |
2897 | | |
2898 | 71.8k | default: |
2899 | 71.8k | if (pCanonic) |
2900 | 38.5k | pCanonic->setLength(nOriginalCanonicLength); |
2901 | 71.8k | return false; |
2902 | 576k | } |
2903 | 576k | } |
2904 | | |
2905 | | // static |
2906 | | bool INetURLObject::parseHostOrNetBiosName( |
2907 | | sal_Unicode const * pBegin, sal_Unicode const * pEnd, |
2908 | | EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bNetBiosName, |
2909 | | OUStringBuffer* pCanonic) |
2910 | 2.11M | { |
2911 | 2.11M | if (pBegin >= pEnd) |
2912 | 1.54M | return true; |
2913 | 576k | sal_Int32 nOriginalCanonicLength = pCanonic ? pCanonic->getLength() : 0; |
2914 | 576k | if (sal_Unicode const* p = pBegin; parseHost(p, pEnd, pCanonic) && p == pEnd) |
2915 | 446k | return true; |
2916 | 129k | if (pCanonic) |
2917 | 70.3k | pCanonic->setLength(nOriginalCanonicLength); // discard parseHost results |
2918 | 129k | if (!bNetBiosName) |
2919 | 42.0k | return false; |
2920 | 559k | while (pBegin < pEnd) |
2921 | 524k | { |
2922 | 524k | EscapeType eEscapeType; |
2923 | 524k | switch (sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, eMechanism, eCharset, eEscapeType)) |
2924 | 524k | { |
2925 | 479k | default: |
2926 | 479k | if (INetMIME::isVisible(nUTF32)) |
2927 | 471k | { |
2928 | 471k | if (pCanonic) |
2929 | 115k | appendUCS4(*pCanonic, nUTF32, eEscapeType, PART_URIC, eCharset, true); |
2930 | 471k | break; |
2931 | 471k | } |
2932 | 8.10k | [[fallthrough]]; |
2933 | 8.98k | case '"': |
2934 | 9.35k | case '*': |
2935 | 10.2k | case '+': |
2936 | 12.5k | case ',': |
2937 | 13.7k | case '/': |
2938 | 15.6k | case ':': |
2939 | 16.5k | case ';': |
2940 | 17.3k | case '<': |
2941 | 18.2k | case '=': |
2942 | 21.7k | case '>': |
2943 | 29.4k | case '?': |
2944 | 50.3k | case '[': |
2945 | 50.5k | case '\\': |
2946 | 51.3k | case ']': |
2947 | 51.9k | case '`': |
2948 | 53.2k | case '|': |
2949 | 53.2k | if (pCanonic) |
2950 | 18.0k | pCanonic->setLength(nOriginalCanonicLength); |
2951 | 53.2k | return false; |
2952 | 524k | } |
2953 | 524k | } |
2954 | 34.6k | return true; |
2955 | 87.8k | } |
2956 | | |
2957 | | // static |
2958 | | bool INetURLObject::parsePath(INetProtocol eScheme, |
2959 | | sal_Unicode const ** pBegin, |
2960 | | sal_Unicode const * pEnd, |
2961 | | EncodeMechanism eMechanism, |
2962 | | rtl_TextEncoding eCharset, |
2963 | | bool bSkippedInitialSlash, |
2964 | | sal_uInt32 nSegmentDelimiter, |
2965 | | sal_uInt32 nAltSegmentDelimiter, |
2966 | | sal_uInt32 nQueryDelimiter, |
2967 | | sal_uInt32 nFragmentDelimiter, |
2968 | | OUStringBuffer &rSynPath) |
2969 | 1.68M | { |
2970 | 1.68M | DBG_ASSERT(pBegin, "INetURLObject::parsePath(): Null output param"); |
2971 | | |
2972 | 1.68M | sal_Unicode const * pPos = *pBegin; |
2973 | 1.68M | const sal_Int32 nSynPathBeforeLen = rSynPath.getLength(); |
2974 | 1.68M | switch (eScheme) |
2975 | 1.68M | { |
2976 | 0 | case INetProtocol::NotValid: |
2977 | 0 | return false; |
2978 | | |
2979 | 55.1k | case INetProtocol::Ftp: |
2980 | 55.1k | if (pPos < pEnd && *pPos != '/' && *pPos != nFragmentDelimiter) |
2981 | 0 | goto failed; |
2982 | 219k | while (pPos < pEnd && *pPos != nFragmentDelimiter) |
2983 | 164k | { |
2984 | 164k | EscapeType eEscapeType; |
2985 | 164k | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
2986 | 164k | eCharset, eEscapeType); |
2987 | 164k | appendUCS4(rSynPath, nUTF32, eEscapeType, |
2988 | 164k | PART_HTTP_PATH, eCharset, true); |
2989 | 164k | } |
2990 | 55.1k | if (rSynPath.getLength() - nSynPathBeforeLen == 0) |
2991 | 2.12k | rSynPath.append('/'); |
2992 | 55.1k | break; |
2993 | | |
2994 | 315k | case INetProtocol::Http: |
2995 | 315k | case INetProtocol::VndSunStarWebdav: |
2996 | 335k | case INetProtocol::Https: |
2997 | 336k | case INetProtocol::Smb: |
2998 | 336k | case INetProtocol::Cmis: |
2999 | 336k | if (pPos < pEnd && *pPos != '/' && *pPos != nQueryDelimiter |
3000 | 79.0k | && *pPos != nFragmentDelimiter) |
3001 | 0 | goto failed; |
3002 | 2.04M | while (pPos < pEnd && *pPos != nQueryDelimiter |
3003 | 1.87M | && *pPos != nFragmentDelimiter) |
3004 | 1.71M | { |
3005 | 1.71M | EscapeType eEscapeType; |
3006 | 1.71M | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3007 | 1.71M | eCharset, eEscapeType); |
3008 | 1.71M | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3009 | 1.71M | PART_HTTP_PATH, eCharset, true); |
3010 | 1.71M | } |
3011 | 336k | if (rSynPath.getLength() - nSynPathBeforeLen == 0) |
3012 | 125k | rSynPath.append('/'); |
3013 | 336k | break; |
3014 | | |
3015 | 1.12M | case INetProtocol::File: |
3016 | 1.12M | { |
3017 | 1.12M | if (bSkippedInitialSlash) |
3018 | 13.1k | rSynPath.append('/'); |
3019 | 1.11M | else if (pPos < pEnd |
3020 | 1.09M | && *pPos != nSegmentDelimiter |
3021 | 591 | && *pPos != nAltSegmentDelimiter) |
3022 | 591 | goto failed; |
3023 | 17.0M | while (pPos < pEnd && *pPos != nFragmentDelimiter) |
3024 | 15.9M | { |
3025 | 15.9M | EscapeType eEscapeType; |
3026 | 15.9M | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3027 | 15.9M | eCharset, eEscapeType); |
3028 | 15.9M | if (eEscapeType == EscapeType::NONE) |
3029 | 15.4M | { |
3030 | 15.4M | if (nUTF32 == nSegmentDelimiter |
3031 | 13.0M | || nUTF32 == nAltSegmentDelimiter) |
3032 | 2.45M | { |
3033 | 2.45M | rSynPath.append('/'); |
3034 | 2.45M | continue; |
3035 | 2.45M | } |
3036 | 13.0M | else if (nUTF32 == '|' |
3037 | 20.6k | && (pPos == pEnd |
3038 | 13.9k | || *pPos == nFragmentDelimiter |
3039 | 13.4k | || *pPos == nSegmentDelimiter |
3040 | 12.2k | || *pPos == nAltSegmentDelimiter) |
3041 | 8.59k | && rSynPath.getLength() - nSynPathBeforeLen == 2 |
3042 | 2.64k | && rtl::isAsciiAlpha(rSynPath[nSynPathBeforeLen + 1])) |
3043 | 1.44k | { |
3044 | | // A first segment of <ALPHA "|"> is translated to |
3045 | | // <ALPHA ":">: |
3046 | 1.44k | rSynPath.append(':'); |
3047 | 1.44k | continue; |
3048 | 1.44k | } |
3049 | 15.4M | } |
3050 | 13.5M | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3051 | 13.5M | PART_PCHAR, eCharset, true); |
3052 | 13.5M | } |
3053 | 1.12M | if (rSynPath.getLength() - nSynPathBeforeLen == 0) |
3054 | 15.1k | rSynPath.append('/'); |
3055 | 1.12M | break; |
3056 | 1.12M | } |
3057 | | |
3058 | 1.84k | case INetProtocol::Mailto: |
3059 | 39.5k | while (pPos < pEnd && *pPos != nQueryDelimiter |
3060 | 37.6k | && *pPos != nFragmentDelimiter) |
3061 | 37.6k | { |
3062 | 37.6k | EscapeType eEscapeType; |
3063 | 37.6k | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3064 | 37.6k | eCharset, eEscapeType); |
3065 | 37.6k | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3066 | 37.6k | PART_MAILTO, eCharset, true); |
3067 | 37.6k | } |
3068 | 1.84k | break; |
3069 | | |
3070 | | |
3071 | 68.9k | case INetProtocol::PrivSoffice: |
3072 | 70.3k | case INetProtocol::Hid: |
3073 | 70.3k | case INetProtocol::Macro: |
3074 | 70.3k | case INetProtocol::Uno: |
3075 | 70.3k | case INetProtocol::Component: |
3076 | 70.6k | case INetProtocol::Ldap: |
3077 | 489k | while (pPos < pEnd && *pPos != nQueryDelimiter |
3078 | 418k | && *pPos != nFragmentDelimiter) |
3079 | 418k | { |
3080 | 418k | EscapeType eEscapeType; |
3081 | 418k | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3082 | 418k | eCharset, eEscapeType); |
3083 | 418k | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3084 | 418k | PART_PATH_BEFORE_QUERY, eCharset, true); |
3085 | 418k | } |
3086 | 70.6k | break; |
3087 | | |
3088 | 0 | case INetProtocol::VndSunStarHelp: |
3089 | 0 | if (pPos == pEnd |
3090 | 0 | || *pPos == nQueryDelimiter |
3091 | 0 | || *pPos == nFragmentDelimiter) |
3092 | 0 | rSynPath.append('/'); |
3093 | 0 | else |
3094 | 0 | { |
3095 | 0 | if (*pPos != '/') |
3096 | 0 | goto failed; |
3097 | 0 | while (pPos < pEnd && *pPos != nQueryDelimiter |
3098 | 0 | && *pPos != nFragmentDelimiter) |
3099 | 0 | { |
3100 | 0 | EscapeType eEscapeType; |
3101 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, |
3102 | 0 | eMechanism, |
3103 | 0 | eCharset, eEscapeType); |
3104 | 0 | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3105 | 0 | PART_HTTP_PATH, eCharset, true); |
3106 | 0 | } |
3107 | 0 | } |
3108 | 0 | break; |
3109 | | |
3110 | 808 | case INetProtocol::Javascript: |
3111 | 81.1k | case INetProtocol::Data: |
3112 | 82.0k | case INetProtocol::Cid: |
3113 | 82.6k | case INetProtocol::Db: |
3114 | 4.87M | while (pPos < pEnd && *pPos != nFragmentDelimiter) |
3115 | 4.78M | { |
3116 | 4.78M | EscapeType eEscapeType; |
3117 | 4.78M | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3118 | 4.78M | eCharset, eEscapeType); |
3119 | 4.78M | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3120 | 4.78M | PART_URIC, eCharset, true); |
3121 | 4.78M | } |
3122 | 82.6k | break; |
3123 | | |
3124 | 0 | case INetProtocol::VndSunStarHier: |
3125 | 45 | case INetProtocol::VndSunStarPkg: |
3126 | 45 | if (pPos < pEnd && *pPos != '/' |
3127 | 0 | && *pPos != nQueryDelimiter && *pPos != nFragmentDelimiter) |
3128 | 0 | goto failed; |
3129 | 45 | while (pPos < pEnd && *pPos != nQueryDelimiter |
3130 | 0 | && *pPos != nFragmentDelimiter) |
3131 | 0 | { |
3132 | 0 | EscapeType eEscapeType; |
3133 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3134 | 0 | eCharset, eEscapeType); |
3135 | 0 | if (eEscapeType == EscapeType::NONE && nUTF32 == '/') |
3136 | 0 | rSynPath.append('/'); |
3137 | 0 | else |
3138 | 0 | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3139 | 0 | PART_PCHAR, eCharset, false); |
3140 | 0 | } |
3141 | 45 | if (rSynPath.getLength() - nSynPathBeforeLen == 0) |
3142 | 45 | rSynPath.append('/'); |
3143 | 45 | break; |
3144 | | |
3145 | 0 | case INetProtocol::VndSunStarCmd: |
3146 | 0 | case INetProtocol::VndSunStarExpand: |
3147 | 0 | { |
3148 | 0 | if (pPos == pEnd || *pPos == nFragmentDelimiter) |
3149 | 0 | goto failed; |
3150 | 0 | Part ePart = PART_URIC_NO_SLASH; |
3151 | 0 | while (pPos != pEnd && *pPos != nFragmentDelimiter) |
3152 | 0 | { |
3153 | 0 | EscapeType eEscapeType; |
3154 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3155 | 0 | eCharset, eEscapeType); |
3156 | 0 | appendUCS4(rSynPath, nUTF32, eEscapeType, ePart, |
3157 | 0 | eCharset, true); |
3158 | 0 | ePart = PART_URIC; |
3159 | 0 | } |
3160 | 0 | break; |
3161 | 0 | } |
3162 | | |
3163 | 1 | case INetProtocol::Telnet: |
3164 | 1 | if (pPos < pEnd) |
3165 | 0 | { |
3166 | 0 | if (*pPos != '/' || pEnd - pPos > 1) |
3167 | 0 | goto failed; |
3168 | 0 | ++pPos; |
3169 | 0 | } |
3170 | 1 | rSynPath.append('/'); |
3171 | 1 | break; |
3172 | | |
3173 | 0 | case INetProtocol::VndSunStarTdoc: |
3174 | 0 | if (pPos == pEnd || *pPos != '/') |
3175 | 0 | goto failed; |
3176 | 0 | while (pPos < pEnd && *pPos != nFragmentDelimiter) |
3177 | 0 | { |
3178 | 0 | EscapeType eEscapeType; |
3179 | 0 | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3180 | 0 | eCharset, eEscapeType); |
3181 | 0 | if (eEscapeType == EscapeType::NONE && nUTF32 == '/') |
3182 | 0 | rSynPath.append('/'); |
3183 | 0 | else |
3184 | 0 | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3185 | 0 | PART_PCHAR, eCharset, false); |
3186 | 0 | } |
3187 | 0 | break; |
3188 | | |
3189 | 12.8k | case INetProtocol::Generic: |
3190 | 12.9k | case INetProtocol::Sftp: |
3191 | 438k | while (pPos < pEnd && *pPos != nFragmentDelimiter) |
3192 | 425k | { |
3193 | 425k | EscapeType eEscapeType; |
3194 | 425k | sal_uInt32 nUTF32 = getUTF32(pPos, pEnd, eMechanism, |
3195 | 425k | eCharset, eEscapeType); |
3196 | 425k | appendUCS4(rSynPath, nUTF32, eEscapeType, |
3197 | 425k | PART_URIC, eCharset, true); |
3198 | 425k | } |
3199 | 12.9k | if (rSynPath.isEmpty()) |
3200 | 0 | goto failed; |
3201 | 12.9k | break; |
3202 | 12.9k | default: |
3203 | 0 | OSL_ASSERT(false); |
3204 | 0 | break; |
3205 | 1.68M | } |
3206 | | |
3207 | 1.68M | *pBegin = pPos; |
3208 | 1.68M | return true; |
3209 | 591 | failed: |
3210 | 591 | rSynPath.setLength(nSynPathBeforeLen); |
3211 | 591 | return false; |
3212 | 1.68M | } |
3213 | | |
3214 | | bool INetURLObject::setPath(std::u16string_view rThePath, |
3215 | | EncodeMechanism eMechanism, |
3216 | | rtl_TextEncoding eCharset) |
3217 | 25.2k | { |
3218 | 25.2k | OUStringBuffer aSynPath(256); |
3219 | 25.2k | sal_Unicode const * p = rThePath.data(); |
3220 | 25.2k | sal_Unicode const * pEnd = p + rThePath.size(); |
3221 | 25.2k | if (!parsePath(m_eScheme, &p, pEnd, eMechanism, eCharset, false, |
3222 | 25.2k | '/', 0x80000000, 0x80000000, 0x80000000, aSynPath) |
3223 | 25.2k | || p != pEnd) |
3224 | 0 | return false; |
3225 | 25.2k | sal_Int32 nDelta = m_aPath.set(m_aAbsURIRef, aSynPath); |
3226 | 25.2k | m_aQuery += nDelta; |
3227 | 25.2k | m_aFragment += nDelta; |
3228 | 25.2k | return true; |
3229 | 25.2k | } |
3230 | | |
3231 | 188k | bool INetURLObject::checkHierarchical() const { |
3232 | 188k | if (m_eScheme == INetProtocol::VndSunStarExpand) { |
3233 | 0 | OSL_FAIL( |
3234 | 0 | "INetURLObject::checkHierarchical vnd.sun.star.expand"); |
3235 | 0 | return true; |
3236 | 188k | } else { |
3237 | 188k | return getSchemeInfo().m_bHierarchical; |
3238 | 188k | } |
3239 | 188k | } |
3240 | | |
3241 | | bool INetURLObject::Append(std::u16string_view rTheSegment, |
3242 | | EncodeMechanism eMechanism, |
3243 | | rtl_TextEncoding eCharset) |
3244 | 439 | { |
3245 | 439 | return insertName(rTheSegment, false, LAST_SEGMENT, eMechanism, eCharset); |
3246 | 439 | } |
3247 | | |
3248 | | INetURLObject::SubString INetURLObject::getSegment(sal_Int32 nIndex, |
3249 | | bool bIgnoreFinalSlash) |
3250 | | const |
3251 | 136k | { |
3252 | 136k | DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT, |
3253 | 136k | "INetURLObject::getSegment(): Bad index"); |
3254 | | |
3255 | 136k | if (!checkHierarchical()) |
3256 | 15.9k | return SubString(); |
3257 | | |
3258 | 120k | sal_Unicode const * pPathBegin |
3259 | 120k | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
3260 | 120k | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
3261 | 120k | sal_Unicode const * pSegBegin; |
3262 | 120k | sal_Unicode const * pSegEnd; |
3263 | 120k | if (nIndex == LAST_SEGMENT) |
3264 | 120k | { |
3265 | 120k | pSegEnd = pPathEnd; |
3266 | 120k | if (bIgnoreFinalSlash && pSegEnd > pPathBegin && pSegEnd[-1] == '/') |
3267 | 349 | --pSegEnd; |
3268 | 120k | if (pSegEnd <= pPathBegin) |
3269 | 343 | return SubString(); |
3270 | 119k | pSegBegin = pSegEnd - 1; |
3271 | 1.00M | while (pSegBegin > pPathBegin && *pSegBegin != '/') |
3272 | 881k | --pSegBegin; |
3273 | 119k | } |
3274 | 174 | else |
3275 | 174 | { |
3276 | 174 | pSegBegin = pPathBegin; |
3277 | 342 | while (nIndex-- > 0) |
3278 | 168 | do |
3279 | 1.02k | { |
3280 | 1.02k | ++pSegBegin; |
3281 | 1.02k | if (pSegBegin >= pPathEnd) |
3282 | 0 | return SubString(); |
3283 | 1.02k | } |
3284 | 1.02k | while (*pSegBegin != '/'); |
3285 | 174 | pSegEnd = pSegBegin + 1; |
3286 | 1.18k | while (pSegEnd < pPathEnd && *pSegEnd != '/') |
3287 | 1.01k | ++pSegEnd; |
3288 | 174 | } |
3289 | | |
3290 | 119k | return SubString(pSegBegin - m_aAbsURIRef.getStr(), |
3291 | 119k | pSegEnd - pSegBegin); |
3292 | 120k | } |
3293 | | |
3294 | | bool INetURLObject::insertName(std::u16string_view rTheName, |
3295 | | bool bAppendFinalSlash, sal_Int32 nIndex, |
3296 | | EncodeMechanism eMechanism, |
3297 | | rtl_TextEncoding eCharset) |
3298 | 7.33k | { |
3299 | 7.33k | DBG_ASSERT(nIndex >= 0 || nIndex == LAST_SEGMENT, |
3300 | 7.33k | "INetURLObject::insertName(): Bad index"); |
3301 | | |
3302 | 7.33k | if (!checkHierarchical()) |
3303 | 414 | return false; |
3304 | | |
3305 | 6.91k | sal_Unicode const * pPathBegin |
3306 | 6.91k | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
3307 | 6.91k | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
3308 | 6.91k | sal_Unicode const * pPrefixEnd; |
3309 | 6.91k | bool bInsertSlash; |
3310 | 6.91k | sal_Unicode const * pSuffixBegin; |
3311 | 6.91k | if (nIndex == LAST_SEGMENT) |
3312 | 6.91k | { |
3313 | 6.91k | pPrefixEnd = pPathEnd; |
3314 | 6.91k | if (pPrefixEnd > pPathBegin && |
3315 | 6.91k | pPrefixEnd[-1] == '/') |
3316 | 6.47k | { |
3317 | 6.47k | --pPrefixEnd; |
3318 | 6.47k | } |
3319 | 6.91k | bInsertSlash = bAppendFinalSlash; |
3320 | 6.91k | pSuffixBegin = pPathEnd; |
3321 | 6.91k | } |
3322 | 0 | else if (nIndex == 0) |
3323 | 0 | { |
3324 | 0 | pPrefixEnd = pPathBegin; |
3325 | 0 | bInsertSlash = |
3326 | 0 | (pPathBegin < pPathEnd && *pPathBegin != '/') || |
3327 | 0 | (pPathBegin == pPathEnd && bAppendFinalSlash); |
3328 | 0 | pSuffixBegin = |
3329 | 0 | (pPathEnd - pPathBegin == 1 && *pPathBegin == '/' && |
3330 | 0 | !bAppendFinalSlash) |
3331 | 0 | ? pPathEnd : pPathBegin; |
3332 | 0 | } |
3333 | 0 | else |
3334 | 0 | { |
3335 | 0 | pPrefixEnd = pPathBegin; |
3336 | 0 | sal_Unicode const * pEnd = pPathEnd; |
3337 | 0 | if (pEnd > pPathBegin && pEnd[-1] == '/') |
3338 | 0 | --pEnd; |
3339 | 0 | bool bSkip = pPrefixEnd < pEnd && *pPrefixEnd == '/'; |
3340 | 0 | bInsertSlash = false; |
3341 | 0 | pSuffixBegin = pPathEnd; |
3342 | 0 | while (nIndex-- > 0) |
3343 | 0 | for (;;) |
3344 | 0 | { |
3345 | 0 | if (bSkip) |
3346 | 0 | ++pPrefixEnd; |
3347 | 0 | bSkip = true; |
3348 | 0 | if (pPrefixEnd >= pEnd) |
3349 | 0 | { |
3350 | 0 | if (nIndex == 0) |
3351 | 0 | { |
3352 | 0 | bInsertSlash = bAppendFinalSlash; |
3353 | 0 | break; |
3354 | 0 | } |
3355 | 0 | else |
3356 | 0 | return false; |
3357 | 0 | } |
3358 | 0 | if (*pPrefixEnd == '/') |
3359 | 0 | { |
3360 | 0 | pSuffixBegin = pPrefixEnd; |
3361 | 0 | break; |
3362 | 0 | } |
3363 | 0 | } |
3364 | 0 | } |
3365 | | |
3366 | 6.91k | OUStringBuffer aNewPath(256); |
3367 | 6.91k | aNewPath.append( |
3368 | 6.91k | OUString::Concat(std::u16string_view(pPathBegin, pPrefixEnd - pPathBegin)) |
3369 | 6.91k | + "/"); |
3370 | 6.91k | encodeText(aNewPath, rTheName, PART_PCHAR, |
3371 | 6.91k | eMechanism, eCharset, true); |
3372 | 6.91k | if (bInsertSlash) { |
3373 | 0 | aNewPath.append('/'); |
3374 | 0 | } |
3375 | 6.91k | aNewPath.append(pSuffixBegin, pPathEnd - pSuffixBegin); |
3376 | | |
3377 | 6.91k | return setPath(aNewPath, EncodeMechanism::NotCanonical, |
3378 | 6.91k | RTL_TEXTENCODING_UTF8); |
3379 | 6.91k | } |
3380 | | |
3381 | | void INetURLObject::clearQuery() |
3382 | 167 | { |
3383 | 167 | if (HasError()) |
3384 | 0 | return; |
3385 | 167 | if (m_aQuery.isPresent()) |
3386 | 67 | { |
3387 | 67 | lcl_Erase(m_aAbsURIRef, m_aQuery.getBegin() - 1, |
3388 | 67 | m_aQuery.getLength() + 1); |
3389 | 67 | m_aFragment += m_aQuery.clear() - 1; |
3390 | 67 | } |
3391 | 167 | } |
3392 | | |
3393 | | bool INetURLObject::setQuery(std::u16string_view rTheQuery, |
3394 | | EncodeMechanism eMechanism, |
3395 | | rtl_TextEncoding eCharset) |
3396 | 0 | { |
3397 | 0 | if (!getSchemeInfo().m_bQuery) |
3398 | 0 | return false; |
3399 | 0 | OUStringBuffer aNewQuery; |
3400 | 0 | encodeText(aNewQuery, rTheQuery, PART_URIC, |
3401 | 0 | eMechanism, eCharset, true); |
3402 | 0 | sal_Int32 nDelta; |
3403 | 0 | if (m_aQuery.isPresent()) |
3404 | 0 | nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery); |
3405 | 0 | else |
3406 | 0 | { |
3407 | 0 | m_aAbsURIRef.insert(m_aPath.getEnd(), u'?'); |
3408 | 0 | nDelta = m_aQuery.set(m_aAbsURIRef, aNewQuery, m_aPath.getEnd() + 1) |
3409 | 0 | + 1; |
3410 | 0 | } |
3411 | 0 | m_aFragment += nDelta; |
3412 | 0 | return true; |
3413 | 0 | } |
3414 | | |
3415 | | bool INetURLObject::clearFragment() |
3416 | 40.1k | { |
3417 | 40.1k | if (HasError()) |
3418 | 22.1k | return false; |
3419 | 17.9k | if (m_aFragment.isPresent()) |
3420 | 2.90k | { |
3421 | 2.90k | m_aAbsURIRef.setLength(m_aFragment.getBegin() - 1); |
3422 | 2.90k | m_aFragment.clear(); |
3423 | 2.90k | } |
3424 | 17.9k | return true; |
3425 | 40.1k | } |
3426 | | |
3427 | | bool INetURLObject::setFragment(std::u16string_view rTheFragment, |
3428 | | EncodeMechanism eMechanism, |
3429 | | rtl_TextEncoding eCharset) |
3430 | 6.86k | { |
3431 | 6.86k | if (HasError()) |
3432 | 6.86k | return false; |
3433 | 0 | OUStringBuffer aNewFragment; |
3434 | 0 | encodeText(aNewFragment, rTheFragment, PART_URIC, |
3435 | 0 | eMechanism, eCharset, true); |
3436 | 0 | if (m_aFragment.isPresent()) |
3437 | 0 | m_aFragment.set(m_aAbsURIRef, aNewFragment); |
3438 | 0 | else |
3439 | 0 | { |
3440 | 0 | m_aAbsURIRef.append('#'); |
3441 | 0 | m_aFragment.set(m_aAbsURIRef, aNewFragment, m_aAbsURIRef.getLength()); |
3442 | 0 | } |
3443 | 0 | return true; |
3444 | 6.86k | } |
3445 | | |
3446 | | bool INetURLObject::hasDosVolume(FSysStyle eStyle) const |
3447 | 0 | { |
3448 | 0 | sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
3449 | 0 | return (eStyle & FSysStyle::Dos) |
3450 | 0 | && m_aPath.getLength() >= 3 |
3451 | 0 | && p[0] == '/' |
3452 | 0 | && rtl::isAsciiAlpha(p[1]) |
3453 | 0 | && p[2] == ':' |
3454 | 0 | && (m_aPath.getLength() == 3 || p[3] == '/'); |
3455 | 0 | } |
3456 | | |
3457 | | // static |
3458 | | void INetURLObject::encodeText( OUStringBuffer& rOutputBuffer, |
3459 | | sal_Unicode const * pBegin, |
3460 | | sal_Unicode const * pEnd, |
3461 | | Part ePart, EncodeMechanism eMechanism, |
3462 | | rtl_TextEncoding eCharset, |
3463 | | bool bKeepVisibleEscapes) |
3464 | 6.96k | { |
3465 | 57.8k | while (pBegin < pEnd) |
3466 | 50.9k | { |
3467 | 50.9k | EscapeType eEscapeType; |
3468 | 50.9k | sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, |
3469 | 50.9k | eMechanism, eCharset, eEscapeType); |
3470 | 50.9k | appendUCS4(rOutputBuffer, nUTF32, eEscapeType, ePart, |
3471 | 50.9k | eCharset, bKeepVisibleEscapes); |
3472 | 50.9k | } |
3473 | 6.96k | } |
3474 | | |
3475 | | // static |
3476 | | OUString INetURLObject::decode(sal_Unicode const * pBegin, |
3477 | | sal_Unicode const * pEnd, |
3478 | | DecodeMechanism eMechanism, |
3479 | | rtl_TextEncoding eCharset) |
3480 | 1.23M | { |
3481 | 1.23M | switch (eMechanism) |
3482 | 1.23M | { |
3483 | 741k | case DecodeMechanism::NONE: |
3484 | 741k | return OUString(pBegin, pEnd - pBegin); |
3485 | | |
3486 | 353k | case DecodeMechanism::ToIUri: |
3487 | 353k | eCharset = RTL_TEXTENCODING_UTF8; |
3488 | 353k | break; |
3489 | | |
3490 | 140k | default: |
3491 | 140k | break; |
3492 | 1.23M | } |
3493 | 493k | OUStringBuffer aResult(static_cast<int>(pEnd-pBegin)); |
3494 | 19.3M | while (pBegin < pEnd) |
3495 | 18.8M | { |
3496 | 18.8M | EscapeType eEscapeType; |
3497 | 18.8M | sal_uInt32 nUTF32 = getUTF32(pBegin, pEnd, |
3498 | 18.8M | EncodeMechanism::WasEncoded, eCharset, eEscapeType); |
3499 | 18.8M | switch (eEscapeType) |
3500 | 18.8M | { |
3501 | 10.6M | case EscapeType::NONE: |
3502 | 10.6M | aResult.appendUtf32(nUTF32); |
3503 | 10.6M | break; |
3504 | | |
3505 | 5.00k | case EscapeType::Octet: |
3506 | 5.00k | appendEscape(aResult, nUTF32); |
3507 | 5.00k | break; |
3508 | | |
3509 | 8.15M | case EscapeType::Utf32: |
3510 | 8.15M | if ( |
3511 | 8.15M | rtl::isAscii(nUTF32) && |
3512 | 4.71M | ( |
3513 | 4.71M | eMechanism == DecodeMechanism::ToIUri || |
3514 | 246k | ( |
3515 | 246k | eMechanism == DecodeMechanism::Unambiguous && |
3516 | 351 | mustEncode(nUTF32, PART_UNAMBIGUOUS) |
3517 | 246k | ) |
3518 | 4.71M | ) |
3519 | 8.15M | ) |
3520 | 4.47M | { |
3521 | 4.47M | appendEscape(aResult, nUTF32); |
3522 | 4.47M | } |
3523 | 3.68M | else |
3524 | 3.68M | aResult.appendUtf32(nUTF32); |
3525 | 8.15M | break; |
3526 | 18.8M | } |
3527 | 18.8M | } |
3528 | 493k | return aResult.makeStringAndClear(); |
3529 | 493k | } |
3530 | | |
3531 | | OUString INetURLObject::GetURLNoPass(DecodeMechanism eMechanism, |
3532 | | rtl_TextEncoding eCharset) const |
3533 | 11.8k | { |
3534 | 11.8k | INetURLObject aTemp(*this); |
3535 | 11.8k | aTemp.clearPassword(); |
3536 | 11.8k | return aTemp.GetMainURL(eMechanism, eCharset); |
3537 | 11.8k | } |
3538 | | |
3539 | | OUString INetURLObject::GetURLNoMark(DecodeMechanism eMechanism, |
3540 | | rtl_TextEncoding eCharset) const |
3541 | 2.88k | { |
3542 | 2.88k | INetURLObject aTemp(*this); |
3543 | 2.88k | aTemp.clearFragment(); |
3544 | 2.88k | return aTemp.GetMainURL(eMechanism, eCharset); |
3545 | 2.88k | } |
3546 | | |
3547 | | OUString |
3548 | | INetURLObject::getAbbreviated( |
3549 | | uno::Reference< util::XStringWidth > const & rStringWidth, |
3550 | | sal_Int32 nWidth, |
3551 | | DecodeMechanism eMechanism, |
3552 | | rtl_TextEncoding eCharset) |
3553 | | const |
3554 | 0 | { |
3555 | 0 | OSL_ENSURE(rStringWidth.is(), "specification violation"); |
3556 | 0 | OUStringBuffer aBuffer; |
3557 | | // make sure that the scheme is copied for generic schemes: getSchemeInfo().m_pScheme |
3558 | | // is empty ("") in that case, so take the scheme from m_aAbsURIRef |
3559 | 0 | if (m_eScheme != INetProtocol::Generic) |
3560 | 0 | { |
3561 | 0 | aBuffer.append(getSchemeInfo().m_sScheme); |
3562 | 0 | } |
3563 | 0 | else |
3564 | 0 | { |
3565 | 0 | if (!m_aAbsURIRef.isEmpty()) |
3566 | 0 | { |
3567 | 0 | sal_Unicode const * pSchemeBegin |
3568 | 0 | = m_aAbsURIRef.getStr(); |
3569 | 0 | sal_Unicode const * pSchemeEnd = pSchemeBegin; |
3570 | |
|
3571 | 0 | while (pSchemeEnd[0] != ':') |
3572 | 0 | { |
3573 | 0 | ++pSchemeEnd; |
3574 | 0 | } |
3575 | 0 | aBuffer.append(pSchemeBegin, pSchemeEnd - pSchemeBegin); |
3576 | 0 | } |
3577 | 0 | } |
3578 | 0 | aBuffer.append(':'); |
3579 | 0 | bool bAuthority = getSchemeInfo().m_bAuthority; |
3580 | 0 | sal_Unicode const * pCoreBegin |
3581 | 0 | = m_aAbsURIRef.getStr() + (bAuthority ? getAuthorityBegin() : |
3582 | 0 | m_aPath.getBegin()); |
3583 | 0 | sal_Unicode const * pCoreEnd |
3584 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin() + m_aPath.getLength(); |
3585 | 0 | bool bSegment = false; |
3586 | 0 | if (getSchemeInfo().m_bHierarchical) |
3587 | 0 | { |
3588 | 0 | OUString aRest; |
3589 | 0 | if (m_aQuery.isPresent()) |
3590 | 0 | aRest = "?..."; |
3591 | 0 | else if (m_aFragment.isPresent()) |
3592 | 0 | aRest = "#..."; |
3593 | 0 | OUStringBuffer aTrailer; |
3594 | 0 | sal_Unicode const * pBegin = pCoreBegin; |
3595 | 0 | sal_Unicode const * pEnd = pCoreEnd; |
3596 | 0 | sal_Unicode const * pPrefixBegin = pBegin; |
3597 | 0 | sal_Unicode const * pSuffixEnd = pEnd; |
3598 | 0 | bool bPrefix = true; |
3599 | 0 | bool bSuffix = true; |
3600 | 0 | do |
3601 | 0 | { |
3602 | 0 | if (bSuffix) |
3603 | 0 | { |
3604 | 0 | sal_Unicode const * p = pSuffixEnd - 1; |
3605 | 0 | if (pSuffixEnd == pCoreEnd && *p == '/') |
3606 | 0 | --p; |
3607 | 0 | while (*p != '/') |
3608 | 0 | --p; |
3609 | 0 | if (bAuthority && p == pCoreBegin + 1) |
3610 | 0 | --p; |
3611 | 0 | OUString |
3612 | 0 | aSegment(decode(p + (p == pBegin && pBegin != pCoreBegin ? |
3613 | 0 | 1 : 0), |
3614 | 0 | pSuffixEnd, |
3615 | 0 | eMechanism, |
3616 | 0 | eCharset)); |
3617 | 0 | pSuffixEnd = p; |
3618 | 0 | OUStringBuffer aResult(aBuffer); |
3619 | 0 | if (pSuffixEnd != pBegin) |
3620 | 0 | aResult.append("..."); |
3621 | 0 | aResult.append(aSegment + aTrailer + aRest); |
3622 | 0 | if (rStringWidth-> |
3623 | 0 | queryStringWidth(aResult.makeStringAndClear()) |
3624 | 0 | <= nWidth) |
3625 | 0 | { |
3626 | 0 | aTrailer.insert(0, aSegment); |
3627 | 0 | bSegment = true; |
3628 | 0 | pEnd = pSuffixEnd; |
3629 | 0 | } |
3630 | 0 | else |
3631 | 0 | bSuffix = false; |
3632 | 0 | if (pPrefixBegin > pSuffixEnd) |
3633 | 0 | pPrefixBegin = pSuffixEnd; |
3634 | 0 | if (pBegin == pEnd) |
3635 | 0 | break; |
3636 | 0 | } |
3637 | 0 | if (bPrefix) |
3638 | 0 | { |
3639 | 0 | sal_Unicode const * p |
3640 | 0 | = pPrefixBegin |
3641 | 0 | + (bAuthority && pPrefixBegin == pCoreBegin ? 2 : |
3642 | 0 | 1); |
3643 | 0 | OSL_ASSERT(p <= pEnd); |
3644 | 0 | while (p < pEnd && *p != '/') |
3645 | 0 | ++p; |
3646 | 0 | if (p == pCoreEnd - 1 && *p == '/') |
3647 | 0 | ++p; |
3648 | 0 | OUString |
3649 | 0 | aSegment(decode(pPrefixBegin |
3650 | 0 | + (pPrefixBegin == pCoreBegin ? 0 : |
3651 | 0 | 1), |
3652 | 0 | p == pEnd ? p : p + 1, |
3653 | 0 | eMechanism, |
3654 | 0 | eCharset)); |
3655 | 0 | pPrefixBegin = p; |
3656 | 0 | OUStringBuffer aResult(aBuffer + aSegment); |
3657 | 0 | if (pPrefixBegin != pEnd) |
3658 | 0 | aResult.append("..."); |
3659 | 0 | aResult.append(aTrailer + aRest); |
3660 | 0 | if (rStringWidth-> |
3661 | 0 | queryStringWidth(aResult.makeStringAndClear()) |
3662 | 0 | <= nWidth) |
3663 | 0 | { |
3664 | 0 | aBuffer.append(aSegment); |
3665 | 0 | bSegment = true; |
3666 | 0 | pBegin = pPrefixBegin; |
3667 | 0 | } |
3668 | 0 | else |
3669 | 0 | bPrefix = false; |
3670 | 0 | if (pPrefixBegin > pSuffixEnd) |
3671 | 0 | pSuffixEnd = pPrefixBegin; |
3672 | 0 | if (pBegin == pEnd) |
3673 | 0 | break; |
3674 | 0 | } |
3675 | 0 | } |
3676 | 0 | while (bPrefix || bSuffix); |
3677 | 0 | if (bSegment) |
3678 | 0 | { |
3679 | 0 | if (pPrefixBegin != pBegin || pSuffixEnd != pEnd) |
3680 | 0 | aBuffer.append("..."); |
3681 | 0 | aBuffer.append(aTrailer); |
3682 | 0 | } |
3683 | 0 | } |
3684 | 0 | if (!bSegment) |
3685 | 0 | aBuffer.append(decode(pCoreBegin, |
3686 | 0 | pCoreEnd, |
3687 | 0 | eMechanism, |
3688 | 0 | eCharset)); |
3689 | 0 | if (m_aQuery.isPresent()) |
3690 | 0 | { |
3691 | 0 | aBuffer.append("?" + decode(m_aQuery, eMechanism, eCharset)); |
3692 | 0 | } |
3693 | 0 | if (m_aFragment.isPresent()) |
3694 | 0 | { |
3695 | 0 | aBuffer.append("#" + decode(m_aFragment, eMechanism, eCharset)); |
3696 | 0 | } |
3697 | 0 | if (!aBuffer.isEmpty()) |
3698 | 0 | { |
3699 | 0 | OUStringBuffer aResult(aBuffer); |
3700 | 0 | if (rStringWidth->queryStringWidth(aResult.makeStringAndClear()) |
3701 | 0 | > nWidth) |
3702 | 0 | for (sal_Int32 i = aBuffer.getLength();;) |
3703 | 0 | { |
3704 | 0 | if (i == 0) |
3705 | 0 | { |
3706 | 0 | aBuffer.setLength(aBuffer.getLength() - 1); |
3707 | 0 | if (aBuffer.isEmpty()) |
3708 | 0 | break; |
3709 | 0 | } |
3710 | 0 | else |
3711 | 0 | { |
3712 | 0 | aBuffer.setLength(--i); |
3713 | 0 | aBuffer.append("..."); |
3714 | 0 | } |
3715 | 0 | aResult = aBuffer; |
3716 | 0 | if (rStringWidth-> |
3717 | 0 | queryStringWidth(aResult.makeStringAndClear()) |
3718 | 0 | <= nWidth) |
3719 | 0 | break; |
3720 | 0 | } |
3721 | 0 | } |
3722 | 0 | return aBuffer.makeStringAndClear(); |
3723 | 0 | } |
3724 | | |
3725 | | bool INetURLObject::operator ==(INetURLObject const & rObject) const |
3726 | 0 | { |
3727 | 0 | if (m_eScheme != rObject.m_eScheme) |
3728 | 0 | return false; |
3729 | 0 | if (m_eScheme == INetProtocol::NotValid) |
3730 | 0 | return std::u16string_view(m_aAbsURIRef) == std::u16string_view(rObject.m_aAbsURIRef); |
3731 | 0 | if ((m_aScheme.compare( |
3732 | 0 | rObject.m_aScheme, m_aAbsURIRef, rObject.m_aAbsURIRef) |
3733 | 0 | != 0) |
3734 | 0 | || GetUser(DecodeMechanism::NONE) != rObject.GetUser(DecodeMechanism::NONE) |
3735 | 0 | || GetPass(DecodeMechanism::NONE) != rObject.GetPass(DecodeMechanism::NONE) |
3736 | 0 | || !GetHost(DecodeMechanism::NONE).equalsIgnoreAsciiCase( |
3737 | 0 | rObject.GetHost(DecodeMechanism::NONE)) |
3738 | 0 | || GetPort() != rObject.GetPort() |
3739 | 0 | || HasParam() != rObject.HasParam() |
3740 | 0 | || GetParam() != rObject.GetParam()) |
3741 | 0 | return false; |
3742 | 0 | OUString aPath1(GetURLPath(DecodeMechanism::NONE)); |
3743 | 0 | OUString aPath2(rObject.GetURLPath(DecodeMechanism::NONE)); |
3744 | 0 | switch (m_eScheme) |
3745 | 0 | { |
3746 | 0 | case INetProtocol::File: |
3747 | 0 | { |
3748 | | // If the URL paths of two file URLs only differ in that one has a |
3749 | | // final '/' and the other has not, take the two paths as |
3750 | | // equivalent (this could be useful for other schemes, too): |
3751 | 0 | sal_Int32 nLength = aPath1.getLength(); |
3752 | 0 | switch (nLength - aPath2.getLength()) |
3753 | 0 | { |
3754 | 0 | case -1: |
3755 | 0 | if (aPath2[nLength] != '/') |
3756 | 0 | return false; |
3757 | 0 | break; |
3758 | | |
3759 | 0 | case 0: |
3760 | 0 | break; |
3761 | | |
3762 | 0 | case 1: |
3763 | 0 | if (aPath1[--nLength] != '/') |
3764 | 0 | return false; |
3765 | 0 | break; |
3766 | | |
3767 | 0 | default: |
3768 | 0 | return false; |
3769 | 0 | } |
3770 | 0 | return aPath1.compareTo(aPath2, nLength) == 0; |
3771 | 0 | } |
3772 | | |
3773 | 0 | default: |
3774 | 0 | return aPath1 == aPath2; |
3775 | 0 | } |
3776 | 0 | } |
3777 | | |
3778 | | bool INetURLObject::ConcatData(INetProtocol eTheScheme, |
3779 | | std::u16string_view rTheUser, |
3780 | | std::u16string_view rThePassword, |
3781 | | std::u16string_view rTheHost, |
3782 | | sal_uInt32 nThePort, |
3783 | | std::u16string_view rThePath) |
3784 | 0 | { |
3785 | 0 | setInvalid(); |
3786 | 0 | m_eScheme = eTheScheme; |
3787 | 0 | if (HasError() || m_eScheme == INetProtocol::Generic) |
3788 | 0 | return false; |
3789 | 0 | m_aAbsURIRef.setLength(0); |
3790 | 0 | m_aAbsURIRef.append(getSchemeInfo().m_sScheme); |
3791 | 0 | m_aAbsURIRef.append(':'); |
3792 | 0 | if (getSchemeInfo().m_bAuthority) |
3793 | 0 | { |
3794 | 0 | m_aAbsURIRef.append("//"); |
3795 | 0 | bool bUserInfo = false; |
3796 | 0 | if (getSchemeInfo().m_bUser) |
3797 | 0 | { |
3798 | 0 | if (!rTheUser.empty()) |
3799 | 0 | { |
3800 | 0 | OUStringBuffer aNewUser; |
3801 | 0 | encodeText(aNewUser, rTheUser, PART_USER_PASSWORD, |
3802 | 0 | EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false); |
3803 | 0 | m_aUser.set(m_aAbsURIRef, aNewUser, m_aAbsURIRef.getLength()); |
3804 | 0 | bUserInfo = true; |
3805 | 0 | } |
3806 | 0 | } |
3807 | 0 | else if (!rTheUser.empty()) |
3808 | 0 | { |
3809 | 0 | setInvalid(); |
3810 | 0 | return false; |
3811 | 0 | } |
3812 | 0 | if (!rThePassword.empty()) |
3813 | 0 | { |
3814 | 0 | if (getSchemeInfo().m_bPassword) |
3815 | 0 | { |
3816 | 0 | m_aAbsURIRef.append(':'); |
3817 | 0 | OUStringBuffer aNewAuth; |
3818 | 0 | encodeText(aNewAuth, rThePassword, PART_USER_PASSWORD, |
3819 | 0 | EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false); |
3820 | 0 | m_aAuth.set(m_aAbsURIRef, aNewAuth, m_aAbsURIRef.getLength()); |
3821 | 0 | bUserInfo = true; |
3822 | 0 | } |
3823 | 0 | else |
3824 | 0 | { |
3825 | 0 | setInvalid(); |
3826 | 0 | return false; |
3827 | 0 | } |
3828 | 0 | } |
3829 | 0 | if (bUserInfo && getSchemeInfo().m_bHost) |
3830 | 0 | m_aAbsURIRef.append('@'); |
3831 | 0 | if (getSchemeInfo().m_bHost) |
3832 | 0 | { |
3833 | 0 | OUStringBuffer aSynHost(rTheHost); |
3834 | 0 | bool bNetBiosName = false; |
3835 | 0 | switch (m_eScheme) |
3836 | 0 | { |
3837 | 0 | case INetProtocol::File: |
3838 | 0 | { |
3839 | 0 | if (OUString::unacquired(aSynHost).equalsIgnoreAsciiCase( "localhost" )) |
3840 | 0 | { |
3841 | 0 | aSynHost.setLength(0); |
3842 | 0 | } |
3843 | 0 | bNetBiosName = true; |
3844 | 0 | } |
3845 | 0 | break; |
3846 | | |
3847 | 0 | case INetProtocol::Ldap: |
3848 | 0 | if (aSynHost.isEmpty() && nThePort != 0) |
3849 | 0 | { |
3850 | 0 | setInvalid(); |
3851 | 0 | return false; |
3852 | 0 | } |
3853 | 0 | break; |
3854 | | |
3855 | 0 | default: |
3856 | 0 | if (aSynHost.isEmpty()) |
3857 | 0 | { |
3858 | 0 | setInvalid(); |
3859 | 0 | return false; |
3860 | 0 | } |
3861 | 0 | break; |
3862 | 0 | } |
3863 | 0 | if (!parseHostOrNetBiosName( |
3864 | 0 | aSynHost.getStr(), aSynHost.getStr() + aSynHost.getLength(), |
3865 | 0 | EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, bNetBiosName, &aSynHost)) |
3866 | 0 | { |
3867 | 0 | setInvalid(); |
3868 | 0 | return false; |
3869 | 0 | } |
3870 | 0 | m_aHost.set(m_aAbsURIRef, aSynHost, m_aAbsURIRef.getLength()); |
3871 | 0 | if (nThePort != 0) |
3872 | 0 | { |
3873 | 0 | if (getSchemeInfo().m_bPort) |
3874 | 0 | { |
3875 | 0 | m_aAbsURIRef.append(':'); |
3876 | 0 | m_aPort.set(m_aAbsURIRef, |
3877 | 0 | OUString::number(nThePort), |
3878 | 0 | m_aAbsURIRef.getLength()); |
3879 | 0 | } |
3880 | 0 | else |
3881 | 0 | { |
3882 | 0 | setInvalid(); |
3883 | 0 | return false; |
3884 | 0 | } |
3885 | 0 | } |
3886 | 0 | } |
3887 | 0 | else if (!rTheHost.empty() || nThePort != 0) |
3888 | 0 | { |
3889 | 0 | setInvalid(); |
3890 | 0 | return false; |
3891 | 0 | } |
3892 | 0 | } |
3893 | 0 | OUStringBuffer aSynPath(256); |
3894 | 0 | sal_Unicode const * p = rThePath.data(); |
3895 | 0 | sal_Unicode const * pEnd = p + rThePath.size(); |
3896 | 0 | if (!parsePath(m_eScheme, &p, pEnd, EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false, '/', |
3897 | 0 | 0x80000000, 0x80000000, 0x80000000, aSynPath) |
3898 | 0 | || p != pEnd) |
3899 | 0 | { |
3900 | 0 | setInvalid(); |
3901 | 0 | return false; |
3902 | 0 | } |
3903 | 0 | m_aPath.set(m_aAbsURIRef, aSynPath, m_aAbsURIRef.getLength()); |
3904 | 0 | return true; |
3905 | 0 | } |
3906 | | |
3907 | | // static |
3908 | | OUString INetURLObject::GetAbsURL(std::u16string_view rTheBaseURIRef, |
3909 | | OUString const & rTheRelURIRef, |
3910 | | EncodeMechanism eEncodeMechanism, |
3911 | | DecodeMechanism eDecodeMechanism, |
3912 | | rtl_TextEncoding eCharset) |
3913 | 85.4k | { |
3914 | | // Backwards compatibility: |
3915 | 85.4k | if (rTheRelURIRef.isEmpty() || rTheRelURIRef[0] == '#') |
3916 | 1.36k | return rTheRelURIRef; |
3917 | | |
3918 | 84.1k | INetURLObject aTheAbsURIRef; |
3919 | 84.1k | bool bWasAbsolute; |
3920 | 84.1k | return INetURLObject(rTheBaseURIRef, eEncodeMechanism, eCharset). |
3921 | 84.1k | convertRelToAbs(rTheRelURIRef, aTheAbsURIRef, |
3922 | 84.1k | bWasAbsolute, eEncodeMechanism, |
3923 | 84.1k | eCharset, false, false, |
3924 | 84.1k | false, FSysStyle::Detect) |
3925 | 37.2k | || eEncodeMechanism != EncodeMechanism::WasEncoded |
3926 | 37.2k | || eDecodeMechanism != DecodeMechanism::ToIUri |
3927 | 37.2k | || eCharset != RTL_TEXTENCODING_UTF8 ? |
3928 | 46.9k | aTheAbsURIRef.GetMainURL(eDecodeMechanism, eCharset) : |
3929 | 84.1k | rTheRelURIRef; |
3930 | 85.4k | } |
3931 | | |
3932 | | OUString INetURLObject::getExternalURL() const |
3933 | 0 | { |
3934 | 0 | OUString aTheExtURIRef; |
3935 | 0 | translateToExternal( |
3936 | 0 | m_aAbsURIRef, aTheExtURIRef); |
3937 | 0 | return aTheExtURIRef; |
3938 | 0 | } |
3939 | | |
3940 | 76.4k | bool INetURLObject::isSchemeEqualTo(std::u16string_view scheme) const { |
3941 | 76.4k | return m_aScheme.isPresent() |
3942 | 11.5k | && (rtl_ustr_compareIgnoreAsciiCase_WithLength( |
3943 | 11.5k | scheme.data(), scheme.size(), |
3944 | 11.5k | m_aAbsURIRef.getStr() + m_aScheme.getBegin(), |
3945 | 11.5k | m_aScheme.getLength()) |
3946 | 11.5k | == 0); |
3947 | 76.4k | } |
3948 | | |
3949 | 25.7k | bool INetURLObject::isAnyKnownWebDAVScheme() const { |
3950 | 25.7k | return ( isSchemeEqualTo( INetProtocol::Http ) || |
3951 | 22.3k | isSchemeEqualTo( INetProtocol::Https ) || |
3952 | 21.9k | isSchemeEqualTo( INetProtocol::VndSunStarWebdav ) || |
3953 | 21.9k | isSchemeEqualTo( u"vnd.sun.star.webdavs" ) || |
3954 | 21.9k | isSchemeEqualTo( u"webdav" ) || |
3955 | 21.9k | isSchemeEqualTo( u"webdavs" )); |
3956 | 25.7k | } |
3957 | | |
3958 | | // static |
3959 | | const OUString & INetURLObject::GetScheme(INetProtocol eTheScheme) |
3960 | 167 | { |
3961 | 167 | return getSchemeInfo(eTheScheme).m_aPrefix; |
3962 | 167 | } |
3963 | | |
3964 | | // static |
3965 | | const OUString & INetURLObject::GetSchemeName(INetProtocol eTheScheme) |
3966 | 0 | { |
3967 | 0 | return getSchemeInfo(eTheScheme).m_sScheme; |
3968 | 0 | } |
3969 | | |
3970 | | // static |
3971 | | INetProtocol INetURLObject::CompareProtocolScheme(std::u16string_view aTheAbsURIRef) |
3972 | 1.30M | { |
3973 | 1.30M | sal_Unicode const * p = aTheAbsURIRef.data(); |
3974 | 1.30M | PrefixInfo const * pPrefix = getPrefix(p, p + aTheAbsURIRef.size()); |
3975 | 1.30M | return pPrefix ? pPrefix->m_eScheme : INetProtocol::NotValid; |
3976 | 1.30M | } |
3977 | | |
3978 | | OUString INetURLObject::GetHostPort(DecodeMechanism eMechanism, |
3979 | | rtl_TextEncoding eCharset) const |
3980 | 0 | { |
3981 | | // Check because PROT_VND_SUN_STAR_HELP, PROT_VND_SUN_STAR_HIER, and |
3982 | | // PROT_VND_SUN_STAR_PKG misuse m_aHost: |
3983 | 0 | if (!getSchemeInfo().m_bHost) |
3984 | 0 | return OUString(); |
3985 | 0 | OUStringBuffer aHostPort(decode(m_aHost, eMechanism, eCharset)); |
3986 | 0 | if (m_aPort.isPresent()) |
3987 | 0 | { |
3988 | 0 | aHostPort.append(":" + decode(m_aPort, eMechanism, eCharset)); |
3989 | 0 | } |
3990 | 0 | return aHostPort.makeStringAndClear(); |
3991 | 0 | } |
3992 | | |
3993 | | sal_uInt32 INetURLObject::GetPort() const |
3994 | 167 | { |
3995 | 167 | if (m_aPort.isPresent()) |
3996 | 0 | { |
3997 | 0 | sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPort.getBegin(); |
3998 | 0 | sal_Unicode const * pEnd = p + m_aPort.getLength(); |
3999 | 0 | sal_uInt32 nThePort; |
4000 | 0 | if (INetMIME::scanUnsigned(p, pEnd, true, nThePort) && p == pEnd) |
4001 | 0 | return nThePort; |
4002 | 0 | } |
4003 | 167 | return 0; |
4004 | 167 | } |
4005 | | |
4006 | | bool INetURLObject::SetPort(sal_uInt32 nThePort) |
4007 | 112k | { |
4008 | 112k | if (getSchemeInfo().m_bPort && m_aHost.isPresent()) |
4009 | 112k | { |
4010 | 112k | sal_Int32 nDelta; |
4011 | 112k | if (m_aPort.isPresent()) |
4012 | 0 | nDelta = m_aPort.set(m_aAbsURIRef, OUString::number(nThePort)); |
4013 | 112k | else |
4014 | 112k | { |
4015 | 112k | m_aAbsURIRef.insert(m_aHost.getEnd(), u':'); |
4016 | 112k | nDelta = m_aPort.set(m_aAbsURIRef, OUString::number(nThePort), m_aHost.getEnd() + 1) |
4017 | 112k | + 1; |
4018 | 112k | } |
4019 | 112k | m_aPath += nDelta; |
4020 | 112k | m_aQuery += nDelta; |
4021 | 112k | m_aFragment += nDelta; |
4022 | 112k | return true; |
4023 | 112k | } |
4024 | 0 | return false; |
4025 | 112k | } |
4026 | | |
4027 | | sal_Int32 INetURLObject::getSegmentCount(bool bIgnoreFinalSlash) const |
4028 | 167 | { |
4029 | 167 | if (!checkHierarchical()) |
4030 | 15 | return 0; |
4031 | | |
4032 | 152 | sal_Unicode const * p = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4033 | 152 | sal_Unicode const * pEnd = p + m_aPath.getLength(); |
4034 | 152 | if (bIgnoreFinalSlash && pEnd > p && pEnd[-1] == '/') |
4035 | 0 | --pEnd; |
4036 | 152 | sal_Int32 n = p == pEnd || *p == '/' ? 0 : 1; |
4037 | 3.56k | while (p != pEnd) |
4038 | 3.41k | if (*p++ == '/') |
4039 | 326 | ++n; |
4040 | 152 | return n; |
4041 | 167 | } |
4042 | | |
4043 | | bool INetURLObject::removeSegment(sal_Int32 nIndex, bool bIgnoreFinalSlash) |
4044 | 9.17k | { |
4045 | 9.17k | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4046 | 9.17k | if (!aSegment.isPresent()) |
4047 | 0 | return false; |
4048 | | |
4049 | 9.17k | OUStringBuffer aNewPath(m_aPath.getLength()); |
4050 | 9.17k | aNewPath.append(m_aAbsURIRef.getStr() + m_aPath.getBegin(), |
4051 | 9.17k | aSegment.getBegin() - m_aPath.getBegin()); |
4052 | 9.17k | if (bIgnoreFinalSlash && aSegment.getEnd() == m_aPath.getEnd()) |
4053 | 9.17k | aNewPath.append('/'); |
4054 | 0 | else |
4055 | 0 | aNewPath.append(m_aAbsURIRef.getStr() + aSegment.getEnd(), |
4056 | 0 | m_aPath.getEnd() - aSegment.getEnd()); |
4057 | 9.17k | if (aNewPath.isEmpty() && !aSegment.isEmpty() && |
4058 | 0 | m_aAbsURIRef[aSegment.getBegin()] == '/') |
4059 | 0 | { |
4060 | 0 | aNewPath.append('/'); |
4061 | 0 | } |
4062 | | |
4063 | 9.17k | return setPath(aNewPath, EncodeMechanism::NotCanonical, |
4064 | 9.17k | RTL_TEXTENCODING_UTF8); |
4065 | 9.17k | } |
4066 | | |
4067 | | OUString INetURLObject::getName(sal_Int32 nIndex, bool bIgnoreFinalSlash, |
4068 | | DecodeMechanism eMechanism, |
4069 | | rtl_TextEncoding eCharset) const |
4070 | 386 | { |
4071 | 386 | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4072 | 386 | if (!aSegment.isPresent()) |
4073 | 60 | return OUString(); |
4074 | | |
4075 | 326 | sal_Unicode const * pSegBegin |
4076 | 326 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4077 | 326 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4078 | | |
4079 | 326 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4080 | 326 | ++pSegBegin; |
4081 | 326 | sal_Unicode const * p = pSegBegin; |
4082 | 3.41k | while (p != pSegEnd && *p != ';') |
4083 | 3.08k | ++p; |
4084 | | |
4085 | 326 | return decode(pSegBegin, p, eMechanism, eCharset); |
4086 | 386 | } |
4087 | | |
4088 | | bool INetURLObject::setName(std::u16string_view rTheName, EncodeMechanism eMechanism, |
4089 | | rtl_TextEncoding eCharset) |
4090 | 0 | { |
4091 | 0 | SubString aSegment(getSegment(LAST_SEGMENT, true)); |
4092 | 0 | if (!aSegment.isPresent()) |
4093 | 0 | return false; |
4094 | | |
4095 | 0 | sal_Unicode const * pPathBegin |
4096 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4097 | 0 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4098 | 0 | sal_Unicode const * pSegBegin |
4099 | 0 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4100 | 0 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4101 | |
|
4102 | 0 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4103 | 0 | ++pSegBegin; |
4104 | 0 | sal_Unicode const * p = pSegBegin; |
4105 | 0 | while (p != pSegEnd && *p != ';') |
4106 | 0 | ++p; |
4107 | |
|
4108 | 0 | OUStringBuffer aNewPath(256); |
4109 | 0 | aNewPath.append(std::u16string_view(pPathBegin, pSegBegin - pPathBegin)); |
4110 | 0 | encodeText(aNewPath, rTheName, PART_PCHAR, eMechanism, eCharset, true); |
4111 | 0 | aNewPath.append(std::u16string_view(p, pPathEnd - p)); |
4112 | 0 | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4113 | 0 | } |
4114 | | |
4115 | | bool INetURLObject::hasExtension() |
4116 | | const |
4117 | 0 | { |
4118 | 0 | SubString aSegment(getSegment(LAST_SEGMENT, true/*bIgnoreFinalSlash*/)); |
4119 | 0 | if (!aSegment.isPresent()) |
4120 | 0 | return false; |
4121 | | |
4122 | 0 | sal_Unicode const * pSegBegin |
4123 | 0 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4124 | 0 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4125 | |
|
4126 | 0 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4127 | 0 | ++pSegBegin; |
4128 | 0 | for (sal_Unicode const * p = pSegBegin; p != pSegEnd && *p != ';'; ++p) |
4129 | 0 | if (*p == '.' && p != pSegBegin) |
4130 | 0 | return true; |
4131 | 0 | return false; |
4132 | 0 | } |
4133 | | |
4134 | | OUString INetURLObject::getBase(sal_Int32 nIndex, bool bIgnoreFinalSlash, |
4135 | | DecodeMechanism eMechanism, |
4136 | | rtl_TextEncoding eCharset) const |
4137 | 24.9k | { |
4138 | 24.9k | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4139 | 24.9k | if (!aSegment.isPresent()) |
4140 | 15.1k | return OUString(); |
4141 | | |
4142 | 9.85k | sal_Unicode const * pSegBegin |
4143 | 9.85k | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4144 | 9.85k | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4145 | | |
4146 | 9.85k | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4147 | 9.85k | ++pSegBegin; |
4148 | 9.85k | sal_Unicode const * pExtension = nullptr; |
4149 | 9.85k | sal_Unicode const * p = pSegBegin; |
4150 | 334k | for (; p != pSegEnd && *p != ';'; ++p) |
4151 | 324k | if (*p == '.' && p != pSegBegin) |
4152 | 9.74k | pExtension = p; |
4153 | 9.85k | if (!pExtension) |
4154 | 138 | pExtension = p; |
4155 | | |
4156 | 9.85k | return decode(pSegBegin, pExtension, eMechanism, eCharset); |
4157 | 24.9k | } |
4158 | | |
4159 | | bool INetURLObject::setBase(std::u16string_view rTheBase, sal_Int32 nIndex, |
4160 | | EncodeMechanism eMechanism, |
4161 | | rtl_TextEncoding eCharset) |
4162 | 0 | { |
4163 | 0 | SubString aSegment(getSegment(nIndex, true/*bIgnoreFinalSlash*/)); |
4164 | 0 | if (!aSegment.isPresent()) |
4165 | 0 | return false; |
4166 | | |
4167 | 0 | sal_Unicode const * pPathBegin |
4168 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4169 | 0 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4170 | 0 | sal_Unicode const * pSegBegin |
4171 | 0 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4172 | 0 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4173 | |
|
4174 | 0 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4175 | 0 | ++pSegBegin; |
4176 | 0 | sal_Unicode const * pExtension = nullptr; |
4177 | 0 | sal_Unicode const * p = pSegBegin; |
4178 | 0 | for (; p != pSegEnd && *p != ';'; ++p) |
4179 | 0 | if (*p == '.' && p != pSegBegin) |
4180 | 0 | pExtension = p; |
4181 | 0 | if (!pExtension) |
4182 | 0 | pExtension = p; |
4183 | |
|
4184 | 0 | OUStringBuffer aNewPath(256); |
4185 | 0 | aNewPath.append(std::u16string_view(pPathBegin, pSegBegin - pPathBegin)); |
4186 | 0 | encodeText(aNewPath, rTheBase, PART_PCHAR, eMechanism, eCharset, true); |
4187 | 0 | aNewPath.append(std::u16string_view(pExtension, pPathEnd - pExtension)); |
4188 | 0 | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4189 | 0 | } |
4190 | | |
4191 | | OUString INetURLObject::getExtension(sal_Int32 nIndex, |
4192 | | bool bIgnoreFinalSlash, |
4193 | | DecodeMechanism eMechanism, |
4194 | | rtl_TextEncoding eCharset) const |
4195 | 101k | { |
4196 | 101k | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4197 | 101k | if (!aSegment.isPresent()) |
4198 | 660 | return OUString(); |
4199 | | |
4200 | 100k | sal_Unicode const * pSegBegin |
4201 | 100k | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4202 | 100k | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4203 | | |
4204 | 100k | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4205 | 100k | ++pSegBegin; |
4206 | 100k | sal_Unicode const * pExtension = nullptr; |
4207 | 100k | sal_Unicode const * p = pSegBegin; |
4208 | 608k | for (; p != pSegEnd && *p != ';'; ++p) |
4209 | 508k | if (*p == '.' && p != pSegBegin) |
4210 | 100k | pExtension = p; |
4211 | | |
4212 | 100k | if (!pExtension) |
4213 | 91 | return OUString(); |
4214 | | |
4215 | 100k | return decode(pExtension + 1, p, eMechanism, eCharset); |
4216 | 100k | } |
4217 | | |
4218 | | bool INetURLObject::setExtension(std::u16string_view rTheExtension, |
4219 | | sal_Int32 nIndex, bool bIgnoreFinalSlash, |
4220 | | rtl_TextEncoding eCharset) |
4221 | 414 | { |
4222 | 414 | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4223 | 414 | if (!aSegment.isPresent()) |
4224 | 414 | return false; |
4225 | | |
4226 | 0 | sal_Unicode const * pPathBegin |
4227 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4228 | 0 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4229 | 0 | sal_Unicode const * pSegBegin |
4230 | 0 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4231 | 0 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4232 | |
|
4233 | 0 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4234 | 0 | ++pSegBegin; |
4235 | 0 | sal_Unicode const * pExtension = nullptr; |
4236 | 0 | sal_Unicode const * p = pSegBegin; |
4237 | 0 | for (; p != pSegEnd && *p != ';'; ++p) |
4238 | 0 | if (*p == '.' && p != pSegBegin) |
4239 | 0 | pExtension = p; |
4240 | 0 | if (!pExtension) |
4241 | 0 | pExtension = p; |
4242 | |
|
4243 | 0 | OUStringBuffer aNewPath(256); |
4244 | 0 | aNewPath.append(OUString::Concat(std::u16string_view(pPathBegin, pExtension - pPathBegin)) + "."); |
4245 | 0 | encodeText(aNewPath, rTheExtension, PART_PCHAR, EncodeMechanism::WasEncoded, eCharset, true); |
4246 | 0 | aNewPath.append(std::u16string_view(p, pPathEnd - p)); |
4247 | 0 | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4248 | 414 | } |
4249 | | |
4250 | | bool INetURLObject::removeExtension(sal_Int32 nIndex, bool bIgnoreFinalSlash) |
4251 | 0 | { |
4252 | 0 | SubString aSegment(getSegment(nIndex, bIgnoreFinalSlash)); |
4253 | 0 | if (!aSegment.isPresent()) |
4254 | 0 | return false; |
4255 | | |
4256 | 0 | sal_Unicode const * pPathBegin |
4257 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4258 | 0 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4259 | 0 | sal_Unicode const * pSegBegin |
4260 | 0 | = m_aAbsURIRef.getStr() + aSegment.getBegin(); |
4261 | 0 | sal_Unicode const * pSegEnd = pSegBegin + aSegment.getLength(); |
4262 | |
|
4263 | 0 | if (pSegBegin < pSegEnd && *pSegBegin == '/') |
4264 | 0 | ++pSegBegin; |
4265 | 0 | sal_Unicode const * pExtension = nullptr; |
4266 | 0 | sal_Unicode const * p = pSegBegin; |
4267 | 0 | for (; p != pSegEnd && *p != ';'; ++p) |
4268 | 0 | if (*p == '.' && p != pSegBegin) |
4269 | 0 | pExtension = p; |
4270 | 0 | if (!pExtension) |
4271 | 0 | return true; |
4272 | | |
4273 | 0 | OUString aNewPath = |
4274 | 0 | OUString::Concat(std::u16string_view(pPathBegin, pExtension - pPathBegin)) + |
4275 | 0 | std::u16string_view(p, pPathEnd - p); |
4276 | |
|
4277 | 0 | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4278 | 0 | } |
4279 | | |
4280 | | bool INetURLObject::hasFinalSlash() const |
4281 | 200 | { |
4282 | 200 | if (!checkHierarchical()) |
4283 | 42 | return false; |
4284 | | |
4285 | 158 | sal_Unicode const * pPathBegin |
4286 | 158 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4287 | 158 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4288 | 158 | return pPathEnd > pPathBegin && pPathEnd[-1] == '/'; |
4289 | 200 | } |
4290 | | |
4291 | | bool INetURLObject::setFinalSlash() |
4292 | 0 | { |
4293 | 0 | if (!checkHierarchical()) |
4294 | 0 | return false; |
4295 | | |
4296 | 0 | sal_Unicode const * pPathBegin |
4297 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4298 | 0 | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4299 | 0 | if (pPathEnd > pPathBegin && pPathEnd[-1] == '/') |
4300 | 0 | return true; |
4301 | | |
4302 | 0 | OUString aNewPath |
4303 | 0 | = OUString::Concat(std::u16string_view(pPathBegin, pPathEnd - pPathBegin)) + "/"; |
4304 | |
|
4305 | 0 | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4306 | 0 | } |
4307 | | |
4308 | | bool INetURLObject::removeFinalSlash() |
4309 | 43.7k | { |
4310 | 43.7k | if (!checkHierarchical()) |
4311 | 0 | return false; |
4312 | | |
4313 | 43.7k | sal_Unicode const * pPathBegin |
4314 | 43.7k | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4315 | 43.7k | sal_Unicode const * pPathEnd = pPathBegin + m_aPath.getLength(); |
4316 | 43.7k | if (pPathEnd <= pPathBegin || pPathEnd[-1] != '/') |
4317 | 34.5k | return true; |
4318 | | |
4319 | 9.17k | --pPathEnd; |
4320 | 9.17k | if (pPathEnd == pPathBegin && *pPathBegin == '/') |
4321 | 0 | return false; |
4322 | 9.17k | OUString aNewPath(pPathBegin, pPathEnd - pPathBegin); |
4323 | | |
4324 | 9.17k | return setPath(aNewPath, EncodeMechanism::NotCanonical, RTL_TEXTENCODING_UTF8); |
4325 | 9.17k | } |
4326 | | |
4327 | | OUString INetURLObject::getFSysPath(FSysStyle eStyle, |
4328 | | sal_Unicode * pDelimiter) const |
4329 | 3.73k | { |
4330 | 3.73k | if (m_eScheme != INetProtocol::File) |
4331 | 3.73k | return OUString(); |
4332 | | |
4333 | 0 | if (((eStyle & FSysStyle::Vos) ? 1 : 0) |
4334 | 0 | + ((eStyle & FSysStyle::Unix) ? 1 : 0) |
4335 | 0 | + ((eStyle & FSysStyle::Dos) ? 1 : 0) |
4336 | 0 | > 1) |
4337 | 0 | { |
4338 | 0 | if(eStyle & FSysStyle::Vos && m_aHost.isPresent() && m_aHost.getLength() > 0) |
4339 | 0 | { |
4340 | 0 | eStyle= FSysStyle::Vos; |
4341 | 0 | } |
4342 | 0 | else |
4343 | 0 | { |
4344 | 0 | if(hasDosVolume(eStyle) || ((eStyle & FSysStyle::Dos) && m_aHost.isPresent() && m_aHost.getLength() > 0)) |
4345 | 0 | { |
4346 | 0 | eStyle = FSysStyle::Dos; |
4347 | 0 | } |
4348 | 0 | else |
4349 | 0 | { |
4350 | 0 | if(eStyle & FSysStyle::Unix && (!m_aHost.isPresent() || m_aHost.getLength() == 0)) |
4351 | 0 | { |
4352 | 0 | eStyle = FSysStyle::Unix; |
4353 | 0 | } |
4354 | 0 | else |
4355 | 0 | { |
4356 | 0 | eStyle= FSysStyle(0); |
4357 | 0 | } |
4358 | 0 | } |
4359 | 0 | } |
4360 | 0 | } |
4361 | |
|
4362 | 0 | switch (eStyle) |
4363 | 0 | { |
4364 | 0 | case FSysStyle::Vos: |
4365 | 0 | { |
4366 | 0 | if (pDelimiter) |
4367 | 0 | *pDelimiter = '/'; |
4368 | |
|
4369 | 0 | OUStringBuffer aSynFSysPath("//"); |
4370 | 0 | if (m_aHost.isPresent() && m_aHost.getLength() > 0) |
4371 | 0 | aSynFSysPath.append(decode(m_aHost, DecodeMechanism::WithCharset, |
4372 | 0 | RTL_TEXTENCODING_UTF8)); |
4373 | 0 | else |
4374 | 0 | aSynFSysPath.append('.'); |
4375 | 0 | aSynFSysPath.append(decode(m_aPath, DecodeMechanism::WithCharset, |
4376 | 0 | RTL_TEXTENCODING_UTF8)); |
4377 | 0 | return aSynFSysPath.makeStringAndClear(); |
4378 | 0 | } |
4379 | | |
4380 | 0 | case FSysStyle::Unix: |
4381 | 0 | { |
4382 | 0 | if (m_aHost.isPresent() && m_aHost.getLength() > 0) |
4383 | 0 | return OUString(); |
4384 | | |
4385 | 0 | if (pDelimiter) |
4386 | 0 | *pDelimiter = '/'; |
4387 | |
|
4388 | 0 | return decode(m_aPath, DecodeMechanism::WithCharset, RTL_TEXTENCODING_UTF8); |
4389 | 0 | } |
4390 | | |
4391 | 0 | case FSysStyle::Dos: |
4392 | 0 | { |
4393 | 0 | if (pDelimiter) |
4394 | 0 | *pDelimiter = '\\'; |
4395 | |
|
4396 | 0 | OUStringBuffer aSynFSysPath(64); |
4397 | 0 | if (m_aHost.isPresent() && m_aHost.getLength() > 0) |
4398 | 0 | { |
4399 | 0 | aSynFSysPath.append("\\\\" |
4400 | 0 | + decode(m_aHost, DecodeMechanism::WithCharset, RTL_TEXTENCODING_UTF8) |
4401 | 0 | + "\\"); |
4402 | 0 | } |
4403 | 0 | sal_Unicode const * p |
4404 | 0 | = m_aAbsURIRef.getStr() + m_aPath.getBegin(); |
4405 | 0 | sal_Unicode const * pEnd = p + m_aPath.getLength(); |
4406 | 0 | DBG_ASSERT(p < pEnd && *p == '/', |
4407 | 0 | "INetURLObject::getFSysPath(): Bad path"); |
4408 | 0 | ++p; |
4409 | 0 | while (p < pEnd) |
4410 | 0 | { |
4411 | 0 | EscapeType eEscapeType; |
4412 | 0 | sal_uInt32 nUTF32 = getUTF32(p, pEnd, EncodeMechanism::WasEncoded, |
4413 | 0 | RTL_TEXTENCODING_UTF8, |
4414 | 0 | eEscapeType); |
4415 | 0 | if (eEscapeType == EscapeType::NONE && nUTF32 == '/') |
4416 | 0 | aSynFSysPath.append('\\'); |
4417 | 0 | else |
4418 | 0 | aSynFSysPath.appendUtf32(nUTF32); |
4419 | 0 | } |
4420 | 0 | return aSynFSysPath.makeStringAndClear(); |
4421 | 0 | } |
4422 | | |
4423 | 0 | default: |
4424 | 0 | return OUString(); |
4425 | 0 | } |
4426 | 0 | } |
4427 | | |
4428 | | // static |
4429 | | void INetURLObject::appendUCS4Escape(OUStringBuffer & rTheText, |
4430 | | sal_uInt32 nUCS4) |
4431 | 16.8M | { |
4432 | 16.8M | DBG_ASSERT(nUCS4 < 0x80000000, |
4433 | 16.8M | "INetURLObject::appendUCS4Escape(): Bad char"); |
4434 | 16.8M | if (nUCS4 < 0x80) |
4435 | 9.51M | appendEscape(rTheText, nUCS4); |
4436 | 7.32M | else if (nUCS4 < 0x800) |
4437 | 3.43M | { |
4438 | 3.43M | appendEscape(rTheText, nUCS4 >> 6 | 0xC0); |
4439 | 3.43M | appendEscape(rTheText, (nUCS4 & 0x3F) | 0x80); |
4440 | 3.43M | } |
4441 | 3.89M | else if (nUCS4 < 0x10000) |
4442 | 3.88M | { |
4443 | 3.88M | appendEscape(rTheText, nUCS4 >> 12 | 0xE0); |
4444 | 3.88M | appendEscape(rTheText, (nUCS4 >> 6 & 0x3F) | 0x80); |
4445 | 3.88M | appendEscape(rTheText, (nUCS4 & 0x3F) | 0x80); |
4446 | 3.88M | } |
4447 | 9.34k | else if (nUCS4 < 0x200000) |
4448 | 9.34k | { |
4449 | 9.34k | appendEscape(rTheText, nUCS4 >> 18 | 0xF0); |
4450 | 9.34k | appendEscape(rTheText, (nUCS4 >> 12 & 0x3F) | 0x80); |
4451 | 9.34k | appendEscape(rTheText, (nUCS4 >> 6 & 0x3F) | 0x80); |
4452 | 9.34k | appendEscape(rTheText, (nUCS4 & 0x3F) | 0x80); |
4453 | 9.34k | } |
4454 | 0 | else if (nUCS4 < 0x4000000) |
4455 | 0 | { |
4456 | 0 | appendEscape(rTheText, nUCS4 >> 24 | 0xF8); |
4457 | 0 | appendEscape(rTheText, (nUCS4 >> 18 & 0x3F) | 0x80); |
4458 | 0 | appendEscape(rTheText, (nUCS4 >> 12 & 0x3F) | 0x80); |
4459 | 0 | appendEscape(rTheText, (nUCS4 >> 6 & 0x3F) | 0x80); |
4460 | 0 | appendEscape(rTheText, (nUCS4 & 0x3F) | 0x80); |
4461 | 0 | } |
4462 | 0 | else |
4463 | 0 | { |
4464 | 0 | appendEscape(rTheText, nUCS4 >> 30 | 0xFC); |
4465 | 0 | appendEscape(rTheText, (nUCS4 >> 24 & 0x3F) | 0x80); |
4466 | 0 | appendEscape(rTheText, (nUCS4 >> 18 & 0x3F) | 0x80); |
4467 | 0 | appendEscape(rTheText, (nUCS4 >> 12 & 0x3F) | 0x80); |
4468 | 0 | appendEscape(rTheText, (nUCS4 >> 6 & 0x3F) | 0x80); |
4469 | 0 | appendEscape(rTheText, (nUCS4 & 0x3F) | 0x80); |
4470 | 0 | } |
4471 | 16.8M | } |
4472 | | |
4473 | | // static |
4474 | | void INetURLObject::appendUCS4(OUStringBuffer& rTheText, sal_uInt32 nUCS4, |
4475 | | EscapeType eEscapeType, |
4476 | | Part ePart, rtl_TextEncoding eCharset, |
4477 | | bool bKeepVisibleEscapes) |
4478 | 43.7M | { |
4479 | 43.7M | bool bEscape; |
4480 | 43.7M | rtl_TextEncoding eTargetCharset = RTL_TEXTENCODING_DONTKNOW; |
4481 | 43.7M | switch (eEscapeType) |
4482 | 43.7M | { |
4483 | 38.6M | case EscapeType::NONE: |
4484 | 38.6M | if (mustEncode(nUCS4, ePart)) |
4485 | 11.8M | { |
4486 | 11.8M | bEscape = true; |
4487 | 11.8M | eTargetCharset = RTL_TEXTENCODING_UTF8; |
4488 | 11.8M | } |
4489 | 26.7M | else |
4490 | 26.7M | bEscape = false; |
4491 | 38.6M | break; |
4492 | | |
4493 | 47.3k | case EscapeType::Octet: |
4494 | 47.3k | bEscape = true; |
4495 | 47.3k | eTargetCharset = RTL_TEXTENCODING_ISO_8859_1; |
4496 | 47.3k | break; |
4497 | | |
4498 | 5.05M | case EscapeType::Utf32: |
4499 | 5.05M | if (mustEncode(nUCS4, ePart)) |
4500 | 5.02M | { |
4501 | 5.02M | bEscape = true; |
4502 | 5.02M | eTargetCharset = eCharset; |
4503 | 5.02M | } |
4504 | 24.2k | else if (bKeepVisibleEscapes && INetMIME::isVisible(nUCS4)) |
4505 | 23.2k | { |
4506 | 23.2k | bEscape = true; |
4507 | 23.2k | eTargetCharset = RTL_TEXTENCODING_ASCII_US; |
4508 | 23.2k | } |
4509 | 986 | else |
4510 | 986 | bEscape = false; |
4511 | 5.05M | break; |
4512 | 0 | default: |
4513 | 0 | bEscape = false; |
4514 | 43.7M | } |
4515 | | |
4516 | 43.7M | if (bEscape) |
4517 | 16.9M | { |
4518 | 16.9M | switch (eTargetCharset) |
4519 | 16.9M | { |
4520 | 0 | default: |
4521 | 0 | OSL_FAIL("INetURLObject::appendUCS4(): Unsupported charset"); |
4522 | 0 | [[fallthrough]]; |
4523 | 23.2k | case RTL_TEXTENCODING_ASCII_US: |
4524 | 70.5k | case RTL_TEXTENCODING_ISO_8859_1: |
4525 | 70.5k | appendEscape(rTheText, nUCS4); |
4526 | 70.5k | break; |
4527 | 16.8M | case RTL_TEXTENCODING_UTF8: |
4528 | 16.8M | appendUCS4Escape(rTheText, nUCS4); |
4529 | 16.8M | break; |
4530 | 16.9M | } |
4531 | 16.9M | } |
4532 | 26.7M | else |
4533 | 26.7M | rTheText.append(sal_Unicode(nUCS4)); |
4534 | 43.7M | } |
4535 | | |
4536 | | // static |
4537 | | sal_uInt32 INetURLObject::getUTF32(sal_Unicode const *& rBegin, |
4538 | | sal_Unicode const * pEnd, |
4539 | | EncodeMechanism eMechanism, |
4540 | | rtl_TextEncoding eCharset, |
4541 | | EscapeType & rEscapeType) |
4542 | 65.5M | { |
4543 | 65.5M | DBG_ASSERT(rBegin < pEnd, "INetURLObject::getUTF32(): Bad sequence"); |
4544 | 65.5M | sal_uInt32 nUTF32 = INetMIME::getUTF32Character(rBegin, pEnd); |
4545 | 65.5M | switch (eMechanism) |
4546 | 65.5M | { |
4547 | 1.65M | case EncodeMechanism::All: |
4548 | 1.65M | rEscapeType = EscapeType::NONE; |
4549 | 1.65M | break; |
4550 | | |
4551 | 63.1M | case EncodeMechanism::WasEncoded: |
4552 | 63.1M | { |
4553 | 63.1M | int nWeight1; |
4554 | 63.1M | int nWeight2; |
4555 | 63.1M | if (nUTF32 == static_cast<unsigned char>('%') && rBegin + 1 < pEnd |
4556 | 13.3M | && (nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0 |
4557 | 13.2M | && (nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0) |
4558 | 13.2M | { |
4559 | 13.2M | rBegin += 2; |
4560 | 13.2M | nUTF32 = nWeight1 << 4 | nWeight2; |
4561 | 13.2M | switch (eCharset) |
4562 | 13.2M | { |
4563 | 0 | default: |
4564 | 0 | OSL_FAIL( |
4565 | 0 | "INetURLObject::getUTF32(): Unsupported charset"); |
4566 | 0 | [[fallthrough]]; |
4567 | 306 | case RTL_TEXTENCODING_ASCII_US: |
4568 | 306 | rEscapeType = rtl::isAscii(nUTF32) ? |
4569 | 177 | EscapeType::Utf32 : EscapeType::Octet; |
4570 | 306 | break; |
4571 | | |
4572 | 357k | case RTL_TEXTENCODING_ISO_8859_1: |
4573 | 357k | rEscapeType = EscapeType::Utf32; |
4574 | 357k | break; |
4575 | | |
4576 | 12.9M | case RTL_TEXTENCODING_UTF8: |
4577 | 12.9M | if (rtl::isAscii(nUTF32)) |
4578 | 9.23M | rEscapeType = EscapeType::Utf32; |
4579 | 3.67M | else |
4580 | 3.67M | { |
4581 | 3.67M | if (nUTF32 >= 0xC0 && nUTF32 <= 0xF4) |
4582 | 3.64M | { |
4583 | 3.64M | sal_uInt32 nEncoded; |
4584 | 3.64M | int nShift; |
4585 | 3.64M | sal_uInt32 nMin; |
4586 | 3.64M | if (nUTF32 <= 0xDF) |
4587 | 1.72M | { |
4588 | 1.72M | nEncoded = (nUTF32 & 0x1F) << 6; |
4589 | 1.72M | nShift = 0; |
4590 | 1.72M | nMin = 0x80; |
4591 | 1.72M | } |
4592 | 1.92M | else if (nUTF32 <= 0xEF) |
4593 | 1.90M | { |
4594 | 1.90M | nEncoded = (nUTF32 & 0x0F) << 12; |
4595 | 1.90M | nShift = 6; |
4596 | 1.90M | nMin = 0x800; |
4597 | 1.90M | } |
4598 | 16.6k | else |
4599 | 16.6k | { |
4600 | 16.6k | nEncoded = (nUTF32 & 0x07) << 18; |
4601 | 16.6k | nShift = 12; |
4602 | 16.6k | nMin = 0x10000; |
4603 | 16.6k | } |
4604 | 3.64M | sal_Unicode const * p = rBegin; |
4605 | 3.64M | bool bUTF8 = true; |
4606 | 3.64M | for (;;) |
4607 | 5.56M | { |
4608 | 5.56M | if (pEnd - p < 3 |
4609 | 5.56M | || p[0] != '%' |
4610 | 5.55M | || (nWeight1 |
4611 | 5.55M | = INetMIME::getHexWeight(p[1])) |
4612 | 5.55M | < 8 |
4613 | 5.54M | || nWeight1 > 11 |
4614 | 5.54M | || (nWeight2 |
4615 | 5.54M | = INetMIME::getHexWeight(p[2])) |
4616 | 5.54M | < 0) |
4617 | 26.2k | { |
4618 | 26.2k | bUTF8 = false; |
4619 | 26.2k | break; |
4620 | 26.2k | } |
4621 | 5.53M | p += 3; |
4622 | 5.53M | nEncoded |
4623 | 5.53M | |= ((nWeight1 & 3) << 4 | nWeight2) |
4624 | 5.53M | << nShift; |
4625 | 5.53M | if (nShift == 0) |
4626 | 3.62M | break; |
4627 | 1.91M | nShift -= 6; |
4628 | 1.91M | } |
4629 | 3.64M | if (bUTF8 && rtl::isUnicodeScalarValue(nEncoded) |
4630 | 3.62M | && nEncoded >= nMin) |
4631 | 3.61M | { |
4632 | 3.61M | rBegin = p; |
4633 | 3.61M | nUTF32 = nEncoded; |
4634 | 3.61M | rEscapeType = EscapeType::Utf32; |
4635 | 3.61M | break; |
4636 | 3.61M | } |
4637 | 3.64M | } |
4638 | 52.0k | rEscapeType = EscapeType::Octet; |
4639 | 52.0k | } |
4640 | 9.28M | break; |
4641 | 13.2M | } |
4642 | 13.2M | } |
4643 | 49.9M | else |
4644 | 49.9M | rEscapeType = EscapeType::NONE; |
4645 | 63.1M | break; |
4646 | 63.1M | } |
4647 | | |
4648 | 63.1M | case EncodeMechanism::NotCanonical: |
4649 | 675k | { |
4650 | 675k | int nWeight1; |
4651 | 675k | int nWeight2; |
4652 | 675k | if (nUTF32 == static_cast<unsigned char>('%') && rBegin + 1 < pEnd |
4653 | 132 | && ((nWeight1 = INetMIME::getHexWeight(rBegin[0])) >= 0) |
4654 | 132 | && ((nWeight2 = INetMIME::getHexWeight(rBegin[1])) >= 0)) |
4655 | 132 | { |
4656 | 132 | rBegin += 2; |
4657 | 132 | nUTF32 = nWeight1 << 4 | nWeight2; |
4658 | 132 | rEscapeType = EscapeType::Octet; |
4659 | 132 | } |
4660 | 675k | else |
4661 | 675k | rEscapeType = EscapeType::NONE; |
4662 | 675k | break; |
4663 | 63.1M | } |
4664 | 65.5M | } |
4665 | 65.5M | return nUTF32; |
4666 | 65.5M | } |
4667 | | |
4668 | | // static |
4669 | | sal_uInt32 INetURLObject::scanDomain(sal_Unicode const *& rBegin, |
4670 | | sal_Unicode const * pEnd, |
4671 | | bool bEager) |
4672 | 172k | { |
4673 | 172k | enum class State { Dot, Label, Hyphen }; |
4674 | 172k | State eState = State::Dot; |
4675 | 172k | sal_Int32 nLabels = 0; |
4676 | 172k | sal_Unicode const * pLastAlphanumeric = nullptr; |
4677 | 837k | for (sal_Unicode const * p = rBegin;; ++p) |
4678 | 1.00M | switch (eState) |
4679 | 1.00M | { |
4680 | 261k | case State::Dot: |
4681 | 261k | if (p != pEnd && (rtl::isAsciiAlphanumeric(*p) || *p == '_')) |
4682 | 162k | { |
4683 | 162k | ++nLabels; |
4684 | 162k | eState = State::Label; |
4685 | 162k | break; |
4686 | 162k | } |
4687 | 98.8k | if (bEager || nLabels == 0) |
4688 | 98.8k | return 0; |
4689 | 0 | rBegin = p - 1; |
4690 | 0 | return nLabels; |
4691 | | |
4692 | 729k | case State::Label: |
4693 | 729k | if (p != pEnd) |
4694 | 708k | { |
4695 | 708k | if (rtl::isAsciiAlphanumeric(*p) || *p == '_') |
4696 | 554k | break; |
4697 | 153k | else if (*p == '.') |
4698 | 89.0k | { |
4699 | 89.0k | eState = State::Dot; |
4700 | 89.0k | break; |
4701 | 89.0k | } |
4702 | 64.9k | else if (*p == '-') |
4703 | 14.6k | { |
4704 | 14.6k | pLastAlphanumeric = p; |
4705 | 14.6k | eState = State::Hyphen; |
4706 | 14.6k | break; |
4707 | 14.6k | } |
4708 | 708k | } |
4709 | 71.1k | rBegin = p; |
4710 | 71.1k | return nLabels; |
4711 | | |
4712 | 19.3k | case State::Hyphen: |
4713 | 19.3k | if (p != pEnd) |
4714 | 19.1k | { |
4715 | 19.1k | if (rtl::isAsciiAlphanumeric(*p) || *p == '_') |
4716 | 12.5k | { |
4717 | 12.5k | eState = State::Label; |
4718 | 12.5k | break; |
4719 | 12.5k | } |
4720 | 6.62k | else if (*p == '-') |
4721 | 4.71k | break; |
4722 | 19.1k | } |
4723 | 2.12k | if (bEager) |
4724 | 2.12k | return 0; |
4725 | 0 | rBegin = pLastAlphanumeric; |
4726 | 0 | return nLabels; |
4727 | 1.00M | } |
4728 | 172k | } |
4729 | | |
4730 | | // static |
4731 | | bool INetURLObject::scanIPv6reference(sal_Unicode const *& rBegin, |
4732 | | sal_Unicode const * pEnd) |
4733 | 6.54k | { |
4734 | 6.54k | if (rBegin != pEnd && *rBegin == '[') { |
4735 | 5.66k | sal_Unicode const * p = rBegin + 1; |
4736 | | //TODO: check for valid IPv6address (RFC 2373): |
4737 | 62.3k | while (p != pEnd && (rtl::isAsciiHexDigit(*p) || *p == ':' || *p == '.')) |
4738 | 56.6k | { |
4739 | 56.6k | ++p; |
4740 | 56.6k | } |
4741 | 5.66k | if (p != pEnd && *p == ']') { |
4742 | 1.88k | rBegin = p + 1; |
4743 | 1.88k | return true; |
4744 | 1.88k | } |
4745 | 5.66k | } |
4746 | 4.66k | return false; |
4747 | 6.54k | } |
4748 | | |
4749 | | OUString INetURLObject::GetPartBeforeLastName() |
4750 | | const |
4751 | 742 | { |
4752 | 742 | if (!checkHierarchical()) |
4753 | 742 | return OUString(); |
4754 | 0 | INetURLObject aTemp(*this); |
4755 | 0 | aTemp.clearFragment(); |
4756 | 0 | aTemp.clearQuery(); |
4757 | 0 | aTemp.removeSegment(LAST_SEGMENT, false); |
4758 | 0 | aTemp.setFinalSlash(); |
4759 | 0 | return aTemp.GetMainURL(DecodeMechanism::ToIUri); |
4760 | 742 | } |
4761 | | |
4762 | | OUString INetURLObject::GetLastName(DecodeMechanism eMechanism, |
4763 | | rtl_TextEncoding eCharset) const |
4764 | 60 | { |
4765 | 60 | return getName(LAST_SEGMENT, true, eMechanism, eCharset); |
4766 | 60 | } |
4767 | | |
4768 | | OUString INetURLObject::GetFileExtension() const |
4769 | 891 | { |
4770 | 891 | return getExtension(LAST_SEGMENT, false); |
4771 | 891 | } |
4772 | | |
4773 | | void INetURLObject::CutLastName() |
4774 | 0 | { |
4775 | 0 | INetURLObject aTemp(*this); |
4776 | 0 | aTemp.clearFragment(); |
4777 | 0 | aTemp.clearQuery(); |
4778 | 0 | if (!aTemp.removeSegment(LAST_SEGMENT, false)) |
4779 | 0 | return; |
4780 | 0 | *this = std::move(aTemp); |
4781 | 0 | } |
4782 | | |
4783 | | OUString INetURLObject::PathToFileName() const |
4784 | 34.5k | { |
4785 | 34.5k | if (m_eScheme != INetProtocol::File) |
4786 | 0 | return OUString(); |
4787 | 34.5k | OUString aSystemPath; |
4788 | 34.5k | if (osl::FileBase::getSystemPathFromFileURL( |
4789 | 34.5k | decode(m_aAbsURIRef.getStr(), |
4790 | 34.5k | m_aAbsURIRef.getStr() + m_aPath.getEnd(), |
4791 | 34.5k | DecodeMechanism::NONE, RTL_TEXTENCODING_UTF8), |
4792 | 34.5k | aSystemPath) |
4793 | 34.5k | != osl::FileBase::E_None) |
4794 | 0 | return OUString(); |
4795 | 34.5k | return aSystemPath; |
4796 | 34.5k | } |
4797 | | |
4798 | | OUString INetURLObject::GetFull() const |
4799 | 34.5k | { |
4800 | 34.5k | INetURLObject aTemp(*this); |
4801 | 34.5k | aTemp.removeFinalSlash(); |
4802 | 34.5k | return aTemp.PathToFileName(); |
4803 | 34.5k | } |
4804 | | |
4805 | | OUString INetURLObject::GetPath() const |
4806 | 0 | { |
4807 | 0 | INetURLObject aTemp(*this); |
4808 | 0 | aTemp.removeSegment(); |
4809 | 0 | aTemp.removeFinalSlash(); |
4810 | 0 | return aTemp.PathToFileName(); |
4811 | 0 | } |
4812 | | |
4813 | | void INetURLObject::SetBase(std::u16string_view rTheBase) |
4814 | 0 | { |
4815 | 0 | setBase(rTheBase, LAST_SEGMENT, EncodeMechanism::All); |
4816 | 0 | } |
4817 | | |
4818 | | OUString INetURLObject::GetBase() const |
4819 | 11.9k | { |
4820 | 11.9k | return getBase(LAST_SEGMENT, true, DecodeMechanism::WithCharset); |
4821 | 11.9k | } |
4822 | | |
4823 | | void INetURLObject::SetExtension(std::u16string_view rTheExtension) |
4824 | 0 | { |
4825 | 0 | setExtension(rTheExtension, LAST_SEGMENT, false); |
4826 | 0 | } |
4827 | | |
4828 | | OUString INetURLObject::CutExtension() |
4829 | 0 | { |
4830 | 0 | OUString aTheExtension(getExtension(LAST_SEGMENT, false)); |
4831 | 0 | if (removeExtension(LAST_SEGMENT, false)) |
4832 | 0 | return aTheExtension; |
4833 | 0 | return OUString(); |
4834 | 0 | } |
4835 | | |
4836 | | namespace { |
4837 | | |
4838 | | // Treat the substring of rURL from nStart up to the next '/' or '?' as a |
4839 | | // percent-encoded nested url and report whether that nested url is an |
4840 | | // exotic protocol. |
4841 | | bool isExoticNestedProtocol(const OUString& rURL, sal_Int32 nStart) |
4842 | 0 | { |
4843 | 0 | auto const find = [&rURL, nStart](auto c) { |
4844 | 0 | auto const n = rURL.indexOf(c, nStart); |
4845 | 0 | return n == -1 ? rURL.getLength() : n; |
4846 | 0 | }; |
4847 | 0 | return INetURLObject( |
4848 | 0 | INetURLObject::decode(rURL.subView(nStart, std::min(find('/'), find('?')) - nStart), |
4849 | 0 | INetURLObject::DecodeMechanism::WithCharset)) |
4850 | 0 | .IsExoticProtocol(); |
4851 | 0 | } |
4852 | | |
4853 | | } |
4854 | | |
4855 | | bool INetURLObject::IsExoticProtocol() const |
4856 | 91.8k | { |
4857 | | // We take a default-deny approach, and check if the protocol is outside |
4858 | | // of the acceptable ones. |
4859 | | |
4860 | 91.8k | if (m_eScheme == INetProtocol::NotValid |
4861 | 42.1k | || m_eScheme == INetProtocol::Ftp |
4862 | 42.1k | || m_eScheme == INetProtocol::Http |
4863 | 28.9k | || m_eScheme == INetProtocol::File |
4864 | 6.79k | || m_eScheme == INetProtocol::Mailto |
4865 | 6.48k | || m_eScheme == INetProtocol::VndSunStarWebdav |
4866 | 6.48k | || m_eScheme == INetProtocol::PrivSoffice |
4867 | 6.48k | || m_eScheme == INetProtocol::VndSunStarHelp |
4868 | 6.48k | || m_eScheme == INetProtocol::Https |
4869 | 5.56k | || m_eScheme == INetProtocol::Data |
4870 | 2.44k | || m_eScheme == INetProtocol::Cid |
4871 | 2.16k | || m_eScheme == INetProtocol::VndSunStarHier |
4872 | 2.16k | || m_eScheme == INetProtocol::Component |
4873 | 2.16k | || m_eScheme == INetProtocol::Ldap |
4874 | 2.16k | || m_eScheme == INetProtocol::Db |
4875 | 2.16k | || m_eScheme == INetProtocol::VndSunStarCmd |
4876 | 2.16k | || m_eScheme == INetProtocol::Telnet |
4877 | 2.16k | || m_eScheme == INetProtocol::VndSunStarTdoc |
4878 | 2.16k | || m_eScheme == INetProtocol::Smb |
4879 | 2.16k | || m_eScheme == INetProtocol::Hid |
4880 | 1.77k | || m_eScheme == INetProtocol::Sftp |
4881 | 1.77k | || m_eScheme == INetProtocol::Cmis) |
4882 | 90.0k | return false; |
4883 | | |
4884 | 1.77k | if (m_eScheme == INetProtocol::VndSunStarPkg) |
4885 | 0 | { |
4886 | | // The package content provider (ucb/source/ucp/package/pkguri.cxx) |
4887 | | // treats the whole authority between "://" and the next '/' as the |
4888 | | // nested package url. GetHost() returns only the part after any '@', |
4889 | | // so match the provider and check that substring instead. |
4890 | 0 | OUString sPayloadURL = GetMainURL(INetURLObject::DecodeMechanism::NONE); |
4891 | 0 | sal_Int32 nStart = sPayloadURL.indexOf(u"://"); |
4892 | 0 | if (nStart == -1) { |
4893 | 0 | return false; |
4894 | 0 | } |
4895 | 0 | return isExoticNestedProtocol(sPayloadURL, nStart + 3); |
4896 | 0 | } |
4897 | | |
4898 | 1.77k | if (m_eScheme == INetProtocol::Generic) |
4899 | 1.77k | { |
4900 | | // Various things parse to INetProtocol::Generic, of which only some are known-good. |
4901 | 1.77k | if (isSchemeEqualTo(u"vnd.sun.star.zip")) |
4902 | 0 | { |
4903 | 0 | OUString sPayloadURL = GetURLPath(INetURLObject::DecodeMechanism::NONE); |
4904 | 0 | if (!sPayloadURL.startsWith(u"//")) { |
4905 | 0 | return false; |
4906 | 0 | } |
4907 | 0 | return isExoticNestedProtocol(sPayloadURL, 2); |
4908 | 0 | } |
4909 | 1.77k | else if (isSchemeEqualTo(u"vnd.sun.star.webdavs")) |
4910 | 0 | return false; |
4911 | 1.77k | else if (isSchemeEqualTo(u"webdav")) |
4912 | 0 | return false; |
4913 | 1.77k | else if (isSchemeEqualTo(u"webdavs")) |
4914 | 0 | return false; |
4915 | 1.77k | else if (isSchemeEqualTo(u"vnd.libreoffice.image")) |
4916 | 0 | return false; |
4917 | 1.77k | else if (isSchemeEqualTo(u"vnd.sun.star.extension")) |
4918 | 0 | return false; |
4919 | 1.77k | } |
4920 | | |
4921 | | // anything else is exotic |
4922 | 1.77k | SAL_INFO("tools.urlobj", "<" << m_aAbsURIRef.toString() << "> considered exotic"); |
4923 | 1.77k | return true; |
4924 | 1.77k | } |
4925 | | |
4926 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |