LCOV - code coverage report
Current view: top level - tools/source/fsys - urlobj.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1400 2500 56.0 %
Date: 2014-11-03 Functions: 72 92 78.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10