LCOV - code coverage report
Current view: top level - tools/source/fsys - urlobj.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 1325 2472 53.6 %
Date: 2014-04-11 Functions: 69 90 76.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10