LCOV - code coverage report
Current view: top level - libreoffice/tools/source/fsys - urlobj.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 874 2367 36.9 %
Date: 2012-12-27 Functions: 59 89 66.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10