1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
45 #include <com/sun/star/uno/Sequence.hxx>
46 #include <sax/tools/converter.hxx>
47 #include <rtl/uri.hxx>
49 namespace unnamed_tools_urlobj
{} using namespace unnamed_tools_urlobj
;
50 // unnamed namespaces don't work well yet...
56 /* The URI grammar (using RFC 2234 conventions).
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).
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)
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 / "$" / "&" / "+" / "," / ":" / "=" / "@"
90 ftp-url = "FTP://" login ["/" segment *("/" segment) [";TYPE=" ("A" / "D" / "I")]]
95 http-url = "HTTP://" hostport ["/" segment *("/" segment) ["?" *uric]]
96 segment = *(pchar / ";")
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)]
102 netbios-name = 1*{<alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "^" / "_" / "{" / "}" / "~"> using (escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "-" / "." / "@" / "_" / "~")}
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 / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "@" / "_" / "~")}
114 ; private (see RFC 1738, RFC 2396)
115 vnd-sun-star-webdav-url = "VND.SUN.STAR.WEBDAV://" hostport ["/" segment *("/" segment) ["?" *uric]]
116 segment = *(pchar / ";")
120 private-url = "PRIVATE:" path ["?" *uric]
121 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
125 vnd-sun-star-help-url = "VND.SUN.STAR.HELP://" name *("/" segment) ["?" *uric]
126 name = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
127 segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
131 https-url = "HTTPS://" hostport ["/" segment *("/" segment) ["?" *uric]]
132 segment = *(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
136 slot-url = "SLOT:" path ["?" *uric]
137 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
141 macro-url = "MACRO:" path ["?" *uric]
142 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
146 javascript-url = "JAVASCRIPT:" *uric
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 / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / ":" / "?" / "@" / "_" / "~")}
159 cid-url = "CID:" {RFC 822 <addr-spec> using *uric}
163 vnd-sun-star-hier-url = "VND.SUN.STAR.HIER:" ["//"reg_name] *("/" *pchar)
164 reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
168 uno-url = ".UNO:" path ["?" *uric]
169 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
173 component-url = ".COMPONENT:" path ["?" *uric]
174 path = *(escaped / alphanum / "!" / "$" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")
178 vnd-sun-star-pkg-url = "VND.SUN.STAR.PKG://" reg_name *("/" *pchar) ["?" *uric]
179 reg_name = 1*(escaped / alphanum / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / "-" / "." / ":" / ";" / "=" / "@" / "_" / "~")
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 / "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "-" / "." / "/" / ":" / ";" / "=" / "@" / "_" / "~")}
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 / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
203 telnet-url = "TELNET://" login ["/"]
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 / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ","
213 vnd-sun-star-tdoc-url = "VND.SUN.STAR.TDOC:/" segment *("/" segment)
218 unknown-url = scheme ":" 1*uric
219 scheme = ALPHA *(alphanum / "+" / "-" / ".")
222 ; private (http://ubiqx.org/cifs/Appendix-D.html):
223 smb-url = "SMB://" login ["/" segment *("/" segment) ["?" *uric]]
224 segment = *(pchar / ";")
227 inline sal_Int32
INetURLObject::SubString::clear()
229 sal_Int32 nDelta
= -m_nLength
;
235 inline sal_Int32
INetURLObject::SubString::set(OUStringBuffer
& rString
,
236 OUString
const & rSubString
)
238 OUString
sTemp(rString
.makeStringAndClear());
239 sal_Int32 nDelta
= set(sTemp
, rSubString
);
240 rString
.append(sTemp
);
244 inline sal_Int32
INetURLObject::SubString::set(OUString
& rString
,
245 OUString
const & rSubString
)
247 sal_Int32 nDelta
= rSubString
.getLength() - m_nLength
;
249 rString
= rString
.replaceAt(m_nBegin
, m_nLength
, rSubString
);
251 m_nLength
= rSubString
.getLength();
255 inline sal_Int32
INetURLObject::SubString::set(OUStringBuffer
& rString
,
256 OUString
const & rSubString
,
259 m_nBegin
= nTheBegin
;
260 return set(rString
, rSubString
);
263 inline void INetURLObject::SubString::operator +=(sal_Int32 nDelta
)
266 m_nBegin
= m_nBegin
+ nDelta
;
269 int INetURLObject::SubString::compare(SubString
const & rOther
,
270 OUStringBuffer
const & rThisString
,
271 OUStringBuffer
const & rOtherString
) const
273 sal_Int32 len
= std::min(m_nLength
, rOther
.m_nLength
);
274 sal_Unicode
const * p1
= rThisString
.getStr() + m_nBegin
;
275 sal_Unicode
const * end
= p1
+ len
;
276 sal_Unicode
const * p2
= rOtherString
.getStr() + rOther
.m_nBegin
;
280 } else if (*p1
> *p2
) {
286 return m_nLength
< rOther
.m_nLength
? -1
287 : m_nLength
> rOther
.m_nLength
? 1
291 struct INetURLObject::SchemeInfo
293 sal_Char
const * m_pScheme
;
294 sal_Char
const * m_pPrefix
;
295 sal_uInt16 m_nDefaultPort
;
302 bool m_bHierarchical
;
306 struct INetURLObject::PrefixInfo
308 enum Kind
{ OFFICIAL
, INTERNAL
, EXTERNAL
, ALIAS
}; // order is important!
310 sal_Char
const * m_pPrefix
;
311 sal_Char
const * m_pTranslatedPrefix
;
312 INetProtocol m_eScheme
;
317 inline INetURLObject::SchemeInfo
const &
318 INetURLObject::getSchemeInfo(INetProtocol eTheScheme
)
320 static o3tl::enumarray
<INetProtocol
, SchemeInfo
> const map
= {
322 "", "", 0, false, false, false, false, false, false, false, false},
324 "ftp", "ftp://", 21, true, true, false, true, true, true, true,
327 "http", "http://", 80, true, false, false, false, true, true, true,
330 "file", "file://", 0, true, false, false, false, true, false, true,
333 "mailto", "mailto:", 0, false, false, false, false, false, false,
336 "vnd.sun.star.webdav", "vnd.sun.star.webdav://", 80, true, false,
337 false, false, true, true, true, true},
339 "private", "private:", 0, false, false, false, false, false, false,
342 "vnd.sun.star.help", "vnd.sun.star.help://", 0, true, false, false,
343 false, false, false, true, true},
345 "https", "https://", 443, true, false, false, false, true, true,
348 "slot", "slot:", 0, false, false, false, false, false, false, false,
351 "macro", "macro:", 0, false, false, false, false, false, false,
354 "javascript", "javascript:", 0, false, false, false, false, false,
355 false, false, false},
357 "data", "data:", 0, false, false, false, false, false, false, false,
360 "cid", "cid:", 0, false, false, false, false, false, false, false,
363 "vnd.sun.star.hier", "vnd.sun.star.hier:", 0, true, false, false,
364 false, false, false, true, false},
366 ".uno", ".uno:", 0, false, false, false, false, false, false, false,
369 ".component", ".component:", 0, false, false, false, false, false,
372 "vnd.sun.star.pkg", "vnd.sun.star.pkg://", 0, true, false, false,
373 false, false, false, true, true},
375 "ldap", "ldap://", 389, true, false, false, false, true, true,
378 "db", "db:", 0, false, false, false, false, false, false, false,
381 "vnd.sun.star.cmd", "vnd.sun.star.cmd:", 0, false, false, false,
382 false, false, false, false, false},
384 "telnet", "telnet://", 23, true, true, false, true, true, true,
387 "vnd.sun.star.expand", "vnd.sun.star.expand:", 0, false, false,
388 false, false, false, false, false, false},
390 "vnd.sun.star.tdoc", "vnd.sun.star.tdoc:", 0, false, false, false,
391 false, false, false, true, false},
393 "", "", 0, false, false, false, false, true, true, true, false },
395 "smb", "smb://", 139, true, true, false, true, true, true, true,
398 "hid", "hid:", 0, false, false, false, false, false, false, false,
401 "sftp", "sftp://", 22, true, true, false, true, true, true, true,
404 "vnd.libreoffice.cmis", "vnd.libreoffice.cmis://", 0, true, true,
405 false, false, true, false, true, true} };
406 return map
[eTheScheme
];
409 inline INetURLObject::SchemeInfo
const & INetURLObject::getSchemeInfo() const
411 return getSchemeInfo(m_eScheme
);
415 inline void INetURLObject::appendEscape(OUStringBuffer
& rTheText
,
418 rTheText
.append( '%' );
419 rTheText
.append( (sal_Unicode
)INetMIME::getHexDigit(int(nOctet
>> 4)) );
420 rTheText
.append( (sal_Unicode
)INetMIME::getHexDigit(int(nOctet
& 15)) );
423 namespace unnamed_tools_urlobj
{
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
,
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,
449 /* ! */ PA
+PD
+PE
+PF
+PG
+PH
+PI
+PJ
+PK
+PL
+PM
+PN
+PO
+PP
+PQ
+PR
,
452 /* $ */ PA
+PD
+PE
+PF
+PG
+PH
+PI
+PJ
+PK
+PL
+PM
+PN
+PO
+PP
+PQ
+PR
,
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
,
509 /* ] */ PG
+PM
+PN
+PO
,
511 /* _ */ PA
+PD
+PE
+PF
+PG
+PH
+PI
+PJ
+PK
+PL
+PM
+PN
+PO
+PP
+PQ
+PR
,
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
,
542 /* ~ */ PA
+PD
+PE
+PF
+PG
+PH
+PI
+PJ
+PK
+PL
+PM
+PN
+PO
+PP
+PQ
,
545 inline bool mustEncode(sal_uInt32 nUTF32
, INetURLObject::Part ePart
)
547 return !rtl::isAscii(nUTF32
) || !(aMustEncodeMap
[nUTF32
] & ePart
);
552 void INetURLObject::setInvalid()
554 m_aAbsURIRef
.setLength(0);
555 m_eScheme
= INetProtocol::NotValid
;
568 std::unique_ptr
<SvMemoryStream
> memoryStream(
569 void const * data
, sal_Int32 length
)
571 std::unique_ptr
<char, boost::checked_array_deleter
<char> > b(
573 memcpy(b
.get(), data
, length
);
574 std::unique_ptr
<SvMemoryStream
> s(
575 new SvMemoryStream(b
.get(), length
, StreamMode::READ
));
576 s
->ObjectOwnsMemory(true);
583 std::unique_ptr
<SvMemoryStream
> INetURLObject::getData()
585 if( GetProtocol() != INetProtocol::Data
)
590 OUString sURLPath
= GetURLPath( DECODE_WITH_CHARSET
, RTL_TEXTENCODING_ISO_8859_1
);
591 sal_Unicode
const * pSkippedMediatype
= INetMIME::scanContentType( sURLPath
.getStr(), sURLPath
.getStr() + sURLPath
.getLength(), NULL
, NULL
, NULL
);
592 sal_Int32 nCharactersSkipped
= pSkippedMediatype
== NULL
593 ? 0 : pSkippedMediatype
-sURLPath
.getStr();
594 if (sURLPath
.match(",", nCharactersSkipped
))
596 nCharactersSkipped
+= strlen(",");
597 OString
sURLEncodedData(
598 sURLPath
.getStr() + nCharactersSkipped
,
599 sURLPath
.getLength() - nCharactersSkipped
,
600 RTL_TEXTENCODING_ISO_8859_1
, OUSTRING_TO_OSTRING_CVTFLAGS
);
602 sURLEncodedData
.getStr(), sURLEncodedData
.getLength());
604 else if (sURLPath
.matchIgnoreAsciiCase(";base64,", nCharactersSkipped
))
606 nCharactersSkipped
+= strlen(";base64,");
607 OUString sBase64Data
= sURLPath
.copy( nCharactersSkipped
);
608 css::uno::Sequence
< sal_Int8
> aDecodedData
;
609 if (sax::Converter::decodeBase64SomeChars(aDecodedData
, sBase64Data
)
610 == sBase64Data
.getLength())
613 aDecodedData
.getArray(), aDecodedData
.getLength());
619 namespace unnamed_tools_urlobj
{
621 INetURLObject::FSysStyle
guessFSysStyleByCounting(sal_Unicode
const * pBegin
,
622 sal_Unicode
const * pEnd
,
623 INetURLObject::FSysStyle 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 = eStyle
& INetURLObject::FSYS_UNX
?
634 0 : std::numeric_limits
< sal_Int32
>::min();
635 sal_Int32 nBackslashCount
636 = eStyle
& INetURLObject::FSYS_DOS
?
637 0 : std::numeric_limits
< sal_Int32
>::min();
638 while (pBegin
!= pEnd
)
649 return nSlashCount
>= nBackslashCount
?
650 INetURLObject::FSYS_UNX
: INetURLObject::FSYS_DOS
;
653 OUString
parseScheme(
654 sal_Unicode
const ** begin
, sal_Unicode
const * end
,
655 sal_uInt32 fragmentDelimiter
)
657 sal_Unicode
const * p
= *begin
;
658 if (p
!= end
&& rtl::isAsciiAlpha(*p
)) {
662 && (rtl::isAsciiAlphanumeric(*p
) || *p
== '+' || *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 if (end
- p
> 1 && p
[0] == ':' && p
[1] != fragmentDelimiter
670 OUString(*begin
, p
- *begin
).toAsciiLowerCase());
680 bool INetURLObject::setAbsURIRef(OUString
const & rTheAbsURIRef
,
682 EncodeMechanism eMechanism
,
683 rtl_TextEncoding eCharset
,
687 sal_Unicode
const * pPos
= rTheAbsURIRef
.getStr();
688 sal_Unicode
const * pEnd
= pPos
+ rTheAbsURIRef
.getLength();
692 sal_uInt32 nFragmentDelimiter
= '#';
694 OUStringBuffer aSynAbsURIRef
;
697 sal_Unicode
const * p
= pPos
;
698 PrefixInfo
const * pPrefix
= getPrefix(p
, pEnd
);
702 m_eScheme
= pPrefix
->m_eScheme
;
704 OUString
sTemp(OUString::createFromAscii(pPrefix
->m_eKind
705 >= PrefixInfo::EXTERNAL
?
706 pPrefix
->m_pTranslatedPrefix
:
707 pPrefix
->m_pPrefix
));
708 aSynAbsURIRef
.append(sTemp
);
709 m_aScheme
= SubString( 0, sTemp
.indexOf(':') );
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
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)
729 // UCS4 = <any UCS4 character>
731 // 1st Production (known scheme):
732 // <one of the known schemes, ignoring case> ":" *UCS4
733 // 2nd Production (mailto):
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):
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]
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.
755 sal_Unicode
const * p1
= pPos
;
756 if (eStyle
& FSYS_DOS
758 && rtl::isAsciiAlpha(p1
[0])
760 && (pEnd
- p1
== 2 || p1
[2] == '/' || p1
[2] == '\\'))
762 m_eScheme
= INetProtocol::File
; // 8th, 9th
763 eMechanism
= ENCODE_ALL
;
764 nFragmentDelimiter
= 0x80000000;
766 else if (pEnd
- p1
>= 2 && p1
[0] == '/' && p1
[1] == '/')
769 if ((scanDomain(p1
, pEnd
) > 0 || scanIPv6reference(p1
, pEnd
))
770 && (p1
== pEnd
|| *p1
== '/'))
771 m_eScheme
= INetProtocol::File
; // 5th
773 else if (p1
!= pEnd
&& *p1
== '/')
775 m_eScheme
= INetProtocol::File
; // 6th
776 eMechanism
= ENCODE_ALL
;
777 nFragmentDelimiter
= 0x80000000;
779 else if (eStyle
& FSYS_DOS
785 sal_Int32 n
= rtl_ustr_indexOfChar_WithLength(
786 p1
, pEnd
- p1
, '\\');
787 sal_Unicode
const * pe
= n
== -1 ? pEnd
: p1
+ n
;
789 parseHostOrNetBiosName(
790 p1
, pe
, bOctets
, ENCODE_ALL
, RTL_TEXTENCODING_DONTKNOW
,
792 (scanDomain(p1
, pe
) > 0 && p1
== pe
)
795 m_eScheme
= INetProtocol::File
; // 7th
796 eMechanism
= ENCODE_ALL
;
797 nFragmentDelimiter
= 0x80000000;
802 sal_Unicode
const * pDomainEnd
= p1
;
803 sal_uInt32 nLabels
= scanDomain(pDomainEnd
, pEnd
);
804 if (nLabels
> 0 && pDomainEnd
!= pEnd
&& *pDomainEnd
== '@')
807 if (scanDomain(pDomainEnd
, pEnd
) > 0
808 && pDomainEnd
== pEnd
)
809 m_eScheme
= INetProtocol::Mailto
; // 2nd
811 else if (nLabels
>= 3
812 && (pDomainEnd
== pEnd
|| *pDomainEnd
== '/'))
814 = pDomainEnd
- p1
>= 4
815 && (p1
[0] == 'f' || p1
[0] == 'F')
816 && (p1
[1] == 't' || p1
[1] == 'T')
817 && (p1
[2] == 'p' || p1
[2] == 'P')
819 INetProtocol::Ftp
: INetProtocol::Http
; // 3rd, 4th
824 if (m_eScheme
== INetProtocol::NotValid
) {
825 sal_Unicode
const * p1
= pPos
;
826 aSynScheme
= parseScheme(&p1
, pEnd
, nFragmentDelimiter
);
827 if (!aSynScheme
.isEmpty())
829 m_eScheme
= INetProtocol::Generic
;
834 if (bSmart
&& m_eScheme
== INetProtocol::NotValid
&& pPos
!= pEnd
835 && *pPos
!= nFragmentDelimiter
)
837 m_eScheme
= m_eSmartScheme
;
840 if (m_eScheme
== INetProtocol::NotValid
)
846 if (m_eScheme
!= INetProtocol::Generic
) {
847 aSynScheme
= OUString::createFromAscii(getSchemeInfo().m_pScheme
);
849 m_aScheme
.set(aSynAbsURIRef
, aSynScheme
, aSynAbsURIRef
.getLength());
850 aSynAbsURIRef
.append(':');
853 sal_uInt32 nSegmentDelimiter
= '/';
854 sal_uInt32 nAltSegmentDelimiter
= 0x80000000;
855 bool bSkippedInitialSlash
= false;
857 // Parse //<user>;AUTH=<auth>@<host>:<port> or
858 // //<user>:<password>@<host>:<port> or
860 if (getSchemeInfo().m_bAuthority
)
862 sal_Unicode
const * pUserInfoBegin
= 0;
863 sal_Unicode
const * pUserInfoEnd
= 0;
864 sal_Unicode
const * pHostPortBegin
= 0;
865 sal_Unicode
const * pHostPortEnd
= 0;
869 case INetProtocol::VndSunStarHelp
:
871 if (pEnd
- pPos
< 2 || *pPos
++ != '/' || *pPos
++ != '/')
876 aSynAbsURIRef
.append("//");
877 OUStringBuffer aSynAuthority
;
879 && *pPos
!= '/' && *pPos
!= '?'
880 && *pPos
!= nFragmentDelimiter
)
882 EscapeType eEscapeType
;
883 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
885 eCharset
, eEscapeType
);
886 appendUCS4(aSynAuthority
, nUTF32
, eEscapeType
, bOctets
,
887 PART_AUTHORITY
, eCharset
, false);
889 m_aHost
.set(aSynAbsURIRef
,
890 aSynAuthority
.makeStringAndClear(),
891 aSynAbsURIRef
.getLength());
892 // misusing m_aHost to store the authority
896 case INetProtocol::VndSunStarHier
:
898 if (pEnd
- pPos
>= 2 && pPos
[0] == '/' && pPos
[1] == '/')
901 aSynAbsURIRef
.append("//");
902 OUStringBuffer aSynAuthority
;
904 && *pPos
!= '/' && *pPos
!= '?'
905 && *pPos
!= nFragmentDelimiter
)
907 EscapeType eEscapeType
;
908 sal_uInt32 nUTF32
= getUTF32(pPos
,
914 appendUCS4(aSynAuthority
,
922 if (aSynAuthority
.isEmpty())
927 m_aHost
.set(aSynAbsURIRef
,
928 aSynAuthority
.makeStringAndClear(),
929 aSynAbsURIRef
.getLength());
930 // misusing m_aHost to store the authority
935 case INetProtocol::VndSunStarPkg
:
936 case INetProtocol::Cmis
:
938 if (pEnd
- pPos
< 2 || *pPos
++ != '/' || *pPos
++ != '/')
943 aSynAbsURIRef
.append("//");
944 OUStringBuffer aSynUser
;
946 bool bHasUser
= false;
947 while (pPos
< pEnd
&& *pPos
!= '@'
948 && *pPos
!= '/' && *pPos
!= '?'
949 && *pPos
!= nFragmentDelimiter
)
951 EscapeType eEscapeType
;
952 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
954 eCharset
, eEscapeType
);
955 appendUCS4(aSynUser
, nUTF32
, eEscapeType
, bOctets
,
956 PART_USER_PASSWORD
, eCharset
, false);
958 bHasUser
= *pPos
== '@';
961 OUStringBuffer aSynAuthority
;
964 aSynAuthority
= aSynUser
;
968 m_aUser
.set(aSynAbsURIRef
,
969 aSynUser
.makeStringAndClear(),
970 aSynAbsURIRef
.getLength());
971 aSynAbsURIRef
.append("@");
975 && *pPos
!= '/' && *pPos
!= '?'
976 && *pPos
!= nFragmentDelimiter
)
978 EscapeType eEscapeType
;
979 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
981 eCharset
, eEscapeType
);
982 appendUCS4(aSynAuthority
, nUTF32
, eEscapeType
, bOctets
,
983 PART_AUTHORITY
, eCharset
, false);
986 if (aSynAuthority
.isEmpty())
991 m_aHost
.set(aSynAbsURIRef
,
992 aSynAuthority
.makeStringAndClear(),
993 aSynAbsURIRef
.getLength());
994 // misusing m_aHost to store the authority
998 case INetProtocol::File
:
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
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)
1016 // path = <any UCS4 character except "#">
1017 // UCS4 = <any UCS4 character>
1019 // 1st Production (URL):
1020 // "//" [domain / IPv6reference] ["/" *path]
1023 // "file://" domain "/" *path ["#" *UCS4]
1024 if (pEnd
- pPos
>= 2 && pPos
[0] == '/' && pPos
[1] == '/')
1026 sal_Unicode
const * p1
= pPos
+ 2;
1027 while (p1
!= pEnd
&& *p1
!= '/' &&
1028 *p1
!= nFragmentDelimiter
)
1032 if (parseHostOrNetBiosName(
1033 pPos
+ 2, p1
, bOctets
, ENCODE_ALL
,
1034 RTL_TEXTENCODING_DONTKNOW
, true, NULL
))
1036 aSynAbsURIRef
.append("//");
1037 pHostPortBegin
= pPos
+ 2;
1044 // 2nd Production (MS IE generated 1; FSYS_DOS only):
1045 // "//" ALPHA ":" ["/" *path] ["#" *UCS4]
1047 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
1048 // replacing "\" by "/" within <*path>
1049 // 3rd Production (MS IE generated 2; FSYS_DOS only):
1050 // "//" ALPHA ":" ["\" *path] ["#" *UCS4]
1052 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
1053 // replacing "\" by "/" within <*path>
1054 // 4th Production (misscounted slashes):
1055 // "//" *path ["#" *UCS4]
1057 // "file:///" *path ["#" *UCS4]
1058 if (pEnd
- pPos
>= 2 && pPos
[0] == '/' && pPos
[1] == '/')
1060 aSynAbsURIRef
.append("//");
1062 bSkippedInitialSlash
= true;
1063 if ((eStyle
& FSYS_DOS
) != 0
1065 && rtl::isAsciiAlpha(pPos
[0])
1067 && (pEnd
- pPos
== 2
1068 || pPos
[2] == '/' || pPos
[2] == '\\'))
1069 nAltSegmentDelimiter
= '\\';
1073 // 5th Production (Unix):
1074 // "/" *path ["#" *UCS4]
1076 // "file:///" *path ["#" *UCS4]
1077 if (pPos
< pEnd
&& *pPos
== '/')
1079 aSynAbsURIRef
.append("//");
1083 // 6th Production (UNC; FSYS_DOS only):
1084 // "\\" domain ["\" *path] ["#" *UCS4]
1086 // "file://" domain "/" *path ["#" *UCS4]
1087 // replacing "\" by "/" within <*path>
1088 if (eStyle
& FSYS_DOS
1093 sal_Unicode
const * p1
= pPos
+ 2;
1094 sal_Unicode
const * pe
= p1
;
1095 while (pe
< pEnd
&& *pe
!= '\\' &&
1096 *pe
!= nFragmentDelimiter
)
1101 parseHostOrNetBiosName(
1102 p1
, pe
, bOctets
, ENCODE_ALL
,
1103 RTL_TEXTENCODING_DONTKNOW
, true, NULL
) ||
1104 (scanDomain(p1
, pe
) > 0 && p1
== pe
)
1107 aSynAbsURIRef
.append("//");
1108 pHostPortBegin
= pPos
+ 2;
1111 nSegmentDelimiter
= '\\';
1116 // 7th Production (Unix-like DOS; FSYS_DOS only):
1117 // ALPHA ":" ["/" *path] ["#" *UCS4]
1119 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
1120 // replacing "\" by "/" within <*path>
1121 // 8th Production (DOS; FSYS_DOS only):
1122 // ALPHA ":" ["\" *path] ["#" *UCS4]
1124 // "file:///" ALPHA ":" ["/" *path] ["#" *UCS4]
1125 // replacing "\" by "/" within <*path>
1126 if (eStyle
& FSYS_DOS
1128 && rtl::isAsciiAlpha(pPos
[0])
1130 && (pEnd
- pPos
== 2
1132 || pPos
[2] == '\\'))
1134 aSynAbsURIRef
.append("//");
1135 nAltSegmentDelimiter
= '\\';
1136 bSkippedInitialSlash
= true;
1140 // 9th Production (any):
1141 // *path ["#" *UCS4]
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 if (eStyle
& (FSYS_UNX
| FSYS_DOS
))
1156 aSynAbsURIRef
.appendAscii("//");
1157 switch (guessFSysStyleByCounting(pPos
, pEnd
, eStyle
))
1160 nSegmentDelimiter
= '/';
1164 nSegmentDelimiter
= '\\';
1169 "INetURLObject::setAbsURIRef():"
1170 " Bad guessFSysStyleByCounting");
1173 bSkippedInitialSlash
1174 = pPos
!= pEnd
&& *pPos
!= nSegmentDelimiter
;
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
1184 if (pEnd
- pPos
>= 2 && pPos
[0] == '/' && pPos
[1] == '/')
1187 && !(m_eScheme
== INetProtocol::File
1188 && pPos
!= pEnd
&& *pPos
== '/'))
1193 aSynAbsURIRef
.append("//");
1195 sal_Unicode
const * pAuthority
= pPos
;
1196 sal_uInt32 c
= getSchemeInfo().m_bQuery
? '?' : 0x80000000;
1197 while (pPos
< pEnd
&& *pPos
!= '/' && *pPos
!= c
1198 && *pPos
!= nFragmentDelimiter
)
1200 if (getSchemeInfo().m_bUser
)
1201 if (getSchemeInfo().m_bHost
)
1203 sal_Unicode
const * p1
= pAuthority
;
1204 while (p1
< pPos
&& *p1
!= '@')
1208 pHostPortBegin
= pAuthority
;
1209 pHostPortEnd
= pPos
;
1213 pUserInfoBegin
= pAuthority
;
1215 pHostPortBegin
= p1
+ 1;
1216 pHostPortEnd
= pPos
;
1221 pUserInfoBegin
= pAuthority
;
1222 pUserInfoEnd
= pPos
;
1224 else if (getSchemeInfo().m_bHost
)
1226 pHostPortBegin
= pAuthority
;
1227 pHostPortEnd
= pPos
;
1229 else if (pPos
!= pAuthority
)
1240 Part ePart
= PART_USER_PASSWORD
;
1241 bool bSupportsPassword
= getSchemeInfo().m_bPassword
;
1243 = !bSupportsPassword
&& getSchemeInfo().m_bAuth
;
1244 bool bHasAuth
= false;
1245 OUStringBuffer aSynUser
;
1246 sal_Unicode
const * p1
= pUserInfoBegin
;
1247 while (p1
< pUserInfoEnd
)
1249 EscapeType eEscapeType
;
1250 sal_uInt32 nUTF32
= getUTF32(p1
, pUserInfoEnd
, bOctets
,
1251 eMechanism
, eCharset
, eEscapeType
);
1252 if (eEscapeType
== ESCAPE_NO
)
1254 if (nUTF32
== ':' && bSupportsPassword
)
1259 else if (nUTF32
== ';' && bSupportsAuth
1260 && pUserInfoEnd
- p1
1261 > RTL_CONSTASCII_LENGTH("auth=")
1262 && INetMIME::equalIgnoreCase(
1264 p1
+ RTL_CONSTASCII_LENGTH("auth="),
1267 p1
+= RTL_CONSTASCII_LENGTH("auth=");
1272 appendUCS4(aSynUser
, nUTF32
, eEscapeType
, bOctets
, ePart
,
1275 m_aUser
.set(aSynAbsURIRef
, aSynUser
.makeStringAndClear(),
1276 aSynAbsURIRef
.getLength());
1279 if (bSupportsPassword
)
1281 aSynAbsURIRef
.append(':');
1282 OUStringBuffer aSynAuth
;
1283 while (p1
< pUserInfoEnd
)
1285 EscapeType eEscapeType
;
1286 sal_uInt32 nUTF32
= getUTF32(p1
, pUserInfoEnd
, bOctets
,
1287 eMechanism
, eCharset
,
1289 appendUCS4(aSynAuth
, nUTF32
, eEscapeType
, bOctets
,
1290 ePart
, eCharset
, false);
1292 m_aAuth
.set(aSynAbsURIRef
, aSynAuth
.makeStringAndClear(),
1293 aSynAbsURIRef
.getLength());
1297 aSynAbsURIRef
.append(";AUTH=");
1298 OUStringBuffer aSynAuth
;
1299 while (p1
< pUserInfoEnd
)
1301 EscapeType eEscapeType
;
1302 sal_uInt32 nUTF32
= getUTF32(p1
, pUserInfoEnd
, bOctets
,
1303 eMechanism
, eCharset
,
1305 if (!INetMIME::isIMAPAtomChar(nUTF32
))
1310 appendUCS4(aSynAuth
, nUTF32
, eEscapeType
, bOctets
,
1311 ePart
, eCharset
, false);
1313 m_aAuth
.set(aSynAbsURIRef
, aSynAuth
.makeStringAndClear(),
1314 aSynAbsURIRef
.getLength());
1318 aSynAbsURIRef
.append('@');
1323 sal_Unicode
const * pPort
= pHostPortEnd
;
1324 if ( getSchemeInfo().m_bPort
&& pHostPortBegin
< pHostPortEnd
)
1326 sal_Unicode
const * p1
= pHostPortEnd
- 1;
1327 while (p1
> pHostPortBegin
&& rtl::isAsciiDigit(*p1
))
1332 bool bNetBiosName
= false;
1335 case INetProtocol::File
:
1336 // If the host equals "LOCALHOST" (unencoded and ignoring
1337 // case), turn it into an empty host:
1338 if (INetMIME::equalIgnoreCase(pHostPortBegin
, pPort
,
1340 pHostPortBegin
= pPort
;
1341 bNetBiosName
= true;
1344 case INetProtocol::Ldap
:
1345 case INetProtocol::Smb
:
1346 if (pHostPortBegin
== pPort
&& pPort
!= pHostPortEnd
)
1353 if (pHostPortBegin
== pPort
)
1360 OUStringBuffer aSynHost
;
1361 if (!parseHostOrNetBiosName(
1362 pHostPortBegin
, pPort
, bOctets
, eMechanism
, eCharset
,
1363 bNetBiosName
, &aSynHost
))
1368 m_aHost
.set(aSynAbsURIRef
, aSynHost
.makeStringAndClear(),
1369 aSynAbsURIRef
.getLength());
1370 if (pPort
!= pHostPortEnd
)
1372 aSynAbsURIRef
.append(':');
1373 m_aPort
.set(aSynAbsURIRef
,
1374 OUString(pPort
+ 1, pHostPortEnd
- (pPort
+ 1)),
1375 aSynAbsURIRef
.getLength());
1381 OUStringBuffer aSynPath
;
1382 if (!parsePath(m_eScheme
, &pPos
, pEnd
, bOctets
, eMechanism
, eCharset
,
1383 bSkippedInitialSlash
, nSegmentDelimiter
,
1384 nAltSegmentDelimiter
,
1385 getSchemeInfo().m_bQuery
? '?' : 0x80000000,
1386 nFragmentDelimiter
, aSynPath
))
1391 m_aPath
.set(aSynAbsURIRef
, aSynPath
.makeStringAndClear(),
1392 aSynAbsURIRef
.getLength());
1395 if (getSchemeInfo().m_bQuery
&& pPos
< pEnd
&& *pPos
== '?')
1397 aSynAbsURIRef
.append('?');
1398 OUStringBuffer aSynQuery
;
1399 for (++pPos
; pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
;)
1401 EscapeType eEscapeType
;
1402 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
1403 eMechanism
, eCharset
, eEscapeType
);
1404 appendUCS4(aSynQuery
, nUTF32
, eEscapeType
, bOctets
,
1405 PART_URIC
, eCharset
, true);
1407 m_aQuery
.set(aSynAbsURIRef
, aSynQuery
.makeStringAndClear(),
1408 aSynAbsURIRef
.getLength());
1411 // Parse #<fragment>
1412 if (pPos
< pEnd
&& *pPos
== nFragmentDelimiter
)
1414 aSynAbsURIRef
.append(sal_Unicode(nFragmentDelimiter
));
1415 OUStringBuffer aSynFragment
;
1416 for (++pPos
; pPos
< pEnd
;)
1418 EscapeType eEscapeType
;
1419 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
1420 eMechanism
, eCharset
, eEscapeType
);
1421 appendUCS4(aSynFragment
, nUTF32
, eEscapeType
, bOctets
, PART_URIC
,
1424 m_aFragment
.set(aSynAbsURIRef
, aSynFragment
.makeStringAndClear(),
1425 aSynAbsURIRef
.getLength());
1434 m_aAbsURIRef
= aSynAbsURIRef
;
1436 // At this point references of type "\\server\paths" have
1437 // been converted to file:://server/path".
1439 if (m_eScheme
==INetProtocol::File
&& !m_aHost
.isEmpty()) {
1440 // Change "file:://server/path" URIs to "smb:://server/path" on
1442 // Leave "file::path" URIs unchanged.
1443 changeScheme(INetProtocol::Smb
);
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
1452 changeScheme(INetProtocol::File
);
1459 void INetURLObject::changeScheme(INetProtocol eTargetScheme
) {
1460 OUString aTmpStr
=m_aAbsURIRef
.makeStringAndClear();
1461 int oldSchemeLen
=strlen(getSchemeInfo().m_pScheme
);
1462 m_eScheme
=eTargetScheme
;
1463 int newSchemeLen
=strlen(getSchemeInfo().m_pScheme
);
1464 m_aAbsURIRef
.appendAscii(getSchemeInfo().m_pScheme
);
1465 m_aAbsURIRef
.append(aTmpStr
.getStr()+oldSchemeLen
);
1466 int delta
=newSchemeLen
-oldSchemeLen
;
1476 bool INetURLObject::convertRelToAbs(OUString
const & rTheRelURIRef
,
1478 INetURLObject
& rTheAbsURIRef
,
1479 bool & rWasAbsolute
,
1480 EncodeMechanism eMechanism
,
1481 rtl_TextEncoding eCharset
,
1482 bool bIgnoreFragment
, bool bSmart
,
1483 bool bRelativeNonURIs
, FSysStyle eStyle
)
1486 sal_Unicode
const * p
= rTheRelURIRef
.getStr();
1487 sal_Unicode
const * pEnd
= p
+ rTheRelURIRef
.getLength();
1489 sal_Unicode
const * pPrefixBegin
= p
;
1490 PrefixInfo
const * pPrefix
= getPrefix(pPrefixBegin
, pEnd
);
1491 bool hasScheme
= pPrefix
!= 0;
1494 hasScheme
= !parseScheme(&pPrefixBegin
, pEnd
, '#').isEmpty();
1497 sal_uInt32 nSegmentDelimiter
= '/';
1498 sal_uInt32 nQueryDelimiter
1499 = !bSmart
|| getSchemeInfo().m_bQuery
? '?' : 0x80000000;
1500 sal_uInt32 nFragmentDelimiter
= '#';
1501 Part ePart
= PART_VISIBLE
;
1503 if (!hasScheme
&& bSmart
)
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
1513 // domain = label *("." label)
1514 // label = alphanum [*(alphanum / "-") alphanum]
1515 // alphanum = ALPHA / DIGIT
1516 // UCS4 = <any UCS4 character>
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 if (eStyle
& FSYS_DOS
)
1527 sal_Unicode
const * q
= p
;
1529 && rtl::isAsciiAlpha(q
[0])
1531 && (pEnd
- q
== 2 || q
[2] == '/' || q
[2] == '\\'))
1532 bFSys
= true; // 2nd, 3rd
1533 else if (pEnd
- q
>= 2 && q
[0] == '\\' && q
[1] == '\\')
1536 sal_Int32 n
= rtl_ustr_indexOfChar_WithLength(
1538 sal_Unicode
const * qe
= n
== -1 ? pEnd
: q
+ n
;
1539 if (parseHostOrNetBiosName(
1540 q
, qe
, bOctets
, ENCODE_ALL
, RTL_TEXTENCODING_DONTKNOW
,
1543 bFSys
= true; // 1st
1548 INetURLObject aNewURI
;
1549 aNewURI
.setAbsURIRef(rTheRelURIRef
, bOctets
, eMechanism
,
1550 eCharset
, true, eStyle
);
1551 if (!aNewURI
.HasError())
1553 rTheAbsURIRef
= aNewURI
;
1554 rWasAbsolute
= true;
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 if (m_eScheme
== INetProtocol::File
)
1564 switch (guessFSysStyleByCounting(p
, pEnd
, eStyle
))
1567 nSegmentDelimiter
= '/';
1571 nSegmentDelimiter
= '\\';
1572 bRelativeNonURIs
= true;
1576 OSL_FAIL("INetURLObject::convertRelToAbs():"
1577 " Bad guessFSysStyleByCounting");
1581 if (bRelativeNonURIs
)
1583 eMechanism
= ENCODE_ALL
;
1584 nQueryDelimiter
= 0x80000000;
1585 nFragmentDelimiter
= 0x80000000;
1586 ePart
= PART_VISIBLE_NONSPECIAL
;
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
1594 if (pPrefix
&& pPrefix
->m_eScheme
== m_eScheme
1595 && getSchemeInfo().m_bHierarchical
)
1598 while (p
!= pEnd
&& *p
++ != ':') ;
1600 rWasAbsolute
= hasScheme
;
1602 // Fast solution for non-relative URIs:
1605 INetURLObject
aNewURI(rTheRelURIRef
, eMechanism
, eCharset
);
1606 if (aNewURI
.HasError())
1608 rWasAbsolute
= false;
1612 if (bIgnoreFragment
)
1613 aNewURI
.clearFragment();
1614 rTheAbsURIRef
= aNewURI
;
1618 enum State
{ STATE_AUTH
, STATE_ABS_PATH
, STATE_REL_PATH
, STATE_FRAGMENT
,
1621 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 if (m_eScheme
!= INetProtocol::Generic
)
1626 aSynAbsURIRef
.appendAscii(getSchemeInfo().m_pScheme
);
1630 sal_Unicode
const * pSchemeBegin
1631 = m_aAbsURIRef
.getStr();
1632 sal_Unicode
const * pSchemeEnd
= pSchemeBegin
;
1633 while (pSchemeEnd
[0] != ':')
1637 aSynAbsURIRef
.append(pSchemeBegin
, pSchemeEnd
- pSchemeBegin
);
1639 aSynAbsURIRef
.append(':');
1641 State eState
= STATE_AUTH
;
1642 bool bSameDoc
= true;
1644 if (getSchemeInfo().m_bAuthority
)
1646 if (pEnd
- p
>= 2 && p
[0] == '/' && p
[1] == '/')
1648 aSynAbsURIRef
.append("//");
1650 eState
= STATE_ABS_PATH
;
1654 EscapeType eEscapeType
;
1656 = getUTF32(p
, pEnd
, bOctets
, eMechanism
,
1657 eCharset
, eEscapeType
);
1658 if (eEscapeType
== ESCAPE_NO
)
1660 if (nUTF32
== nSegmentDelimiter
)
1662 else if (nUTF32
== nFragmentDelimiter
)
1664 eState
= STATE_FRAGMENT
;
1668 appendUCS4(aSynAbsURIRef
, nUTF32
, eEscapeType
, bOctets
,
1669 PART_VISIBLE
, eCharset
, true);
1674 SubString
aAuthority(getAuthority());
1675 aSynAbsURIRef
.append(m_aAbsURIRef
.getStr()
1676 + aAuthority
.getBegin(),
1677 aAuthority
.getLength());
1681 if (eState
== STATE_AUTH
)
1684 eState
= STATE_DONE
;
1685 else if (*p
== nFragmentDelimiter
)
1688 eState
= STATE_FRAGMENT
;
1690 else if (*p
== nSegmentDelimiter
)
1693 eState
= STATE_ABS_PATH
;
1698 eState
= STATE_REL_PATH
;
1703 if (eState
== STATE_ABS_PATH
)
1705 aSynAbsURIRef
.append('/');
1706 eState
= STATE_DONE
;
1709 EscapeType eEscapeType
;
1711 = getUTF32(p
, pEnd
, bOctets
, eMechanism
, eCharset
, eEscapeType
);
1712 if (eEscapeType
== ESCAPE_NO
)
1714 if (nUTF32
== nFragmentDelimiter
)
1716 eState
= STATE_FRAGMENT
;
1719 else if (nUTF32
== nSegmentDelimiter
)
1722 appendUCS4(aSynAbsURIRef
, nUTF32
, eEscapeType
, bOctets
, ePart
,
1726 else if (eState
== STATE_REL_PATH
)
1728 if (!getSchemeInfo().m_bHierarchical
)
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
1734 HasError(), "tools.urlobj",
1735 "cannot make <" << rTheRelURIRef
1736 << "> absolute against broken base <"
1737 << GetMainURL(NO_DECODE
) << ">");
1738 rWasAbsolute
= false;
1742 sal_Unicode
const * pBasePathBegin
1743 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
1744 sal_Unicode
const * pBasePathEnd
1745 = pBasePathBegin
+ m_aPath
.getLength();
1746 while (pBasePathEnd
!= pBasePathBegin
)
1747 if (*(--pBasePathEnd
) == '/')
1753 sal_Int32 nPathBegin
= aSynAbsURIRef
.getLength();
1754 aSynAbsURIRef
.append(pBasePathBegin
, pBasePathEnd
- pBasePathBegin
);
1755 DBG_ASSERT(aSynAbsURIRef
.getLength() > nPathBegin
1756 && aSynAbsURIRef
[aSynAbsURIRef
.getLength() - 1] == '/',
1757 "INetURLObject::convertRelToAbs(): Bad base path");
1759 while (p
!= pEnd
&& *p
!= nQueryDelimiter
&& *p
!= nFragmentDelimiter
)
1764 || p
[1] == nSegmentDelimiter
1765 || p
[1] == nQueryDelimiter
1766 || p
[1] == nFragmentDelimiter
)
1769 if (p
!= pEnd
&& *p
== nSegmentDelimiter
)
1773 else if (pEnd
- p
>= 2
1776 || p
[2] == nSegmentDelimiter
1777 || p
[2] == nQueryDelimiter
1778 || p
[2] == nFragmentDelimiter
)
1779 && aSynAbsURIRef
.getLength() - nPathBegin
> 1)
1782 if (p
!= pEnd
&& *p
== nSegmentDelimiter
)
1785 sal_Int32 i
= aSynAbsURIRef
.getLength() - 2;
1786 while (i
> nPathBegin
&& aSynAbsURIRef
[i
] != '/')
1788 aSynAbsURIRef
.setLength(i
+ 1);
1790 aSynAbsURIRef
.getLength() > nPathBegin
1791 && aSynAbsURIRef
[aSynAbsURIRef
.getLength() - 1] == '/',
1792 "INetURLObject::convertRelToAbs(): Bad base path");
1798 && *p
!= nSegmentDelimiter
1799 && *p
!= nQueryDelimiter
1800 && *p
!= nFragmentDelimiter
)
1802 EscapeType eEscapeType
;
1804 = getUTF32(p
, pEnd
, bOctets
, eMechanism
,
1805 eCharset
, eEscapeType
);
1806 appendUCS4(aSynAbsURIRef
, nUTF32
, eEscapeType
, bOctets
, ePart
,
1809 if (p
!= pEnd
&& *p
== nSegmentDelimiter
)
1811 aSynAbsURIRef
.append('/');
1816 while (p
!= pEnd
&& *p
!= nFragmentDelimiter
)
1818 EscapeType eEscapeType
;
1820 = getUTF32(p
, pEnd
, bOctets
, eMechanism
, eCharset
, eEscapeType
);
1821 appendUCS4(aSynAbsURIRef
, nUTF32
, eEscapeType
, bOctets
, ePart
,
1826 eState
= STATE_DONE
;
1830 eState
= STATE_FRAGMENT
;
1835 aSynAbsURIRef
.append(m_aAbsURIRef
.getStr() + m_aPath
.getBegin(),
1836 m_aPath
.getLength());
1837 if (m_aQuery
.isPresent())
1838 aSynAbsURIRef
.append(m_aAbsURIRef
.getStr()
1839 + m_aQuery
.getBegin() - 1,
1840 m_aQuery
.getLength() + 1);
1843 if (eState
== STATE_FRAGMENT
&& !bIgnoreFragment
)
1845 aSynAbsURIRef
.append('#');
1848 EscapeType eEscapeType
;
1850 = getUTF32(p
, pEnd
, bOctets
, eMechanism
, eCharset
, eEscapeType
);
1851 appendUCS4(aSynAbsURIRef
, nUTF32
, eEscapeType
, bOctets
,
1852 PART_VISIBLE
, eCharset
, true);
1856 INetURLObject
aNewURI(aSynAbsURIRef
.makeStringAndClear());
1857 if (aNewURI
.HasError())
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
1863 HasError(), "tools.urlobj",
1864 "cannot make <" << rTheRelURIRef
1865 << "> absolute against broken base <" << GetMainURL(NO_DECODE
)
1867 rWasAbsolute
= false;
1871 rTheAbsURIRef
= aNewURI
;
1875 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
1882 // Check for hierarchical base URL:
1883 if (!getSchemeInfo().m_bHierarchical
)
1885 rTheRelURIRef
= decode(rTheAbsURIRef
, eDecodeMechanism
, eCharset
);
1889 // Convert the input (absolute or relative URI ref) to an absolute URI
1891 INetURLObject aSubject
;
1893 if (!convertRelToAbs(rTheAbsURIRef
, bOctets
, aSubject
, bWasAbsolute
,
1894 eEncodeMechanism
, eCharset
, false, false, false,
1897 rTheRelURIRef
= decode(rTheAbsURIRef
, eDecodeMechanism
, eCharset
);
1901 // Check for differing scheme or authority parts:
1902 if ((m_aScheme
.compare(
1903 aSubject
.m_aScheme
, m_aAbsURIRef
, aSubject
.m_aAbsURIRef
)
1905 || (m_aUser
.compare(
1906 aSubject
.m_aUser
, m_aAbsURIRef
, aSubject
.m_aAbsURIRef
)
1908 || (m_aAuth
.compare(
1909 aSubject
.m_aAuth
, m_aAbsURIRef
, aSubject
.m_aAbsURIRef
)
1911 || (m_aHost
.compare(
1912 aSubject
.m_aHost
, m_aAbsURIRef
, aSubject
.m_aAbsURIRef
)
1914 || (m_aPort
.compare(
1915 aSubject
.m_aPort
, m_aAbsURIRef
, aSubject
.m_aAbsURIRef
)
1918 rTheRelURIRef
= aSubject
.GetMainURL(eDecodeMechanism
, eCharset
);
1922 sal_Unicode
const * pBasePathBegin
1923 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
1924 sal_Unicode
const * pBasePathEnd
= pBasePathBegin
+ m_aPath
.getLength();
1925 sal_Unicode
const * pSubjectPathBegin
1926 = aSubject
.m_aAbsURIRef
.getStr() + aSubject
.m_aPath
.getBegin();
1927 sal_Unicode
const * pSubjectPathEnd
1928 = pSubjectPathBegin
+ aSubject
.m_aPath
.getLength();
1930 // Make nMatch point past the last matching slash, or past the end of the
1931 // paths, in case they are equal:
1932 sal_Unicode
const * pSlash
= 0;
1933 sal_Unicode
const * p1
= pBasePathBegin
;
1934 sal_Unicode
const * p2
= pSubjectPathBegin
;
1937 if (p1
== pBasePathEnd
|| p2
== pSubjectPathEnd
)
1939 if (p1
== pBasePathEnd
&& p2
== pSubjectPathEnd
)
1944 sal_Unicode c
= *p1
++;
1952 // One of the paths does not start with '/':
1953 rTheRelURIRef
= aSubject
.GetMainURL(eDecodeMechanism
, eCharset
);
1956 sal_Int32 nMatch
= pSlash
- pBasePathBegin
;
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 if (m_eScheme
== INetProtocol::File
1963 && hasDosVolume(eStyle
)
1964 && aSubject
.hasDosVolume(eStyle
)) //TODO! ok to use eStyle for these?
1966 rTheRelURIRef
= aSubject
.GetMainURL(eDecodeMechanism
, eCharset
);
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
1975 OUStringBuffer aSynRelURIRef
;
1976 for (sal_Unicode
const * p
= pBasePathBegin
+ nMatch
; p
!= pBasePathEnd
;
1980 aSynRelURIRef
.append("../");
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 if (aSynRelURIRef
.isEmpty())
1990 if (pSubjectPathEnd
- pSubjectPathBegin
>= nMatch
+ 2
1991 && pSubjectPathBegin
[nMatch
] == '/'
1992 && pSubjectPathBegin
[nMatch
+ 1] == '/')
1994 aSynRelURIRef
.append("./");
1998 for (sal_Unicode
const * p
= pSubjectPathBegin
+ nMatch
;
1999 p
!= pSubjectPathEnd
&& *p
!= '/'; ++p
)
2001 if (mustEncode(*p
, PART_REL_SEGMENT_EXTRA
))
2003 aSynRelURIRef
.append("./");
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 eDecodeMechanism
, eCharset
));
2015 // If the subject has defined query or fragment parts, they are appended
2016 // to the new relative URL:
2017 if (aSubject
.m_aQuery
.isPresent())
2019 aSynRelURIRef
.append('?');
2020 aSynRelURIRef
.append(aSubject
.decode(aSubject
.m_aQuery
,
2021 eDecodeMechanism
, eCharset
));
2023 if (aSubject
.m_aFragment
.isPresent())
2025 aSynRelURIRef
.append('#');
2026 aSynRelURIRef
.append(aSubject
.decode(aSubject
.m_aFragment
,
2027 eDecodeMechanism
, eCharset
));
2030 rTheRelURIRef
= aSynRelURIRef
.makeStringAndClear();
2035 bool INetURLObject::convertIntToExt(OUString
const & rTheIntURIRef
,
2036 bool bOctets
, OUString
& rTheExtURIRef
,
2037 DecodeMechanism eDecodeMechanism
,
2038 rtl_TextEncoding eCharset
)
2040 OUString
aSynExtURIRef(encodeText(rTheIntURIRef
, bOctets
, PART_VISIBLE
,
2041 NOT_CANONIC
, eCharset
, true));
2042 sal_Unicode
const * pBegin
= aSynExtURIRef
.getStr();
2043 sal_Unicode
const * pEnd
= pBegin
+ aSynExtURIRef
.getLength();
2044 sal_Unicode
const * p
= pBegin
;
2045 PrefixInfo
const * pPrefix
= getPrefix(p
, pEnd
);
2046 bool bConvert
= pPrefix
&& pPrefix
->m_eKind
== PrefixInfo::INTERNAL
;
2050 aSynExtURIRef
.replaceAt(0, p
- pBegin
,
2051 OUString::createFromAscii(pPrefix
->m_pTranslatedPrefix
));
2053 rTheExtURIRef
= decode(aSynExtURIRef
, eDecodeMechanism
, eCharset
);
2058 bool INetURLObject::convertExtToInt(OUString
const & rTheExtURIRef
,
2059 bool bOctets
, OUString
& rTheIntURIRef
,
2060 DecodeMechanism eDecodeMechanism
,
2061 rtl_TextEncoding eCharset
)
2063 OUString
aSynIntURIRef(encodeText(rTheExtURIRef
, bOctets
, PART_VISIBLE
,
2064 NOT_CANONIC
, eCharset
, true));
2065 sal_Unicode
const * pBegin
= aSynIntURIRef
.getStr();
2066 sal_Unicode
const * pEnd
= pBegin
+ aSynIntURIRef
.getLength();
2067 sal_Unicode
const * p
= pBegin
;
2068 PrefixInfo
const * pPrefix
= getPrefix(p
, pEnd
);
2069 bool bConvert
= pPrefix
&& pPrefix
->m_eKind
== PrefixInfo::EXTERNAL
;
2073 aSynIntURIRef
.replaceAt(0, p
- pBegin
,
2074 OUString::createFromAscii(pPrefix
->m_pTranslatedPrefix
));
2076 rTheIntURIRef
= decode(aSynIntURIRef
, eDecodeMechanism
, eCharset
);
2081 INetURLObject::PrefixInfo
const * INetURLObject::getPrefix(sal_Unicode
const *& rBegin
,
2082 sal_Unicode
const * pEnd
)
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 */
2164 PrefixInfo
const * pFirst
= aMap
+ 1;
2165 PrefixInfo
const * pLast
= aMap
+ sizeof aMap
/ sizeof (PrefixInfo
) - 1;
2166 PrefixInfo
const * pMatch
= 0;
2167 sal_Unicode
const * pMatched
= rBegin
;
2168 sal_Unicode
const * p
= rBegin
;
2170 for (; pFirst
< pLast
; ++i
)
2172 if (pFirst
->m_pPrefix
[i
] == '\0')
2179 sal_uInt32 nChar
= rtl::toAsciiLowerCase(*p
++);
2180 while (pFirst
<= pLast
&& static_cast<unsigned char>(pFirst
->m_pPrefix
[i
]) < nChar
)
2182 while (pFirst
<= pLast
&& static_cast<unsigned char>(pLast
->m_pPrefix
[i
]) > nChar
)
2185 if (pFirst
== pLast
)
2187 sal_Char
const * q
= pFirst
->m_pPrefix
+ i
;
2188 while (p
< pEnd
&& *q
!= '\0'
2189 && rtl::toAsciiLowerCase(*p
) == static_cast<unsigned char>(*q
))
2204 sal_Int32
INetURLObject::getAuthorityBegin() const
2206 DBG_ASSERT(getSchemeInfo().m_bAuthority
,
2207 "INetURLObject::getAuthority(): Bad scheme");
2209 if (m_aUser
.isPresent())
2210 nBegin
= m_aUser
.getBegin();
2211 else if (m_aHost
.isPresent())
2212 nBegin
= m_aHost
.getBegin();
2214 nBegin
= m_aPath
.getBegin();
2215 nBegin
-= RTL_CONSTASCII_LENGTH("//");
2216 DBG_ASSERT(m_aAbsURIRef
[nBegin
] == '/' && m_aAbsURIRef
[nBegin
+ 1] == '/',
2217 "INetURLObject::getAuthority(): Bad authority");
2221 INetURLObject::SubString
INetURLObject::getAuthority() const
2223 sal_Int32 nBegin
= getAuthorityBegin();
2224 sal_Int32 nEnd
= m_aPort
.isPresent() ? m_aPort
.getEnd() :
2225 m_aHost
.isPresent() ? m_aHost
.getEnd() :
2226 m_aAuth
.isPresent() ? m_aAuth
.getEnd() :
2227 m_aUser
.isPresent() ? m_aUser
.getEnd() :
2228 nBegin
+ RTL_CONSTASCII_LENGTH("//");
2229 return SubString(nBegin
, nEnd
- nBegin
);
2232 bool INetURLObject::setUser(OUString
const & rTheUser
,
2233 bool bOctets
, EncodeMechanism eMechanism
,
2234 rtl_TextEncoding eCharset
)
2237 !getSchemeInfo().m_bUser
2243 OUString
aNewUser(encodeText(rTheUser
, bOctets
, PART_USER_PASSWORD
,
2244 eMechanism
, eCharset
, false));
2246 if (m_aUser
.isPresent())
2247 nDelta
= m_aUser
.set(m_aAbsURIRef
, aNewUser
);
2248 else if (m_aHost
.isPresent())
2250 m_aAbsURIRef
.insert(m_aHost
.getBegin(), sal_Unicode('@'));
2251 nDelta
= m_aUser
.set(m_aAbsURIRef
, aNewUser
, m_aHost
.getBegin()) + 1;
2253 else if (getSchemeInfo().m_bHost
)
2256 nDelta
= m_aUser
.set(m_aAbsURIRef
, aNewUser
, m_aPath
.getBegin());
2262 m_aFragment
+= nDelta
;
2268 void lcl_Erase(OUStringBuffer
&rBuf
, sal_Int32 index
, sal_Int32 count
)
2270 OUString
sTemp(rBuf
.makeStringAndClear());
2271 rBuf
.append(sTemp
.replaceAt(index
, count
, OUString()));
2275 bool INetURLObject::clearPassword()
2277 if (!getSchemeInfo().m_bPassword
)
2279 if (m_aAuth
.isPresent())
2281 lcl_Erase(m_aAbsURIRef
, m_aAuth
.getBegin() - 1,
2282 m_aAuth
.getLength() + 1);
2283 sal_Int32 nDelta
= m_aAuth
.clear() - 1;
2288 m_aFragment
+= nDelta
;
2293 bool INetURLObject::setPassword(OUString
const & rThePassword
,
2294 bool bOctets
, EncodeMechanism eMechanism
,
2295 rtl_TextEncoding eCharset
)
2297 if (!getSchemeInfo().m_bPassword
)
2299 OUString
aNewAuth(encodeText(rThePassword
, bOctets
, PART_USER_PASSWORD
,
2300 eMechanism
, eCharset
, false));
2302 if (m_aAuth
.isPresent())
2303 nDelta
= m_aAuth
.set(m_aAbsURIRef
, aNewAuth
);
2304 else if (m_aUser
.isPresent())
2306 m_aAbsURIRef
.insert(m_aUser
.getEnd(), sal_Unicode(':'));
2308 = m_aAuth
.set(m_aAbsURIRef
, aNewAuth
, m_aUser
.getEnd() + 1) + 1;
2310 else if (m_aHost
.isPresent())
2312 m_aAbsURIRef
.insert(m_aHost
.getBegin(),
2314 m_aUser
.set(m_aAbsURIRef
, OUString(), m_aHost
.getBegin());
2316 = m_aAuth
.set(m_aAbsURIRef
, aNewAuth
, m_aHost
.getBegin() + 1) + 2;
2318 else if (getSchemeInfo().m_bHost
)
2322 m_aAbsURIRef
.insert(m_aPath
.getBegin(), sal_Unicode(':'));
2323 m_aUser
.set(m_aAbsURIRef
, OUString(), m_aPath
.getBegin());
2325 = m_aAuth
.set(m_aAbsURIRef
, aNewAuth
, m_aPath
.getBegin() + 1) + 1;
2331 m_aFragment
+= nDelta
;
2336 bool INetURLObject::parseHost(sal_Unicode
const *& rBegin
, sal_Unicode
const * pEnd
,
2337 OUString
& rCanonic
)
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 OUStringBuffer aTheCanonic
;
2352 sal_uInt32 nNumber
= 0;
2355 State eState
= STATE_INITIAL
;
2356 sal_Unicode
const * p
= rBegin
;
2357 for (; p
!= pEnd
; ++p
)
2363 aTheCanonic
.append('[');
2366 else if (rtl::isAsciiAlpha(*p
) || *p
== '_')
2367 eState
= STATE_TOPLABEL
;
2368 else if (rtl::isAsciiDigit(*p
))
2370 nNumber
= INetMIME::getWeight(*p
);
2381 eState
= STATE_LABEL_DOT
;
2383 eState
= STATE_LABEL_HYPHEN
;
2384 else if (!rtl::isAsciiAlphanumeric(*p
) && *p
!= '_')
2388 case STATE_LABEL_HYPHEN
:
2389 if (rtl::isAsciiAlphanumeric(*p
) || *p
== '_')
2390 eState
= STATE_LABEL
;
2395 case STATE_LABEL_DOT
:
2396 if (rtl::isAsciiAlpha(*p
) || *p
== '_')
2397 eState
= STATE_TOPLABEL
;
2398 else if (rtl::isAsciiDigit(*p
))
2399 eState
= STATE_LABEL
;
2404 case STATE_TOPLABEL
:
2406 eState
= STATE_TOPLABEL_DOT
;
2408 eState
= STATE_TOPLABEL_HYPHEN
;
2409 else if (!rtl::isAsciiAlphanumeric(*p
) && *p
!= '_')
2413 case STATE_TOPLABEL_HYPHEN
:
2414 if (rtl::isAsciiAlphanumeric(*p
) || *p
== '_')
2415 eState
= STATE_TOPLABEL
;
2420 case STATE_TOPLABEL_DOT
:
2421 if (rtl::isAsciiAlpha(*p
) || *p
== '_')
2422 eState
= STATE_TOPLABEL
;
2423 else if (rtl::isAsciiDigit(*p
))
2424 eState
= STATE_LABEL
;
2433 aTheCanonic
.append( OUString::number(nNumber
) );
2434 aTheCanonic
.append( '.' );
2436 eState
= STATE_IP4_DOT
;
2439 eState
= STATE_LABEL_DOT
;
2441 eState
= STATE_LABEL_HYPHEN
;
2442 else if (rtl::isAsciiAlpha(*p
) || *p
== '_')
2443 eState
= STATE_LABEL
;
2444 else if (rtl::isAsciiDigit(*p
))
2447 nNumber
= 10 * nNumber
+ INetMIME::getWeight(*p
);
2451 eState
= STATE_LABEL
;
2457 if (rtl::isAsciiAlpha(*p
) || *p
== '_')
2458 eState
= STATE_TOPLABEL
;
2459 else if (rtl::isAsciiDigit(*p
))
2461 nNumber
= INetMIME::getWeight(*p
);
2471 eState
= STATE_IP6_COLON
;
2472 else if (rtl::isAsciiHexDigit(*p
))
2474 nNumber
= INetMIME::getHexWeight(*p
);
2476 eState
= STATE_IP6_HEXSEQ1
;
2482 case STATE_IP6_COLON
:
2485 aTheCanonic
.append("::");
2486 eState
= STATE_IP6_2COLON
;
2492 case STATE_IP6_2COLON
:
2494 eState
= STATE_IP6_DONE
;
2497 aTheCanonic
.append(':');
2498 eState
= STATE_IP6_3COLON
;
2500 else if (rtl::isAsciiDigit(*p
))
2502 nNumber
= INetMIME::getWeight(*p
);
2504 eState
= STATE_IP6_HEXSEQ2_MAYBE_IP4
;
2506 else if (rtl::isAsciiHexDigit(*p
))
2508 nNumber
= INetMIME::getHexWeight(*p
);
2510 eState
= STATE_IP6_HEXSEQ2
;
2516 case STATE_IP6_3COLON
:
2517 if (rtl::isAsciiDigit(*p
))
2519 nNumber
= INetMIME::getWeight(*p
);
2522 eState
= STATE_IP6_IP4
;
2528 case STATE_IP6_HEXSEQ1
:
2532 OUString::number(nNumber
, 16));
2533 eState
= STATE_IP6_DONE
;
2538 OUString::number(nNumber
, 16));
2539 aTheCanonic
.append(':');
2540 eState
= STATE_IP6_HEXSEQ1_COLON
;
2542 else if (rtl::isAsciiHexDigit(*p
) && nDigits
< 4)
2544 nNumber
= 16 * nNumber
+ INetMIME::getHexWeight(*p
);
2551 case STATE_IP6_HEXSEQ1_COLON
:
2554 aTheCanonic
.append(':');
2555 eState
= STATE_IP6_2COLON
;
2557 else if (rtl::isAsciiDigit(*p
))
2559 nNumber
= INetMIME::getWeight(*p
);
2561 eState
= STATE_IP6_HEXSEQ1_MAYBE_IP4
;
2563 else if (rtl::isAsciiHexDigit(*p
))
2565 nNumber
= INetMIME::getHexWeight(*p
);
2567 eState
= STATE_IP6_HEXSEQ1
;
2573 case STATE_IP6_HEXSEQ1_MAYBE_IP4
:
2577 OUString::number(nNumber
, 16));
2578 eState
= STATE_IP6_DONE
;
2583 OUString::number(nNumber
, 16));
2584 aTheCanonic
.append(':');
2585 eState
= STATE_IP6_HEXSEQ1_COLON
;
2589 nNumber
= 100 * (nNumber
>> 8) + 10 * (nNumber
>> 4 & 15)
2592 OUString::number(nNumber
));
2593 aTheCanonic
.append('.');
2595 eState
= STATE_IP6_IP4_DOT
;
2597 else if (rtl::isAsciiDigit(*p
) && nDigits
< 3)
2599 nNumber
= 16 * nNumber
+ INetMIME::getWeight(*p
);
2602 else if (rtl::isAsciiHexDigit(*p
) && nDigits
< 4)
2604 nNumber
= 16 * nNumber
+ INetMIME::getHexWeight(*p
);
2606 eState
= STATE_IP6_HEXSEQ1
;
2612 case STATE_IP6_HEXSEQ2
:
2616 OUString::number(nNumber
, 16));
2617 eState
= STATE_IP6_DONE
;
2622 OUString::number(nNumber
, 16));
2623 aTheCanonic
.append(':');
2624 eState
= STATE_IP6_HEXSEQ2_COLON
;
2626 else if (rtl::isAsciiHexDigit(*p
) && nDigits
< 4)
2628 nNumber
= 16 * nNumber
+ INetMIME::getHexWeight(*p
);
2635 case STATE_IP6_HEXSEQ2_COLON
:
2636 if (rtl::isAsciiDigit(*p
))
2638 nNumber
= INetMIME::getWeight(*p
);
2640 eState
= STATE_IP6_HEXSEQ2_MAYBE_IP4
;
2642 else if (rtl::isAsciiHexDigit(*p
))
2644 nNumber
= INetMIME::getHexWeight(*p
);
2646 eState
= STATE_IP6_HEXSEQ2
;
2652 case STATE_IP6_HEXSEQ2_MAYBE_IP4
:
2656 OUString::number(nNumber
, 16));
2657 eState
= STATE_IP6_DONE
;
2662 OUString::number(nNumber
, 16));
2663 aTheCanonic
.append(':');
2664 eState
= STATE_IP6_HEXSEQ2_COLON
;
2668 nNumber
= 100 * (nNumber
>> 8) + 10 * (nNumber
>> 4 & 15)
2671 OUString::number(nNumber
));
2672 aTheCanonic
.append('.');
2674 eState
= STATE_IP6_IP4_DOT
;
2676 else if (rtl::isAsciiDigit(*p
) && nDigits
< 3)
2678 nNumber
= 16 * nNumber
+ INetMIME::getWeight(*p
);
2681 else if (rtl::isAsciiHexDigit(*p
) && nDigits
< 4)
2683 nNumber
= 16 * nNumber
+ INetMIME::getHexWeight(*p
);
2685 eState
= STATE_IP6_HEXSEQ2
;
2696 OUString::number(nNumber
));
2697 eState
= STATE_IP6_DONE
;
2705 OUString::number(nNumber
));
2706 aTheCanonic
.append('.');
2708 eState
= STATE_IP6_IP4_DOT
;
2712 else if (rtl::isAsciiDigit(*p
) && nDigits
< 3)
2714 nNumber
= 10 * nNumber
+ INetMIME::getWeight(*p
);
2721 case STATE_IP6_IP4_DOT
:
2722 if (rtl::isAsciiDigit(*p
))
2724 nNumber
= INetMIME::getWeight(*p
);
2726 eState
= STATE_IP6_IP4
;
2732 case STATE_IP6_DONE
:
2739 case STATE_TOPLABEL
:
2740 case STATE_TOPLABEL_DOT
:
2741 aTheCanonic
.setLength(0);
2742 aTheCanonic
.append(rBegin
, p
- rBegin
);
2744 rCanonic
= aTheCanonic
.makeStringAndClear();
2751 OUString::number(nNumber
));
2753 rCanonic
= aTheCanonic
.makeStringAndClear();
2758 case STATE_IP6_DONE
:
2759 aTheCanonic
.append(']');
2761 rCanonic
= aTheCanonic
.makeStringAndClear();
2770 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
)
2775 OUString aTheCanonic
;
2778 sal_Unicode
const * p
= pBegin
;
2779 if (!parseHost(p
, pEnd
, aTheCanonic
) || p
!= pEnd
)
2784 while (pBegin
< pEnd
)
2786 EscapeType eEscapeType
;
2787 sal_uInt32 nUTF32
= getUTF32(pBegin
, pEnd
, bOctets
,
2788 eMechanism
, eCharset
,
2790 if (!INetMIME::isVisible(nUTF32
))
2792 if (!rtl::isAsciiAlphanumeric(nUTF32
))
2813 if (pCanonic
!= NULL
) {
2815 buf
, nUTF32
, eEscapeType
, bOctets
, PART_URIC
,
2819 aTheCanonic
= buf
.makeStringAndClear();
2825 if (pCanonic
!= NULL
) {
2826 *pCanonic
= aTheCanonic
;
2831 bool INetURLObject::setHost(OUString
const & rTheHost
, bool bOctets
,
2832 EncodeMechanism eMechanism
,
2833 rtl_TextEncoding eCharset
)
2835 if (!getSchemeInfo().m_bHost
)
2837 OUStringBuffer
aSynHost(rTheHost
);
2838 bool bNetBiosName
= false;
2841 case INetProtocol::File
:
2843 OUString
sTemp(aSynHost
.toString());
2844 if (sTemp
.equalsIgnoreAsciiCase("localhost"))
2846 aSynHost
.setLength(0);
2848 bNetBiosName
= true;
2851 case INetProtocol::Ldap
:
2852 if (aSynHost
.isEmpty() && m_aPort
.isPresent())
2857 if (aSynHost
.isEmpty())
2861 if (!parseHostOrNetBiosName(
2862 aSynHost
.getStr(), aSynHost
.getStr() + aSynHost
.getLength(),
2863 bOctets
, eMechanism
, eCharset
, bNetBiosName
, &aSynHost
))
2865 sal_Int32 nDelta
= m_aHost
.set(m_aAbsURIRef
, aSynHost
.makeStringAndClear());
2869 m_aFragment
+= nDelta
;
2874 bool INetURLObject::parsePath(INetProtocol eScheme
,
2875 sal_Unicode
const ** pBegin
,
2876 sal_Unicode
const * pEnd
,
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
)
2887 DBG_ASSERT(pBegin
, "INetURLObject::parsePath(): Null output param");
2889 sal_Unicode
const * pPos
= *pBegin
;
2890 OUStringBuffer aTheSynPath
;
2894 case INetProtocol::NotValid
:
2897 case INetProtocol::Ftp
:
2898 if (pPos
< pEnd
&& *pPos
!= '/' && *pPos
!= nFragmentDelimiter
)
2900 while (pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
)
2902 EscapeType eEscapeType
;
2903 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
2904 eCharset
, eEscapeType
);
2905 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
2906 PART_HTTP_PATH
, eCharset
, true);
2908 if (aTheSynPath
.isEmpty())
2909 aTheSynPath
.append('/');
2912 case INetProtocol::Http
:
2913 case INetProtocol::VndSunStarWebdav
:
2914 case INetProtocol::Https
:
2915 case INetProtocol::Smb
:
2916 case INetProtocol::Cmis
:
2917 if (pPos
< pEnd
&& *pPos
!= '/' && *pPos
!= nFragmentDelimiter
)
2919 while (pPos
< pEnd
&& *pPos
!= nQueryDelimiter
2920 && *pPos
!= nFragmentDelimiter
)
2922 EscapeType eEscapeType
;
2923 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
2924 eCharset
, eEscapeType
);
2925 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
2926 PART_HTTP_PATH
, eCharset
, true);
2928 if (aTheSynPath
.isEmpty())
2929 aTheSynPath
.append('/');
2932 case INetProtocol::File
:
2934 if (bSkippedInitialSlash
)
2935 aTheSynPath
.append('/');
2936 else if (pPos
< pEnd
2937 && *pPos
!= nSegmentDelimiter
2938 && *pPos
!= nAltSegmentDelimiter
)
2940 while (pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
)
2942 EscapeType eEscapeType
;
2943 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
2944 eCharset
, eEscapeType
);
2945 if (eEscapeType
== ESCAPE_NO
)
2947 if (nUTF32
== nSegmentDelimiter
2948 || nUTF32
== nAltSegmentDelimiter
)
2950 aTheSynPath
.append('/');
2953 else if (nUTF32
== '|'
2955 || *pPos
== nFragmentDelimiter
2956 || *pPos
== nSegmentDelimiter
2957 || *pPos
== nAltSegmentDelimiter
)
2958 && aTheSynPath
.getLength() == 2
2959 && rtl::isAsciiAlpha(aTheSynPath
[1]))
2961 // A first segment of <ALPHA "|"> is translated to
2963 aTheSynPath
.append(':');
2967 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
2968 PART_PCHAR
, eCharset
, true);
2970 if (aTheSynPath
.isEmpty())
2971 aTheSynPath
.append('/');
2975 case INetProtocol::Mailto
:
2976 while (pPos
< pEnd
&& *pPos
!= nQueryDelimiter
2977 && *pPos
!= nFragmentDelimiter
)
2979 EscapeType eEscapeType
;
2980 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
2981 eCharset
, eEscapeType
);
2982 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
2983 PART_MAILTO
, eCharset
, true);
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 while (pPos
< pEnd
&& *pPos
!= nQueryDelimiter
2996 && *pPos
!= nFragmentDelimiter
)
2998 EscapeType eEscapeType
;
2999 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3000 eCharset
, eEscapeType
);
3001 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3002 PART_PATH_BEFORE_QUERY
, eCharset
, true);
3006 case INetProtocol::VndSunStarHelp
:
3008 || *pPos
== nQueryDelimiter
3009 || *pPos
== nFragmentDelimiter
)
3010 aTheSynPath
.append('/');
3015 while (pPos
< pEnd
&& *pPos
!= nQueryDelimiter
3016 && *pPos
!= nFragmentDelimiter
)
3018 EscapeType eEscapeType
;
3019 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
,
3021 eCharset
, eEscapeType
);
3022 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3023 PART_HTTP_PATH
, eCharset
, true);
3028 case INetProtocol::Javascript
:
3029 case INetProtocol::Data
:
3030 case INetProtocol::Cid
:
3031 case INetProtocol::Db
:
3032 while (pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
)
3034 EscapeType eEscapeType
;
3035 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3036 eCharset
, eEscapeType
);
3037 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3038 PART_URIC
, eCharset
, true);
3042 case INetProtocol::VndSunStarHier
:
3043 case INetProtocol::VndSunStarPkg
:
3044 if (pPos
< pEnd
&& *pPos
!= '/'
3045 && *pPos
!= nQueryDelimiter
&& *pPos
!= nFragmentDelimiter
)
3047 while (pPos
< pEnd
&& *pPos
!= nQueryDelimiter
3048 && *pPos
!= nFragmentDelimiter
)
3050 EscapeType eEscapeType
;
3051 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3052 eCharset
, eEscapeType
);
3053 if (eEscapeType
== ESCAPE_NO
&& nUTF32
== '/')
3054 aTheSynPath
.append('/');
3056 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3057 PART_PCHAR
, eCharset
, false);
3059 if (aTheSynPath
.isEmpty())
3060 aTheSynPath
.append('/');
3063 case INetProtocol::VndSunStarCmd
:
3064 case INetProtocol::VndSunStarExpand
:
3066 if (pPos
== pEnd
|| *pPos
== nFragmentDelimiter
)
3068 Part ePart
= PART_URIC_NO_SLASH
;
3069 while (pPos
!= pEnd
&& *pPos
!= nFragmentDelimiter
)
3071 EscapeType eEscapeType
;
3072 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3073 eCharset
, eEscapeType
);
3074 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
, ePart
,
3081 case INetProtocol::Telnet
:
3084 if (*pPos
!= '/' || pEnd
- pPos
> 1)
3088 aTheSynPath
.append('/');
3091 case INetProtocol::VndSunStarTdoc
:
3092 if (pPos
== pEnd
|| *pPos
!= '/')
3094 while (pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
)
3096 EscapeType eEscapeType
;
3097 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3098 eCharset
, eEscapeType
);
3099 if (eEscapeType
== ESCAPE_NO
&& nUTF32
== '/')
3100 aTheSynPath
.append('/');
3102 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3103 PART_PCHAR
, eCharset
, false);
3107 case INetProtocol::Generic
:
3108 case INetProtocol::Sftp
:
3109 while (pPos
< pEnd
&& *pPos
!= nFragmentDelimiter
)
3111 EscapeType eEscapeType
;
3112 sal_uInt32 nUTF32
= getUTF32(pPos
, pEnd
, bOctets
, eMechanism
,
3113 eCharset
, eEscapeType
);
3114 appendUCS4(aTheSynPath
, nUTF32
, eEscapeType
, bOctets
,
3115 PART_URIC
, eCharset
, true);
3117 if (aTheSynPath
.isEmpty())
3126 rSynPath
= aTheSynPath
;
3130 bool INetURLObject::setPath(OUString
const & rThePath
, bool bOctets
,
3131 EncodeMechanism eMechanism
,
3132 rtl_TextEncoding eCharset
)
3134 OUStringBuffer aSynPath
;
3135 sal_Unicode
const * p
= rThePath
.getStr();
3136 sal_Unicode
const * pEnd
= p
+ rThePath
.getLength();
3137 if (!parsePath(m_eScheme
, &p
, pEnd
, bOctets
, eMechanism
, eCharset
, false,
3138 '/', 0x80000000, 0x80000000, 0x80000000, aSynPath
)
3141 sal_Int32 nDelta
= m_aPath
.set(m_aAbsURIRef
, aSynPath
.makeStringAndClear());
3143 m_aFragment
+= nDelta
;
3147 bool INetURLObject::checkHierarchical() const {
3148 if (m_eScheme
== INetProtocol::VndSunStarExpand
) {
3150 "INetURLObject::checkHierarchical vnd.sun.star.expand");
3153 return getSchemeInfo().m_bHierarchical
;
3157 bool INetURLObject::appendSegment(OUString
const & rTheSegment
,
3158 bool bOctets
, EncodeMechanism eMechanism
,
3159 rtl_TextEncoding eCharset
)
3161 return insertName(rTheSegment
, bOctets
, false, LAST_SEGMENT
, true,
3162 eMechanism
, eCharset
);
3165 INetURLObject::SubString
INetURLObject::getSegment(sal_Int32 nIndex
,
3166 bool bIgnoreFinalSlash
)
3169 DBG_ASSERT(nIndex
>= 0 || nIndex
== LAST_SEGMENT
,
3170 "INetURLObject::getSegment(): Bad index");
3172 if (!checkHierarchical())
3175 sal_Unicode
const * pPathBegin
3176 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
3177 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
3178 sal_Unicode
const * pSegBegin
;
3179 sal_Unicode
const * pSegEnd
;
3180 if (nIndex
== LAST_SEGMENT
)
3183 if (bIgnoreFinalSlash
&& pSegEnd
> pPathBegin
&& pSegEnd
[-1] == '/')
3185 if (pSegEnd
<= pPathBegin
)
3187 pSegBegin
= pSegEnd
- 1;
3188 while (pSegBegin
> pPathBegin
&& *pSegBegin
!= '/')
3193 pSegBegin
= pPathBegin
;
3194 while (nIndex
-- > 0)
3198 if (pSegBegin
>= pPathEnd
)
3201 while (*pSegBegin
!= '/');
3202 pSegEnd
= pSegBegin
+ 1;
3203 while (pSegEnd
< pPathEnd
&& *pSegEnd
!= '/')
3207 return SubString(pSegBegin
- m_aAbsURIRef
.getStr(),
3208 pSegEnd
- pSegBegin
);
3211 bool INetURLObject::insertName(OUString
const & rTheName
, bool bOctets
,
3212 bool bAppendFinalSlash
, sal_Int32 nIndex
,
3213 bool bIgnoreFinalSlash
,
3214 EncodeMechanism eMechanism
,
3215 rtl_TextEncoding eCharset
)
3217 DBG_ASSERT(nIndex
>= 0 || nIndex
== LAST_SEGMENT
,
3218 "INetURLObject::insertName(): Bad index");
3220 if (!checkHierarchical())
3223 sal_Unicode
const * pPathBegin
3224 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
3225 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
3226 sal_Unicode
const * pPrefixEnd
;
3228 sal_Unicode
const * pSuffixBegin
;
3229 if (nIndex
== LAST_SEGMENT
)
3231 pPrefixEnd
= pPathEnd
;
3232 if (bIgnoreFinalSlash
&& pPrefixEnd
> pPathBegin
&&
3233 pPrefixEnd
[-1] == '/')
3237 bInsertSlash
= bAppendFinalSlash
;
3238 pSuffixBegin
= pPathEnd
;
3240 else if (nIndex
== 0)
3242 pPrefixEnd
= pPathBegin
;
3244 (pPathBegin
< pPathEnd
&& *pPathBegin
!= '/') ||
3245 (pPathBegin
== pPathEnd
&& bAppendFinalSlash
);
3247 (pPathEnd
- pPathBegin
== 1 && *pPathBegin
== '/' &&
3248 !bAppendFinalSlash
&& bIgnoreFinalSlash
)
3249 ? pPathEnd
: pPathBegin
;
3253 pPrefixEnd
= pPathBegin
;
3254 sal_Unicode
const * pEnd
= pPathEnd
;
3255 if (bIgnoreFinalSlash
&& pEnd
> pPathBegin
&& pEnd
[-1] == '/')
3257 bool bSkip
= pPrefixEnd
< pEnd
&& *pPrefixEnd
== '/';
3258 bInsertSlash
= false;
3259 pSuffixBegin
= pPathEnd
;
3260 while (nIndex
-- > 0)
3266 if (pPrefixEnd
>= pEnd
)
3270 bInsertSlash
= bAppendFinalSlash
;
3276 if (*pPrefixEnd
== '/')
3278 pSuffixBegin
= pPrefixEnd
;
3284 OUStringBuffer aNewPath
;
3285 aNewPath
.append(pPathBegin
, pPrefixEnd
- pPathBegin
);
3286 aNewPath
.append('/');
3287 aNewPath
.append(encodeText(rTheName
, bOctets
, PART_PCHAR
,
3288 eMechanism
, eCharset
, true));
3290 aNewPath
.append('/');
3292 aNewPath
.append(pSuffixBegin
, pPathEnd
- pSuffixBegin
);
3294 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
3295 RTL_TEXTENCODING_UTF8
);
3298 bool INetURLObject::clearQuery()
3302 if (m_aQuery
.isPresent())
3304 lcl_Erase(m_aAbsURIRef
, m_aQuery
.getBegin() - 1,
3305 m_aQuery
.getLength() + 1);
3306 m_aFragment
+= m_aQuery
.clear() - 1;
3311 bool INetURLObject::setQuery(OUString
const & rTheQuery
, bool bOctets
,
3312 EncodeMechanism eMechanism
,
3313 rtl_TextEncoding eCharset
)
3315 if (!getSchemeInfo().m_bQuery
)
3317 OUString
aNewQuery(encodeText(rTheQuery
, bOctets
, PART_URIC
,
3318 eMechanism
, eCharset
, true));
3320 if (m_aQuery
.isPresent())
3321 nDelta
= m_aQuery
.set(m_aAbsURIRef
, aNewQuery
);
3324 m_aAbsURIRef
.insert(m_aPath
.getEnd(), sal_Unicode('?'));
3325 nDelta
= m_aQuery
.set(m_aAbsURIRef
, aNewQuery
, m_aPath
.getEnd() + 1)
3328 m_aFragment
+= nDelta
;
3332 bool INetURLObject::clearFragment()
3336 if (m_aFragment
.isPresent())
3338 m_aAbsURIRef
.setLength(m_aFragment
.getBegin() - 1);
3339 m_aFragment
.clear();
3344 bool INetURLObject::setFragment(OUString
const & rTheFragment
,
3345 bool bOctets
, EncodeMechanism eMechanism
,
3346 rtl_TextEncoding eCharset
)
3350 OUString
aNewFragment(encodeText(rTheFragment
, bOctets
, PART_URIC
,
3351 eMechanism
, eCharset
, true));
3352 if (m_aFragment
.isPresent())
3353 m_aFragment
.set(m_aAbsURIRef
, aNewFragment
);
3356 m_aAbsURIRef
.append('#');
3357 m_aFragment
.set(m_aAbsURIRef
, aNewFragment
, m_aAbsURIRef
.getLength());
3362 bool INetURLObject::hasDosVolume(FSysStyle eStyle
) const
3364 sal_Unicode
const * p
= m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
3365 return (eStyle
& FSYS_DOS
) != 0
3366 && m_aPath
.getLength() >= 3
3368 && rtl::isAsciiAlpha(p
[1])
3370 && (m_aPath
.getLength() == 3 || p
[3] == '/');
3374 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
)
3380 OUStringBuffer aResult
;
3381 while (pBegin
< pEnd
)
3383 EscapeType eEscapeType
;
3384 sal_uInt32 nUTF32
= getUTF32(pBegin
, pEnd
, bOctets
,
3385 eMechanism
, eCharset
, eEscapeType
);
3386 appendUCS4(aResult
, nUTF32
, eEscapeType
, bOctets
, ePart
,
3387 eCharset
, bKeepVisibleEscapes
);
3389 return aResult
.makeStringAndClear();
3393 OUString
INetURLObject::decode(sal_Unicode
const * pBegin
,
3394 sal_Unicode
const * pEnd
,
3395 DecodeMechanism eMechanism
,
3396 rtl_TextEncoding eCharset
)
3401 return OUString(pBegin
, pEnd
- pBegin
);
3403 case DECODE_TO_IURI
:
3404 eCharset
= RTL_TEXTENCODING_UTF8
;
3410 OUStringBuffer aResult
;
3411 while (pBegin
< pEnd
)
3413 EscapeType eEscapeType
;
3414 sal_uInt32 nUTF32
= getUTF32(pBegin
, pEnd
, false,
3415 WAS_ENCODED
, eCharset
, eEscapeType
);
3416 switch (eEscapeType
)
3419 aResult
.appendUtf32(nUTF32
);
3423 appendEscape(aResult
, nUTF32
);
3428 rtl::isAscii(nUTF32
) &&
3430 eMechanism
== DECODE_TO_IURI
||
3432 eMechanism
== DECODE_UNAMBIGUOUS
&&
3433 mustEncode(nUTF32
, PART_UNAMBIGUOUS
)
3438 appendEscape(aResult
, nUTF32
);
3441 aResult
.appendUtf32(nUTF32
);
3445 return aResult
.makeStringAndClear();
3448 OUString
INetURLObject::GetURLNoPass(DecodeMechanism eMechanism
,
3449 rtl_TextEncoding eCharset
) const
3451 INetURLObject
aTemp(*this);
3452 aTemp
.clearPassword();
3453 return aTemp
.GetMainURL(eMechanism
, eCharset
);
3456 OUString
INetURLObject::GetURLNoMark(DecodeMechanism eMechanism
,
3457 rtl_TextEncoding eCharset
) const
3459 INetURLObject
aTemp(*this);
3460 aTemp
.clearFragment();
3461 return aTemp
.GetMainURL(eMechanism
, eCharset
);
3465 INetURLObject::getAbbreviated(
3466 uno::Reference
< util::XStringWidth
> const & rStringWidth
,
3468 DecodeMechanism eMechanism
,
3469 rtl_TextEncoding eCharset
)
3472 OSL_ENSURE(rStringWidth
.is(), "specification violation");
3473 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 if (m_eScheme
!= INetProtocol::Generic
)
3478 aBuffer
.appendAscii(getSchemeInfo().m_pScheme
);
3482 if (!m_aAbsURIRef
.isEmpty())
3484 sal_Unicode
const * pSchemeBegin
3485 = m_aAbsURIRef
.getStr();
3486 sal_Unicode
const * pSchemeEnd
= pSchemeBegin
;
3488 while (pSchemeEnd
[0] != ':')
3492 aBuffer
.append(pSchemeBegin
, pSchemeEnd
- pSchemeBegin
);
3495 aBuffer
.append(':');
3496 bool bAuthority
= getSchemeInfo().m_bAuthority
;
3497 sal_Unicode
const * pCoreBegin
3498 = m_aAbsURIRef
.getStr() + (bAuthority
? getAuthorityBegin() :
3499 m_aPath
.getBegin());
3500 sal_Unicode
const * pCoreEnd
3501 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin() + m_aPath
.getLength();
3502 bool bSegment
= false;
3503 if (getSchemeInfo().m_bHierarchical
)
3506 if (m_aQuery
.isPresent())
3508 else if (m_aFragment
.isPresent())
3510 OUStringBuffer aTrailer
;
3511 sal_Unicode
const * pBegin
= pCoreBegin
;
3512 sal_Unicode
const * pEnd
= pCoreEnd
;
3513 sal_Unicode
const * pPrefixBegin
= pBegin
;
3514 sal_Unicode
const * pSuffixEnd
= pEnd
;
3515 bool bPrefix
= true;
3516 bool bSuffix
= true;
3521 sal_Unicode
const * p
= pSuffixEnd
- 1;
3522 if (pSuffixEnd
== pCoreEnd
&& *p
== '/')
3526 if (bAuthority
&& p
== pCoreBegin
+ 1)
3529 aSegment(decode(p
+ (p
== pBegin
&& pBegin
!= pCoreBegin
?
3535 OUStringBuffer
aResult(aBuffer
);
3536 if (pSuffixEnd
!= pBegin
)
3537 aResult
.append("...");
3538 aResult
.append(aSegment
);
3539 aResult
.append(aTrailer
.toString());
3540 aResult
.append(aRest
);
3542 queryStringWidth(aResult
.makeStringAndClear())
3545 aTrailer
.insert(0, aSegment
);
3551 if (pPrefixBegin
> pSuffixEnd
)
3552 pPrefixBegin
= pSuffixEnd
;
3558 sal_Unicode
const * p
3560 + (bAuthority
&& pPrefixBegin
== pCoreBegin
? 2 :
3562 OSL_ASSERT(p
<= pEnd
);
3563 while (p
< pEnd
&& *p
!= '/')
3565 if (p
== pCoreEnd
- 1 && *p
== '/')
3568 aSegment(decode(pPrefixBegin
3569 + (pPrefixBegin
== pCoreBegin
? 0 :
3571 p
== pEnd
? p
: p
+ 1,
3575 OUStringBuffer
aResult(aBuffer
);
3576 aResult
.append(aSegment
);
3577 if (pPrefixBegin
!= pEnd
)
3578 aResult
.append("...");
3579 aResult
.append(aTrailer
.toString());
3580 aResult
.append(aRest
);
3582 queryStringWidth(aResult
.makeStringAndClear())
3585 aBuffer
.append(aSegment
);
3587 pBegin
= pPrefixBegin
;
3591 if (pPrefixBegin
> pSuffixEnd
)
3592 pSuffixEnd
= pPrefixBegin
;
3597 while (bPrefix
|| bSuffix
);
3600 if (pPrefixBegin
!= pBegin
|| pSuffixEnd
!= pEnd
)
3601 aBuffer
.append("...");
3602 aBuffer
.append(aTrailer
.toString());
3606 aBuffer
.append(decode(pCoreBegin
,
3610 if (m_aQuery
.isPresent())
3612 aBuffer
.append('?');
3613 aBuffer
.append(decode(m_aQuery
, eMechanism
, eCharset
));
3615 if (m_aFragment
.isPresent())
3617 aBuffer
.append('#');
3618 aBuffer
.append(decode(m_aFragment
, eMechanism
, eCharset
));
3620 if (!aBuffer
.isEmpty())
3622 OUStringBuffer
aResult(aBuffer
);
3623 if (rStringWidth
->queryStringWidth(aResult
.makeStringAndClear())
3625 for (sal_Int32 i
= aBuffer
.getLength();;)
3629 aBuffer
.setLength(aBuffer
.getLength() - 1);
3630 if (aBuffer
.isEmpty())
3635 aBuffer
.setLength(--i
);
3636 aBuffer
.append("...");
3640 queryStringWidth(aResult
.makeStringAndClear())
3645 return aBuffer
.makeStringAndClear();
3648 bool INetURLObject::operator ==(INetURLObject
const & rObject
) const
3650 if (m_eScheme
!= rObject
.m_eScheme
)
3652 if (m_eScheme
== INetProtocol::NotValid
)
3653 return m_aAbsURIRef
.toString() == rObject
.m_aAbsURIRef
.toString();
3654 if ((m_aScheme
.compare(
3655 rObject
.m_aScheme
, m_aAbsURIRef
, rObject
.m_aAbsURIRef
)
3657 || GetUser(NO_DECODE
) != rObject
.GetUser(NO_DECODE
)
3658 || GetPass(NO_DECODE
) != rObject
.GetPass(NO_DECODE
)
3659 || !GetHost(NO_DECODE
).equalsIgnoreAsciiCase(
3660 rObject
.GetHost(NO_DECODE
))
3661 || GetPort() != rObject
.GetPort()
3662 || HasParam() != rObject
.HasParam()
3663 || GetParam(NO_DECODE
) != rObject
.GetParam(NO_DECODE
)
3664 || GetMsgId(NO_DECODE
) != INetURLObject::GetMsgId(NO_DECODE
))
3666 OUString
aPath1(GetURLPath(NO_DECODE
));
3667 OUString
aPath2(rObject
.GetURLPath(NO_DECODE
));
3670 case INetProtocol::File
:
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 sal_Int32 nLength
= aPath1
.getLength();
3676 switch (nLength
- aPath2
.getLength())
3679 if (aPath2
[nLength
] != '/')
3687 if (aPath1
[--nLength
] != '/')
3694 return aPath1
.compareTo(aPath2
, nLength
) == 0;
3698 return aPath1
== aPath2
;
3702 bool INetURLObject::operator <(INetURLObject
const & rObject
) const
3704 sal_Int32 nCompare
= m_aScheme
.compare(
3705 rObject
.m_aScheme
, m_aAbsURIRef
, rObject
.m_aAbsURIRef
);
3708 } else if (nCompare
> 0) {
3711 sal_uInt32 nPort1
= GetPort();
3712 sal_uInt32 nPort2
= rObject
.GetPort();
3713 if (nPort1
< nPort2
)
3715 else if (nPort1
> nPort2
)
3717 nCompare
= GetUser(NO_DECODE
).compareTo(rObject
.GetUser(NO_DECODE
));
3720 else if (nCompare
> 0)
3722 nCompare
= GetPass(NO_DECODE
).compareTo(rObject
.GetPass(NO_DECODE
));
3725 else if (nCompare
> 0)
3727 nCompare
= GetHost(NO_DECODE
).compareTo(rObject
.GetHost(NO_DECODE
));
3730 else if (nCompare
> 0)
3732 const OUString
&rPath1(GetURLPath(NO_DECODE
));
3733 const OUString
&rPath2(rObject
.GetURLPath(NO_DECODE
));
3734 nCompare
= rPath1
.compareTo(rPath2
);
3737 else if (nCompare
> 0)
3739 nCompare
= GetParam(NO_DECODE
).compareTo(rObject
.GetParam(NO_DECODE
));
3742 else if (nCompare
> 0)
3744 return GetMsgId(NO_DECODE
).compareTo(INetURLObject::GetMsgId(NO_DECODE
)) < 0;
3747 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
)
3757 m_eScheme
= eTheScheme
;
3758 if (HasError() || m_eScheme
== INetProtocol::Generic
)
3760 m_aAbsURIRef
.setLength(0);
3761 m_aAbsURIRef
.appendAscii(getSchemeInfo().m_pScheme
);
3762 m_aAbsURIRef
.append(':');
3763 if (getSchemeInfo().m_bAuthority
)
3765 m_aAbsURIRef
.append("//");
3766 bool bUserInfo
= false;
3767 if (getSchemeInfo().m_bUser
)
3769 if (!rTheUser
.isEmpty())
3771 m_aUser
.set(m_aAbsURIRef
,
3772 encodeText(rTheUser
, false, PART_USER_PASSWORD
,
3773 eMechanism
, eCharset
, false),
3774 m_aAbsURIRef
.getLength());
3778 else if (!rTheUser
.isEmpty())
3783 if (!rThePassword
.isEmpty())
3785 if (getSchemeInfo().m_bPassword
)
3787 m_aAbsURIRef
.append(':');
3788 m_aAuth
.set(m_aAbsURIRef
,
3789 encodeText(rThePassword
, false, PART_USER_PASSWORD
,
3790 eMechanism
, eCharset
, false),
3791 m_aAbsURIRef
.getLength());
3800 if (bUserInfo
&& getSchemeInfo().m_bHost
)
3801 m_aAbsURIRef
.append('@');
3802 if (getSchemeInfo().m_bHost
)
3804 OUStringBuffer
aSynHost(rTheHost
);
3805 bool bNetBiosName
= false;
3808 case INetProtocol::File
:
3810 OUString
sTemp(aSynHost
.toString());
3811 if (sTemp
.equalsIgnoreAsciiCase( "localhost" ))
3813 aSynHost
.setLength(0);
3815 bNetBiosName
= true;
3819 case INetProtocol::Ldap
:
3820 if (aSynHost
.isEmpty() && nThePort
!= 0)
3828 if (aSynHost
.isEmpty())
3835 if (!parseHostOrNetBiosName(
3836 aSynHost
.getStr(), aSynHost
.getStr() + aSynHost
.getLength(),
3837 false, eMechanism
, eCharset
, bNetBiosName
, &aSynHost
))
3842 m_aHost
.set(m_aAbsURIRef
, aSynHost
.makeStringAndClear(),
3843 m_aAbsURIRef
.getLength());
3846 if (getSchemeInfo().m_bPort
)
3848 m_aAbsURIRef
.append(':');
3849 m_aPort
.set(m_aAbsURIRef
,
3850 OUString::number(nThePort
),
3851 m_aAbsURIRef
.getLength());
3860 else if (!rTheHost
.isEmpty() || nThePort
!= 0)
3866 OUStringBuffer aSynPath
;
3867 sal_Unicode
const * p
= rThePath
.getStr();
3868 sal_Unicode
const * pEnd
= p
+ rThePath
.getLength();
3869 if (!parsePath(m_eScheme
, &p
, pEnd
, false, eMechanism
, eCharset
, false, '/',
3870 0x80000000, 0x80000000, 0x80000000, aSynPath
)
3876 m_aPath
.set(m_aAbsURIRef
, aSynPath
.makeStringAndClear(),
3877 m_aAbsURIRef
.getLength());
3882 OUString
INetURLObject::GetAbsURL(OUString
const & rTheBaseURIRef
,
3883 OUString
const & rTheRelURIRef
,
3884 bool bIgnoreFragment
,
3885 EncodeMechanism eEncodeMechanism
,
3886 DecodeMechanism eDecodeMechanism
,
3887 rtl_TextEncoding eCharset
,
3890 // Backwards compatibility:
3891 if (rTheRelURIRef
.isEmpty() || rTheRelURIRef
[0] == '#')
3892 return rTheRelURIRef
;
3894 INetURLObject aTheAbsURIRef
;
3896 return INetURLObject(rTheBaseURIRef
, eEncodeMechanism
, eCharset
).
3897 convertRelToAbs(rTheRelURIRef
, false, aTheAbsURIRef
,
3898 bWasAbsolute
, eEncodeMechanism
,
3899 eCharset
, bIgnoreFragment
, false,
3901 || eEncodeMechanism
!= WAS_ENCODED
3902 || eDecodeMechanism
!= DECODE_TO_IURI
3903 || eCharset
!= RTL_TEXTENCODING_UTF8
?
3904 aTheAbsURIRef
.GetMainURL(eDecodeMechanism
, eCharset
) :
3908 OUString
INetURLObject::getExternalURL(DecodeMechanism eMechanism
,
3909 rtl_TextEncoding eCharset
) const
3911 OUString aTheExtURIRef
;
3912 translateToExternal(
3913 m_aAbsURIRef
.toString(), aTheExtURIRef
, eMechanism
, eCharset
);
3914 return aTheExtURIRef
;
3918 OUString
INetURLObject::GetScheme(INetProtocol eTheScheme
)
3920 return OUString::createFromAscii(getSchemeInfo(eTheScheme
).m_pPrefix
);
3924 OUString
INetURLObject::GetSchemeName(INetProtocol eTheScheme
)
3926 return OUString::createFromAscii(getSchemeInfo(eTheScheme
).m_pScheme
);
3930 INetProtocol
INetURLObject::CompareProtocolScheme(OUString
const &
3933 sal_Unicode
const * p
= rTheAbsURIRef
.getStr();
3934 PrefixInfo
const * pPrefix
= getPrefix(p
, p
+ rTheAbsURIRef
.getLength());
3935 return pPrefix
? pPrefix
->m_eScheme
: INetProtocol::NotValid
;
3938 OUString
INetURLObject::GetHostPort(DecodeMechanism eMechanism
,
3939 rtl_TextEncoding eCharset
)
3941 // Check because PROT_VND_SUN_STAR_HELP, PROT_VND_SUN_STAR_HIER, and
3942 // PROT_VND_SUN_STAR_PKG misuse m_aHost:
3943 if (!getSchemeInfo().m_bHost
)
3945 OUStringBuffer
aHostPort(decode(m_aHost
, eMechanism
, eCharset
));
3946 if (m_aPort
.isPresent())
3948 aHostPort
.append(':');
3949 aHostPort
.append(decode(m_aPort
, eMechanism
, eCharset
));
3951 return aHostPort
.makeStringAndClear();
3954 sal_uInt32
INetURLObject::GetPort() const
3956 if (m_aPort
.isPresent())
3958 sal_Unicode
const * p
= m_aAbsURIRef
.getStr() + m_aPort
.getBegin();
3959 sal_Unicode
const * pEnd
= p
+ m_aPort
.getLength();
3960 sal_uInt32 nThePort
;
3961 if (INetMIME::scanUnsigned(p
, pEnd
, true, nThePort
) && p
== pEnd
)
3967 bool INetURLObject::SetPort(sal_uInt32 nThePort
)
3969 if (getSchemeInfo().m_bPort
&& m_aHost
.isPresent())
3971 OUString
aNewPort(OUString::number(nThePort
));
3973 if (m_aPort
.isPresent())
3974 nDelta
= m_aPort
.set(m_aAbsURIRef
, aNewPort
);
3977 m_aAbsURIRef
.insert(m_aHost
.getEnd(), sal_Unicode(':'));
3978 nDelta
= m_aPort
.set(m_aAbsURIRef
, aNewPort
, m_aHost
.getEnd() + 1)
3983 m_aFragment
+= nDelta
;
3989 sal_Int32
INetURLObject::getSegmentCount(bool bIgnoreFinalSlash
) const
3991 if (!checkHierarchical())
3994 sal_Unicode
const * p
= m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
3995 sal_Unicode
const * pEnd
= p
+ m_aPath
.getLength();
3996 if (bIgnoreFinalSlash
&& pEnd
> p
&& pEnd
[-1] == '/')
3998 sal_Int32 n
= p
== pEnd
|| *p
== '/' ? 0 : 1;
4005 bool INetURLObject::removeSegment(sal_Int32 nIndex
, bool bIgnoreFinalSlash
)
4007 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4008 if (!aSegment
.isPresent())
4011 OUStringBuffer aNewPath
;
4012 aNewPath
.append(m_aAbsURIRef
.getStr() + m_aPath
.getBegin(),
4013 aSegment
.getBegin() - m_aPath
.getBegin());
4014 if (bIgnoreFinalSlash
&& aSegment
.getEnd() == m_aPath
.getEnd())
4015 aNewPath
.append('/');
4017 aNewPath
.append(m_aAbsURIRef
.getStr() + aSegment
.getEnd(),
4018 m_aPath
.getEnd() - aSegment
.getEnd());
4019 if (aNewPath
.isEmpty() && !aSegment
.isEmpty() &&
4020 m_aAbsURIRef
[aSegment
.getBegin()] == '/')
4022 aNewPath
.append('/');
4025 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4026 RTL_TEXTENCODING_UTF8
);
4029 OUString
INetURLObject::getName(sal_Int32 nIndex
, bool bIgnoreFinalSlash
,
4030 DecodeMechanism eMechanism
,
4031 rtl_TextEncoding eCharset
) const
4033 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4034 if (!aSegment
.isPresent())
4037 sal_Unicode
const * pSegBegin
4038 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4039 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4041 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4043 sal_Unicode
const * p
= pSegBegin
;
4044 while (p
!= pSegEnd
&& *p
!= ';')
4047 return decode(pSegBegin
, p
, eMechanism
, eCharset
);
4050 bool INetURLObject::setName(OUString
const & rTheName
, sal_Int32 nIndex
,
4051 bool bIgnoreFinalSlash
,
4052 EncodeMechanism eMechanism
,
4053 rtl_TextEncoding eCharset
)
4055 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4056 if (!aSegment
.isPresent())
4059 sal_Unicode
const * pPathBegin
4060 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4061 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4062 sal_Unicode
const * pSegBegin
4063 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4064 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4066 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4068 sal_Unicode
const * p
= pSegBegin
;
4069 while (p
!= pSegEnd
&& *p
!= ';')
4072 OUStringBuffer aNewPath
;
4073 aNewPath
.append(pPathBegin
, pSegBegin
- pPathBegin
);
4074 aNewPath
.append(encodeText(rTheName
, false, PART_PCHAR
,
4075 eMechanism
, eCharset
, true));
4076 aNewPath
.append(p
, pPathEnd
- p
);
4078 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4079 RTL_TEXTENCODING_UTF8
);
4082 bool INetURLObject::hasExtension(sal_Int32 nIndex
, bool bIgnoreFinalSlash
)
4085 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4086 if (!aSegment
.isPresent())
4089 sal_Unicode
const * pSegBegin
4090 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4091 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4093 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4095 for (sal_Unicode
const * p
= pSegBegin
; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4096 if (*p
== '.' && p
!= pSegBegin
)
4101 OUString
INetURLObject::getBase(sal_Int32 nIndex
, bool bIgnoreFinalSlash
,
4102 DecodeMechanism eMechanism
,
4103 rtl_TextEncoding eCharset
) const
4105 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4106 if (!aSegment
.isPresent())
4109 sal_Unicode
const * pSegBegin
4110 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4111 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4113 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4115 sal_Unicode
const * pExtension
= 0;
4116 sal_Unicode
const * p
= pSegBegin
;
4117 for (; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4118 if (*p
== '.' && p
!= pSegBegin
)
4123 return decode(pSegBegin
, pExtension
, eMechanism
, eCharset
);
4126 bool INetURLObject::setBase(OUString
const & rTheBase
, sal_Int32 nIndex
,
4127 bool bIgnoreFinalSlash
,
4128 EncodeMechanism eMechanism
,
4129 rtl_TextEncoding eCharset
)
4131 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4132 if (!aSegment
.isPresent())
4135 sal_Unicode
const * pPathBegin
4136 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4137 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4138 sal_Unicode
const * pSegBegin
4139 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4140 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4142 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4144 sal_Unicode
const * pExtension
= 0;
4145 sal_Unicode
const * p
= pSegBegin
;
4146 for (; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4147 if (*p
== '.' && p
!= pSegBegin
)
4152 OUStringBuffer aNewPath
;
4153 aNewPath
.append(pPathBegin
, pSegBegin
- pPathBegin
);
4154 aNewPath
.append(encodeText(rTheBase
, false, PART_PCHAR
,
4155 eMechanism
, eCharset
, true));
4156 aNewPath
.append(pExtension
, pPathEnd
- pExtension
);
4158 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4159 RTL_TEXTENCODING_UTF8
);
4162 OUString
INetURLObject::getExtension(sal_Int32 nIndex
,
4163 bool bIgnoreFinalSlash
,
4164 DecodeMechanism eMechanism
,
4165 rtl_TextEncoding eCharset
) const
4167 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4168 if (!aSegment
.isPresent())
4171 sal_Unicode
const * pSegBegin
4172 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4173 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4175 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4177 sal_Unicode
const * pExtension
= 0;
4178 sal_Unicode
const * p
= pSegBegin
;
4179 for (; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4180 if (*p
== '.' && p
!= pSegBegin
)
4186 return decode(pExtension
+ 1, p
, eMechanism
, eCharset
);
4189 bool INetURLObject::setExtension(OUString
const & rTheExtension
,
4190 sal_Int32 nIndex
, bool bIgnoreFinalSlash
,
4191 EncodeMechanism eMechanism
,
4192 rtl_TextEncoding eCharset
)
4194 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4195 if (!aSegment
.isPresent())
4198 sal_Unicode
const * pPathBegin
4199 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4200 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4201 sal_Unicode
const * pSegBegin
4202 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4203 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4205 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4207 sal_Unicode
const * pExtension
= 0;
4208 sal_Unicode
const * p
= pSegBegin
;
4209 for (; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4210 if (*p
== '.' && p
!= pSegBegin
)
4215 OUStringBuffer aNewPath
;
4216 aNewPath
.append(pPathBegin
, pExtension
- pPathBegin
);
4217 aNewPath
.append('.');
4218 aNewPath
.append(encodeText(rTheExtension
, false, PART_PCHAR
,
4219 eMechanism
, eCharset
, true));
4220 aNewPath
.append(p
, pPathEnd
- p
);
4222 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4223 RTL_TEXTENCODING_UTF8
);
4226 bool INetURLObject::removeExtension(sal_Int32 nIndex
, bool bIgnoreFinalSlash
)
4228 SubString
aSegment(getSegment(nIndex
, bIgnoreFinalSlash
));
4229 if (!aSegment
.isPresent())
4232 sal_Unicode
const * pPathBegin
4233 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4234 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4235 sal_Unicode
const * pSegBegin
4236 = m_aAbsURIRef
.getStr() + aSegment
.getBegin();
4237 sal_Unicode
const * pSegEnd
= pSegBegin
+ aSegment
.getLength();
4239 if (pSegBegin
< pSegEnd
&& *pSegBegin
== '/')
4241 sal_Unicode
const * pExtension
= 0;
4242 sal_Unicode
const * p
= pSegBegin
;
4243 for (; p
!= pSegEnd
&& *p
!= ';'; ++p
)
4244 if (*p
== '.' && p
!= pSegBegin
)
4249 OUStringBuffer aNewPath
;
4250 aNewPath
.append(pPathBegin
, pExtension
- pPathBegin
);
4251 aNewPath
.append(p
, pPathEnd
- p
);
4253 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4254 RTL_TEXTENCODING_UTF8
);
4257 bool INetURLObject::hasFinalSlash() const
4259 if (!checkHierarchical())
4262 sal_Unicode
const * pPathBegin
4263 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4264 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4265 return pPathEnd
> pPathBegin
&& pPathEnd
[-1] == '/';
4268 bool INetURLObject::setFinalSlash()
4270 if (!checkHierarchical())
4273 sal_Unicode
const * pPathBegin
4274 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4275 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4276 if (pPathEnd
> pPathBegin
&& pPathEnd
[-1] == '/')
4279 OUStringBuffer aNewPath
;
4280 aNewPath
.append(pPathBegin
, pPathEnd
- pPathBegin
);
4281 aNewPath
.append('/');
4283 return setPath(aNewPath
.makeStringAndClear(), false, NOT_CANONIC
,
4284 RTL_TEXTENCODING_UTF8
);
4287 bool INetURLObject::removeFinalSlash()
4289 if (!checkHierarchical())
4292 sal_Unicode
const * pPathBegin
4293 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4294 sal_Unicode
const * pPathEnd
= pPathBegin
+ m_aPath
.getLength();
4295 if (pPathEnd
<= pPathBegin
|| pPathEnd
[-1] != '/')
4299 if (pPathEnd
== pPathBegin
&& *pPathBegin
== '/')
4301 OUString
aNewPath(pPathBegin
, pPathEnd
- pPathBegin
);
4303 return setPath(aNewPath
, false, NOT_CANONIC
, RTL_TEXTENCODING_UTF8
);
4306 bool INetURLObject::setFSysPath(OUString
const & rFSysPath
,
4309 sal_Unicode
const * pFSysBegin
= rFSysPath
.getStr();
4310 sal_Unicode
const * pFSysEnd
= pFSysBegin
+ rFSysPath
.getLength();
4312 switch ((eStyle
& FSYS_VOS
? 1 : 0)
4313 + (eStyle
& FSYS_UNX
? 1 : 0)
4314 + (eStyle
& FSYS_DOS
? 1 : 0))
4323 if (eStyle
& FSYS_VOS
4324 && pFSysEnd
- pFSysBegin
>= 2
4325 && pFSysBegin
[0] == '/'
4326 && pFSysBegin
[1] == '/')
4328 if (pFSysEnd
- pFSysBegin
>= 3
4329 && pFSysBegin
[2] == '.'
4330 && (pFSysEnd
- pFSysBegin
== 3 || pFSysBegin
[3] == '/'))
4332 eStyle
= FSYS_VOS
; // Production T1
4336 sal_Unicode
const * p
= pFSysBegin
+ 2;
4338 if (parseHost(p
, pFSysEnd
, aHost
)
4339 && (p
== pFSysEnd
|| *p
== '/'))
4341 eStyle
= FSYS_VOS
; // Production T2
4346 if (eStyle
& FSYS_DOS
4347 && pFSysEnd
- pFSysBegin
>= 2
4348 && pFSysBegin
[0] == '\\'
4349 && pFSysBegin
[1] == '\\')
4351 sal_Unicode
const * p
= pFSysBegin
+ 2;
4353 if (parseHost(p
, pFSysEnd
, aHost
)
4354 && (p
== pFSysEnd
|| *p
== '\\'))
4356 eStyle
= FSYS_DOS
; // Production T3
4361 if (eStyle
& FSYS_DOS
4362 && pFSysEnd
- pFSysBegin
>= 2
4363 && rtl::isAsciiAlpha(pFSysBegin
[0])
4364 && pFSysBegin
[1] == ':'
4365 && (pFSysEnd
- pFSysBegin
== 2
4366 || pFSysBegin
[2] == '/'
4367 || pFSysBegin
[2] == '\\'))
4369 eStyle
= FSYS_DOS
; // Productions T4, T5
4373 if (!(eStyle
& (FSYS_UNX
| FSYS_DOS
)))
4376 eStyle
= guessFSysStyleByCounting(pFSysBegin
, pFSysEnd
, eStyle
);
4381 OUStringBuffer
aSynAbsURIRef("file://");
4387 sal_Unicode
const * p
= pFSysBegin
;
4388 if (pFSysEnd
- p
< 2 || *p
++ != '/' || *p
++ != '/')
4390 if (p
!= pFSysEnd
&& *p
== '.'
4391 && (pFSysEnd
- p
== 1 || p
[1] == '/'))
4393 for (; p
!= pFSysEnd
; ++p
)
4398 appendEscape(aSynAbsURIRef
, *p
);
4402 aSynAbsURIRef
.append(*p
);
4410 sal_Unicode
const * p
= pFSysBegin
;
4411 if (p
!= pFSysEnd
&& *p
!= '/')
4413 for (; p
!= pFSysEnd
; ++p
)
4419 appendEscape(aSynAbsURIRef
, *p
);
4423 aSynAbsURIRef
.append(*p
);
4431 sal_uInt32 nAltDelimiter
= 0x80000000;
4432 sal_Unicode
const * p
= pFSysBegin
;
4433 if (pFSysEnd
- p
>= 3 && p
[0] == '\\' && p
[1] == '\\')
4437 aSynAbsURIRef
.append('/');
4438 if (pFSysEnd
- p
>= 2
4439 && rtl::isAsciiAlpha(p
[0])
4441 && (pFSysEnd
- p
== 2 || p
[2] == '\\' || p
[2] == '/'))
4442 nAltDelimiter
= '/';
4444 for (; p
!= pFSysEnd
; ++p
)
4445 if (*p
== '\\' || *p
== nAltDelimiter
)
4446 aSynAbsURIRef
.append('/');
4453 appendEscape(aSynAbsURIRef
, *p
);
4457 aSynAbsURIRef
.append(*p
);
4468 INetURLObject
aTemp(aSynAbsURIRef
.makeStringAndClear(), WAS_ENCODED
,
4469 RTL_TEXTENCODING_UTF8
);
4470 if (aTemp
.HasError())
4477 OUString
INetURLObject::getFSysPath(FSysStyle eStyle
,
4478 sal_Unicode
* pDelimiter
) const
4480 if (m_eScheme
!= INetProtocol::File
)
4483 if ((eStyle
& FSYS_VOS
? 1 : 0)
4484 + (eStyle
& FSYS_UNX
? 1 : 0)
4485 + (eStyle
& FSYS_DOS
? 1 : 0)
4488 eStyle
= eStyle
& FSYS_VOS
4489 && m_aHost
.isPresent()
4490 && m_aHost
.getLength() > 0 ?
4492 hasDosVolume(eStyle
)
4493 || ((eStyle
& FSYS_DOS
) != 0
4494 && m_aHost
.isPresent()
4495 && m_aHost
.getLength() > 0) ?
4498 && (!m_aHost
.isPresent() || m_aHost
.getLength() == 0) ?
4510 OUStringBuffer aSynFSysPath
;
4511 aSynFSysPath
.append("//");
4512 if (m_aHost
.isPresent() && m_aHost
.getLength() > 0)
4513 aSynFSysPath
.append(decode(m_aHost
, DECODE_WITH_CHARSET
,
4514 RTL_TEXTENCODING_UTF8
));
4516 aSynFSysPath
.append('.');
4517 aSynFSysPath
.append(decode(m_aPath
, DECODE_WITH_CHARSET
,
4518 RTL_TEXTENCODING_UTF8
));
4519 return aSynFSysPath
.makeStringAndClear();
4524 if (m_aHost
.isPresent() && m_aHost
.getLength() > 0)
4530 return decode(m_aPath
, DECODE_WITH_CHARSET
, RTL_TEXTENCODING_UTF8
);
4538 OUStringBuffer aSynFSysPath
;
4539 if (m_aHost
.isPresent() && m_aHost
.getLength() > 0)
4541 aSynFSysPath
.append("\\\\");
4542 aSynFSysPath
.append(decode(m_aHost
, DECODE_WITH_CHARSET
,
4543 RTL_TEXTENCODING_UTF8
));
4544 aSynFSysPath
.append('\\');
4546 sal_Unicode
const * p
4547 = m_aAbsURIRef
.getStr() + m_aPath
.getBegin();
4548 sal_Unicode
const * pEnd
= p
+ m_aPath
.getLength();
4549 DBG_ASSERT(p
< pEnd
&& *p
== '/',
4550 "INetURLObject::getFSysPath(): Bad path");
4554 EscapeType eEscapeType
;
4555 sal_uInt32 nUTF32
= getUTF32(p
, pEnd
, false, WAS_ENCODED
,
4556 RTL_TEXTENCODING_UTF8
,
4558 if (eEscapeType
== ESCAPE_NO
&& nUTF32
== '/')
4559 aSynFSysPath
.append('\\');
4561 aSynFSysPath
.appendUtf32(nUTF32
);
4563 return aSynFSysPath
.makeStringAndClear();
4571 OUString
INetURLObject::GetMsgId(DecodeMechanism
,
4578 void INetURLObject::appendUCS4Escape(OUStringBuffer
& rTheText
,
4581 DBG_ASSERT(nUCS4
< 0x80000000,
4582 "INetURLObject::appendUCS4Escape(): Bad char");
4584 appendEscape(rTheText
, nUCS4
);
4585 else if (nUCS4
< 0x800)
4587 appendEscape(rTheText
, nUCS4
>> 6 | 0xC0);
4588 appendEscape(rTheText
, (nUCS4
& 0x3F) | 0x80);
4590 else if (nUCS4
< 0x10000)
4592 appendEscape(rTheText
, nUCS4
>> 12 | 0xE0);
4593 appendEscape(rTheText
, (nUCS4
>> 6 & 0x3F) | 0x80);
4594 appendEscape(rTheText
, (nUCS4
& 0x3F) | 0x80);
4596 else if (nUCS4
< 0x200000)
4598 appendEscape(rTheText
, nUCS4
>> 18 | 0xF0);
4599 appendEscape(rTheText
, (nUCS4
>> 12 & 0x3F) | 0x80);
4600 appendEscape(rTheText
, (nUCS4
>> 6 & 0x3F) | 0x80);
4601 appendEscape(rTheText
, (nUCS4
& 0x3F) | 0x80);
4603 else if (nUCS4
< 0x4000000)
4605 appendEscape(rTheText
, nUCS4
>> 24 | 0xF8);
4606 appendEscape(rTheText
, (nUCS4
>> 18 & 0x3F) | 0x80);
4607 appendEscape(rTheText
, (nUCS4
>> 12 & 0x3F) | 0x80);
4608 appendEscape(rTheText
, (nUCS4
>> 6 & 0x3F) | 0x80);
4609 appendEscape(rTheText
, (nUCS4
& 0x3F) | 0x80);
4613 appendEscape(rTheText
, nUCS4
>> 30 | 0xFC);
4614 appendEscape(rTheText
, (nUCS4
>> 24 & 0x3F) | 0x80);
4615 appendEscape(rTheText
, (nUCS4
>> 18 & 0x3F) | 0x80);
4616 appendEscape(rTheText
, (nUCS4
>> 12 & 0x3F) | 0x80);
4617 appendEscape(rTheText
, (nUCS4
>> 6 & 0x3F) | 0x80);
4618 appendEscape(rTheText
, (nUCS4
& 0x3F) | 0x80);
4623 void INetURLObject::appendUCS4(OUStringBuffer
& rTheText
, sal_uInt32 nUCS4
,
4624 EscapeType eEscapeType
, bool bOctets
,
4625 Part ePart
, rtl_TextEncoding eCharset
,
4626 bool bKeepVisibleEscapes
)
4629 rtl_TextEncoding eTargetCharset
= RTL_TEXTENCODING_DONTKNOW
;
4630 switch (eEscapeType
)
4633 if (mustEncode(nUCS4
, ePart
))
4636 eTargetCharset
= bOctets
? RTL_TEXTENCODING_ISO_8859_1
:
4637 RTL_TEXTENCODING_UTF8
;
4645 eTargetCharset
= RTL_TEXTENCODING_ISO_8859_1
;
4649 if (mustEncode(nUCS4
, ePart
))
4652 eTargetCharset
= eCharset
;
4654 else if (bKeepVisibleEscapes
&& INetMIME::isVisible(nUCS4
))
4657 eTargetCharset
= RTL_TEXTENCODING_ASCII_US
;
4668 switch (eTargetCharset
)
4671 OSL_FAIL("INetURLObject::appendUCS4(): Unsupported charset");
4673 case RTL_TEXTENCODING_ASCII_US
:
4674 case RTL_TEXTENCODING_ISO_8859_1
:
4675 appendEscape(rTheText
, nUCS4
);
4677 case RTL_TEXTENCODING_UTF8
:
4678 appendUCS4Escape(rTheText
, nUCS4
);
4683 rTheText
.append(sal_Unicode(nUCS4
));
4687 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
)
4693 DBG_ASSERT(rBegin
< pEnd
, "INetURLObject::getUTF32(): Bad sequence");
4694 sal_uInt32 nUTF32
= bOctets
? *rBegin
++ :
4695 INetMIME::getUTF32Character(rBegin
, pEnd
);
4699 rEscapeType
= ESCAPE_NO
;
4706 if (nUTF32
== static_cast<unsigned char>('%') && rBegin
+ 1 < pEnd
4707 && (nWeight1
= INetMIME::getHexWeight(rBegin
[0])) >= 0
4708 && (nWeight2
= INetMIME::getHexWeight(rBegin
[1])) >= 0)
4711 nUTF32
= nWeight1
<< 4 | nWeight2
;
4716 "INetURLObject::getUTF32(): Unsupported charset");
4718 case RTL_TEXTENCODING_ASCII_US
:
4719 rEscapeType
= rtl::isAscii(nUTF32
) ?
4720 ESCAPE_UTF32
: ESCAPE_OCTET
;
4723 case RTL_TEXTENCODING_ISO_8859_1
:
4724 rEscapeType
= ESCAPE_UTF32
;
4727 case RTL_TEXTENCODING_UTF8
:
4728 if (rtl::isAscii(nUTF32
))
4729 rEscapeType
= ESCAPE_UTF32
;
4732 if (nUTF32
>= 0xC0 && nUTF32
<= 0xF4)
4734 sal_uInt32 nEncoded
;
4739 nEncoded
= (nUTF32
& 0x1F) << 6;
4743 else if (nUTF32
<= 0xEF)
4745 nEncoded
= (nUTF32
& 0x0F) << 12;
4751 nEncoded
= (nUTF32
& 0x07) << 18;
4755 sal_Unicode
const * p
= rBegin
;
4762 = INetMIME::getHexWeight(p
[1]))
4766 = INetMIME::getHexWeight(p
[2]))
4774 |= ((nWeight1
& 3) << 4 | nWeight2
)
4780 if (bUTF8
&& nEncoded
>= nMin
4781 && nEncoded
<= 0x10FFFF
4782 && !rtl::isHighSurrogate(nEncoded
)
4783 && !rtl::isLowSurrogate(nEncoded
))
4787 rEscapeType
= ESCAPE_UTF32
;
4791 rEscapeType
= ESCAPE_OCTET
;
4797 rEscapeType
= ESCAPE_NO
;
4805 if (nUTF32
== static_cast<unsigned char>('%') && rBegin
+ 1 < pEnd
4806 && ((nWeight1
= INetMIME::getHexWeight(rBegin
[0])) >= 0)
4807 && ((nWeight2
= INetMIME::getHexWeight(rBegin
[1])) >= 0))
4810 nUTF32
= nWeight1
<< 4 | nWeight2
;
4811 rEscapeType
= ESCAPE_OCTET
;
4814 rEscapeType
= ESCAPE_NO
;
4822 sal_uInt32
INetURLObject::scanDomain(sal_Unicode
const *& rBegin
,
4823 sal_Unicode
const * pEnd
,
4826 enum State
{ STATE_DOT
, STATE_LABEL
, STATE_HYPHEN
};
4827 State eState
= STATE_DOT
;
4828 sal_Int32 nLabels
= 0;
4829 sal_Unicode
const * pLastAlphanumeric
= 0;
4830 for (sal_Unicode
const * p
= rBegin
;; ++p
)
4834 if (p
!= pEnd
&& (rtl::isAsciiAlphanumeric(*p
) || *p
== '_'))
4837 eState
= STATE_LABEL
;
4840 if (bEager
|| nLabels
== 0)
4848 if (rtl::isAsciiAlphanumeric(*p
) || *p
== '_')
4857 pLastAlphanumeric
= p
;
4858 eState
= STATE_HYPHEN
;
4868 if (rtl::isAsciiAlphanumeric(*p
) || *p
== '_')
4870 eState
= STATE_LABEL
;
4878 rBegin
= pLastAlphanumeric
;
4884 bool INetURLObject::scanIPv6reference(sal_Unicode
const *& rBegin
,
4885 sal_Unicode
const * pEnd
)
4887 if (rBegin
!= pEnd
&& *rBegin
== '[') {
4888 sal_Unicode
const * p
= rBegin
+ 1;
4889 //TODO: check for valid IPv6address (RFC 2373):
4890 while (p
!= pEnd
&& (rtl::isAsciiHexDigit(*p
) || *p
== ':' || *p
== '.'))
4894 if (p
!= pEnd
&& *p
== ']') {
4902 OUString
INetURLObject::GetPartBeforeLastName(DecodeMechanism eMechanism
,
4903 rtl_TextEncoding eCharset
)
4906 if (!checkHierarchical())
4908 INetURLObject
aTemp(*this);
4909 aTemp
.clearFragment();
4911 aTemp
.removeSegment(LAST_SEGMENT
, false);
4912 aTemp
.setFinalSlash();
4913 return aTemp
.GetMainURL(eMechanism
, eCharset
);
4916 OUString
INetURLObject::GetLastName(DecodeMechanism eMechanism
,
4917 rtl_TextEncoding eCharset
) const
4919 return getName(LAST_SEGMENT
, true, eMechanism
, eCharset
);
4922 OUString
INetURLObject::GetFileExtension(DecodeMechanism eMechanism
,
4923 rtl_TextEncoding eCharset
) const
4925 return getExtension(LAST_SEGMENT
, false, eMechanism
, eCharset
);
4928 bool INetURLObject::CutLastName()
4930 INetURLObject
aTemp(*this);
4931 aTemp
.clearFragment();
4933 if (!aTemp
.removeSegment(LAST_SEGMENT
, false))
4939 OUString
INetURLObject::PathToFileName() const
4941 if (m_eScheme
!= INetProtocol::File
)
4943 OUString aSystemPath
;
4944 if (osl::FileBase::getSystemPathFromFileURL(
4945 decode(m_aAbsURIRef
.getStr(),
4946 m_aAbsURIRef
.getStr() + m_aPath
.getEnd(),
4947 NO_DECODE
, RTL_TEXTENCODING_UTF8
),
4949 != osl::FileBase::E_None
)
4954 OUString
INetURLObject::GetFull() const
4956 INetURLObject
aTemp(*this);
4957 aTemp
.removeFinalSlash();
4958 return aTemp
.PathToFileName();
4961 OUString
INetURLObject::GetPath() const
4963 INetURLObject
aTemp(*this);
4964 aTemp
.removeSegment(LAST_SEGMENT
, true);
4965 aTemp
.removeFinalSlash();
4966 return aTemp
.PathToFileName();
4969 void INetURLObject::SetBase(OUString
const & rTheBase
)
4971 setBase(rTheBase
, LAST_SEGMENT
, true, ENCODE_ALL
);
4974 OUString
INetURLObject::GetBase() const
4976 return getBase(LAST_SEGMENT
, true, DECODE_WITH_CHARSET
);
4979 void INetURLObject::SetName(OUString
const & rTheName
,
4980 EncodeMechanism eMechanism
,
4981 rtl_TextEncoding eCharset
)
4983 INetURLObject
aTemp(*this);
4984 if (aTemp
.removeSegment(LAST_SEGMENT
, true)
4985 && aTemp
.insertName(rTheName
, false, LAST_SEGMENT
, true, eMechanism
,
4990 void INetURLObject::SetExtension(OUString
const & rTheExtension
,
4991 EncodeMechanism eMechanism
,
4992 rtl_TextEncoding eCharset
)
4994 setExtension(rTheExtension
, LAST_SEGMENT
, false, eMechanism
, eCharset
);
4997 OUString
INetURLObject::CutExtension(DecodeMechanism eMechanism
,
4998 rtl_TextEncoding eCharset
)
5000 OUString
aTheExtension(getExtension(LAST_SEGMENT
, false, eMechanism
,
5002 return removeExtension(LAST_SEGMENT
, false)
5003 ? aTheExtension
: OUString();
5006 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */