LCOV - code coverage report
Current view: top level - stoc/source/uriproc - UriReferenceFactory.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 327 0.0 %
Date: 2014-04-14 Functions: 0 37 0.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 "sal/config.h"
      21             : 
      22             : #include <algorithm>
      23             : #include <cassert>
      24             : #include <cstdlib>
      25             : #include <exception>
      26             : #include <vector>
      27             : 
      28             : #include "boost/noncopyable.hpp"
      29             : #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
      30             : #include "com/sun/star/lang/XMultiComponentFactory.hpp"
      31             : #include "com/sun/star/lang/XServiceInfo.hpp"
      32             : #include "com/sun/star/uno/Any.hxx"
      33             : #include "com/sun/star/uno/Exception.hpp"
      34             : #include "com/sun/star/uno/Reference.hxx"
      35             : #include "com/sun/star/uno/RuntimeException.hpp"
      36             : #include "com/sun/star/uno/Sequence.hxx"
      37             : #include "com/sun/star/uno/XComponentContext.hpp"
      38             : #include "com/sun/star/uno/XInterface.hpp"
      39             : #include "com/sun/star/uri/RelativeUriExcessParentSegments.hpp"
      40             : #include "com/sun/star/uri/XUriReference.hpp"
      41             : #include "com/sun/star/uri/XUriReferenceFactory.hpp"
      42             : #include "com/sun/star/uri/XUriSchemeParser.hpp"
      43             : #include "cppuhelper/implbase1.hxx"
      44             : #include "cppuhelper/implbase2.hxx"
      45             : #include "cppuhelper/supportsservice.hxx"
      46             : #include "cppuhelper/weak.hxx"
      47             : #include "rtl/character.hxx"
      48             : #include "rtl/ustrbuf.hxx"
      49             : #include "rtl/ustring.hxx"
      50             : #include "sal/types.h"
      51             : 
      52             : #include "UriReference.hxx"
      53             : #include "stocservices.hxx"
      54             : 
      55             : namespace {
      56             : 
      57           0 : bool equalIgnoreEscapeCase(OUString const & s1, OUString const & s2) {
      58           0 :     if (s1.getLength() == s2.getLength()) {
      59           0 :         for (sal_Int32 i = 0; i < s1.getLength();) {
      60           0 :             if (s1[i] == '%' && s2[i] == '%' && s1.getLength() - i > 2
      61           0 :                 && rtl::isAsciiHexDigit(s1[i + 1])
      62           0 :                 && rtl::isAsciiHexDigit(s1[i + 2])
      63           0 :                 && rtl::isAsciiHexDigit(s2[i + 1])
      64           0 :                 && rtl::isAsciiHexDigit(s2[i + 2])
      65           0 :                 && rtl::compareIgnoreAsciiCase(s1[i + 1], s2[i + 1]) == 0
      66           0 :                 && rtl::compareIgnoreAsciiCase(s1[i + 2], s2[i + 2]) == 0)
      67             :             {
      68           0 :                 i += 3;
      69           0 :             } else if (s1[i] != s2[i]) {
      70           0 :                 return false;
      71             :             } else {
      72           0 :                 ++i;
      73             :             }
      74             :         }
      75           0 :         return true;
      76             :     } else {
      77           0 :         return false;
      78             :     }
      79             : }
      80             : 
      81           0 : sal_Int32 parseScheme(OUString const & uriReference) {
      82           0 :     if (uriReference.getLength() >= 2 && rtl::isAsciiAlpha(uriReference[0])) {
      83           0 :         for (sal_Int32 i = 0; i < uriReference.getLength(); ++i) {
      84           0 :             sal_Unicode c = uriReference[i];
      85           0 :             if (c == ':') {
      86           0 :                 return i;
      87           0 :             } else if (!rtl::isAsciiAlpha(c) && !rtl::isAsciiDigit(c)
      88           0 :                        && c != '+' && c != '-' && c != '.')
      89             :             {
      90           0 :                 break;
      91             :             }
      92             :         }
      93             :     }
      94           0 :     return -1;
      95             : }
      96             : 
      97             : class UriReference:
      98             :     public cppu::WeakImplHelper1<css::uri::XUriReference>,
      99             :     private boost::noncopyable
     100             : {
     101             : public:
     102           0 :     UriReference(
     103             :         OUString const & scheme, bool bIsHierarchical, bool bHasAuthority,
     104             :         OUString const & authority, OUString const & path,
     105             :         bool bHasQuery, OUString const & query):
     106             :         m_base(
     107             :             scheme, bIsHierarchical, bHasAuthority, authority, path, bHasQuery,
     108           0 :             query)
     109           0 :     {}
     110             : 
     111           0 :     virtual OUString SAL_CALL getUriReference()
     112             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     113           0 :     { return m_base.getUriReference(); }
     114             : 
     115           0 :     virtual sal_Bool SAL_CALL isAbsolute()
     116             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     117           0 :     { return m_base.isAbsolute(); }
     118             : 
     119           0 :     virtual OUString SAL_CALL getScheme()
     120             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     121           0 :     { return m_base.getScheme(); }
     122             : 
     123           0 :     virtual OUString SAL_CALL getSchemeSpecificPart()
     124             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     125           0 :     { return m_base.getSchemeSpecificPart(); }
     126             : 
     127           0 :     virtual sal_Bool SAL_CALL isHierarchical()
     128             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     129           0 :     { return m_base.isHierarchical(); }
     130             : 
     131           0 :     virtual sal_Bool SAL_CALL hasAuthority()
     132             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     133           0 :     { return m_base.hasAuthority(); }
     134             : 
     135           0 :     virtual OUString SAL_CALL getAuthority()
     136             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     137           0 :     { return m_base.getAuthority(); }
     138             : 
     139           0 :     virtual OUString SAL_CALL getPath()
     140             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     141           0 :     { return m_base.getPath(); }
     142             : 
     143           0 :     virtual sal_Bool SAL_CALL hasRelativePath()
     144             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     145           0 :     { return m_base.hasRelativePath(); }
     146             : 
     147           0 :     virtual sal_Int32 SAL_CALL getPathSegmentCount()
     148             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     149           0 :     { return m_base.getPathSegmentCount(); }
     150             : 
     151           0 :     virtual OUString SAL_CALL getPathSegment(sal_Int32 index)
     152             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     153           0 :     { return m_base.getPathSegment(index); }
     154             : 
     155           0 :     virtual sal_Bool SAL_CALL hasQuery()
     156             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     157           0 :     { return m_base.hasQuery(); }
     158             : 
     159           0 :     virtual OUString SAL_CALL getQuery()
     160             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     161           0 :     { return m_base.getQuery(); }
     162             : 
     163           0 :     virtual sal_Bool SAL_CALL hasFragment()
     164             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     165           0 :     { return m_base.hasFragment(); }
     166             : 
     167           0 :     virtual OUString SAL_CALL getFragment()
     168             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     169           0 :     { return m_base.getFragment(); }
     170             : 
     171           0 :     virtual void SAL_CALL setFragment(OUString const & fragment)
     172             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     173           0 :     { m_base.setFragment(fragment); }
     174             : 
     175           0 :     virtual void SAL_CALL clearFragment()
     176             :         throw (com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
     177           0 :     { m_base.clearFragment(); }
     178             : 
     179             : private:
     180           0 :     virtual ~UriReference() {}
     181             : 
     182             :     stoc::uriproc::UriReference m_base;
     183             : };
     184             : 
     185           0 : css::uno::Reference< css::uri::XUriReference > parseGeneric(
     186             :     OUString const & scheme, OUString const & schemeSpecificPart)
     187             : {
     188           0 :     bool isAbsolute = !scheme.isEmpty();
     189           0 :     bool isHierarchical = !isAbsolute || schemeSpecificPart.startsWith("/");
     190           0 :     bool hasAuthority = false;
     191           0 :     OUString authority;
     192           0 :     OUString path;
     193           0 :     bool hasQuery = false;
     194           0 :     OUString query;
     195           0 :     if (isHierarchical) {
     196           0 :         sal_Int32 len = schemeSpecificPart.getLength();
     197           0 :         sal_Int32 i = 0;
     198           0 :         if (len - i >= 2 && schemeSpecificPart[i] == '/'
     199           0 :             && schemeSpecificPart[i + 1] == '/')
     200             :         {
     201           0 :             i += 2;
     202           0 :             sal_Int32 n = i;
     203           0 :             while (i < len && schemeSpecificPart[i] != '/'
     204           0 :                    && schemeSpecificPart[i] != '?') {
     205           0 :                 ++i;
     206             :             }
     207           0 :             hasAuthority = true;
     208           0 :             authority = schemeSpecificPart.copy(n, i - n);
     209             :         }
     210           0 :         sal_Int32 n = i;
     211           0 :         i = schemeSpecificPart.indexOf('?', i);
     212           0 :         if (i == -1) {
     213           0 :             i = len;
     214             :         }
     215           0 :         path = schemeSpecificPart.copy(n, i - n);
     216           0 :         if (i != len) {
     217           0 :             hasQuery = true;
     218           0 :             query = schemeSpecificPart.copy(i + 1);
     219             :         }
     220             :     } else {
     221           0 :         if (schemeSpecificPart.isEmpty()) {
     222             :             // The scheme-specific part of an opaque URI must not be empty:
     223           0 :             return 0;
     224             :         }
     225           0 :         path = schemeSpecificPart;
     226             :     }
     227             :     return new UriReference(
     228           0 :         scheme, isHierarchical, hasAuthority, authority, path, hasQuery, query);
     229             : }
     230             : 
     231             : typedef std::vector< sal_Int32 > Segments;
     232             : 
     233           0 : void processSegments(
     234             :     Segments & segments,
     235             :     css::uno::Reference< css::uri::XUriReference > const & uriReference,
     236             :     bool base, bool processSpecialSegments)
     237             : {
     238           0 :     sal_Int32 count = uriReference->getPathSegmentCount() - (base ? 1 : 0);
     239             :     assert(count <= SAL_MAX_INT32 - 1 && -count >= SAL_MIN_INT32 + 1);
     240           0 :     for (sal_Int32 i = 0; i < count; ++i) {
     241           0 :         if (processSpecialSegments) {
     242           0 :             OUString segment(uriReference->getPathSegment(i));
     243           0 :             if ( segment == "." ) {
     244           0 :                 if (!base && i == count - 1) {
     245           0 :                     segments.push_back(0);
     246             :                 }
     247           0 :                 continue;
     248           0 :             } else if ( segment == ".." ) {
     249           0 :                 if (segments.empty() || std::abs(segments.back()) == 1) {
     250           0 :                     segments.push_back(base ? -1 : 1);
     251             :                 } else {
     252           0 :                     segments.pop_back();
     253             :                 }
     254           0 :                 continue;
     255           0 :             }
     256             :         }
     257           0 :         segments.push_back(base ? -(i + 2) : i + 2);
     258             :     }
     259           0 : }
     260             : 
     261             : class Factory:
     262             :     public cppu::WeakImplHelper2<
     263             :         css::lang::XServiceInfo, css::uri::XUriReferenceFactory>,
     264             :     private boost::noncopyable
     265             : {
     266             : public:
     267           0 :     explicit Factory(
     268             :         css::uno::Reference< css::uno::XComponentContext > const & context):
     269           0 :         m_context(context) {}
     270             : 
     271             :     virtual OUString SAL_CALL getImplementationName()
     272             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     273             : 
     274             :     virtual sal_Bool SAL_CALL supportsService(OUString const & serviceName)
     275             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     276             : 
     277             :     virtual css::uno::Sequence< OUString > SAL_CALL
     278             :     getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     279             : 
     280             :     virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
     281             :     parse(OUString const & uriReference)
     282             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     283             : 
     284             :     virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
     285             :     makeAbsolute(
     286             :         css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
     287             :         css::uno::Reference< css::uri::XUriReference > const & uriReference,
     288             :         sal_Bool processSpecialBaseSegments,
     289             :         css::uri::RelativeUriExcessParentSegments excessParentSegments)
     290             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     291             : 
     292             :     virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL
     293             :     makeRelative(
     294             :         css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
     295             :         css::uno::Reference< css::uri::XUriReference > const & uriReference,
     296             :         sal_Bool preferAuthorityOverRelativePath,
     297             :         sal_Bool preferAbsoluteOverRelativePath,
     298             :         sal_Bool encodeRetainedSpecialSegments)
     299             :         throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
     300             : 
     301             : private:
     302           0 :     virtual ~Factory() {}
     303             : 
     304           0 :     css::uno::Reference< css::uri::XUriReference > clone(
     305             :         css::uno::Reference< css::uri::XUriReference > const & uriReference)
     306           0 :     { return parse(uriReference->getUriReference()); }
     307             : 
     308             :     css::uno::Reference< css::uno::XComponentContext > m_context;
     309             : };
     310             : 
     311           0 : OUString Factory::getImplementationName()
     312             :     throw (css::uno::RuntimeException, std::exception)
     313             : {
     314           0 :     return stoc_services::UriReferenceFactory::getImplementationName();
     315             : }
     316             : 
     317           0 : sal_Bool Factory::supportsService(OUString const & serviceName)
     318             :     throw (css::uno::RuntimeException, std::exception)
     319             : {
     320           0 :     return cppu::supportsService(this, serviceName);
     321             : }
     322             : 
     323           0 : css::uno::Sequence< OUString > Factory::getSupportedServiceNames()
     324             :     throw (css::uno::RuntimeException, std::exception)
     325             : {
     326           0 :     return stoc_services::UriReferenceFactory::getSupportedServiceNames();
     327             : }
     328             : 
     329           0 : css::uno::Reference< css::uri::XUriReference > Factory::parse(
     330             :     OUString const & uriReference)
     331             :     throw (css::uno::RuntimeException, std::exception)
     332             : {
     333           0 :     sal_Int32 fragment = uriReference.indexOf('#');
     334           0 :     if (fragment == -1) {
     335           0 :         fragment = uriReference.getLength();
     336             :     }
     337           0 :     OUString scheme;
     338           0 :     OUString schemeSpecificPart;
     339           0 :     OUString serviceName;
     340           0 :     sal_Int32 n = parseScheme(uriReference);
     341             :     assert(n < fragment);
     342           0 :     if (n >= 0) {
     343           0 :         scheme = uriReference.copy(0, n);
     344           0 :         schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1));
     345           0 :         OUStringBuffer buf;
     346           0 :         buf.append("com.sun.star.uri.UriSchemeParser_");
     347           0 :         for (sal_Int32 i = 0; i < scheme.getLength(); ++i) {
     348           0 :             sal_Unicode c = scheme[i];
     349           0 :             if (rtl::isAsciiUpperCase(c)) {
     350           0 :                 buf.append(static_cast<sal_Unicode>(rtl::toAsciiLowerCase(c)));
     351           0 :             } else if (c == '+') {
     352           0 :                 buf.append("PLUS");
     353           0 :             } else if (c == '-') {
     354           0 :                 buf.append("HYPHEN");
     355           0 :             } else if (c == '.') {
     356           0 :                 buf.append("DOT");
     357             :             } else {
     358             :                 assert(rtl::isAsciiLowerCase(c) || rtl::isAsciiDigit(c));
     359           0 :                 buf.append(c);
     360             :             }
     361             :         }
     362           0 :         serviceName = buf.makeStringAndClear();
     363             :     } else {
     364           0 :         schemeSpecificPart = uriReference.copy(0, fragment);
     365             :     }
     366           0 :     css::uno::Reference< css::uri::XUriSchemeParser > parser;
     367           0 :     if (!serviceName.isEmpty()) {
     368             :         css::uno::Reference< css::lang::XMultiComponentFactory > factory(
     369           0 :             m_context->getServiceManager());
     370           0 :         if (factory.is()) {
     371           0 :             css::uno::Reference< css::uno::XInterface > service;
     372             :             try {
     373           0 :                 service = factory->createInstanceWithContext(
     374           0 :                     serviceName, m_context);
     375           0 :             } catch (css::uno::RuntimeException &) {
     376           0 :                 throw;
     377           0 :             } catch (const css::uno::Exception & e) {
     378             :                 throw css::lang::WrappedTargetRuntimeException(
     379           0 :                     "creating service " + serviceName,
     380             :                     static_cast< cppu::OWeakObject * >(this),
     381           0 :                     css::uno::makeAny(e)); //TODO: preserve type of e
     382             :             }
     383           0 :             if (service.is()) {
     384           0 :                 parser = css::uno::Reference< css::uri::XUriSchemeParser >(
     385           0 :                     service, css::uno::UNO_QUERY_THROW);
     386           0 :             }
     387           0 :         }
     388             :     }
     389             :     css::uno::Reference< css::uri::XUriReference > uriRef(
     390           0 :         parser.is()
     391           0 :         ? parser->parse(scheme, schemeSpecificPart)
     392           0 :         : parseGeneric(scheme, schemeSpecificPart));
     393           0 :     if (uriRef.is() && fragment != uriReference.getLength()) {
     394           0 :         uriRef->setFragment(uriReference.copy(fragment + 1));
     395             :     }
     396           0 :     return uriRef;
     397             : }
     398             : 
     399           0 : css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute(
     400             :     css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
     401             :     css::uno::Reference< css::uri::XUriReference > const & uriReference,
     402             :     sal_Bool processSpecialBaseSegments,
     403             :     css::uri::RelativeUriExcessParentSegments excessParentSegments)
     404             :     throw (css::uno::RuntimeException, std::exception)
     405             : {
     406           0 :     if (!baseUriReference.is() || !baseUriReference->isAbsolute()
     407           0 :         || !baseUriReference->isHierarchical() || !uriReference.is()) {
     408           0 :         return 0;
     409           0 :     } else if (uriReference->isAbsolute()) {
     410           0 :         return clone(uriReference);
     411           0 :     } else if (!uriReference->hasAuthority()
     412           0 :                && uriReference->getPath().isEmpty()
     413           0 :                && !uriReference->hasQuery()) {
     414             :         css::uno::Reference< css::uri::XUriReference > abs(
     415           0 :             clone(baseUriReference));
     416           0 :         if (uriReference->hasFragment()) {
     417           0 :             abs->setFragment(uriReference->getFragment());
     418             :         } else {
     419           0 :             abs->clearFragment();
     420             :         }
     421           0 :         return abs;
     422             :     } else {
     423           0 :         OUStringBuffer abs(baseUriReference->getScheme());
     424           0 :         abs.append(':');
     425           0 :         if (uriReference->hasAuthority()) {
     426           0 :             abs.append("//");
     427           0 :             abs.append(uriReference->getAuthority());
     428           0 :         } else if (baseUriReference->hasAuthority()) {
     429           0 :             abs.append("//");
     430           0 :             abs.append(baseUriReference->getAuthority());
     431             :         }
     432           0 :         if (uriReference->hasRelativePath()) {
     433           0 :             Segments segments;
     434             :             processSegments(
     435           0 :                 segments, baseUriReference, true, processSpecialBaseSegments);
     436           0 :             processSegments(segments, uriReference, false, true);
     437             :             // If the path component of the base URI reference is empty (which
     438             :             // implies that the base URI reference denotes a "root entity"), and
     439             :             // the resulting URI reference denotes the same root entity, make
     440             :             // sure the path component of the resulting URI reference is also
     441             :             // empty (and not "/").  RFC 2396 is unclear about this, and I chose
     442             :             // these rules for consistent results.
     443           0 :             bool slash = !baseUriReference->getPath().isEmpty();
     444           0 :             if (slash) {
     445           0 :                 abs.append('/');
     446             :             }
     447           0 :             for (Segments::iterator i(segments.begin()); i != segments.end();
     448             :                  ++i)
     449             :             {
     450           0 :                 if (*i < -1) {
     451             :                     OUString segment(
     452           0 :                         baseUriReference->getPathSegment(-(*i + 2)));
     453           0 :                     if (!segment.isEmpty() || segments.size() > 1) {
     454           0 :                         if (!slash) {
     455           0 :                             abs.append('/');
     456             :                         }
     457           0 :                         abs.append(segment);
     458           0 :                         slash = true;
     459           0 :                         abs.append('/');
     460           0 :                     }
     461           0 :                 } else if (*i > 1) {
     462           0 :                     OUString segment(uriReference->getPathSegment(*i - 2));
     463           0 :                     if (!segment.isEmpty() || segments.size() > 1) {
     464           0 :                         if (!slash) {
     465           0 :                             abs.append('/');
     466             :                         }
     467           0 :                         abs.append(segment);
     468           0 :                         slash = false;
     469           0 :                     }
     470           0 :                 } else if (*i == 0) {
     471           0 :                     if (segments.size() > 1 && !slash) {
     472           0 :                         abs.append('/');
     473             :                     }
     474             :                 } else {
     475           0 :                     switch (excessParentSegments) {
     476             :                     case css::uri::RelativeUriExcessParentSegments_ERROR:
     477           0 :                         return 0;
     478             : 
     479             :                     case css::uri::RelativeUriExcessParentSegments_RETAIN:
     480           0 :                         if (!slash) {
     481           0 :                             abs.append('/');
     482             :                         }
     483           0 :                         abs.append("..");
     484           0 :                         slash = *i < 0;
     485           0 :                         if (slash) {
     486           0 :                             abs.append('/');
     487             :                         }
     488           0 :                         break;
     489             : 
     490             :                     case css::uri::RelativeUriExcessParentSegments_REMOVE:
     491           0 :                         break;
     492             : 
     493             :                     default:
     494             :                         assert(false);
     495           0 :                         break;
     496             :                     }
     497             :                 }
     498           0 :             }
     499             :         } else {
     500           0 :             abs.append(uriReference->getPath());
     501             :         }
     502           0 :         if (uriReference->hasQuery()) {
     503           0 :             abs.append('?');
     504           0 :             abs.append(uriReference->getQuery());
     505             :         }
     506           0 :         if (uriReference->hasFragment()) {
     507           0 :             abs.append('#');
     508           0 :             abs.append(uriReference->getFragment());
     509             :         }
     510           0 :         return parse(abs.makeStringAndClear());
     511             :     }
     512             : }
     513             : 
     514           0 : css::uno::Reference< css::uri::XUriReference > Factory::makeRelative(
     515             :     css::uno::Reference< css::uri::XUriReference > const & baseUriReference,
     516             :     css::uno::Reference< css::uri::XUriReference > const & uriReference,
     517             :     sal_Bool preferAuthorityOverRelativePath,
     518             :     sal_Bool preferAbsoluteOverRelativePath,
     519             :     sal_Bool encodeRetainedSpecialSegments)
     520             :     throw (css::uno::RuntimeException, std::exception)
     521             : {
     522           0 :     if (!baseUriReference.is() || !baseUriReference->isAbsolute()
     523           0 :         || !baseUriReference->isHierarchical() || !uriReference.is()) {
     524           0 :         return 0;
     525           0 :     } else if (!uriReference->isAbsolute() || !uriReference->isHierarchical()
     526           0 :                || !baseUriReference->getScheme().equalsIgnoreAsciiCase(
     527           0 :                    uriReference->getScheme())) {
     528           0 :         return clone(uriReference);
     529             :     } else {
     530           0 :         OUStringBuffer rel;
     531           0 :         bool omitQuery = false;
     532           0 :         if ((baseUriReference->hasAuthority() != uriReference->hasAuthority())
     533           0 :             || !equalIgnoreEscapeCase(
     534           0 :                 baseUriReference->getAuthority(),
     535           0 :                 uriReference->getAuthority()))
     536             :         {
     537           0 :             if (uriReference->hasAuthority()) {
     538           0 :                 rel.append("//");
     539           0 :                 rel.append(uriReference->getAuthority());
     540             :             }
     541           0 :             rel.append(uriReference->getPath());
     542           0 :         } else if ((equalIgnoreEscapeCase(
     543           0 :                         baseUriReference->getPath(), uriReference->getPath())
     544           0 :                     || (baseUriReference->getPath().getLength() <= 1
     545           0 :                         && uriReference->getPath().getLength() <= 1))
     546           0 :                    && baseUriReference->hasQuery() == uriReference->hasQuery()
     547           0 :                    && equalIgnoreEscapeCase(
     548           0 :                        baseUriReference->getQuery(), uriReference->getQuery()))
     549             :         {
     550           0 :             omitQuery = true;
     551             :         } else {
     552             :             sal_Int32 count1 = std::max< sal_Int32 >(
     553           0 :                 baseUriReference->getPathSegmentCount(), 1);
     554             :             sal_Int32 count2 = std::max< sal_Int32 >(
     555           0 :                 uriReference->getPathSegmentCount(), 1);
     556           0 :             sal_Int32 i = 0;
     557           0 :             for (; i < std::min(count1, count2) - 1; ++i) {
     558           0 :                 if (!equalIgnoreEscapeCase(
     559           0 :                         baseUriReference->getPathSegment(i),
     560           0 :                         uriReference->getPathSegment(i)))
     561             :                 {
     562           0 :                     break;
     563             :                 }
     564             :             }
     565           0 :             if (i == 0 && preferAbsoluteOverRelativePath
     566           0 :                 && (preferAuthorityOverRelativePath
     567           0 :                     || !uriReference->getPath().startsWith("//")))
     568             :             {
     569           0 :                 if (baseUriReference->getPath().getLength() > 1
     570           0 :                     || uriReference->getPath().getLength() > 1)
     571             :                 {
     572           0 :                     if (uriReference->getPath().isEmpty()) {
     573           0 :                         rel.append('/');
     574             :                     } else {
     575             :                         assert(uriReference->getPath()[0] == '/');
     576           0 :                         if (uriReference->getPath().startsWith("//")) {
     577             :                             assert(uriReference->hasAuthority());
     578           0 :                             rel.append("//");
     579           0 :                             rel.append(uriReference->getAuthority());
     580             :                         }
     581           0 :                         rel.append(uriReference->getPath());
     582             :                     }
     583             :                 }
     584             :             } else {
     585           0 :                 bool segments = false;
     586           0 :                 for (sal_Int32 j = i; j < count1 - 1; ++j) {
     587           0 :                     if (segments) {
     588           0 :                         rel.append('/');
     589             :                     }
     590           0 :                     rel.append("..");
     591           0 :                     segments = true;
     592             :                 }
     593           0 :                 if (i < count2 - 1
     594           0 :                     || (!uriReference->getPathSegment(count2 - 1).isEmpty()))
     595             :                 {
     596           0 :                     if (!segments
     597           0 :                         && (uriReference->getPathSegment(i).isEmpty()
     598           0 :                             || (parseScheme(uriReference->getPathSegment(i))
     599             :                                 >= 0)))
     600             :                     {
     601           0 :                         rel.append('.');
     602           0 :                         segments = true;
     603             :                     }
     604           0 :                     for (; i < count2; ++i) {
     605           0 :                         if (segments) {
     606           0 :                             rel.append('/');
     607             :                         }
     608           0 :                         OUString s(uriReference->getPathSegment(i));
     609           0 :                         if (encodeRetainedSpecialSegments && s == ".") {
     610           0 :                             rel.append("%2E");
     611           0 :                         } else if (encodeRetainedSpecialSegments && s == "..") {
     612           0 :                             rel.append("%2E%2E");
     613             :                         } else {
     614           0 :                             rel.append(s);
     615             :                         }
     616           0 :                         segments = true;
     617           0 :                     }
     618             :                 }
     619             :             }
     620             :         }
     621           0 :         if (!omitQuery && uriReference->hasQuery()) {
     622           0 :             rel.append('?');
     623           0 :             rel.append(uriReference->getQuery());
     624             :         }
     625           0 :         if (uriReference->hasFragment()) {
     626           0 :             rel.append('#');
     627           0 :             rel.append(uriReference->getFragment());
     628             :         }
     629           0 :         return parse(rel.makeStringAndClear());
     630             :     }
     631             : }
     632             : 
     633             : }
     634             : 
     635             : namespace stoc_services { namespace UriReferenceFactory {
     636             : 
     637           0 : css::uno::Reference< css::uno::XInterface > create(
     638             :     css::uno::Reference< css::uno::XComponentContext > const & context)
     639             :     SAL_THROW((css::uno::Exception))
     640             : {
     641           0 :     return static_cast< cppu::OWeakObject * >(new Factory(context));
     642             : }
     643             : 
     644           0 : OUString getImplementationName() {
     645           0 :     return OUString("com.sun.star.comp.uri.UriReferenceFactory");
     646             : }
     647             : 
     648           0 : css::uno::Sequence< OUString > getSupportedServiceNames() {
     649           0 :     css::uno::Sequence< OUString > s(1);
     650           0 :     s[0] = "com.sun.star.uri.UriReferenceFactory";
     651           0 :     return s;
     652             : }
     653             : 
     654             : } }
     655             : 
     656             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10