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

Generated by: LCOV version 1.11