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