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