LCOV - code coverage report
Current view: top level - libreoffice/desktop/source/deployment/misc - dp_descriptioninfoset.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 376 0.0 %
Date: 2012-12-27 Functions: 0 44 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 "dp_descriptioninfoset.hxx"
      21             : 
      22             : #include "dp_resource.h"
      23             : #include "sal/config.h"
      24             : 
      25             : #include "comphelper/sequence.hxx"
      26             : #include "comphelper/seqstream.hxx"
      27             : #include "comphelper/makesequence.hxx"
      28             : #include "comphelper/processfactory.hxx"
      29             : #include "boost/optional.hpp"
      30             : #include "com/sun/star/container/XNameAccess.hpp"
      31             : #include "com/sun/star/beans/Optional.hpp"
      32             : #include "com/sun/star/beans/PropertyValue.hpp"
      33             : #include "com/sun/star/beans/XPropertySet.hpp"
      34             : #include "com/sun/star/io/SequenceInputStream.hpp"
      35             : #include "com/sun/star/lang/XMultiComponentFactory.hpp"
      36             : #include "com/sun/star/lang/Locale.hpp"
      37             : #include "com/sun/star/uno/Reference.hxx"
      38             : #include "com/sun/star/uno/RuntimeException.hpp"
      39             : #include "com/sun/star/uno/Sequence.hxx"
      40             : #include "com/sun/star/uno/XComponentContext.hpp"
      41             : #include "com/sun/star/uno/XInterface.hpp"
      42             : #include "com/sun/star/xml/dom/DOMException.hpp"
      43             : #include "com/sun/star/xml/dom/XNode.hpp"
      44             : #include "com/sun/star/xml/dom/XNodeList.hpp"
      45             : #include "com/sun/star/xml/dom/DocumentBuilder.hpp"
      46             : #include "com/sun/star/xml/xpath/XXPathAPI.hpp"
      47             : #include "com/sun/star/ucb/InteractiveIOException.hpp"
      48             : #include "cppuhelper/implbase1.hxx"
      49             : #include "cppuhelper/implbase2.hxx"
      50             : #include "cppuhelper/weak.hxx"
      51             : #include "cppuhelper/exc_hlp.hxx"
      52             : #include "rtl/ustring.h"
      53             : #include "rtl/ustring.hxx"
      54             : #include "sal/types.h"
      55             : #include "ucbhelper/content.hxx"
      56             : 
      57             : namespace {
      58             : 
      59             : using css::uno::Reference;
      60             : using ::rtl::OUString;
      61             : 
      62             : class EmptyNodeList: public ::cppu::WeakImplHelper1< css::xml::dom::XNodeList >
      63             : {
      64             : public:
      65             :     EmptyNodeList();
      66             : 
      67             :     virtual ~EmptyNodeList();
      68             : 
      69             :     virtual ::sal_Int32 SAL_CALL getLength() throw (css::uno::RuntimeException);
      70             : 
      71             :     virtual css::uno::Reference< css::xml::dom::XNode > SAL_CALL
      72             :     item(::sal_Int32 index) throw (css::uno::RuntimeException);
      73             : 
      74             : private:
      75             :     EmptyNodeList(EmptyNodeList &); // not defined
      76             :     void operator =(EmptyNodeList &); // not defined
      77             : };
      78             : 
      79           0 : EmptyNodeList::EmptyNodeList() {}
      80             : 
      81           0 : EmptyNodeList::~EmptyNodeList() {}
      82             : 
      83           0 : ::sal_Int32 EmptyNodeList::getLength() throw (css::uno::RuntimeException) {
      84           0 :     return 0;
      85             : }
      86             : 
      87           0 : css::uno::Reference< css::xml::dom::XNode > EmptyNodeList::item(::sal_Int32)
      88             :     throw (css::uno::RuntimeException)
      89             : {
      90             :     throw css::uno::RuntimeException(
      91             :         ::rtl::OUString(
      92             :             RTL_CONSTASCII_USTRINGPARAM(
      93             :                 "bad EmptyNodeList com.sun.star.xml.dom.XNodeList.item call")),
      94           0 :         static_cast< ::cppu::OWeakObject * >(this));
      95             : }
      96             : 
      97           0 : ::rtl::OUString getNodeValue(
      98             :     css::uno::Reference< css::xml::dom::XNode > const & node)
      99             : {
     100             :     OSL_ASSERT(node.is());
     101             :     try {
     102           0 :         return node->getNodeValue();
     103           0 :     } catch (const css::xml::dom::DOMException & e) {
     104             :         throw css::uno::RuntimeException(
     105             :             (::rtl::OUString(
     106             :                 RTL_CONSTASCII_USTRINGPARAM(
     107             :                     "com.sun.star.xml.dom.DOMException: ")) +
     108           0 :              e.Message),
     109           0 :             css::uno::Reference< css::uno::XInterface >());
     110             :     }
     111             : }
     112             : 
     113             : /**The class uses the UCB to access the description.xml file in an
     114             :    extension. The UCB must have been initialized already. It also
     115             :    requires that the extension has already be unzipped to a particular
     116             :    location.
     117             :  */
     118             : class ExtensionDescription
     119             : {
     120             : public:
     121             :     /**throws an exception if the description.xml is not
     122             :         available, cannot be read, does not contain the expected data,
     123             :         or any other error occurred. Therefore it shoult only be used with
     124             :         new extensions.
     125             : 
     126             :         Throws com::sun::star::uno::RuntimeException,
     127             :         com::sun::star::deployment::DeploymentException,
     128             :         dp_registry::backend::bundle::NoDescriptionException.
     129             :      */
     130             :     ExtensionDescription(
     131             :         const css::uno::Reference<css::uno::XComponentContext>& xContext,
     132             :         const ::rtl::OUString& installDir,
     133             :         const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
     134             : 
     135             :     ~ExtensionDescription();
     136             : 
     137           0 :     css::uno::Reference<css::xml::dom::XNode> getRootElement() const
     138             :     {
     139           0 :         return m_xRoot;
     140             :     }
     141             : 
     142             :     ::rtl::OUString getExtensionRootUrl() const
     143             :     {
     144             :         return m_sExtensionRootUrl;
     145             :     }
     146             : 
     147             : 
     148             : private:
     149             :     css::uno::Reference<css::xml::dom::XNode> m_xRoot;
     150             :     ::rtl::OUString m_sExtensionRootUrl;
     151             : };
     152             : 
     153             : class NoDescriptionException
     154             : {
     155             : };
     156             : 
     157             : class FileDoesNotExistFilter
     158             :     : public ::cppu::WeakImplHelper2< css::ucb::XCommandEnvironment,
     159             :                                       css::task::XInteractionHandler >
     160             : 
     161             : {
     162             :     bool m_bExist;
     163             :     css::uno::Reference< css::ucb::XCommandEnvironment > m_xCommandEnv;
     164             : 
     165             : public:
     166             :     virtual ~FileDoesNotExistFilter();
     167             :     FileDoesNotExistFilter(
     168             :         const css::uno::Reference< css::ucb::XCommandEnvironment >& xCmdEnv);
     169             : 
     170             :     bool exist();
     171             :     // XCommandEnvironment
     172             :     virtual css::uno::Reference<css::task::XInteractionHandler > SAL_CALL
     173             :     getInteractionHandler() throw (css::uno::RuntimeException);
     174             :     virtual css::uno::Reference<css::ucb::XProgressHandler >
     175             :     SAL_CALL getProgressHandler() throw (css::uno::RuntimeException);
     176             : 
     177             :     // XInteractionHandler
     178             :     virtual void SAL_CALL handle(
     179             :         css::uno::Reference<css::task::XInteractionRequest > const & xRequest )
     180             :         throw (css::uno::RuntimeException);
     181             : };
     182             : 
     183           0 : ExtensionDescription::ExtensionDescription(
     184             :     const Reference<css::uno::XComponentContext>& xContext,
     185             :     const OUString& installDir,
     186           0 :     const Reference< css::ucb::XCommandEnvironment >& xCmdEnv)
     187             : {
     188             :     try {
     189           0 :         m_sExtensionRootUrl = installDir;
     190             :         //may throw ::com::sun::star::ucb::ContentCreationException
     191             :         //If there is no description.xml then ucb will start an interaction which
     192             :         //brings up a dialog.We want to prevent this. Therefore we wrap the xCmdEnv
     193             :         //and filter the respective exception out.
     194           0 :         OUString sDescriptionUri(installDir + OUSTR("/description.xml"));
     195             :         Reference<css::ucb::XCommandEnvironment> xFilter =
     196             :             static_cast<css::ucb::XCommandEnvironment*>(
     197           0 :                 new FileDoesNotExistFilter(xCmdEnv));
     198           0 :         ::ucbhelper::Content descContent(sDescriptionUri, xFilter, xContext);
     199             : 
     200             :         //throws an com::sun::star::uno::Exception if the file is not available
     201           0 :         Reference<css::io::XInputStream> xIn;
     202             :         try
     203             :         {   //throws com.sun.star.ucb.InteractiveIOException
     204           0 :             xIn = descContent.openStream();
     205             :         }
     206           0 :         catch ( const css::uno::Exception& )
     207             :         {
     208           0 :             if ( ! static_cast<FileDoesNotExistFilter*>(xFilter.get())->exist())
     209           0 :                 throw NoDescriptionException();
     210           0 :             throw;
     211             :         }
     212           0 :         if (!xIn.is())
     213             :         {
     214             :             throw css::uno::Exception(
     215             :                 OUSTR("Could not get XInputStream for description.xml of extension ") +
     216           0 :                 sDescriptionUri, 0);
     217             :         }
     218             : 
     219             :         //get root node of description.xml
     220             :         Reference<css::xml::dom::XDocumentBuilder> xDocBuilder(
     221           0 :             css::xml::dom::DocumentBuilder::create(xContext) );
     222             : 
     223           0 :         if (xDocBuilder->isNamespaceAware() == sal_False)
     224             :         {
     225             :             throw css::uno::Exception(
     226           0 :                 OUSTR("Service com.sun.star.xml.dom.DocumentBuilder is not namespace aware."), 0);
     227             :         }
     228             : 
     229           0 :         Reference<css::xml::dom::XDocument> xDoc = xDocBuilder->parse(xIn);
     230           0 :         if (!xDoc.is())
     231             :         {
     232           0 :             throw css::uno::Exception(sDescriptionUri + OUSTR(" contains data which cannot be parsed. "), 0);
     233             :         }
     234             : 
     235             :         //check for proper root element and namespace
     236           0 :         Reference<css::xml::dom::XElement> xRoot = xDoc->getDocumentElement();
     237           0 :         if (!xRoot.is())
     238             :         {
     239             :             throw css::uno::Exception(
     240           0 :                 sDescriptionUri + OUSTR(" contains no root element."), 0);
     241             :         }
     242             : 
     243           0 :         if ( ! xRoot->getTagName().equals(OUSTR("description")))
     244             :         {
     245             :             throw css::uno::Exception(
     246           0 :                 sDescriptionUri + OUSTR(" does not contain the root element <description>."), 0);
     247             :         }
     248             : 
     249             :         m_xRoot = Reference<css::xml::dom::XNode>(
     250           0 :             xRoot, css::uno::UNO_QUERY_THROW);
     251           0 :         OUString nsDescription = xRoot->getNamespaceURI();
     252             : 
     253             :         //check if this namespace is supported
     254           0 :         if ( ! nsDescription.equals(OUSTR("http://openoffice.org/extensions/description/2006")))
     255             :         {
     256           0 :             throw css::uno::Exception(sDescriptionUri + OUSTR(" contains a root element with an unsupported namespace. "), 0);
     257           0 :         }
     258           0 :     } catch (const css::uno::RuntimeException &) {
     259           0 :         throw;
     260           0 :     } catch (const css::deployment::DeploymentException &) {
     261           0 :         throw;
     262           0 :     } catch (const css::uno::Exception & e) {
     263           0 :         css::uno::Any a(cppu::getCaughtException());
     264             :         throw css::deployment::DeploymentException(
     265           0 :             e.Message, Reference< css::uno::XInterface >(), a);
     266             :     }
     267           0 : }
     268             : 
     269           0 : ExtensionDescription::~ExtensionDescription()
     270             : {
     271           0 : }
     272             : 
     273             : //======================================================================
     274           0 : FileDoesNotExistFilter::FileDoesNotExistFilter(
     275             :     const Reference< css::ucb::XCommandEnvironment >& xCmdEnv):
     276           0 :     m_bExist(true), m_xCommandEnv(xCmdEnv)
     277           0 : {}
     278             : 
     279           0 : FileDoesNotExistFilter::~FileDoesNotExistFilter()
     280             : {
     281           0 : };
     282             : 
     283           0 : bool FileDoesNotExistFilter::exist()
     284             : {
     285           0 :     return m_bExist;
     286             : }
     287             :     // XCommandEnvironment
     288             : Reference<css::task::XInteractionHandler >
     289           0 :     FileDoesNotExistFilter::getInteractionHandler() throw (css::uno::RuntimeException)
     290             : {
     291           0 :     return static_cast<css::task::XInteractionHandler*>(this);
     292             : }
     293             : 
     294             : Reference<css::ucb::XProgressHandler >
     295           0 :     FileDoesNotExistFilter::getProgressHandler() throw (css::uno::RuntimeException)
     296             : {
     297           0 :     return m_xCommandEnv.is()
     298           0 :         ? m_xCommandEnv->getProgressHandler()
     299           0 :         : Reference<css::ucb::XProgressHandler>();
     300             : }
     301             : 
     302             : // XInteractionHandler
     303             : //If the interaction was caused by a non-existing file which is specified in the ctor
     304             : //of FileDoesNotExistFilter, then we do nothing
     305           0 : void  FileDoesNotExistFilter::handle(
     306             :         Reference<css::task::XInteractionRequest > const & xRequest )
     307             :         throw (css::uno::RuntimeException)
     308             : {
     309           0 :     css::uno::Any request( xRequest->getRequest() );
     310             : 
     311           0 :     css::ucb::InteractiveIOException ioexc;
     312           0 :     if ((request>>= ioexc)
     313             :         && (ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING
     314             :             || ioexc.Code == css::ucb::IOErrorCode_NOT_EXISTING_PATH))
     315             :     {
     316           0 :         m_bExist = false;
     317           0 :         return;
     318             :     }
     319           0 :     Reference<css::task::XInteractionHandler> xInteraction;
     320           0 :     if (m_xCommandEnv.is()) {
     321           0 :         xInteraction = m_xCommandEnv->getInteractionHandler();
     322             :     }
     323           0 :     if (xInteraction.is()) {
     324           0 :         xInteraction->handle(xRequest);
     325           0 :     }
     326             : }
     327             : 
     328             : }
     329             : 
     330             : namespace dp_misc {
     331             : 
     332           0 : DescriptionInfoset getDescriptionInfoset(OUString const & sExtensionFolderURL)
     333             : {
     334           0 :     Reference< css::xml::dom::XNode > root;
     335             :     Reference<css::uno::XComponentContext> context =
     336           0 :         comphelper_getProcessComponentContext();
     337             :     OSL_ASSERT(context.is());
     338             :     try {
     339             :         root =
     340             :             ExtensionDescription(
     341             :                 context, sExtensionFolderURL,
     342             :                 Reference< css::ucb::XCommandEnvironment >()).
     343           0 :             getRootElement();
     344           0 :     } catch (const NoDescriptionException &) {
     345           0 :     } catch (const css::deployment::DeploymentException & e) {
     346             :         throw css::uno::RuntimeException(
     347             :             (OUString(
     348             :                 RTL_CONSTASCII_USTRINGPARAM(
     349             :                     "com.sun.star.deployment.DeploymentException: ")) +
     350           0 :              e.Message), 0);
     351             :     }
     352           0 :     return DescriptionInfoset(context, root);
     353             : }
     354             : 
     355           0 : DescriptionInfoset::DescriptionInfoset(
     356             :     css::uno::Reference< css::uno::XComponentContext > const & context,
     357             :     css::uno::Reference< css::xml::dom::XNode > const & element):
     358             :     m_context(context),
     359           0 :     m_element(element)
     360             : {
     361             :     css::uno::Reference< css::lang::XMultiComponentFactory > manager(
     362           0 :         context->getServiceManager(), css::uno::UNO_QUERY_THROW);
     363           0 :     if (m_element.is()) {
     364             :         m_xpath = css::uno::Reference< css::xml::xpath::XXPathAPI >(
     365           0 :             manager->createInstanceWithContext(
     366             :                 ::rtl::OUString(
     367             :                     RTL_CONSTASCII_USTRINGPARAM(
     368             :                         "com.sun.star.xml.xpath.XPathAPI")),
     369           0 :                 context),
     370           0 :             css::uno::UNO_QUERY_THROW);
     371           0 :         m_xpath->registerNS(
     372             :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc")),
     373           0 :             element->getNamespaceURI());
     374           0 :         m_xpath->registerNS(
     375             :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("xlink")),
     376             :             ::rtl::OUString(
     377           0 :                 RTL_CONSTASCII_USTRINGPARAM("http://www.w3.org/1999/xlink")));
     378           0 :     }
     379           0 : }
     380             : 
     381           0 : DescriptionInfoset::~DescriptionInfoset() {}
     382             : 
     383           0 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getIdentifier() const {
     384             :     return getOptionalValue(
     385           0 :         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:identifier/@value")));
     386             : }
     387             : 
     388           0 : ::rtl::OUString DescriptionInfoset::getNodeValueFromExpression(::rtl::OUString const & expression) const
     389             : {
     390           0 :     css::uno::Reference< css::xml::dom::XNode > n;
     391           0 :     if (m_element.is()) {
     392             :         try {
     393           0 :             n = m_xpath->selectSingleNode(m_element, expression);
     394           0 :         } catch (const css::xml::xpath::XPathException &) {
     395             :             // ignore
     396             :         }
     397             :     }
     398           0 :     return n.is() ? getNodeValue(n) : ::rtl::OUString();
     399             : }
     400             : 
     401           0 : void DescriptionInfoset::checkBlacklist() const
     402             : {
     403           0 :     if (m_element.is()) {
     404           0 :         boost::optional< OUString > id(getIdentifier());
     405           0 :         if (!id)
     406             :             return; // nothing to check
     407           0 :         OUString currentversion(getVersion());
     408           0 :         if (currentversion.getLength() == 0)
     409             :             return;  // nothing to check
     410             : 
     411             :         css::uno::Reference< css::lang::XMultiComponentFactory > manager(
     412           0 :             m_context->getServiceManager(), css::uno::UNO_QUERY_THROW);
     413             :         css::uno::Reference< css::lang::XMultiServiceFactory> provider(
     414           0 :             manager->createInstanceWithContext(
     415           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationProvider")), m_context),
     416           0 :                 css::uno::UNO_QUERY_THROW);
     417             : 
     418           0 :         css::uno::Sequence< css::uno::Any > args = css::uno::Sequence< css::uno::Any >(1);
     419           0 :         css::beans::PropertyValue prop;
     420           0 :         prop.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath"));
     421           0 :         prop.Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/org.openoffice.Office.ExtensionDependencies/Extensions"));
     422           0 :         args[0] <<= prop;
     423             : 
     424             :         css::uno::Reference< css::container::XNameAccess > blacklist(
     425           0 :             provider->createInstanceWithArguments(
     426           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationAccess")), args),
     427           0 :                 css::uno::UNO_QUERY_THROW);
     428             : 
     429             :         // check first if a blacklist entry is available
     430           0 :         if (blacklist.is() && blacklist->hasByName(*id)) {
     431             :             css::uno::Reference< css::beans::XPropertySet > extProps(
     432           0 :                 blacklist->getByName(*id), css::uno::UNO_QUERY_THROW);
     433             : 
     434           0 :             css::uno::Any anyValue = extProps->getPropertyValue(
     435           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Versions")));
     436             : 
     437           0 :             css::uno::Sequence< ::rtl::OUString > blversions;
     438           0 :             anyValue >>= blversions;
     439             : 
     440             :             // check if the current version requires further dependency checks from the blacklist
     441           0 :             if (checkBlacklistVersion(currentversion, blversions)) {
     442           0 :                 anyValue = extProps->getPropertyValue(
     443           0 :                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Dependencies")));
     444           0 :                 ::rtl::OUString udeps;
     445           0 :                 anyValue >>= udeps;
     446             : 
     447           0 :                 if (udeps.getLength() == 0)
     448             :                     return; // nothing todo
     449             : 
     450           0 :                 ::rtl::OString xmlDependencies = ::rtl::OUStringToOString(udeps, RTL_TEXTENCODING_UNICODE);
     451             : 
     452             :                 css::uno::Reference< css::xml::dom::XDocumentBuilder> docbuilder(
     453           0 :                     manager->createInstanceWithContext(
     454           0 :                         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.xml.dom.DocumentBuilder")), m_context),
     455           0 :                     css::uno::UNO_QUERY_THROW);
     456             : 
     457           0 :                 css::uno::Sequence< sal_Int8 > byteSeq((const sal_Int8*)xmlDependencies.getStr(), xmlDependencies.getLength());
     458             : 
     459             :                 css::uno::Reference< css::io::XInputStream> inputstream( css::io::SequenceInputStream::createStreamFromSequence(m_context, byteSeq),
     460           0 :                                                                          css::uno::UNO_QUERY_THROW);
     461             : 
     462           0 :                 css::uno::Reference< css::xml::dom::XDocument > xDocument(docbuilder->parse(inputstream));
     463           0 :                 css::uno::Reference< css::xml::dom::XElement > xElement(xDocument->getDocumentElement());
     464           0 :                 css::uno::Reference< css::xml::dom::XNodeList > xDeps(xElement->getChildNodes());
     465           0 :                 sal_Int32 nLen = xDeps->getLength();
     466             : 
     467             :                 // get the parent xml document  of current description info for the import
     468           0 :                 css::uno::Reference< css::xml::dom::XDocument > xCurrentDescInfo(m_element->getOwnerDocument());
     469             : 
     470             :                 // get dependency node of current description info to merge the new dependencies from the blacklist
     471             :                 css::uno::Reference< css::xml::dom::XNode > xCurrentDeps(
     472           0 :                     m_xpath->selectSingleNode(m_element, ::rtl::OUString(
     473           0 :                                                   RTL_CONSTASCII_USTRINGPARAM("desc:dependencies"))));
     474             : 
     475             :                 // if no dependency node exists, create a new one in the current description info
     476           0 :                 if (!xCurrentDeps.is()) {
     477             :                     css::uno::Reference< css::xml::dom::XNode > xNewDepNode(
     478           0 :                         xCurrentDescInfo->createElementNS(
     479             :                             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http://openoffice.org/extensions/description/2006")),
     480           0 :                             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("dependencies"))), css::uno::UNO_QUERY_THROW);
     481           0 :                     m_element->appendChild(xNewDepNode);
     482           0 :                     xCurrentDeps = m_xpath->selectSingleNode(m_element, ::rtl::OUString(
     483           0 :                                                   RTL_CONSTASCII_USTRINGPARAM("desc:dependencies")));
     484             :                 }
     485             : 
     486           0 :                 for (sal_Int32 i=0; i<nLen; i++) {
     487           0 :                     css::uno::Reference< css::xml::dom::XNode > xNode(xDeps->item(i));
     488           0 :                     css::uno::Reference< css::xml::dom::XElement > xDep(xNode, css::uno::UNO_QUERY);
     489           0 :                     if (xDep.is()) {
     490             :                         // found valid blacklist dependency, import the node first and append it to the existing dependency node
     491           0 :                         css::uno::Reference< css::xml::dom::XNode > importedNode = xCurrentDescInfo->importNode(xNode, true);
     492           0 :                         xCurrentDeps->appendChild(importedNode);
     493             :                     }
     494           0 :                 }
     495           0 :             }
     496           0 :         }
     497             :     }
     498             : }
     499             : 
     500           0 : bool DescriptionInfoset::checkBlacklistVersion(
     501             :     ::rtl::OUString currentversion,
     502             :     ::com::sun::star::uno::Sequence< ::rtl::OUString > const & versions) const
     503             : {
     504           0 :     sal_Int32 nLen = versions.getLength();
     505           0 :     for (sal_Int32 i=0; i<nLen; i++) {
     506           0 :         if (currentversion.equals(versions[i]))
     507           0 :             return true;
     508             :     }
     509             : 
     510           0 :     return false;
     511             : }
     512             : 
     513           0 : ::rtl::OUString DescriptionInfoset::getVersion() const
     514             : {
     515             :     return getNodeValueFromExpression( ::rtl::OUString(
     516           0 :             RTL_CONSTASCII_USTRINGPARAM("desc:version/@value")));
     517             : }
     518             : 
     519           0 : css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getSupportedPlaforms() const
     520             : {
     521             :     //When there is no description.xml then we assume that we support all platforms
     522           0 :     if (! m_element.is())
     523             :     {
     524             :         return comphelper::makeSequence(
     525           0 :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
     526             :     }
     527             : 
     528             :     //Check if the <platform> element was provided. If not the default is "all" platforms
     529             :     css::uno::Reference< css::xml::dom::XNode > nodePlatform(
     530           0 :         m_xpath->selectSingleNode(m_element, ::rtl::OUString(
     531           0 :             RTL_CONSTASCII_USTRINGPARAM("desc:platform"))));
     532           0 :     if (!nodePlatform.is())
     533             :     {
     534             :         return comphelper::makeSequence(
     535           0 :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("all")));
     536             :     }
     537             : 
     538             :     //There is a platform element.
     539             :     const ::rtl::OUString value = getNodeValueFromExpression(::rtl::OUString(
     540           0 :             RTL_CONSTASCII_USTRINGPARAM("desc:platform/@value")));
     541             :     //parse the string, it can contained multiple strings separated by commas
     542           0 :     ::std::vector< ::rtl::OUString> vec;
     543           0 :     sal_Int32 nIndex = 0;
     544           0 :     do
     545             :     {
     546           0 :         ::rtl::OUString aToken = value.getToken( 0, ',', nIndex );
     547           0 :         aToken = aToken.trim();
     548           0 :         if (!aToken.isEmpty())
     549           0 :             vec.push_back(aToken);
     550             : 
     551             :     }
     552             :     while (nIndex >= 0);
     553             : 
     554           0 :     return comphelper::containerToSequence(vec);
     555             : }
     556             : 
     557             : css::uno::Reference< css::xml::dom::XNodeList >
     558           0 : DescriptionInfoset::getDependencies() const {
     559           0 :     if (m_element.is()) {
     560             :         try {
     561             :             // check the extension blacklist first and expand the dependencies if applicable
     562           0 :             checkBlacklist();
     563             : 
     564           0 :             return m_xpath->selectNodeList(m_element, ::rtl::OUString(
     565           0 :                         RTL_CONSTASCII_USTRINGPARAM("desc:dependencies/*")));
     566           0 :         } catch (const css::xml::xpath::XPathException &) {
     567             :             // ignore
     568             :         }
     569             :     }
     570           0 :     return new EmptyNodeList;
     571             : }
     572             : 
     573             : css::uno::Sequence< ::rtl::OUString >
     574           0 : DescriptionInfoset::getUpdateInformationUrls() const {
     575             :     return getUrls(
     576             :         ::rtl::OUString(
     577             :             RTL_CONSTASCII_USTRINGPARAM(
     578           0 :                 "desc:update-information/desc:src/@xlink:href")));
     579             : }
     580             : 
     581             : css::uno::Sequence< ::rtl::OUString >
     582           0 : DescriptionInfoset::getUpdateDownloadUrls() const
     583             : {
     584             :     return getUrls(
     585             :         ::rtl::OUString(
     586             :             RTL_CONSTASCII_USTRINGPARAM(
     587           0 :                 "desc:update-download/desc:src/@xlink:href")));
     588             : }
     589             : 
     590           0 : ::rtl::OUString DescriptionInfoset::getIconURL( sal_Bool bHighContrast ) const
     591             : {
     592             :     css::uno::Sequence< ::rtl::OUString > aStrList = getUrls( ::rtl::OUString(
     593           0 :             RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:default/@xlink:href")));
     594             :     css::uno::Sequence< ::rtl::OUString > aStrListHC = getUrls( ::rtl::OUString(
     595           0 :             RTL_CONSTASCII_USTRINGPARAM( "desc:icon/desc:high-contrast/@xlink:href")));
     596             : 
     597           0 :     if ( bHighContrast && aStrListHC.hasElements() && !aStrListHC[0].isEmpty() )
     598           0 :         return aStrListHC[0];
     599             : 
     600           0 :     if ( aStrList.hasElements() && !aStrList[0].isEmpty() )
     601           0 :         return aStrList[0];
     602             : 
     603           0 :     return ::rtl::OUString();
     604             : }
     605             : 
     606           0 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getLocalizedUpdateWebsiteURL()
     607             :     const
     608             : {
     609           0 :     bool bParentExists = false;
     610             :     const ::rtl::OUString sURL (getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     611           0 :         "/desc:description/desc:update-website")), &bParentExists ));
     612             : 
     613           0 :     if (!sURL.isEmpty())
     614           0 :         return ::boost::optional< ::rtl::OUString >(sURL);
     615             :     else
     616             :         return bParentExists ? ::boost::optional< ::rtl::OUString >(::rtl::OUString()) :
     617           0 :             ::boost::optional< ::rtl::OUString >();
     618             : }
     619             : 
     620           0 : ::boost::optional< ::rtl::OUString > DescriptionInfoset::getOptionalValue(
     621             :     ::rtl::OUString const & expression) const
     622             : {
     623           0 :     css::uno::Reference< css::xml::dom::XNode > n;
     624           0 :     if (m_element.is()) {
     625             :         try {
     626           0 :             n = m_xpath->selectSingleNode(m_element, expression);
     627           0 :         } catch (const css::xml::xpath::XPathException &) {
     628             :             // ignore
     629             :         }
     630             :     }
     631           0 :     return n.is()
     632             :         ? ::boost::optional< ::rtl::OUString >(getNodeValue(n))
     633           0 :         : ::boost::optional< ::rtl::OUString >();
     634             : }
     635             : 
     636           0 : css::uno::Sequence< ::rtl::OUString > DescriptionInfoset::getUrls(
     637             :     ::rtl::OUString const & expression) const
     638             : {
     639           0 :     css::uno::Reference< css::xml::dom::XNodeList > ns;
     640           0 :     if (m_element.is()) {
     641             :         try {
     642           0 :             ns = m_xpath->selectNodeList(m_element, expression);
     643           0 :         } catch (const css::xml::xpath::XPathException &) {
     644             :             // ignore
     645             :         }
     646             :     }
     647           0 :     css::uno::Sequence< ::rtl::OUString > urls(ns.is() ? ns->getLength() : 0);
     648           0 :     for (::sal_Int32 i = 0; i < urls.getLength(); ++i) {
     649           0 :         urls[i] = getNodeValue(ns->item(i));
     650             :     }
     651           0 :     return urls;
     652             : }
     653             : 
     654           0 : ::std::pair< ::rtl::OUString, ::rtl::OUString > DescriptionInfoset::getLocalizedPublisherNameAndURL() const
     655             : {
     656             :     css::uno::Reference< css::xml::dom::XNode > node =
     657           0 :         getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:publisher")));
     658             : 
     659           0 :     ::rtl::OUString sPublisherName;
     660           0 :     ::rtl::OUString sURL;
     661           0 :     if (node.is())
     662             :     {
     663           0 :         const ::rtl::OUString exp1(RTL_CONSTASCII_USTRINGPARAM("text()"));
     664           0 :         css::uno::Reference< css::xml::dom::XNode > xPathName;
     665             :         try {
     666           0 :             xPathName = m_xpath->selectSingleNode(node, exp1);
     667           0 :         } catch (const css::xml::xpath::XPathException &) {
     668             :             // ignore
     669             :         }
     670             :         OSL_ASSERT(xPathName.is());
     671           0 :         if (xPathName.is())
     672           0 :             sPublisherName = xPathName->getNodeValue();
     673             : 
     674           0 :         const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
     675           0 :         css::uno::Reference< css::xml::dom::XNode > xURL;
     676             :         try {
     677           0 :             xURL = m_xpath->selectSingleNode(node, exp2);
     678           0 :         } catch (const css::xml::xpath::XPathException &) {
     679             :             // ignore
     680             :         }
     681             :         OSL_ASSERT(xURL.is());
     682           0 :         if (xURL.is())
     683           0 :            sURL = xURL->getNodeValue();
     684             :     }
     685           0 :     return ::std::make_pair(sPublisherName, sURL);
     686             : }
     687             : 
     688           0 : ::rtl::OUString DescriptionInfoset::getLocalizedReleaseNotesURL() const
     689             : {
     690             :     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     691           0 :         "/desc:description/desc:release-notes")), NULL);
     692             : }
     693             : 
     694           0 : ::rtl::OUString DescriptionInfoset::getLocalizedDisplayName() const
     695             : {
     696             :     css::uno::Reference< css::xml::dom::XNode > node =
     697           0 :         getLocalizedChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:display-name")));
     698           0 :     if (node.is())
     699             :     {
     700           0 :         const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("text()"));
     701           0 :         css::uno::Reference< css::xml::dom::XNode > xtext;
     702             :         try {
     703           0 :             xtext = m_xpath->selectSingleNode(node, exp);
     704           0 :         } catch (const css::xml::xpath::XPathException &) {
     705             :             // ignore
     706             :         }
     707           0 :         if (xtext.is())
     708           0 :             return xtext->getNodeValue();
     709             :     }
     710           0 :     return ::rtl::OUString();
     711             : }
     712             : 
     713           0 : ::rtl::OUString DescriptionInfoset::getLocalizedLicenseURL() const
     714             : {
     715             :     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     716           0 :         "/desc:description/desc:registration/desc:simple-license")), NULL);
     717             : 
     718             : }
     719             : 
     720             : ::boost::optional<SimpleLicenseAttributes>
     721           0 : DescriptionInfoset::getSimpleLicenseAttributes() const
     722             : {
     723             :     //Check if the node exist
     724           0 :     css::uno::Reference< css::xml::dom::XNode > n;
     725           0 :     if (m_element.is()) {
     726             :         try {
     727           0 :             n = m_xpath->selectSingleNode(m_element,
     728             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     729           0 :                 "/desc:description/desc:registration/desc:simple-license/@accept-by")));
     730           0 :         } catch (const css::xml::xpath::XPathException &) {
     731             :             // ignore
     732             :         }
     733           0 :         if (n.is())
     734             :         {
     735           0 :             SimpleLicenseAttributes attributes;
     736             :             attributes.acceptBy =
     737             :                 getNodeValueFromExpression(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     738           0 :                 "/desc:description/desc:registration/desc:simple-license/@accept-by")));
     739             : 
     740             :             ::boost::optional< ::rtl::OUString > suppressOnUpdate = getOptionalValue(
     741             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     742           0 :                 "/desc:description/desc:registration/desc:simple-license/@suppress-on-update")));
     743           0 :             if (suppressOnUpdate)
     744           0 :                 attributes.suppressOnUpdate = (*suppressOnUpdate).trim().equalsIgnoreAsciiCase(
     745           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
     746             :             else
     747           0 :                 attributes.suppressOnUpdate = false;
     748             : 
     749             :             ::boost::optional< ::rtl::OUString > suppressIfRequired = getOptionalValue(
     750             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     751           0 :                 "/desc:description/desc:registration/desc:simple-license/@suppress-if-required")));
     752           0 :             if (suppressIfRequired)
     753           0 :                 attributes.suppressIfRequired = (*suppressIfRequired).trim().equalsIgnoreAsciiCase(
     754           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")));
     755             :             else
     756           0 :                 attributes.suppressIfRequired = false;
     757             : 
     758           0 :             return ::boost::optional<SimpleLicenseAttributes>(attributes);
     759             :         }
     760             :     }
     761           0 :     return ::boost::optional<SimpleLicenseAttributes>();
     762             : }
     763             : 
     764           0 : ::rtl::OUString DescriptionInfoset::getLocalizedDescriptionURL() const
     765             : {
     766             :     return getLocalizedHREFAttrFromChild(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     767           0 :         "/desc:description/desc:extension-description")), NULL);
     768             : }
     769             : 
     770             : css::uno::Reference< css::xml::dom::XNode >
     771           0 : DescriptionInfoset::getLocalizedChild( const ::rtl::OUString & sParent) const
     772             : {
     773           0 :     if ( ! m_element.is() || sParent.isEmpty())
     774           0 :         return css::uno::Reference< css::xml::dom::XNode > ();
     775             : 
     776           0 :     css::uno::Reference< css::xml::dom::XNode > xParent;
     777             :     try {
     778           0 :         xParent = m_xpath->selectSingleNode(m_element, sParent);
     779           0 :     } catch (const css::xml::xpath::XPathException &) {
     780             :         // ignore
     781             :     }
     782           0 :     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
     783           0 :     if (xParent.is())
     784             :     {
     785           0 :         const ::rtl::OUString sLocale = getOfficeLocaleString();
     786           0 :         nodeMatch = matchFullLocale(xParent, sLocale);
     787             : 
     788             :         //office: en-DE, en, en-DE-altmark
     789           0 :         if (! nodeMatch.is())
     790             :         {
     791           0 :             const css::lang::Locale officeLocale = getOfficeLocale();
     792           0 :             nodeMatch = matchCountryAndLanguage(xParent, officeLocale);
     793           0 :             if ( ! nodeMatch.is())
     794             :             {
     795           0 :                 nodeMatch = matchLanguage(xParent, officeLocale);
     796           0 :                 if (! nodeMatch.is())
     797           0 :                     nodeMatch = getChildWithDefaultLocale(xParent);
     798           0 :             }
     799           0 :         }
     800             :     }
     801             : 
     802           0 :     return nodeMatch;
     803             : }
     804             : 
     805             : css::uno::Reference<css::xml::dom::XNode>
     806           0 : DescriptionInfoset::matchFullLocale(css::uno::Reference< css::xml::dom::XNode >
     807             :                                     const & xParent, ::rtl::OUString const & sLocale) const
     808             : {
     809             :     OSL_ASSERT(xParent.is());
     810             :     const ::rtl::OUString exp1(
     811             :         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
     812           0 :         + sLocale +
     813           0 :         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
     814             :     try {
     815           0 :         return m_xpath->selectSingleNode(xParent, exp1);
     816           0 :     } catch (const css::xml::xpath::XPathException &) {
     817             :         // ignore
     818           0 :         return 0;
     819           0 :     }
     820             : }
     821             : 
     822             : css::uno::Reference<css::xml::dom::XNode>
     823           0 : DescriptionInfoset::matchCountryAndLanguage(
     824             :     css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
     825             : {
     826             :     OSL_ASSERT(xParent.is());
     827           0 :     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
     828             : 
     829           0 :     if (!officeLocale.Country.isEmpty())
     830             :     {
     831             :         const ::rtl::OUString sLangCountry(officeLocale.Language +
     832           0 :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-")) +
     833           0 :             officeLocale.Country);
     834             :         //first try exact match for lang-country
     835             :         const ::rtl::OUString exp1(
     836             :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
     837           0 :             + sLangCountry +
     838           0 :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
     839             :         try {
     840           0 :             nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
     841           0 :         } catch (const css::xml::xpath::XPathException &) {
     842             :             // ignore
     843             :         }
     844             : 
     845             :         //try to match in strings that also have a variant, for example en-US matches in
     846             :         //en-US-montana
     847           0 :         if (!nodeMatch.is())
     848             :         {
     849             :             const ::rtl::OUString exp2(
     850             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
     851           0 :                 + sLangCountry +
     852           0 :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
     853             :             try {
     854           0 :                 nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
     855           0 :             } catch (const css::xml::xpath::XPathException &) {
     856             :                 // ignore
     857           0 :             }
     858           0 :         }
     859             :     }
     860             : 
     861           0 :     return nodeMatch;
     862             : }
     863             : 
     864             : 
     865             : css::uno::Reference<css::xml::dom::XNode>
     866           0 : DescriptionInfoset::matchLanguage(
     867             :     css::uno::Reference< css::xml::dom::XNode > const & xParent, css::lang::Locale const & officeLocale) const
     868             : {
     869             :     OSL_ASSERT(xParent.is());
     870           0 :     css::uno::Reference<css::xml::dom::XNode> nodeMatch;
     871             : 
     872             :     //first try exact match for lang
     873             :     const ::rtl::OUString exp1(
     874             :         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[@lang=\""))
     875           0 :         + officeLocale.Language
     876           0 :         + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
     877             :     try {
     878           0 :         nodeMatch = m_xpath->selectSingleNode(xParent, exp1);
     879           0 :     } catch (const css::xml::xpath::XPathException &) {
     880             :         // ignore
     881             :     }
     882             : 
     883             :     //try to match in strings that also have a country and/orvariant, for example en  matches in
     884             :     //en-US-montana, en-US, en-montana
     885           0 :     if (!nodeMatch.is())
     886             :     {
     887             :         const ::rtl::OUString exp2(
     888             :             ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("*[starts-with(@lang,\""))
     889           0 :             + officeLocale.Language
     890           0 :             + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("-\")]")));
     891             :         try {
     892           0 :             nodeMatch = m_xpath->selectSingleNode(xParent, exp2);
     893           0 :         } catch (const css::xml::xpath::XPathException &) {
     894             :             // ignore
     895           0 :         }
     896             :     }
     897           0 :     return nodeMatch;
     898             : }
     899             : 
     900             : css::uno::Reference<css::xml::dom::XNode>
     901           0 : DescriptionInfoset::getChildWithDefaultLocale(css::uno::Reference< css::xml::dom::XNode >
     902             :                                     const & xParent) const
     903             : {
     904             :     OSL_ASSERT(xParent.is());
     905           0 :     if ( xParent->getNodeName() == "simple-license" )
     906             :     {
     907           0 :         css::uno::Reference<css::xml::dom::XNode> nodeDefault;
     908             :         try {
     909           0 :             nodeDefault = m_xpath->selectSingleNode(xParent, ::rtl::OUString(
     910           0 :                 RTL_CONSTASCII_USTRINGPARAM("@default-license-id")));
     911           0 :         } catch (const css::xml::xpath::XPathException &) {
     912             :             // ignore
     913             :         }
     914           0 :         if (nodeDefault.is())
     915             :         {
     916             :             //The old way
     917             :             const ::rtl::OUString exp1(
     918             :                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("desc:license-text[@license-id = \""))
     919           0 :                 + nodeDefault->getNodeValue()
     920           0 :                 + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\"]")));
     921             :             try {
     922           0 :                 return m_xpath->selectSingleNode(xParent, exp1);
     923           0 :             } catch (const css::xml::xpath::XPathException &) {
     924             :                 // ignore
     925           0 :             }
     926           0 :         }
     927             :     }
     928             : 
     929           0 :     const ::rtl::OUString exp2(RTL_CONSTASCII_USTRINGPARAM("*[1]"));
     930             :     try {
     931           0 :         return m_xpath->selectSingleNode(xParent, exp2);
     932           0 :     } catch (const css::xml::xpath::XPathException &) {
     933             :         // ignore
     934           0 :         return 0;
     935           0 :     }
     936             : }
     937             : 
     938           0 : ::rtl::OUString DescriptionInfoset::getLocalizedHREFAttrFromChild(
     939             :     ::rtl::OUString const & sXPathParent, bool * out_bParentExists)
     940             :     const
     941             : {
     942             :     css::uno::Reference< css::xml::dom::XNode > node =
     943           0 :         getLocalizedChild(sXPathParent);
     944             : 
     945           0 :     ::rtl::OUString sURL;
     946           0 :     if (node.is())
     947             :     {
     948           0 :         if (out_bParentExists)
     949           0 :             *out_bParentExists = true;
     950           0 :         const ::rtl::OUString exp(RTL_CONSTASCII_USTRINGPARAM("@xlink:href"));
     951           0 :         css::uno::Reference< css::xml::dom::XNode > xURL;
     952             :         try {
     953           0 :             xURL = m_xpath->selectSingleNode(node, exp);
     954           0 :         } catch (const css::xml::xpath::XPathException &) {
     955             :             // ignore
     956             :         }
     957             :         OSL_ASSERT(xURL.is());
     958           0 :         if (xURL.is())
     959           0 :             sURL = xURL->getNodeValue();
     960             :     }
     961             :     else
     962             :     {
     963           0 :         if (out_bParentExists)
     964           0 :             *out_bParentExists = false;
     965             :     }
     966           0 :     return sURL;
     967             : }
     968             : 
     969             : }
     970             : 
     971             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10