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 <o3tl/optional.hxx>
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 
330 ::o3tl::optional< OUString > DescriptionInfoset::getIdentifier() const {
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()) {
350  o3tl::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 > 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 ::o3tl::optional< OUString >(sURL);
532  else
533  return bParentExists ? ::o3tl::optional< OUString >(OUString()) :
534  ::o3tl::optional< OUString >();
535 }
536 
537 ::o3tl::optional< OUString > DescriptionInfoset::getOptionalValue(
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  ? ::o3tl::optional< OUString >(getNodeValue(n))
550  : ::o3tl::optional< OUString >();
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 
635 ::o3tl::optional<SimpleLicenseAttributes>
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  ::o3tl::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  ::o3tl::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 ::o3tl::optional<SimpleLicenseAttributes>(attributes);
665  }
666  }
667  return ::o3tl::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: */
::o3tl::optional< OUString > getIdentifier() const
Return the identifier.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC const LanguageTag & getOfficeLanguageTag()
Definition: dp_resource.cxx:51
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
::o3tl::optional< SimpleLicenseAttributes > getSimpleLicenseAttributes() const
returns the attributes of the simple-license element
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
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.
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
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
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:2087
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
css::uno::Reference< css::xml::dom::XNode > m_element
::o3tl::optional< OUString > getLocalizedUpdateWebsiteURL() const
returns the download website URL from the update information.
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.
SAL_DLLPRIVATE::o3tl::optional< OUString > getOptionalValue(OUString const &expression) const
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.