24#include <config_folders.h>
30#include <com/sun/star/beans/Property.hpp>
31#include <com/sun/star/beans/PropertyValue.hpp>
32#include <com/sun/star/beans/NamedValue.hpp>
33#include <com/sun/star/configuration/theDefaultProvider.hpp>
34#include <com/sun/star/container/XNameAccess.hpp>
35#include <com/sun/star/deployment/UpdateInformationEntry.hpp>
36#include <com/sun/star/deployment/XUpdateInformationProvider.hpp>
37#include <com/sun/star/io/XActiveDataSink.hpp>
38#include <com/sun/star/io/XInputStream.hpp>
39#include <com/sun/star/lang/XServiceInfo.hpp>
40#include <com/sun/star/ucb/CommandAbortedException.hpp>
41#include <com/sun/star/ucb/UniversalContentBroker.hpp>
42#include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
43#include <com/sun/star/ucb/XCommandProcessor2.hpp>
44#include <com/sun/star/ucb/OpenCommandArgument3.hpp>
45#include <com/sun/star/ucb/OpenMode.hpp>
46#include <com/sun/star/task/PasswordContainerInteractionHandler.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>
51#include <rtl/bootstrap.hxx>
52#include <rtl/ustrbuf.hxx>
54#include <osl/diagnose.h>
55#include <osl/conditn.hxx>
75class InputStreamWrapper :
public ::cppu::WeakImplHelper< io::XInputStream >
77 uno::Reference< io::XInputStream >
m_xStream;
80 explicit InputStreamWrapper(
const uno::Reference< io::XInputStream >& rxStream) :
83 virtual sal_Int32 SAL_CALL readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
85 sal_Int32
n =
m_xStream->readBytes(aData, nBytesToRead);
88 virtual sal_Int32 SAL_CALL readSomeBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
90 sal_Int32
n =
m_xStream->readSomeBytes(aData, nMaxBytesToRead);
93 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
95 virtual sal_Int32 SAL_CALL available()
97 virtual void SAL_CALL closeInput( )
101#define INPUT_STREAM(i) new InputStreamWrapper(i)
103#define INPUT_STREAM(i) i
107class ActiveDataSink :
public ::cppu::WeakImplHelper< io::XActiveDataSink >
109 uno::Reference< io::XInputStream >
m_xStream;
114 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
override {
return m_xStream; };
115 virtual void SAL_CALL setInputStream( uno::Reference< io::XInputStream >
const & rStream )
override {
m_xStream = rStream; };
119class UpdateInformationProvider :
120 public ::cppu::WeakImplHelper< deployment::XUpdateInformationProvider,
121 ucb::XWebDAVCommandEnvironment,
124 OUString getUserAgent(
bool bExtended);
125 bool isUserAgentExtended()
const;
127 uno::Reference< xml::dom::XElement > getDocumentRoot(
const uno::Reference< xml::dom::XNode >& rxNode);
128 uno::Reference< xml::dom::XNode > getChildNode(
const uno::Reference< xml::dom::XNode >& rxNode, std::u16string_view rName);
132 virtual uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
133 getUpdateInformation(
134 uno::Sequence< OUString >
const & repositories,
135 OUString
const & extensionId
138 virtual void SAL_CALL cancel()
override;
140 virtual void SAL_CALL setInteractionHandler(
141 uno::Reference< task::XInteractionHandler >
const & handler )
override;
143 virtual uno::Reference< container::XEnumeration > SAL_CALL
144 getUpdateInformationEnumeration(
145 uno::Sequence< OUString >
const & repositories,
146 OUString
const & extensionId
150 virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
override;
152 virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler()
override {
return uno::Reference< ucb::XProgressHandler >(); };
155 virtual uno::Sequence< beans::StringPair > SAL_CALL getUserRequestHeaders(
156 const OUString&, ucb::WebDAVHTTPMethod )
override;
163 UpdateInformationProvider(uno::Reference<uno::XComponentContext> xContext,
164 uno::Reference< ucb::XUniversalContentBroker > xUniversalContentBroker,
165 uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder,
166 uno::Reference< xml::xpath::XXPathAPI > xXPathAPI);
170 virtual ~UpdateInformationProvider()
override;
171 static OUString getConfigurationItem(uno::Reference<lang::XMultiServiceFactory>
const & configurationProvider, OUString
const & node, OUString
const & item);
172 static uno::Any getConfigurationItemAny(uno::Reference<lang::XMultiServiceFactory>
const & configurationProvider, OUString
const & node, OUString
const & item);
175 uno::Reference< io::XInputStream > load(
const OUString& rURL);
177 void storeCommandInfo( sal_Int32 nCommandId,
178 uno::Reference< ucb::XCommandProcessor >
const & rxCommandProcessor);
180 const uno::Reference< uno::XComponentContext>
m_xContext;
182 const uno::Reference< ucb::XUniversalContentBroker > m_xUniversalContentBroker;
183 const uno::Reference< xml::dom::XDocumentBuilder > m_xDocumentBuilder;
184 const uno::Reference< xml::xpath::XXPathAPI > m_xXPathAPI;
186 uno::Sequence< beans::StringPair > m_aRequestHeaderList;
188 uno::Reference< ucb::XCommandProcessor > m_xCommandProcessor;
190 uno::Reference< task::XInteractionHandler > m_xPwContainerInteractionHandler;
193 osl::Condition m_bCancelled;
195 sal_Int32 m_nCommandId;
199class UpdateInformationEnumeration :
public ::cppu::WeakImplHelper< container::XEnumeration >
202 UpdateInformationEnumeration(
const uno::Reference< xml::dom::XNodeList >& xNodeList,
204 m_xUpdateInformationProvider(
std::move(xUpdateInformationProvider)),
205 m_xNodeList(xNodeList),
206 m_nNodes(xNodeList.is() ? xNodeList->
getLength() : 0),
212 sal_Bool SAL_CALL hasMoreElements()
override {
return m_nCount < m_nNodes; };
213 uno::Any SAL_CALL nextElement()
override
215 OSL_ASSERT( m_xNodeList.is() );
216 OSL_ASSERT( m_xUpdateInformationProvider.is() );
218 if( m_nCount >= m_nNodes )
219 throw container::NoSuchElementException(OUString::number(m_nCount), *
this);
223 deployment::UpdateInformationEntry aEntry;
225 uno::Reference< xml::dom::XNode > xAtomEntryNode( m_xNodeList->item(m_nCount++) );
227 uno::Reference< xml::dom::XNode > xSummaryNode(
228 m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, u
"summary/text()" )
231 if( xSummaryNode.is() )
232 aEntry.Description = xSummaryNode->getNodeValue();
234 uno::Reference< xml::dom::XNode > xContentNode(
235 m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, u
"content" ) );
237 if( xContentNode.is() )
238 aEntry.UpdateDocument = m_xUpdateInformationProvider->getDocumentRoot(xContentNode);
242 catch( ucb::CommandAbortedException
const &)
246 throw lang::WrappedTargetException(
"Command aborted", *
this, anyEx );
248 catch( uno::RuntimeException
const & )
253 catch( uno::Exception
const &)
257 throw lang::WrappedTargetException(
"Document not accessible", *
this, anyEx );
263 const uno::Reference< xml::dom::XNodeList > m_xNodeList;
264 const sal_Int32 m_nNodes;
269class SingleUpdateInformationEnumeration :
public ::cppu::WeakImplHelper< container::XEnumeration >
272 explicit SingleUpdateInformationEnumeration(
const uno::Reference< xml::dom::XElement >& xElement)
273 :
m_nCount(0) { m_aEntry.UpdateDocument = xElement; };
277 uno::Any SAL_CALL nextElement()
override
280 throw container::NoSuchElementException(OUString::number(m_nCount), *
this);
288 deployment::UpdateInformationEntry m_aEntry;
291UpdateInformationProvider::UpdateInformationProvider(
292 uno::Reference<uno::XComponentContext> xContext,
293 uno::Reference< ucb::XUniversalContentBroker > xUniversalContentBroker,
294 uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder,
295 uno::Reference< xml::xpath::XXPathAPI > xXPathAPI)
297 , m_xUniversalContentBroker(
std::move(xUniversalContentBroker))
298 , m_xDocumentBuilder(
std::move(xDocumentBuilder))
299 , m_xXPathAPI(
std::move(xXPathAPI))
300 , m_aRequestHeaderList(2)
303 uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
304 css::configuration::theDefaultProvider::get(
m_xContext));
306 auto pRequestHeaderList = m_aRequestHeaderList.getArray();
307 pRequestHeaderList[0].First =
"Accept-Language";
308 pRequestHeaderList[0].Second = getConfigurationItem( xConfigurationProvider,
"org.openoffice.Setup/L10N",
"ooLocale" );
312UpdateInformationProvider::isUserAgentExtended()
const
314 bool bExtendedUserAgent =
false;
316 uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
317 css::configuration::theDefaultProvider::get(
m_xContext));
319 uno::Any aExtended = getConfigurationItemAny(
320 xConfigurationProvider,
321 "org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments",
322 "ExtendedUserAgent");
323 aExtended >>= bExtendedUserAgent;
324 }
catch (
const uno::RuntimeException &) {
325 SAL_WARN(
"extensions.update",
"Online update disabled");
327 return bExtendedUserAgent;
330OUString UpdateInformationProvider::getUserAgent(
bool bExtended)
332 uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
333 css::configuration::theDefaultProvider::get(
m_xContext));
337 getConfigurationItem(
338 xConfigurationProvider,
339 "org.openoffice.Setup/Product",
343 getConfigurationItem(
344 xConfigurationProvider,
345 "org.openoffice.Setup/Product",
349 getConfigurationItem(
350 xConfigurationProvider,
351 "org.openoffice.Setup/Product",
352 "ooSetupExtension"));
353 if (!extension.isEmpty())
354 buf.append(extension);
356 OUString product(buf.makeStringAndClear());
358 OUString aUserAgent(
"${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"version")
":UpdateUserAgent}" );
364 rtl::Bootstrap::expandMacros( aUserAgent );
365 aUserAgent = aUserAgent.replaceAll(
"<PRODUCT>", product);
366 aUserAgent = aUserAgent.replaceAll(
"<OPTIONAL_OS_HW_DATA>", aExtended);
367 SAL_INFO(
"extensions.update",
"UpdateUserAgent: " << aUserAgent);
374uno::Sequence< beans::StringPair > SAL_CALL UpdateInformationProvider::getUserRequestHeaders(
375 const OUString &aURL, ucb::WebDAVHTTPMethod )
377 bool bExtendedUserAgent;
378 uno::Sequence< beans::StringPair > aPair = m_aRequestHeaderList;
381 if(
aURL.startsWith(
"useragent:" ) )
382 bExtendedUserAgent = (
aURL ==
"useragent:extended");
384 bExtendedUserAgent = isUserAgentExtended();
386 OUString aUserAgent = getUserAgent(bExtendedUserAgent);
388 if( aUserAgent.isEmpty() )
392 auto pPair = aPair.getArray();
393 pPair[1].First =
"User-Agent";
394 pPair[1].Second = aUserAgent;
400UpdateInformationProvider::~UpdateInformationProvider()
405UpdateInformationProvider::getConfigurationItemAny(uno::Reference<lang::XMultiServiceFactory>
const & configurationProvider, OUString
const & node, OUString
const & item)
407 beans::PropertyValue aProperty;
408 aProperty.Name =
"nodepath";
409 aProperty.
Value <<= node;
411 uno::Sequence< uno::Any > aArgumentList{
uno::Any(aProperty) };
412 uno::Reference< container::XNameAccess > xNameAccess(
413 configurationProvider->createInstanceWithArguments(
414 "com.sun.star.configuration.ConfigurationAccess",
416 uno::UNO_QUERY_THROW);
418 return xNameAccess->getByName(item);
422UpdateInformationProvider::getConfigurationItem(uno::Reference<lang::XMultiServiceFactory>
const & configurationProvider, OUString
const & node, OUString
const & item)
425 getConfigurationItemAny(configurationProvider, node, item) >>= sRet;
430UpdateInformationProvider::storeCommandInfo(
431 sal_Int32 nCommandId,
432 uno::Reference< ucb::XCommandProcessor >
const & rxCommandProcessor)
436 m_nCommandId = nCommandId;
437 m_xCommandProcessor = rxCommandProcessor;
440uno::Reference< io::XInputStream >
441UpdateInformationProvider::load(
const OUString& rURL)
443 uno::Reference< ucb::XContentIdentifier > xId = m_xUniversalContentBroker->createContentIdentifier(rURL);
446 throw uno::RuntimeException(
447 "unable to obtain universal content id", *
this);
449 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(m_xUniversalContentBroker->queryContent(xId), uno::UNO_QUERY_THROW);
454 uno::Sequence< beans::NamedValue > aProps { {
"KeepAlive",
uno::Any(
false) } };
456 ucb::OpenCommandArgument3 aOpenArgument;
457 aOpenArgument.Mode = ucb::OpenMode::DOCUMENT;
458 aOpenArgument.Priority = 32768;
459 aOpenArgument.Sink = *aSink;
460 aOpenArgument.OpeningFlags = aProps;
464 aCommand.Argument <<= aOpenArgument;
466 sal_Int32 nCommandId = xCommandProcessor->createCommandIdentifier();
468 storeCommandInfo(nCommandId, xCommandProcessor);
471 xCommandProcessor->execute(aCommand, nCommandId,
472 static_cast < XCommandEnvironment *
> (
this));
474 catch(
const uno::Exception & )
476 storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
478 uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
479 if( xCommandProcessor2.is() )
480 xCommandProcessor2->releaseCommandIdentifier(nCommandId);
484 storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
486 uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
487 if( xCommandProcessor2.is() )
488 xCommandProcessor2->releaseCommandIdentifier(nCommandId);
496uno::Reference< xml::dom::XElement >
497UpdateInformationProvider::getDocumentRoot(
const uno::Reference< xml::dom::XNode >& rxNode)
499 OSL_ASSERT(m_xDocumentBuilder.is());
501 uno::Reference< xml::dom::XElement > xElement(rxNode, uno::UNO_QUERY_THROW);
504 if( xElement->hasAttribute(
"src" ) )
506 uno::Reference< xml::dom::XDocument > xUpdateXML =
507 m_xDocumentBuilder->parse(load(xElement->getAttribute(
"src" )));
509 OSL_ASSERT( xUpdateXML.is() );
511 if( xUpdateXML.is() )
512 return xUpdateXML->getDocumentElement();
517 uno::Reference< xml::dom::XNodeList> xChildNodes = rxNode->getChildNodes();
520 sal_Int32 nmax = xChildNodes->getLength();
521 for(sal_Int32 n=0;
n < nmax;
n++)
523 uno::Reference< xml::dom::XElement > xChildElement(xChildNodes->item(n), uno::UNO_QUERY);
524 if( xChildElement.is() )
529 uno::Reference< xml::dom::XDocument > xUpdateXML = m_xDocumentBuilder->newDocument();
530 xUpdateXML->appendChild( xUpdateXML->importNode(xChildElement,
true ) );
531 return xUpdateXML->getDocumentElement();
536 return uno::Reference< xml::dom::XElement > ();
540uno::Reference< xml::dom::XNode >
541UpdateInformationProvider::getChildNode(
const uno::Reference< xml::dom::XNode >& rxNode,
542 std::u16string_view rName)
544 OSL_ASSERT(m_xXPathAPI.is());
546 return m_xXPathAPI->selectSingleNode(rxNode, OUString::Concat(
"./atom:") + rName);
547 }
catch (
const xml::xpath::XPathException &) {
554uno::Reference< container::XEnumeration > SAL_CALL
555UpdateInformationProvider::getUpdateInformationEnumeration(
556 uno::Sequence< OUString >
const & repositories,
557 OUString
const & extensionId
560 OSL_ASSERT(m_xDocumentBuilder.is());
563 m_bCancelled.reset();
565 for(sal_Int32 n=0;
n<repositories.getLength();
n++)
569 uno::Reference< xml::dom::XDocument > xDocument = m_xDocumentBuilder->parse(load(repositories[n]));
570 uno::Reference< xml::dom::XElement > xElement;
573 xElement = xDocument->getDocumentElement();
577 if( xElement->getNodeName() ==
"feed" )
579 OUString aXPathExpression;
581 if( !extensionId.isEmpty() )
582 aXPathExpression =
"//atom:entry/atom:category[@term=\'" + extensionId +
"\']/..";
584 aXPathExpression =
"//atom:entry";
586 uno::Reference< xml::dom::XNodeList > xNodeList;
588 xNodeList = m_xXPathAPI->selectNodeList(xDocument,
590 }
catch (
const xml::xpath::XPathException &) {
594 return new UpdateInformationEnumeration(xNodeList,
this);
598 return new SingleUpdateInformationEnumeration(xElement);
602 if( m_bCancelled.check() )
605 catch( uno::RuntimeException
const& )
613 catch( uno::Exception
const & )
615 if( n+1 >= repositories.getLength() )
620 return uno::Reference< container::XEnumeration >();
624uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
625UpdateInformationProvider::getUpdateInformation(
626 uno::Sequence< OUString >
const & repositories,
627 OUString
const & extensionId
630 uno::Reference< container::XEnumeration > xEnumeration(
631 getUpdateInformationEnumeration(repositories, extensionId)
634 std::vector< uno::Reference< xml::dom::XElement > > aRet;
636 if( xEnumeration.is() )
638 while( xEnumeration->hasMoreElements() )
642 deployment::UpdateInformationEntry aEntry;
643 if( (xEnumeration->nextElement() >>= aEntry ) && aEntry.UpdateDocument.is() )
645 aRet.push_back(aEntry.UpdateDocument);
649 catch(
const lang::WrappedTargetException& e )
667UpdateInformationProvider::cancel()
672 if( m_xCommandProcessor.is() )
673 m_xCommandProcessor->abort(m_nCommandId);
678UpdateInformationProvider::setInteractionHandler(
679 uno::Reference< task::XInteractionHandler >
const & handler )
686uno::Reference< task::XInteractionHandler > SAL_CALL
687UpdateInformationProvider::getInteractionHandler()
700 if ( !m_xPwContainerInteractionHandler.is() )
701 m_xPwContainerInteractionHandler
702 = task::PasswordContainerInteractionHandler::create(
705 catch ( uno::RuntimeException
const & )
709 catch ( uno::Exception
const & )
712 return m_xPwContainerInteractionHandler;
719UpdateInformationProvider::getImplementationName()
721 return "vnd.sun.UpdateInformationProvider";
725uno::Sequence< OUString > SAL_CALL
726UpdateInformationProvider::getSupportedServiceNames()
728 return {
"com.sun.star.deployment.UpdateInformationProvider" };
732UpdateInformationProvider::supportsService( OUString
const & serviceName )
739extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
741 css::uno::XComponentContext* xContext , css::uno::Sequence<css::uno::Any>
const&)
743 uno::Reference< ucb::XUniversalContentBroker > xUniversalContentBroker =
744 ucb::UniversalContentBroker::create(xContext);
746 uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder(
747 xml::dom::DocumentBuilder::create(xContext));
749 uno::Reference< xml::xpath::XXPathAPI > xXPath = xml::xpath::XPathAPI::create( xContext );
751 xXPath->registerNS(
"atom",
"http://www.w3.org/2005/Atom" );
753 return cppu::acquire(
754 new UpdateInformationProvider(xContext, xUniversalContentBroker, xDocumentBuilder, xXPath));
static OUString GetHWOSConfInfo(const int bSelection=0, bool bLocalize=true)
#define SAL_CONFIGFILE(name)
Reference< XInteractionHandler2 > m_xInteractionHandler
Reference< XComponentContext > m_xContext
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
double getLength(const B2DPolygon &rCandidate)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
Any SAL_CALL getCaughtException()
Reference< XStream > m_xStream
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * extensions_update_UpdateInformationProvider_get_implementation(css::uno::XComponentContext *xContext, css::uno::Sequence< css::uno::Any > const &)