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