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