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