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

Generated by: LCOV version 1.11