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