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