1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: updatefeed.cxx,v $
10 * $Revision: 1.11.52.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
34 #include <cppuhelper/implbase1.hxx>
35 #include <cppuhelper/implbase5.hxx>
36 #include <cppuhelper/implementationentry.hxx>
37 #include <com/sun/star/beans/Property.hpp>
38 #include <com/sun/star/beans/XPropertySetInfo.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/deployment/UpdateInformationEntry.hpp>
42 #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
43 #include <com/sun/star/io/XActiveDataSink.hpp>
44 #include <com/sun/star/io/XInputStream.hpp>
45 #include <com/sun/star/lang/XComponent.hpp>
46 #include <com/sun/star/lang/XServiceInfo.hpp>
47 #include <com/sun/star/task/XPasswordContainer.hpp>
48 #include "com/sun/star/task/NoMasterException.hpp"
49 #include "com/sun/star/ucb/AuthenticationRequest.hpp"
50 #ifndef _COM_SUN_STAR_UCB_XCOMMMANDENVIRONMENT_HPP_
51 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
53 #ifndef _COM_SUN_STAR_UCB_XWEBDAVCOMMMANDENVIRONMENT_HPP_
54 #include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
56 #ifndef _COM_SUN_STAR_UCB_XCOMMMANDPROCESSOR2_HPP_
57 #include <com/sun/star/ucb/XCommandProcessor2.hpp>
59 #ifndef _COM_SUN_STAR_UCB_XCONTENTIDNETIFIERFACTORY_HPP_
60 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
62 #include <com/sun/star/ucb/XContentProvider.hpp>
63 #include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
64 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
65 #include <com/sun/star/ucb/OpenMode.hpp>
66 #include <com/sun/star/sdbc/XRow.hpp>
67 #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
68 #include <com/sun/star/xml/xpath/XXPathAPI.hpp>
70 #include <rtl/ref.hxx>
71 #include <rtl/memory.h>
72 #include <rtl/bootstrap.hxx>
73 #include <rtl/ustrbuf.hxx>
74 #include <osl/process.h>
75 #include <osl/conditn.hxx>
81 #include "zlib/zlib.h"
85 namespace beans
= com::sun::star::beans
;
86 namespace container
= com::sun::star::container
;
87 namespace deployment
= com::sun::star::deployment
;
88 namespace io
= com::sun::star::io
;
89 namespace lang
= com::sun::star::lang
;
90 namespace task
= com::sun::star::task
;
91 namespace ucb
= com::sun::star::ucb
;
92 namespace uno
= com::sun::star::uno
;
93 namespace xml
= com::sun::star::xml
;
94 namespace sdbc
= com::sun::star::sdbc
;
96 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
98 //------------------------------------------------------------------------------
105 class InputStreamWrapper
: public ::cppu::WeakImplHelper1
< io::XInputStream
>
107 uno::Reference
< io::XInputStream
> m_xStream
;
110 InputStreamWrapper(const uno::Reference
< io::XInputStream
>& rxStream
) :
111 m_xStream(rxStream
) {};
113 virtual sal_Int32 SAL_CALL
readBytes(uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
114 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
116 sal_Int32 n
= m_xStream
->readBytes(aData
, nBytesToRead
);
117 OSL_TRACE( aData
.get()->elements
);
120 virtual sal_Int32 SAL_CALL
readSomeBytes(uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
121 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
123 sal_Int32 n
= m_xStream
->readSomeBytes(aData
, nMaxBytesToRead
);
124 OSL_TRACE( aData
.get()->elements
);
127 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
)
128 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
129 { m_xStream
->skipBytes(nBytesToSkip
); };
130 virtual sal_Int32 SAL_CALL
available()
131 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
132 { return m_xStream
->available(); };
133 virtual void SAL_CALL
closeInput( )
134 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
138 #define INPUT_STREAM(i) new InputStreamWrapper(i)
140 #define INPUT_STREAM(i) i
143 //------------------------------------------------------------------------------
145 class ActiveDataSink
: public ::cppu::WeakImplHelper1
< io::XActiveDataSink
>
147 uno::Reference
< io::XInputStream
> m_xStream
;
152 inline operator uno::Reference
< io::XActiveDataSink
> () { return this; };
154 virtual uno::Reference
< io::XInputStream
> SAL_CALL
getInputStream()
155 throw (uno::RuntimeException
) { return m_xStream
; };
156 virtual void SAL_CALL
setInputStream( uno::Reference
< io::XInputStream
> const & rStream
)
157 throw (uno::RuntimeException
) { m_xStream
= rStream
; };
160 //------------------------------------------------------------------------------
162 class InflateInputStream
: public ::cppu::WeakImplHelper1
< io::XInputStream
>
164 uno::Reference
< io::XInputStream
> m_xStream
;
166 uno::Sequence
< sal_Int8
> m_aBuffer
;
170 rtl::OUString m_aContentEncoding
;
172 void readIntoMemory();
175 InflateInputStream(const uno::Reference
< io::XInputStream
>& rxStream
,const rtl::OUString
& rContentEncoding
) :
176 m_xStream(rxStream
), m_nOffset(0), m_bRead(false), m_aContentEncoding(rContentEncoding
) {};
178 virtual sal_Int32 SAL_CALL
readBytes(uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
179 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
);
180 virtual sal_Int32 SAL_CALL
readSomeBytes(uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
181 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
182 { readIntoMemory(); return readBytes(aData
, nMaxBytesToRead
); };
183 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
)
184 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
187 if( m_nOffset
+ nBytesToSkip
< m_aBuffer
.getLength() )
188 m_nOffset
+= nBytesToSkip
;
190 m_nOffset
= m_aBuffer
.getLength();
192 virtual sal_Int32 SAL_CALL
available()
193 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
194 { readIntoMemory(); return m_aBuffer
.getLength() - m_nOffset
; };
195 virtual void SAL_CALL
closeInput( )
196 throw (io::NotConnectedException
, io::IOException
, uno::RuntimeException
)
197 { m_xStream
->closeInput(); };
202 InflateInputStream::readBytes(uno::Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
203 throw (io::NotConnectedException
, io::BufferSizeExceededException
, io::IOException
, uno::RuntimeException
)
206 sal_Int32 nAvailable
= available();
207 sal_Int32 nBytesToCopy
= nAvailable
< nBytesToRead
? nAvailable
: nBytesToRead
;
208 if( nBytesToCopy
> 0 )
210 aData
.realloc(nBytesToCopy
);
211 rtl_copyMemory(aData
.getArray(), m_aBuffer
.getConstArray() + m_nOffset
, nBytesToCopy
);
212 m_nOffset
+= nBytesToCopy
;
218 void InflateInputStream::readIntoMemory()
220 if( !m_bRead
&& m_xStream
.is() )
222 const sal_Int32 nBytesRequested
= 4096;
224 uno::Sequence
< sal_Int8
> aTempBuffer(nBytesRequested
);
225 uno::Sequence
< sal_Int8
> aCompressedBuffer
;
226 sal_Int32 nBytesRead
;
232 nBytesRead
= m_xStream
->readBytes(aTempBuffer
, nBytesRequested
);
236 sal_Int32 nOffset
= aCompressedBuffer
.getLength();
237 aCompressedBuffer
.realloc( nOffset
+ nBytesRead
);
239 rtl_copyMemory(aCompressedBuffer
.getArray() + nOffset
, aTempBuffer
.getConstArray(), nBytesRead
);
242 while( nBytesRead
== nBytesRequested
);
244 z_stream
*pStream
= new z_stream
;
245 /* memset to 0 to set zalloc/opaque etc */
246 rtl_zeroMemory (pStream
, sizeof(*pStream
));
249 int headerOffset
= 0;
251 if( m_aContentEncoding
.equalsAscii("gzip") )
254 magic
[0] = *((sal_uInt8
*) aCompressedBuffer
.getConstArray());
255 magic
[1] = *((sal_uInt8
*) aCompressedBuffer
.getConstArray() + 1);
257 if( (magic
[0] == 0x1f) && (magic
[1] == 0x8b) )
264 pStream
->next_in
= (unsigned char *) aCompressedBuffer
.getConstArray();
265 pStream
->avail_in
= aCompressedBuffer
.getLength();
267 pStream
->next_in
+= headerOffset
;
268 pStream
->avail_in
-= headerOffset
;
270 if( Z_OK
== inflateInit2(pStream
, windowSize
) )
276 sal_Int32 nOffset
= m_aBuffer
.getLength();
277 m_aBuffer
.realloc(nOffset
+ 4096);
279 pStream
->next_out
= reinterpret_cast < unsigned char* > ( m_aBuffer
.getArray() + nOffset
);
280 pStream
->avail_out
= 4096;
282 result
= ::inflate(pStream
, Z_FINISH
);
284 if( result
== Z_STREAM_END
)
287 } while( result
== Z_BUF_ERROR
);
290 m_aBuffer
.realloc(pStream
->total_out
);
302 //------------------------------------------------------------------------------
304 class UpdateInformationProvider
:
305 public ::cppu::WeakImplHelper5
< deployment::XUpdateInformationProvider
,
306 ucb::XCommandEnvironment
,
307 ucb::XWebDAVCommandEnvironment
,
309 task::XInteractionHandler
>
312 static uno::Reference
< uno::XInterface
> createInstance(const uno::Reference
<uno::XComponentContext
>& xContext
);
314 static uno::Sequence
< rtl::OUString
> getServiceNames();
315 static rtl::OUString
getImplName();
317 uno::Reference
< xml::dom::XElement
> getDocumentRoot(const uno::Reference
< xml::dom::XNode
>& rxNode
);
318 uno::Reference
< xml::dom::XNode
> getChildNode(const uno::Reference
< xml::dom::XNode
>& rxNode
, const rtl::OUString
& rName
);
321 // XUpdateInformationService
322 virtual uno::Sequence
< uno::Reference
< xml::dom::XElement
> > SAL_CALL
323 getUpdateInformation(
324 uno::Sequence
< rtl::OUString
> const & repositories
,
325 rtl::OUString
const & extensionId
326 ) throw (uno::Exception
, uno::RuntimeException
);
328 virtual void SAL_CALL
cancel()
329 throw (uno::RuntimeException
);
331 virtual void SAL_CALL
setInteractionHandler(
332 uno::Reference
< task::XInteractionHandler
> const & handler
)
333 throw (uno::RuntimeException
);
335 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
336 getUpdateInformationEnumeration(
337 uno::Sequence
< rtl::OUString
> const & repositories
,
338 rtl::OUString
const & extensionId
339 ) throw (uno::Exception
, uno::RuntimeException
);
341 // XCommandEnvironment
342 virtual uno::Reference
< task::XInteractionHandler
> SAL_CALL
getInteractionHandler()
343 throw ( uno::RuntimeException
);
345 virtual uno::Reference
< ucb::XProgressHandler
> SAL_CALL
getProgressHandler()
346 throw ( uno::RuntimeException
) { return uno::Reference
< ucb::XProgressHandler
>(); };
348 // XWebDAVCommandEnvironment
349 virtual uno::Sequence
< beans::NamedValue
> SAL_CALL
getUserRequestHeaders(
350 const rtl::OUString
&, const rtl::OUString
& )
351 throw ( uno::RuntimeException
) { return m_aRequestHeaderList
; };
354 virtual rtl::OUString SAL_CALL
getImplementationName()
355 throw (uno::RuntimeException
);
356 virtual sal_Bool SAL_CALL
supportsService(rtl::OUString
const & serviceName
)
357 throw (uno::RuntimeException
);
358 virtual uno::Sequence
< rtl::OUString
> SAL_CALL
getSupportedServiceNames()
359 throw (uno::RuntimeException
);
361 // XInteractionHandler
362 virtual void SAL_CALL
handle( const uno::Reference
< task::XInteractionRequest
>& rRequest
)
363 throw( uno::RuntimeException
);
367 virtual ~UpdateInformationProvider();
368 static uno::Any
getConfigurationItem(uno::Reference
<lang::XMultiServiceFactory
> const & configurationProvider
, rtl::OUString
const & node
, rtl::OUString
const & item
);
371 uno::Reference
< io::XInputStream
> load(const rtl::OUString
& rURL
);
373 void storeCommandInfo( sal_Int32 nCommandId
,
374 uno::Reference
< ucb::XCommandProcessor
> const & rxCommandProcessor
);
376 bool initPasswordContainer( uno::Reference
< task::XPasswordContainer
> * pContainer
);
378 UpdateInformationProvider(const uno::Reference
<uno::XComponentContext
>& xContext
,
379 const uno::Reference
< ucb::XContentIdentifierFactory
>& xContentIdFactory
,
380 const uno::Reference
< ucb::XContentProvider
>& xContentProvider
,
381 const uno::Reference
< xml::dom::XDocumentBuilder
>& xDocumentBuilder
,
382 const uno::Reference
< xml::xpath::XXPathAPI
>& xXPathAPI
);
384 const uno::Reference
< uno::XComponentContext
> m_xContext
;
386 const uno::Reference
< ucb::XContentIdentifierFactory
> m_xContentIdFactory
;
387 const uno::Reference
< ucb::XContentProvider
> m_xContentProvider
;
388 const uno::Reference
< xml::dom::XDocumentBuilder
> m_xDocumentBuilder
;
389 const uno::Reference
< xml::xpath::XXPathAPI
> m_xXPathAPI
;
391 uno::Sequence
< beans::NamedValue
> m_aRequestHeaderList
;
393 uno::Reference
< ucb::XCommandProcessor
> m_xCommandProcessor
;
394 uno::Reference
< task::XInteractionHandler
> m_xInteractionHandler
;
397 osl::Condition m_bCancelled
;
399 sal_Int32 m_nCommandId
;
402 //------------------------------------------------------------------------------
404 class UpdateInformationEnumeration
: public ::cppu::WeakImplHelper1
< container::XEnumeration
>
407 UpdateInformationEnumeration(const uno::Reference
< xml::dom::XNodeList
>& xNodeList
,
408 const uno::Reference
< UpdateInformationProvider
> xUpdateInformationProvider
) :
409 m_xUpdateInformationProvider(xUpdateInformationProvider
),
410 m_xNodeList(xNodeList
),
411 m_nNodes(xNodeList
.is() ? xNodeList
->getLength() : 0),
416 virtual ~UpdateInformationEnumeration() {};
419 sal_Bool SAL_CALL
hasMoreElements() throw (uno::RuntimeException
) { return m_nCount
< m_nNodes
; };
420 uno::Any SAL_CALL
nextElement() throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
422 OSL_ASSERT( m_xNodeList
.is() );
423 OSL_ASSERT( m_xUpdateInformationProvider
.is() );
425 if( !(m_nCount
< m_nNodes
) )
426 throw container::NoSuchElementException(rtl::OUString::valueOf(m_nCount
), *this);
430 deployment::UpdateInformationEntry aEntry
;
432 uno::Reference
< xml::dom::XNode
> xAtomEntryNode( m_xNodeList
->item(m_nCount
++) );
434 uno::Reference
< xml::dom::XNode
> xSummaryNode(
435 m_xUpdateInformationProvider
->getChildNode( xAtomEntryNode
, UNISTRING( "summary/text()" ) )
438 if( xSummaryNode
.is() )
439 aEntry
.Description
= xSummaryNode
->getNodeValue();
441 uno::Reference
< xml::dom::XNode
> xContentNode(
442 m_xUpdateInformationProvider
->getChildNode( xAtomEntryNode
, UNISTRING( "content" ) ) );
444 if( xContentNode
.is() )
445 aEntry
.UpdateDocument
= m_xUpdateInformationProvider
->getDocumentRoot(xContentNode
);
447 return uno::makeAny(aEntry
);
450 // action has been aborted
451 catch( ucb::CommandAbortedException
const & e
)
452 { throw lang::WrappedTargetException( UNISTRING( "Command aborted" ), *this, uno::makeAny(e
) ); }
454 // let runtime exception pass
455 catch( uno::RuntimeException
const & ) { throw; }
457 // document not accessible
458 catch( uno::Exception
const & e
)
459 { throw lang::WrappedTargetException( UNISTRING( "Document not accessible" ), *this, uno::makeAny(e
) ); }
463 const uno::Reference
< UpdateInformationProvider
> m_xUpdateInformationProvider
;
464 const uno::Reference
< xml::dom::XNodeList
> m_xNodeList
;
465 const sal_Int32 m_nNodes
;
469 //------------------------------------------------------------------------------
471 class SingleUpdateInformationEnumeration
: public ::cppu::WeakImplHelper1
< container::XEnumeration
>
474 SingleUpdateInformationEnumeration(const uno::Reference
< xml::dom::XElement
>& xElement
)
475 : m_nCount(0) { m_aEntry
.UpdateDocument
= xElement
; };
476 virtual ~SingleUpdateInformationEnumeration() {};
479 sal_Bool SAL_CALL
hasMoreElements() throw (uno::RuntimeException
) { return 0 == m_nCount
; };
480 uno::Any SAL_CALL
nextElement() throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
483 throw container::NoSuchElementException(rtl::OUString::valueOf(m_nCount
), *this);
486 return uno::makeAny(m_aEntry
);
491 deployment::UpdateInformationEntry m_aEntry
;
495 //------------------------------------------------------------------------------
497 UpdateInformationProvider::UpdateInformationProvider(
498 const uno::Reference
<uno::XComponentContext
>& xContext
,
499 const uno::Reference
< ucb::XContentIdentifierFactory
>& xContentIdFactory
,
500 const uno::Reference
< ucb::XContentProvider
>& xContentProvider
,
501 const uno::Reference
< xml::dom::XDocumentBuilder
>& xDocumentBuilder
,
502 const uno::Reference
< xml::xpath::XXPathAPI
>& xXPathAPI
503 ) : m_xContext(xContext
), m_xContentIdFactory(xContentIdFactory
),
504 m_xContentProvider(xContentProvider
), m_xDocumentBuilder(xDocumentBuilder
),
505 m_xXPathAPI(xXPathAPI
), m_aRequestHeaderList(2)
507 uno::Reference
< lang::XMultiComponentFactory
> xServiceManager(xContext
->getServiceManager());
508 if( !xServiceManager
.is() )
509 throw uno::RuntimeException(
510 UNISTRING("unable to obtain service manager from component context"),
511 uno::Reference
< uno::XInterface
>());
513 uno::Reference
< lang::XMultiServiceFactory
> xConfigurationProvider(
514 xServiceManager
->createInstanceWithContext(
515 UNISTRING("com.sun.star.configuration.ConfigurationProvider"),
517 uno::UNO_QUERY_THROW
);
519 rtl::OUStringBuffer buf
;
521 getConfigurationItem(
522 xConfigurationProvider
,
523 UNISTRING("org.openoffice.Setup/Product"),
524 UNISTRING("ooName")) >>= name
;
526 buf
.append(sal_Unicode(' '));
527 rtl::OUString version
;
528 getConfigurationItem(
529 xConfigurationProvider
,
530 UNISTRING("org.openoffice.Setup/Product"),
531 UNISTRING("ooSetupVersion")) >>= version
;
533 rtl::OUString
edition(
535 "${${BRAND_BASE_DIR}/program/edition/edition.ini:"
537 rtl::Bootstrap::expandMacros(edition
);
538 if (edition
.getLength() != 0) {
539 buf
.append(sal_Unicode(' '));
542 rtl::OUString extension
;
543 getConfigurationItem(
544 xConfigurationProvider
,
545 UNISTRING("org.openoffice.Setup/Product"),
546 UNISTRING("ooSetupExtension")) >>= extension
;
547 if (extension
.getLength() != 0) {
548 buf
.append(sal_Unicode(' '));
549 buf
.append(extension
);
551 rtl::OUString
product(buf
.makeStringAndClear());
553 rtl::OUString
aBaseBuildId( UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) );
554 rtl::Bootstrap::expandMacros( aBaseBuildId
);
556 rtl::OUString
aBrandBuildId( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) );
557 rtl::Bootstrap::expandMacros( aBrandBuildId
);
559 rtl::OUString
aUserAgent( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateUserAgent}" ) );
560 rtl::Bootstrap::expandMacros( aUserAgent
);
562 if ( ! aBaseBuildId
.equals( aBrandBuildId
) )
564 sal_Int32 nIndex
= aUserAgent
.indexOf( aBrandBuildId
, 0 );
566 aUserAgent
= aUserAgent
.replaceAt( nIndex
, aBrandBuildId
.getLength(), aBaseBuildId
);
569 for (sal_Int32 i
= 0;;) {
570 i
= aUserAgent
.indexOfAsciiL(
571 RTL_CONSTASCII_STRINGPARAM("<PRODUCT>"), i
);
575 aUserAgent
= aUserAgent
.replaceAt(
576 i
, RTL_CONSTASCII_LENGTH("<PRODUCT>"), product
);
577 i
+= product
.getLength();
580 m_aRequestHeaderList
[0].Name
= UNISTRING("Accept-Language");
581 m_aRequestHeaderList
[0].Value
= getConfigurationItem( xConfigurationProvider
, UNISTRING("org.openoffice.Setup/L10N"), UNISTRING("ooLocale") );
582 m_aRequestHeaderList
[1].Name
= UNISTRING("Accept-Encoding");
583 m_aRequestHeaderList
[1].Value
= uno::makeAny( UNISTRING("gzip,deflate") );
585 if( aUserAgent
.getLength() > 0 )
587 m_aRequestHeaderList
.realloc(3);
588 m_aRequestHeaderList
[2].Name
= UNISTRING("User-Agent");
589 m_aRequestHeaderList
[2].Value
= uno::makeAny(aUserAgent
);
593 //------------------------------------------------------------------------------
594 uno::Reference
< uno::XInterface
>
595 UpdateInformationProvider::createInstance(const uno::Reference
<uno::XComponentContext
>& xContext
)
597 uno::Reference
< lang::XMultiComponentFactory
> xServiceManager(xContext
->getServiceManager());
598 if( !xServiceManager
.is() )
599 throw uno::RuntimeException(
600 UNISTRING( "unable to obtain service manager from component context" ),
601 uno::Reference
< uno::XInterface
> ());
603 uno::Reference
< ucb::XContentIdentifierFactory
> xContentIdFactory(
604 xServiceManager
->createInstanceWithContext( UNISTRING( "com.sun.star.ucb.UniversalContentBroker" ), xContext
),
605 uno::UNO_QUERY_THROW
);
607 uno::Reference
< ucb::XContentProvider
> xContentProvider(xContentIdFactory
, uno::UNO_QUERY_THROW
);
609 uno::Reference
< xml::dom::XDocumentBuilder
> xDocumentBuilder(
610 xServiceManager
->createInstanceWithContext( UNISTRING( "com.sun.star.xml.dom.DocumentBuilder" ), xContext
),
611 uno::UNO_QUERY_THROW
);
613 uno::Reference
< xml::xpath::XXPathAPI
> xXPath(
614 xServiceManager
->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), xContext
),
615 uno::UNO_QUERY_THROW
);
617 xXPath
->registerNS( UNISTRING("atom"), UNISTRING("http://www.w3.org/2005/Atom") );
619 return *new UpdateInformationProvider(xContext
, xContentIdFactory
, xContentProvider
, xDocumentBuilder
, xXPath
);
622 //------------------------------------------------------------------------------
624 UpdateInformationProvider::~UpdateInformationProvider()
628 //------------------------------------------------------------------------------
631 UpdateInformationProvider::getConfigurationItem(uno::Reference
<lang::XMultiServiceFactory
> const & configurationProvider
, rtl::OUString
const & node
, rtl::OUString
const & item
)
633 beans::PropertyValue aProperty
;
634 aProperty
.Name
= UNISTRING("nodepath");
635 aProperty
.Value
= uno::makeAny(node
);
637 uno::Sequence
< uno::Any
> aArgumentList( 1 );
638 aArgumentList
[0] = uno::makeAny( aProperty
);
640 uno::Reference
< container::XNameAccess
> xNameAccess(
641 configurationProvider
->createInstanceWithArguments(
642 UNISTRING("com.sun.star.configuration.ConfigurationAccess"),
644 uno::UNO_QUERY_THROW
);
646 return xNameAccess
->getByName(item
);
649 //------------------------------------------------------------------------------
652 UpdateInformationProvider::storeCommandInfo(
653 sal_Int32 nCommandId
,
654 uno::Reference
< ucb::XCommandProcessor
> const & rxCommandProcessor
)
656 osl::MutexGuard
aGuard(m_aMutex
);
658 m_nCommandId
= nCommandId
;
659 m_xCommandProcessor
= rxCommandProcessor
;
662 //------------------------------------------------------------------------------
664 bool UpdateInformationProvider::initPasswordContainer( uno::Reference
< task::XPasswordContainer
> * pContainer
)
666 OSL_ENSURE( pContainer
, "specification violation" );
668 if ( !pContainer
->is() )
670 uno::Reference
<uno::XComponentContext
> xContext(m_xContext
);
673 throw uno::RuntimeException( UNISTRING( "UpdateInformationProvider: empty component context" ), *this );
675 uno::Reference
< lang::XMultiComponentFactory
> xServiceManager(xContext
->getServiceManager());
677 if( !xServiceManager
.is() )
678 throw uno::RuntimeException( UNISTRING( "UpdateInformationProvider: unable to obtain service manager from component context" ), *this );
680 *pContainer
= uno::Reference
< task::XPasswordContainer
>(
681 xServiceManager
->createInstanceWithContext( UNISTRING( "com.sun.star.task.PasswordContainer" ), xContext
),
685 OSL_ENSURE(pContainer
->is(), "unexpected situation");
686 return pContainer
->is();
689 //------------------------------------------------------------------------------
691 uno::Reference
< io::XInputStream
>
692 UpdateInformationProvider::load(const rtl::OUString
& rURL
)
694 uno::Reference
< ucb::XContentIdentifier
> xId
= m_xContentIdFactory
->createContentIdentifier(rURL
);
697 throw uno::RuntimeException(
698 UNISTRING( "unable to obtain universal content id" ), *this);
700 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(m_xContentProvider
->queryContent(xId
), uno::UNO_QUERY_THROW
);
701 rtl::Reference
< ActiveDataSink
> aSink(new ActiveDataSink());
703 ucb::OpenCommandArgument2 aOpenArgument
;
704 aOpenArgument
.Mode
= ucb::OpenMode::DOCUMENT
;
705 aOpenArgument
.Priority
= 32768;
706 aOpenArgument
.Sink
= *aSink
;
708 ucb::Command aCommand
;
709 aCommand
.Name
= UNISTRING("open");
710 aCommand
.Argument
= uno::makeAny(aOpenArgument
);
712 sal_Int32 nCommandId
= xCommandProcessor
->createCommandIdentifier();
714 storeCommandInfo(nCommandId
, xCommandProcessor
);
717 uno::Any aResult
= xCommandProcessor
->execute(aCommand
, nCommandId
,
718 static_cast < XCommandEnvironment
*> (this));
720 catch( const uno::Exception
& /* e */ )
722 storeCommandInfo(0, uno::Reference
< ucb::XCommandProcessor
> ());
724 uno::Reference
< ucb::XCommandProcessor2
> xCommandProcessor2(xCommandProcessor
, uno::UNO_QUERY
);
725 if( xCommandProcessor2
.is() )
726 xCommandProcessor2
->releaseCommandIdentifier(nCommandId
);
731 uno::Sequence
< beans::Property
> aProps( 1 );
732 aProps
[0].Name
= UNISTRING( "Content-Encoding" );
734 aCommand
.Name
= UNISTRING("getPropertyValues");
735 aCommand
.Argument
= uno::makeAny( aProps
);
737 sal_Bool bCompressed
= sal_False
;
738 rtl::OUString aContentEncoding
;
742 uno::Any aResult
= xCommandProcessor
->execute(aCommand
, 0,
743 static_cast < XCommandEnvironment
*> (this));
744 uno::Reference
< sdbc::XRow
> xPropList( aResult
, uno::UNO_QUERY
);
745 if ( xPropList
.is() ) {
746 aContentEncoding
= xPropList
->getString(1);
747 if( aContentEncoding
.equalsAscii("gzip") || aContentEncoding
.equalsAscii("deflate"))
748 bCompressed
= sal_True
;
751 catch( const uno::Exception
&e
)
753 OSL_TRACE( "Caught exception: %s\n",
754 rtl::OUStringToOString(e
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
757 storeCommandInfo(0, uno::Reference
< ucb::XCommandProcessor
> ());
759 uno::Reference
< ucb::XCommandProcessor2
> xCommandProcessor2(xCommandProcessor
, uno::UNO_QUERY
);
760 if( xCommandProcessor2
.is() )
761 xCommandProcessor2
->releaseCommandIdentifier(nCommandId
);
764 return INPUT_STREAM( new InflateInputStream( aSink
->getInputStream(), aContentEncoding
) );
766 return INPUT_STREAM(aSink
->getInputStream());
769 //------------------------------------------------------------------------------
771 // TODO: docu content node
773 uno::Reference
< xml::dom::XElement
>
774 UpdateInformationProvider::getDocumentRoot(const uno::Reference
< xml::dom::XNode
>& rxNode
)
776 OSL_ASSERT(m_xDocumentBuilder
.is());
778 uno::Reference
< xml::dom::XElement
> xElement(rxNode
, uno::UNO_QUERY_THROW
);
780 // load the document referenced in 'src' attribute ..
781 if( xElement
->hasAttribute( UNISTRING("src") ) )
783 uno::Reference
< xml::dom::XDocument
> xUpdateXML
=
784 m_xDocumentBuilder
->parse(load(xElement
->getAttribute( UNISTRING("src") )));
786 OSL_ASSERT( xUpdateXML
.is() );
788 if( xUpdateXML
.is() )
789 return xUpdateXML
->getDocumentElement();
791 // .. or return the (single) child element
794 uno::Reference
< xml::dom::XNodeList
> xChildNodes
= rxNode
->getChildNodes();
796 // ignore possible #text nodes
797 sal_Int32 nmax
= xChildNodes
->getLength();
798 for(sal_Int32 n
=0; n
< nmax
; n
++)
800 uno::Reference
< xml::dom::XElement
> xChildElement(xChildNodes
->item(n
), uno::UNO_QUERY
);
801 if( xChildElement
.is() )
803 /* Copy the content to a dedicated document since XXPathAPI->selectNodeList
804 * seems to evaluate expression always relative to the root node.
806 uno::Reference
< xml::dom::XDocument
> xUpdateXML
= m_xDocumentBuilder
->newDocument();
807 xUpdateXML
->appendChild( xUpdateXML
->importNode(xChildElement
.get(), sal_True
) );
808 return xUpdateXML
->getDocumentElement();
813 return uno::Reference
< xml::dom::XElement
> ();
816 //------------------------------------------------------------------------------
818 uno::Reference
< xml::dom::XNode
>
819 UpdateInformationProvider::getChildNode(const uno::Reference
< xml::dom::XNode
>& rxNode
,
820 const rtl::OUString
& rName
)
822 OSL_ASSERT(m_xXPathAPI
.is());
824 return m_xXPathAPI
->selectSingleNode(rxNode
, UNISTRING( "./atom:" ) + rName
);
825 } catch (xml::xpath::XPathException
&) {
831 //------------------------------------------------------------------------------
833 uno::Reference
< container::XEnumeration
> SAL_CALL
834 UpdateInformationProvider::getUpdateInformationEnumeration(
835 uno::Sequence
< rtl::OUString
> const & repositories
,
836 rtl::OUString
const & extensionId
837 ) throw (uno::Exception
, uno::RuntimeException
)
839 OSL_ASSERT(m_xDocumentBuilder
.is());
841 // reset cancelled flag
842 m_bCancelled
.reset();
844 for(sal_Int32 n
=0; n
<repositories
.getLength(); n
++)
848 uno::Reference
< xml::dom::XDocument
> xDocument
= m_xDocumentBuilder
->parse(load(repositories
[n
]));
849 uno::Reference
< xml::dom::XElement
> xElement
;
852 xElement
= xDocument
->getDocumentElement();
856 if( xElement
->getNodeName().equalsAsciiL("feed", 4) )
858 rtl::OUString aXPathExpression
;
860 if( extensionId
.getLength() > 0 )
861 aXPathExpression
= UNISTRING("//atom:entry/atom:category[@term=\'") + extensionId
+ UNISTRING("\']/..");
863 aXPathExpression
= UNISTRING("//atom:entry");
865 uno::Reference
< xml::dom::XNodeList
> xNodeList
;
867 xNodeList
= m_xXPathAPI
->selectNodeList(xDocument
.get(),
869 } catch (xml::xpath::XPathException
&) {
873 return new UpdateInformationEnumeration(xNodeList
, this);
877 return new SingleUpdateInformationEnumeration(xElement
);
881 if( m_bCancelled
.check() )
884 // rethrow runtime exceptions
885 catch( uno::RuntimeException
const & ) { throw; }
887 // rethrow only if last url in the list
888 catch( uno::Exception
const & )
890 if( n
+1 >= repositories
.getLength() )
895 return uno::Reference
< container::XEnumeration
>();
898 //------------------------------------------------------------------------------
900 uno::Sequence
< uno::Reference
< xml::dom::XElement
> > SAL_CALL
901 UpdateInformationProvider::getUpdateInformation(
902 uno::Sequence
< rtl::OUString
> const & repositories
,
903 rtl::OUString
const & extensionId
904 ) throw (uno::Exception
, uno::RuntimeException
)
906 uno::Reference
< container::XEnumeration
> xEnumeration(
907 getUpdateInformationEnumeration(repositories
, extensionId
)
910 uno::Sequence
< uno::Reference
< xml::dom::XElement
> > aRet
;
912 if( xEnumeration
.is() )
914 while( xEnumeration
->hasMoreElements() )
918 deployment::UpdateInformationEntry aEntry
;
919 if( (xEnumeration
->nextElement() >>= aEntry
) && aEntry
.UpdateDocument
.is() )
921 sal_Int32 n
= aRet
.getLength();
923 aRet
[n
] = aEntry
.UpdateDocument
;
927 catch( const lang::WrappedTargetException
& e
)
929 // command aborted, return what we have got so far
930 if( e
.TargetException
.isExtractableTo( ::cppu::UnoType
< ::com::sun::star::ucb::CommandAbortedException
>::get() ) )
935 // ignore files that can't be loaded
943 //------------------------------------------------------------------------------
946 UpdateInformationProvider::cancel() throw (uno::RuntimeException
)
950 osl::MutexGuard
aGuard(m_aMutex
);
951 if( m_xCommandProcessor
.is() )
952 m_xCommandProcessor
->abort(m_nCommandId
);
955 //------------------------------------------------------------------------------
958 UpdateInformationProvider::setInteractionHandler(
959 uno::Reference
< task::XInteractionHandler
> const & handler
)
960 throw (uno::RuntimeException
)
962 osl::MutexGuard
aGuard(m_aMutex
);
963 m_xInteractionHandler
= handler
;
966 //------------------------------------------------------------------------------
968 uno::Reference
< task::XInteractionHandler
> SAL_CALL
969 UpdateInformationProvider::getInteractionHandler()
970 throw ( uno::RuntimeException
)
972 osl::MutexGuard
aGuard( m_aMutex
);
974 if ( m_xInteractionHandler
.is() )
975 return m_xInteractionHandler
;
979 //------------------------------------------------------------------------------
981 uno::Sequence
< rtl::OUString
>
982 UpdateInformationProvider::getServiceNames()
984 uno::Sequence
< rtl::OUString
> aServiceList(1);
985 aServiceList
[0] = UNISTRING( "com.sun.star.deployment.UpdateInformationProvider");
989 //------------------------------------------------------------------------------
992 UpdateInformationProvider::getImplName()
994 return UNISTRING( "vnd.sun.UpdateInformationProvider");
997 //------------------------------------------------------------------------------
999 rtl::OUString SAL_CALL
1000 UpdateInformationProvider::getImplementationName() throw (uno::RuntimeException
)
1002 return getImplName();
1005 //------------------------------------------------------------------------------
1007 uno::Sequence
< rtl::OUString
> SAL_CALL
1008 UpdateInformationProvider::getSupportedServiceNames() throw (uno::RuntimeException
)
1010 return getServiceNames();
1013 //------------------------------------------------------------------------------
1016 UpdateInformationProvider::supportsService( rtl::OUString
const & serviceName
) throw (uno::RuntimeException
)
1018 uno::Sequence
< rtl::OUString
> aServiceNameList
= getServiceNames();
1020 for( sal_Int32 n
=0; n
< aServiceNameList
.getLength(); n
++ )
1021 if( aServiceNameList
[n
].equals(serviceName
) )
1027 //------------------------------------------------------------------------------
1029 void SAL_CALL
UpdateInformationProvider::handle( uno::Reference
< task::XInteractionRequest
> const & rRequest
)
1030 throw (uno::RuntimeException
)
1032 uno::Any
aAnyRequest( rRequest
->getRequest() );
1033 ucb::AuthenticationRequest aAuthenticationRequest
;
1035 if ( aAnyRequest
>>= aAuthenticationRequest
)
1037 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > xContinuations
= rRequest
->getContinuations();
1038 uno::Reference
< task::XInteractionHandler
> xIH
;
1039 uno::Reference
< ucb::XInteractionSupplyAuthentication
> xSupplyAuthentication
;
1040 uno::Reference
< task::XPasswordContainer
> xContainer
;
1042 for ( sal_Int32 i
= 0; i
< xContinuations
.getLength(); ++i
)
1044 xSupplyAuthentication
= uno::Reference
< ucb::XInteractionSupplyAuthentication
>(
1045 xContinuations
[i
], uno::UNO_QUERY
);
1046 if ( xSupplyAuthentication
.is() )
1050 // xContainer works with userName passwdSequences pairs:
1051 if ( xSupplyAuthentication
.is() &&
1052 aAuthenticationRequest
.HasUserName
&&
1053 aAuthenticationRequest
.HasPassword
&&
1054 initPasswordContainer( &xContainer
) )
1056 xIH
= getInteractionHandler();
1059 if ( aAuthenticationRequest
.UserName
.getLength() == 0 )
1061 task::UrlRecord
aRec( xContainer
->find( aAuthenticationRequest
.ServerName
, xIH
) );
1062 if ( aRec
.UserList
.getLength() != 0 )
1064 if ( xSupplyAuthentication
->canSetUserName() )
1065 xSupplyAuthentication
->setUserName( aRec
.UserList
[0].UserName
.getStr() );
1066 if ( xSupplyAuthentication
->canSetPassword() )
1068 OSL_ENSURE( aRec
.UserList
[0].Passwords
.getLength() != 0, "empty password list" );
1069 xSupplyAuthentication
->setPassword( aRec
.UserList
[0].Passwords
[0].getStr() );
1071 if ( aRec
.UserList
[0].Passwords
.getLength() > 1 )
1073 if ( aAuthenticationRequest
.HasRealm
)
1075 if ( xSupplyAuthentication
->canSetRealm() )
1076 xSupplyAuthentication
->setRealm( aRec
.UserList
[0].Passwords
[1].getStr() );
1078 else if ( xSupplyAuthentication
->canSetAccount() )
1079 xSupplyAuthentication
->setAccount( aRec
.UserList
[0].Passwords
[1].getStr() );
1081 xSupplyAuthentication
->select();
1087 task::UrlRecord
aRec(xContainer
->findForName( aAuthenticationRequest
.ServerName
,
1088 aAuthenticationRequest
.UserName
,
1090 if ( aRec
.UserList
.getLength() != 0 )
1092 OSL_ENSURE( aRec
.UserList
[0].Passwords
.getLength() != 0, "empty password list" );
1093 if ( !aAuthenticationRequest
.HasPassword
||
1094 ( aAuthenticationRequest
.Password
!= aRec
.UserList
[0].Passwords
[0] ) )
1096 if ( xSupplyAuthentication
->canSetUserName() )
1097 xSupplyAuthentication
->setUserName( aRec
.UserList
[0].UserName
.getStr() );
1098 if ( xSupplyAuthentication
->canSetPassword() )
1099 xSupplyAuthentication
->setPassword(aRec
.UserList
[0].Passwords
[0].getStr());
1100 if ( aRec
.UserList
[0].Passwords
.getLength() > 1 )
1102 if ( aAuthenticationRequest
.HasRealm
)
1104 if ( xSupplyAuthentication
->canSetRealm() )
1105 xSupplyAuthentication
->setRealm(aRec
.UserList
[0].Passwords
[1].getStr());
1107 else if ( xSupplyAuthentication
->canSetAccount() )
1108 xSupplyAuthentication
->setAccount(aRec
.UserList
[0].Passwords
[1].getStr());
1110 xSupplyAuthentication
->select();
1116 catch (task::NoMasterException
const &)
1117 {} // user did not enter master password
1122 } // anonymous namespace
1124 //------------------------------------------------------------------------------
1126 static uno::Reference
<uno::XInterface
> SAL_CALL
1127 createInstance(uno::Reference
<uno::XComponentContext
> const & xContext
)
1129 return UpdateInformationProvider::createInstance(xContext
);
1132 //------------------------------------------------------------------------------
1134 static const cppu::ImplementationEntry kImplementations_entries
[] =
1138 UpdateInformationProvider::getImplName
,
1139 UpdateInformationProvider::getServiceNames
,
1140 cppu::createSingleComponentFactory
,
1144 { NULL
, NULL
, NULL
, NULL
, NULL
, 0 }
1147 //------------------------------------------------------------------------------
1149 extern "C" void SAL_CALL
1150 component_getImplementationEnvironment( const sal_Char
**aEnvTypeName
, uno_Environment
**)
1152 *aEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
1155 //------------------------------------------------------------------------------
1157 extern "C" sal_Bool SAL_CALL
1158 component_writeInfo(void *pServiceManager
, void *pRegistryKey
)
1160 return cppu::component_writeInfoHelper(
1163 kImplementations_entries
1167 //------------------------------------------------------------------------------
1170 component_getFactory(const sal_Char
*pszImplementationName
, void *pServiceManager
, void *pRegistryKey
)
1172 return cppu::component_getFactoryHelper(
1173 pszImplementationName
,
1176 kImplementations_entries
) ;