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

Generated by: LCOV version 1.10