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