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

Generated by: LCOV version 1.10