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

Generated by: LCOV version 1.10