LCOV - code coverage report
Current view: top level - desktop/source/deployment/misc - dp_descriptioninfoset.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 336 0.0 %
Date: 2014-04-14 Functions: 0 42 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10