LCOV - code coverage report
Current view: top level - svl/source/misc - urihelper.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 251 299 83.9 %
Date: 2015-06-13 12:38:46 Functions: 15 15 100.0 %
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 <svl/urihelper.hxx>
      21             : #include <com/sun/star/ucb/Command.hpp>
      22             : #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
      23             : #include <com/sun/star/ucb/UniversalContentBroker.hpp>
      24             : #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
      25             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      26             : #include <com/sun/star/ucb/XCommandProcessor.hpp>
      27             : #include <com/sun/star/ucb/XContent.hpp>
      28             : #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
      29             : #include <com/sun/star/uno/Any.hxx>
      30             : #include <com/sun/star/uno/Exception.hpp>
      31             : #include <com/sun/star/uno/Reference.hxx>
      32             : #include <com/sun/star/uno/RuntimeException.hpp>
      33             : #include <com/sun/star/uno/XComponentContext.hpp>
      34             : #include <com/sun/star/uri/UriReferenceFactory.hpp>
      35             : #include <com/sun/star/uri/XUriReference.hpp>
      36             : #include <com/sun/star/uri/XUriReferenceFactory.hpp>
      37             : #include <comphelper/processfactory.hxx>
      38             : #include <osl/diagnose.h>
      39             : #include <rtl/character.hxx>
      40             : #include <rtl/instance.hxx>
      41             : #include <rtl/ustrbuf.hxx>
      42             : #include <rtl/ustring.h>
      43             : #include <rtl/ustring.hxx>
      44             : #include <sal/types.h>
      45             : #include <tools/inetmime.hxx>
      46             : #include <unotools/charclass.hxx>
      47             : 
      48             : using namespace com::sun::star;
      49             : 
      50          40 : OUString URIHelper::SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
      51             :                                  OUString const & rTheRelURIRef,
      52             :                                  Link<OUString *, bool> const & rMaybeFileHdl,
      53             :                                  bool bCheckFileExists,
      54             :                                  bool bIgnoreFragment,
      55             :                                  INetURLObject::EncodeMechanism eEncodeMechanism,
      56             :                                  INetURLObject::DecodeMechanism eDecodeMechanism,
      57             :                                  rtl_TextEncoding eCharset,
      58             :                                  bool bRelativeNonURIs,
      59             :                                  INetURLObject::FSysStyle eStyle)
      60             : {
      61             :     // Backwards compatibility:
      62          40 :     if( rTheRelURIRef.startsWith("#") )
      63           0 :         return rTheRelURIRef;
      64             : 
      65          40 :     INetURLObject aAbsURIRef;
      66          40 :     if (rTheBaseURIRef.HasError())
      67          24 :         aAbsURIRef. SetSmartURL(rTheRelURIRef, eEncodeMechanism, eCharset, eStyle);
      68             :     else
      69             :     {
      70             :         bool bWasAbsolute;
      71          32 :         aAbsURIRef = rTheBaseURIRef.smartRel2Abs(rTheRelURIRef,
      72             :                                                  bWasAbsolute,
      73             :                                                  bIgnoreFragment,
      74             :                                                  eEncodeMechanism,
      75             :                                                  eCharset,
      76             :                                                  bRelativeNonURIs,
      77          16 :                                                  eStyle);
      78          16 :         if (bCheckFileExists
      79           4 :             && !bWasAbsolute
      80          20 :             && (aAbsURIRef.GetProtocol() == INetProtocol::File))
      81             :         {
      82           4 :             INetURLObject aNonFileURIRef;
      83             :             aNonFileURIRef.SetSmartURL(rTheRelURIRef,
      84             :                                        eEncodeMechanism,
      85             :                                        eCharset,
      86           4 :                                        eStyle);
      87           8 :             if (!aNonFileURIRef.HasError()
      88           4 :                 && aNonFileURIRef.GetProtocol() != INetProtocol::File)
      89             :             {
      90           0 :                 bool bMaybeFile = false;
      91           0 :                 if (rMaybeFileHdl.IsSet())
      92             :                 {
      93           0 :                     OUString aFilePath(rTheRelURIRef);
      94           0 :                     bMaybeFile = rMaybeFileHdl.Call(&aFilePath);
      95             :                 }
      96           0 :                 if (!bMaybeFile)
      97           0 :                     aAbsURIRef = aNonFileURIRef;
      98           4 :             }
      99             :         }
     100             :     }
     101          40 :     return aAbsURIRef.GetMainURL(eDecodeMechanism, eCharset);
     102             : }
     103             : 
     104             : namespace { struct MaybeFileHdl : public rtl::Static< Link<OUString *, bool>, MaybeFileHdl > {}; }
     105             : 
     106          63 : void URIHelper::SetMaybeFileHdl(Link<OUString *, bool> const & rTheMaybeFileHdl)
     107             : {
     108          63 :     MaybeFileHdl::get() = rTheMaybeFileHdl;
     109          63 : }
     110             : 
     111          28 : Link<OUString *, bool> URIHelper::GetMaybeFileHdl()
     112             : {
     113          28 :     return MaybeFileHdl::get();
     114             : }
     115             : 
     116             : namespace {
     117             : 
     118          16 : bool isAbsoluteHierarchicalUriReference(
     119             :     css::uno::Reference< css::uri::XUriReference > const & uriReference)
     120             : {
     121          32 :     return uriReference.is() && uriReference->isAbsolute()
     122          32 :         && uriReference->isHierarchical() && !uriReference->hasRelativePath();
     123             : }
     124             : 
     125             : // To improve performance, assume that if for any prefix URL of a given
     126             : // hierarchical URL either a UCB content cannot be created, or the UCB content
     127             : // does not support the getCasePreservingURL command, then this will hold for
     128             : // any other prefix URL of the given URL, too:
     129             : enum Result { Success, GeneralFailure, SpecificFailure };
     130             : 
     131          96 : Result normalizePrefix( css::uno::Reference< css::ucb::XUniversalContentBroker > const & broker,
     132             :                         OUString const & uri, OUString * normalized)
     133             : {
     134             :     OSL_ASSERT(broker.is() && normalized != 0);
     135          96 :     css::uno::Reference< css::ucb::XContent > content;
     136             :     try {
     137          96 :         content = broker->queryContent(broker->createContentIdentifier(uri));
     138           0 :     } catch (css::ucb::IllegalIdentifierException &) {}
     139          96 :     if (!content.is()) {
     140          23 :         return GeneralFailure;
     141             :     }
     142             :     try {
     143             :         #if OSL_DEBUG_LEVEL > 0
     144             :         bool ok =
     145             :         #endif
     146             :             (css::uno::Reference< css::ucb::XCommandProcessor >(
     147         146 :                    content, css::uno::UNO_QUERY_THROW)->execute(
     148             :                        css::ucb::Command("getCasePreservingURL",
     149             :                            -1, css::uno::Any()),
     150             :                        0,
     151          73 :                        css::uno::Reference< css::ucb::XCommandEnvironment >())
     152          81 :                >>= *normalized);
     153             :         OSL_ASSERT(ok);
     154           0 :     } catch (css::uno::RuntimeException &) {
     155           0 :         throw;
     156           0 :     } catch (css::ucb::UnsupportedCommandException &) {
     157           0 :         return GeneralFailure;
     158          16 :     } catch (css::uno::Exception &) {
     159           8 :         return SpecificFailure;
     160             :     }
     161          65 :     return Success;
     162             : }
     163             : 
     164          88 : OUString normalize(
     165             :     css::uno::Reference< css::ucb::XUniversalContentBroker > const & broker,
     166             :     css::uno::Reference< css::uri::XUriReferenceFactory > const & uriFactory,
     167             :     OUString const & uriReference)
     168             : {
     169             :     // normalizePrefix can potentially fail (a typically example being a file
     170             :     // URL that denotes a non-existing resource); in such a case, try to
     171             :     // normalize as long a prefix of the given URL as possible (i.e., normalize
     172             :     // all the existing directories within the path):
     173          88 :     OUString normalized;
     174          88 :     sal_Int32 n = uriReference.indexOf('#');
     175          88 :     normalized = n == -1 ? uriReference : uriReference.copy(0, n);
     176          88 :     switch (normalizePrefix(broker, normalized, &normalized)) {
     177             :     case Success:
     178          57 :         return n == -1 ? normalized : normalized + uriReference.copy(n);
     179             :     case GeneralFailure:
     180          23 :         return uriReference;
     181             :     case SpecificFailure:
     182             :     default:
     183           8 :         break;
     184             :     }
     185             :     css::uno::Reference< css::uri::XUriReference > ref(
     186           8 :         uriFactory->parse(uriReference));
     187           8 :     if (!isAbsoluteHierarchicalUriReference(ref)) {
     188           0 :         return uriReference;
     189             :     }
     190           8 :     sal_Int32 count = ref->getPathSegmentCount();
     191           8 :     if (count < 2) {
     192           0 :         return uriReference;
     193             :     }
     194          16 :     OUStringBuffer head(ref->getScheme());
     195           8 :     head.append(':');
     196           8 :     if (ref->hasAuthority()) {
     197           0 :         head.append("//");
     198           0 :         head.append(ref->getAuthority());
     199             :     }
     200           8 :     for (sal_Int32 i = count - 1; i > 0; --i) {
     201           8 :         OUStringBuffer buf(head);
     202          20 :         for (sal_Int32 j = 0; j < i; ++j) {
     203          12 :             buf.append('/');
     204          12 :             buf.append(ref->getPathSegment(j));
     205             :         }
     206           8 :         normalized = buf.makeStringAndClear();
     207           8 :         if (normalizePrefix(broker, normalized, &normalized) != SpecificFailure)
     208             :         {
     209           8 :             buf.append(normalized);
     210             :             css::uno::Reference< css::uri::XUriReference > preRef(
     211           8 :                 uriFactory->parse(normalized));
     212           8 :             if (!isAbsoluteHierarchicalUriReference(preRef)) {
     213             :                 // This could only happen if something is inconsistent:
     214           0 :                 break;
     215             :             }
     216           8 :             sal_Int32 preCount = preRef->getPathSegmentCount();
     217             :             // normalizePrefix may have added or removed a final slash:
     218           8 :             if (preCount != i) {
     219           3 :                 if (preCount == i - 1) {
     220           1 :                     buf.append('/');
     221           6 :                 } else if (preCount - 1 == i && !buf.isEmpty()
     222           4 :                            && buf[buf.getLength() - 1] == '/')
     223             :                 {
     224           2 :                     buf.setLength(buf.getLength() - 1);
     225             :                 } else {
     226             :                     // This could only happen if something is inconsistent:
     227           0 :                     break;
     228             :                 }
     229             :             }
     230          16 :             for (sal_Int32 j = i; j < count; ++j) {
     231           8 :                 buf.append('/');
     232           8 :                 buf.append(ref->getPathSegment(j));
     233             :             }
     234           8 :             if (ref->hasQuery()) {
     235           0 :                 buf.append('?');
     236           0 :                 buf.append(ref->getQuery());
     237             :             }
     238           8 :             if (ref->hasFragment()) {
     239           1 :                 buf.append('#');
     240           1 :                 buf.append(ref->getFragment());
     241             :             }
     242           8 :             return buf.makeStringAndClear();
     243             :         }
     244           0 :     }
     245           8 :     return uriReference;
     246             : }
     247             : 
     248             : }
     249             : 
     250             : css::uno::Reference< css::uri::XUriReference >
     251          44 : URIHelper::normalizedMakeRelative(
     252             :     css::uno::Reference< css::uno::XComponentContext > const & context,
     253             :     OUString const & baseUriReference, OUString const & uriReference)
     254             : {
     255             :     OSL_ASSERT(context.is());
     256             :     css::uno::Reference< css::ucb::XUniversalContentBroker > broker(
     257          44 :         css::ucb::UniversalContentBroker::create(context));
     258             :     css::uno::Reference< css::uri::XUriReferenceFactory > uriFactory(
     259          88 :         css::uri::UriReferenceFactory::create(context));
     260          44 :     return uriFactory->makeRelative(
     261          44 :         uriFactory->parse(normalize(broker, uriFactory, baseUriReference)),
     262          44 :         uriFactory->parse(normalize(broker, uriFactory, uriReference)), true,
     263         176 :         true, false);
     264             : }
     265             : 
     266          32 : OUString URIHelper::simpleNormalizedMakeRelative(
     267             :     OUString const & baseUriReference, OUString const & uriReference)
     268             : {
     269             :     com::sun::star::uno::Reference< com::sun::star::uri::XUriReference > rel(
     270             :         URIHelper::normalizedMakeRelative(
     271             :             comphelper::getProcessComponentContext(), baseUriReference,
     272          32 :             uriReference));
     273          32 :     return rel.is() ? rel->getUriReference() : uriReference;
     274             : }
     275             : 
     276             : 
     277             : //  FindFirstURLInText
     278             : 
     279             : 
     280             : namespace {
     281             : 
     282         746 : inline sal_Int32 nextChar(OUString const & rStr, sal_Int32 nPos)
     283             : {
     284         746 :     return rtl::isHighSurrogate(rStr[nPos])
     285           0 :            && rStr.getLength() - nPos >= 2
     286           0 :            && rtl::isLowSurrogate(rStr[nPos + 1]) ?
     287         746 :         nPos + 2 : nPos + 1;
     288             : }
     289             : 
     290         771 : bool isBoundary1(CharClass const & rCharClass, OUString const & rStr,
     291             :                  sal_Int32 nPos, sal_Int32 nEnd)
     292             : {
     293         771 :     if (nPos == nEnd)
     294           8 :         return true;
     295         763 :     if (rCharClass.isLetterNumeric(rStr, nPos))
     296         599 :         return false;
     297         164 :     switch (rStr[nPos])
     298             :     {
     299             :     case '$':
     300             :     case '%':
     301             :     case '&':
     302             :     case '-':
     303             :     case '/':
     304             :     case '@':
     305             :     case '\\':
     306          19 :         return false;
     307             :     default:
     308         145 :         return true;
     309             :     }
     310             : }
     311             : 
     312         746 : bool isBoundary2(CharClass const & rCharClass, OUString const & rStr,
     313             :                  sal_Int32 nPos, sal_Int32 nEnd)
     314             : {
     315         746 :     if (nPos == nEnd)
     316           0 :         return true;
     317         746 :     if (rCharClass.isLetterNumeric(rStr, nPos))
     318         599 :         return false;
     319         147 :     switch (rStr[nPos])
     320             :     {
     321             :     case '!':
     322             :     case '#':
     323             :     case '$':
     324             :     case '%':
     325             :     case '&':
     326             :     case '\'':
     327             :     case '*':
     328             :     case '+':
     329             :     case '-':
     330             :     case '/':
     331             :     case '=':
     332             :     case '?':
     333             :     case '@':
     334             :     case '^':
     335             :     case '_':
     336             :     case '`':
     337             :     case '{':
     338             :     case '|':
     339             :     case '}':
     340             :     case '~':
     341          15 :         return false;
     342             :     default:
     343         132 :         return true;
     344             :     }
     345             : }
     346             : 
     347         221 : bool checkWChar(CharClass const & rCharClass, OUString const & rStr,
     348             :                 sal_Int32 * pPos, sal_Int32 * pEnd, bool bBackslash = false,
     349             :                 bool bPipe = false)
     350             : {
     351         221 :     sal_Unicode c = rStr[*pPos];
     352         221 :     if (rtl::isAscii(c))
     353             :     {
     354             :         static sal_uInt8 const aMap[128]
     355             :             = { 0, 0, 0, 0, 0, 0, 0, 0,
     356             :                 0, 0, 0, 0, 0, 0, 0, 0,
     357             :                 0, 0, 0, 0, 0, 0, 0, 0,
     358             :                 0, 0, 0, 0, 0, 0, 0, 0,
     359             :                 0, 1, 0, 0, 4, 4, 4, 1,   //  !"#$%&'
     360             :                 1, 1, 1, 1, 1, 4, 1, 4,   // ()*+,-./
     361             :                 4, 4, 4, 4, 4, 4, 4, 4,   // 01234567
     362             :                 4, 4, 1, 1, 0, 1, 0, 1,   // 89:;<=>?
     363             :                 4, 4, 4, 4, 4, 4, 4, 4,   // @ABCDEFG
     364             :                 4, 4, 4, 4, 4, 4, 4, 4,   // HIJKLMNO
     365             :                 4, 4, 4, 4, 4, 4, 4, 4,   // PQRSTUVW
     366             :                 4, 4, 4, 1, 2, 1, 0, 1,   // XYZ[\]^_
     367             :                 0, 4, 4, 4, 4, 4, 4, 4,   // `abcdefg
     368             :                 4, 4, 4, 4, 4, 4, 4, 4,   // hijklmno
     369             :                 4, 4, 4, 4, 4, 4, 4, 4,   // pqrstuvw
     370             :                 4, 4, 4, 0, 3, 0, 1, 0 }; // xyz{|}~
     371         221 :         switch (aMap[c])
     372             :         {
     373             :             default: // not uric
     374           4 :                 return false;
     375             : 
     376             :             case 1: // uric
     377          41 :                 ++(*pPos);
     378          41 :                 return true;
     379             : 
     380             :             case 2: // "\"
     381           0 :                 if (bBackslash)
     382             :                 {
     383           0 :                     *pEnd = ++(*pPos);
     384           0 :                     return true;
     385             :                 }
     386             :                 else
     387           0 :                     return false;
     388             : 
     389             :             case 3: // "|"
     390           5 :                 if (bPipe)
     391             :                 {
     392           5 :                     *pEnd = ++(*pPos);
     393           5 :                     return true;
     394             :                 }
     395             :                 else
     396           0 :                     return false;
     397             : 
     398             :             case 4: // alpha, digit, "$", "%", "&", "-", "/", "@" (see
     399             :                     // isBoundary1)
     400         171 :                 *pEnd = ++(*pPos);
     401         171 :                 return true;
     402             :         }
     403             :     }
     404           0 :     else if (rCharClass.isLetterNumeric(rStr, *pPos))
     405             :     {
     406           0 :         *pEnd = *pPos = nextChar(rStr, *pPos);
     407           0 :         return true;
     408             :     }
     409             :     else
     410           0 :         return false;
     411             : }
     412             : 
     413         133 : sal_uInt32 scanDomain(OUString const & rStr, sal_Int32 * pPos,
     414             :                       sal_Int32 nEnd)
     415             : {
     416         133 :     sal_Unicode const * pBuffer = rStr.getStr();
     417         133 :     sal_Unicode const * p = pBuffer + *pPos;
     418         133 :     sal_uInt32 nLabels = INetURLObject::scanDomain(p, pBuffer + nEnd, false);
     419         133 :     *pPos = sal::static_int_cast< sal_Int32 >(p - pBuffer);
     420         133 :     return nLabels;
     421             : }
     422             : 
     423             : }
     424             : 
     425          73 : OUString URIHelper::FindFirstURLInText(OUString const & rText,
     426             :                                        sal_Int32 & rBegin,
     427             :                                        sal_Int32 & rEnd,
     428             :                                        CharClass const & rCharClass,
     429             :                                        INetURLObject::EncodeMechanism eMechanism,
     430             :                                        rtl_TextEncoding eCharset,
     431             :                                        INetURLObject::FSysStyle eStyle)
     432             : {
     433          73 :     if (!(rBegin <= rEnd && rEnd <= rText.getLength()))
     434           0 :         return OUString();
     435             : 
     436             :     // Search for the first substring of [rBegin..rEnd[ that matches any of the
     437             :     // following productions (for which the appropriate style bit is set in
     438             :     // eStyle, if applicable).
     439             : 
     440             :     // 1st Production (known scheme):
     441             :     //    \B1 <one of the known schemes, except file> ":" 1*wchar ["#" 1*wchar]
     442             :     //        \B1
     443             : 
     444             :     // 2nd Production (file):
     445             :     //    \B1 "FILE:" 1*(wchar / "\" / "|") ["#" 1*wchar] \B1
     446             : 
     447             :     // 3rd Production (ftp):
     448             :     //    \B1 "FTP" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
     449             : 
     450             :     // 4th Production (http):
     451             :     //    \B1 "WWW" 2*("." label) ["/" *wchar] ["#" 1*wchar] \B1
     452             : 
     453             :     // 5th Production (mailto):
     454             :     //    \B2 local-part "@" domain \B1
     455             : 
     456             :     // 6th Production (UNC file):
     457             :     //    \B1 "\\" domain "\" *(wchar / "\") \B1
     458             : 
     459             :     // 7th Production (DOS file):
     460             :     //    \B1 ALPHA ":\" *(wchar / "\") \B1
     461             : 
     462             :     // 8th Production (Unix-like DOS file):
     463             :     //    \B1 ALPHA ":/" *(wchar / "\") \B1
     464             : 
     465             :     // The productions use the following auxiliary rules.
     466             : 
     467             :     //    local-part = atom *("." atom)
     468             :     //    atom = 1*(alphanum / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+"
     469             :     //              / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}"
     470             :     //              / "~")
     471             :     //    domain = label *("." label)
     472             :     //    label = alphanum [*(alphanum / "-") alphanum]
     473             :     //    alphanum = ALPHA / DIGIT
     474             :     //    wchar = <any uric character (ignoring the escaped rule), or "%", or
     475             :     //             a letter or digit (according to rCharClass)>
     476             : 
     477             :     // "\B1" (boundary 1) stands for the beginning or end of the block of text,
     478             :     // or a character that is neither (a) a letter or digit (according to
     479             :     // rCharClass), nor (b) any of "$", "%", "&", "-", "/", "@", or "\".
     480             :     // (FIXME:  What was the rationale for this set of punctuation characters?)
     481             : 
     482             :     // "\B2" (boundary 2) stands for the beginning or end of the block of text,
     483             :     // or a character that is neither (a) a letter or digit (according to
     484             :     // rCharClass), nor (b) any of "!", "#", "$", "%", "&", "'", "*", "+", "-",
     485             :     // "/", "=", "?", "@", "^", "_", "`", "{", "|", "}", or "~" (i.e., an RFC
     486             :     // 822 <atom> character, or "@" from \B1's set above).
     487             : 
     488             :     // Productions 1--4, and 6--8 try to find a maximum-length match, but they
     489             :     // stop at the first <wchar> character that is a "\B1" character which is
     490             :     // only followed by "\B1" characters (taking "\" and "|" characters into
     491             :     // account appropriately).  Production 5 simply tries to find a maximum-
     492             :     // length match.
     493             : 
     494             :     // Productions 1--4 use the given eMechanism and eCharset.  Productions 5--9
     495             :     // use ENCODE_ALL.
     496             : 
     497             :     // Productions 6--9 are only applicable if the FSYS_DOS bit is set in
     498             :     // eStyle.
     499             : 
     500          73 :     bool bBoundary1 = true;
     501          73 :     bool bBoundary2 = true;
     502         819 :     for (sal_Int32 nPos = rBegin; nPos != rEnd; nPos = nextChar(rText, nPos))
     503             :     {
     504         766 :         sal_Unicode c = rText[nPos];
     505         766 :         if (bBoundary1)
     506             :         {
     507         160 :             if (rtl::isAsciiAlpha(c))
     508             :             {
     509         132 :                 sal_Int32 i = nPos;
     510         132 :                 INetProtocol eScheme = INetURLObject::CompareProtocolScheme(rText.copy(i, rEnd - i));
     511         132 :                 if (eScheme == INetProtocol::File) // 2nd
     512             :                 {
     513           5 :                     while (rText[i++] != ':') ;
     514           5 :                     sal_Int32 nPrefixEnd = i;
     515           5 :                     sal_Int32 nUriEnd = i;
     516          43 :                     while (i != rEnd
     517          73 :                            && checkWChar(rCharClass, rText, &i, &nUriEnd, true,
     518          35 :                                          true)) ;
     519           5 :                     if (i != nPrefixEnd && i != rEnd && rText[i] == '#')
     520             :                     {
     521           2 :                         ++i;
     522          12 :                         while (i != rEnd
     523          10 :                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     524             :                     }
     525          10 :                     if (nUriEnd != nPrefixEnd
     526           5 :                         && isBoundary1(rCharClass, rText, nUriEnd, rEnd))
     527             :                     {
     528             :                         INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
     529             :                                            INetProtocol::File, eMechanism, eCharset,
     530           4 :                                            eStyle);
     531           4 :                         if (!aUri.HasError())
     532             :                         {
     533           4 :                             rBegin = nPos;
     534           4 :                             rEnd = nUriEnd;
     535             :                             return
     536           4 :                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
     537           0 :                         }
     538             :                     }
     539             :                 }
     540         127 :                 else if (eScheme != INetProtocol::NotValid) // 1st
     541             :                 {
     542          38 :                     while (rText[i++] != ':') ;
     543          38 :                     sal_Int32 nPrefixEnd = i;
     544          38 :                     sal_Int32 nUriEnd = i;
     545         212 :                     while (i != rEnd
     546         174 :                            && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     547          38 :                     if (i != nPrefixEnd && i != rEnd && rText[i] == '#')
     548             :                     {
     549           0 :                         ++i;
     550           0 :                         while (i != rEnd
     551           0 :                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     552             :                     }
     553          76 :                     if (nUriEnd != nPrefixEnd
     554          43 :                         && (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
     555           0 :                             || rText[nUriEnd] == '\\'))
     556             :                     {
     557             :                         INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
     558             :                                            INetProtocol::Http, eMechanism,
     559           5 :                                            eCharset);
     560           5 :                         if (!aUri.HasError())
     561             :                         {
     562           4 :                             rBegin = nPos;
     563           4 :                             rEnd = nUriEnd;
     564             :                             return
     565           4 :                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
     566           1 :                         }
     567             :                     }
     568             :                 }
     569             : 
     570             :                 // 3rd, 4th:
     571         124 :                 i = nPos;
     572         124 :                 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
     573         124 :                 if (nLabels >= 3
     574          26 :                     && rText[nPos + 3] == '.'
     575         152 :                     && (((rText[nPos] == 'w'
     576          22 :                           || rText[nPos] == 'W')
     577           2 :                          && (rText[nPos + 1] == 'w'
     578           1 :                              || rText[nPos + 1] == 'W')
     579           2 :                          && (rText[nPos + 2] == 'w'
     580           1 :                              || rText[nPos + 2] == 'W'))
     581          22 :                         || ((rText[nPos] == 'f'
     582          21 :                              || rText[nPos] == 'F')
     583           2 :                             && (rText[nPos + 1] == 't'
     584           0 :                                 || rText[nPos + 1] == 'T')
     585           2 :                             && (rText[nPos + 2] == 'p'
     586           0 :                                 || rText[nPos + 2] == 'P'))))
     587             :                     // (note that rText.GetChar(nPos + 3) is guaranteed to be
     588             :                     // valid)
     589             :                 {
     590           4 :                     sal_Int32 nUriEnd = i;
     591           4 :                     if (i != rEnd && rText[i] == '/')
     592             :                     {
     593           2 :                         nUriEnd = ++i;
     594          16 :                         while (i != rEnd
     595          14 :                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     596             :                     }
     597           4 :                     if (i != rEnd && rText[i] == '#')
     598             :                     {
     599           0 :                         ++i;
     600           0 :                         while (i != rEnd
     601           0 :                                && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     602             :                     }
     603           8 :                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd)
     604           4 :                         || rText[nUriEnd] == '\\')
     605             :                     {
     606             :                         INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
     607             :                                            INetProtocol::Http, eMechanism,
     608           4 :                                            eCharset);
     609           4 :                         if (!aUri.HasError())
     610             :                         {
     611           4 :                             rBegin = nPos;
     612           4 :                             rEnd = nUriEnd;
     613             :                             return
     614           4 :                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
     615           0 :                         }
     616             :                     }
     617             :                 }
     618             : 
     619         360 :                 if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 3
     620         119 :                     && rText[nPos + 1] == ':'
     621         126 :                     && (rText[nPos + 2] == '/'
     622           1 :                         || rText[nPos + 2] == '\\')) // 7th, 8th
     623             :                 {
     624           3 :                     i = nPos + 3;
     625           3 :                     sal_Int32 nUriEnd = i;
     626          23 :                     while (i != rEnd
     627          20 :                            && checkWChar(rCharClass, rText, &i, &nUriEnd)) ;
     628           3 :                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
     629             :                     {
     630             :                         INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
     631             :                                            INetProtocol::File,
     632             :                                            INetURLObject::ENCODE_ALL,
     633             :                                            RTL_TEXTENCODING_UTF8,
     634           3 :                                            INetURLObject::FSYS_DOS);
     635           3 :                         if (!aUri.HasError())
     636             :                         {
     637           3 :                             rBegin = nPos;
     638           3 :                             rEnd = nUriEnd;
     639             :                             return
     640           3 :                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
     641           0 :                         }
     642             :                     }
     643             :                 }
     644             :             }
     645          84 :             else if ((eStyle & INetURLObject::FSYS_DOS) != 0 && rEnd - nPos >= 2
     646          24 :                      && rText[nPos] == '\\'
     647          31 :                      && rText[nPos + 1] == '\\') // 6th
     648             :             {
     649           1 :                 sal_Int32 i = nPos + 2;
     650           1 :                 sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
     651           1 :                 if (nLabels >= 1 && i != rEnd && rText[i] == '\\')
     652             :                 {
     653           1 :                     sal_Int32 nUriEnd = ++i;
     654          13 :                     while (i != rEnd
     655          23 :                            && checkWChar(rCharClass, rText, &i, &nUriEnd,
     656          11 :                                          true)) ;
     657           1 :                     if (isBoundary1(rCharClass, rText, nUriEnd, rEnd))
     658             :                     {
     659             :                         INetURLObject aUri(rText.copy(nPos, nUriEnd - nPos),
     660             :                                            INetProtocol::File,
     661             :                                            INetURLObject::ENCODE_ALL,
     662             :                                            RTL_TEXTENCODING_UTF8,
     663           1 :                                            INetURLObject::FSYS_DOS);
     664           1 :                         if (!aUri.HasError())
     665             :                         {
     666           1 :                             rBegin = nPos;
     667           1 :                             rEnd = nUriEnd;
     668             :                             return
     669           1 :                                 aUri.GetMainURL(INetURLObject::DECODE_TO_IURI);
     670           0 :                         }
     671             :                     }
     672             :                 }
     673             :             }
     674             :         }
     675         750 :         if (bBoundary2 && INetMIME::isAtomChar(c)) // 5th
     676             :         {
     677         131 :             bool bDot = false;
     678        1096 :             for (sal_Int32 i = nPos + 1; i != rEnd; ++i)
     679             :             {
     680        1080 :                 sal_Unicode c2 = rText[i];
     681        1080 :                 if (INetMIME::isAtomChar(c2))
     682         863 :                     bDot = false;
     683         217 :                 else if (bDot)
     684           6 :                     break;
     685         211 :                 else if (c2 == '.')
     686         102 :                     bDot = true;
     687             :                 else
     688             :                 {
     689         109 :                     if (c2 == '@')
     690             :                     {
     691           8 :                         ++i;
     692           8 :                         sal_uInt32 nLabels = scanDomain(rText, &i, rEnd);
     693           8 :                         if (nLabels >= 1
     694           8 :                             && isBoundary1(rCharClass, rText, i, rEnd))
     695             :                         {
     696             :                             INetURLObject aUri(rText.copy(nPos, i - nPos),
     697             :                                                INetProtocol::Mailto,
     698           4 :                                                INetURLObject::ENCODE_ALL);
     699           4 :                             if (!aUri.HasError())
     700             :                             {
     701           4 :                                 rBegin = nPos;
     702           4 :                                 rEnd = i;
     703             :                                 return aUri.GetMainURL(
     704           4 :                                            INetURLObject::DECODE_TO_IURI);
     705           0 :                             }
     706             :                         }
     707             :                     }
     708         105 :                     break;
     709             :                 }
     710             :             }
     711             :         }
     712         746 :         bBoundary1 = isBoundary1(rCharClass, rText, nPos, rEnd);
     713         746 :         bBoundary2 = isBoundary2(rCharClass, rText, nPos, rEnd);
     714             :     }
     715          53 :     rBegin = rEnd;
     716          53 :     return OUString();
     717             : }
     718             : 
     719          56 : OUString URIHelper::removePassword(OUString const & rURI,
     720             :                                    INetURLObject::EncodeMechanism eEncodeMechanism,
     721             :                                    INetURLObject::DecodeMechanism eDecodeMechanism,
     722             :                                    rtl_TextEncoding eCharset)
     723             : {
     724          56 :     INetURLObject aObj(rURI, eEncodeMechanism, eCharset);
     725          56 :     return aObj.HasError() ?
     726             :                rURI :
     727          56 :                aObj.GetURLNoPass(eDecodeMechanism, eCharset);
     728             : }
     729             : 
     730             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11