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