1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <com/sun/star/xml/xpath/XXPathAPI.hpp>
31 #include "updateprotocol.hxx"
32 #include "updatecheckconfig.hxx"
34 #include <com/sun/star/deployment/UpdateInformationEntry.hpp>
35 #include <com/sun/star/deployment/XPackageInformationProvider.hpp>
38 #include <rtl/ref.hxx>
39 #include <rtl/uri.hxx>
40 #include <rtl/strbuf.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <rtl/bootstrap.hxx>
43 #include <osl/process.h>
45 #include <cppuhelper/implbase1.hxx>
47 namespace css
= com::sun::star
;
48 namespace container
= css::container
;
49 namespace deployment
= css::deployment
;
50 namespace lang
= css::lang
;
51 namespace uno
= css::uno
;
52 namespace task
= css::task
;
53 namespace xml
= css::xml
;
55 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
57 //------------------------------------------------------------------------------
61 uno::Sequence
< ::rtl::OUString
> & rRepositoryList
,
62 ::rtl::OUString
& rGitID
,
63 ::rtl::OUString
& rInstallSetID
)
65 rGitID
= UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" );
66 rtl::Bootstrap::expandMacros( rGitID
);
67 if ( rGitID
.isEmpty() )
70 rInstallSetID
= UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateID}" );
71 rtl::Bootstrap::expandMacros( rInstallSetID
);
72 if ( rInstallSetID
.isEmpty() )
75 rtl::OUString
aValue( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateURL}" ) );
76 rtl::Bootstrap::expandMacros( aValue
);
78 if( !aValue
.isEmpty() )
80 rRepositoryList
.realloc(1);
81 rRepositoryList
[0] = aValue
;
87 //------------------------------------------------------------------------------
89 // Returns 'true' if successfully connected to the update server
92 UpdateInfo
& o_rUpdateInfo
,
93 uno::Reference
< uno::XComponentContext
> const & rxContext
,
94 uno::Reference
< task::XInteractionHandler
> const & rxInteractionHandler
,
95 const uno::Reference
< deployment::XUpdateInformationProvider
>& rUpdateInfoProvider
)
97 OSL_TRACE("checking for updates ..");
99 ::rtl::OUString myArch
;
100 ::rtl::OUString myOS
;
102 rtl::Bootstrap::get(UNISTRING("_OS"), myOS
);
103 rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch
);
105 uno::Sequence
< ::rtl::OUString
> aRepositoryList
;
106 ::rtl::OUString aGitID
;
107 ::rtl::OUString aInstallSetID
;
109 if( ! ( getBootstrapData(aRepositoryList
, aGitID
, aInstallSetID
) && (aRepositoryList
.getLength() > 0) ) )
112 return checkForUpdates( o_rUpdateInfo
, rxContext
, rxInteractionHandler
, rUpdateInfoProvider
,
114 aRepositoryList
, aGitID
, aInstallSetID
);
119 UpdateInfo
& o_rUpdateInfo
,
120 const uno::Reference
< uno::XComponentContext
> & rxContext
,
121 const uno::Reference
< task::XInteractionHandler
> & rxInteractionHandler
,
122 const uno::Reference
< deployment::XUpdateInformationProvider
>& rUpdateInfoProvider
,
123 const rtl::OUString
&rOS
,
124 const rtl::OUString
&rArch
,
125 const uno::Sequence
< rtl::OUString
> &rRepositoryList
,
126 const rtl::OUString
&rGitID
,
127 const rtl::OUString
&rInstallSetID
)
129 if( !rxContext
.is() )
130 throw uno::RuntimeException(
131 UNISTRING( "checkForUpdates: empty component context" ), uno::Reference
< uno::XInterface
>() );
133 OSL_ASSERT( rxContext
->getServiceManager().is() );
135 // XPath implementation
136 uno::Reference
< xml::xpath::XXPathAPI
> xXPath(
137 rxContext
->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext
),
138 uno::UNO_QUERY_THROW
);
140 xXPath
->registerNS( UNISTRING("inst"), UNISTRING("http://update.libreoffice.org/description") );
142 if( rxInteractionHandler
.is() )
143 rUpdateInfoProvider
->setInteractionHandler(rxInteractionHandler
);
147 uno::Reference
< container::XEnumeration
> aUpdateInfoEnumeration
=
148 rUpdateInfoProvider
->getUpdateInformationEnumeration( rRepositoryList
, rInstallSetID
);
150 if ( !aUpdateInfoEnumeration
.is() )
151 return false; // something went wrong ..
153 rtl::OUStringBuffer aBuffer
;
154 aBuffer
.appendAscii("/child::inst:description[inst:os=\'");
155 aBuffer
.append( rOS
);
156 aBuffer
.appendAscii("\' and inst:arch=\'");
157 aBuffer
.append( rArch
);
158 aBuffer
.appendAscii("\' and inst:gitid!=\'");
159 aBuffer
.append( rGitID
);
160 aBuffer
.appendAscii("\']");
162 rtl::OUString aXPathExpression
= aBuffer
.makeStringAndClear();
164 while( aUpdateInfoEnumeration
->hasMoreElements() )
166 deployment::UpdateInformationEntry aEntry
;
168 if( aUpdateInfoEnumeration
->nextElement() >>= aEntry
)
170 uno::Reference
< xml::dom::XNode
> xNode( aEntry
.UpdateDocument
.get() );
171 uno::Reference
< xml::dom::XNodeList
> xNodeList
;
173 xNodeList
= xXPath
->selectNodeList(xNode
, aXPathExpression
174 + UNISTRING("/inst:update/attribute::src"));
175 } catch (const css::xml::xpath::XPathException
&) {
180 o_rUpdateInfo.Sources.push_back( DownloadSource(true,
181 UNISTRING("http://openoffice.bouncer.osuosl.org/?product=OpenOffice.org&os=solarissparcwjre&lang=en-US&version=2.2.1") ) );
184 sal_Int32 i
, imax
= xNodeList
->getLength();
185 for( i
= 0; i
< imax
; ++i
)
187 uno::Reference
< xml::dom::XNode
> xNode2( xNodeList
->item(i
) );
191 uno::Reference
< xml::dom::XElement
> xParent(xNode2
->getParentNode(), uno::UNO_QUERY_THROW
);
192 rtl::OUString aType
= xParent
->getAttribute(UNISTRING("type"));
193 bool bIsDirect
= ( sal_False
== aType
.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("text/html")) );
195 o_rUpdateInfo
.Sources
.push_back( DownloadSource(bIsDirect
, xNode2
->getNodeValue()) );
199 uno::Reference
< xml::dom::XNode
> xNode2
;
201 xNode2
= xXPath
->selectSingleNode(xNode
, aXPathExpression
202 + UNISTRING("/inst:version/text()"));
203 } catch (const css::xml::xpath::XPathException
&) {
208 o_rUpdateInfo
.Version
= xNode2
->getNodeValue();
211 xNode2
= xXPath
->selectSingleNode(xNode
, aXPathExpression
212 + UNISTRING("/inst:buildid/text()"));
213 } catch (const css::xml::xpath::XPathException
&) {
218 o_rUpdateInfo
.BuildId
= xNode2
->getNodeValue();
220 o_rUpdateInfo
.Description
= aEntry
.Description
;
224 xNodeList
= xXPath
->selectNodeList(xNode
, aXPathExpression
225 + UNISTRING("/inst:relnote"));
226 } catch (const css::xml::xpath::XPathException
&) {
229 imax
= xNodeList
->getLength();
230 for( i
= 0; i
< imax
; ++i
)
232 uno::Reference
< xml::dom::XElement
> xRelNote(xNodeList
->item(i
), uno::UNO_QUERY
);
235 sal_Int32 pos
= xRelNote
->getAttribute(UNISTRING("pos")).toInt32();
237 ReleaseNote
aRelNote((sal_uInt8
) pos
, xRelNote
->getAttribute(UNISTRING("src")));
239 if( xRelNote
->hasAttribute(UNISTRING("src2")) )
241 pos
= xRelNote
->getAttribute(UNISTRING("pos2")).toInt32();
242 aRelNote
.Pos2
= (sal_Int8
) pos
;
243 aRelNote
.URL2
= xRelNote
->getAttribute(UNISTRING("src2"));
246 o_rUpdateInfo
.ReleaseNotes
.push_back(aRelNote
);
250 if( !o_rUpdateInfo
.Sources
.empty() )
263 //------------------------------------------------------------------------------
264 bool storeExtensionUpdateInfos( const uno::Reference
< uno::XComponentContext
> & rxContext
,
265 const uno::Sequence
< uno::Sequence
< rtl::OUString
> > &rUpdateInfos
)
267 bool bNotify
= false;
269 if ( rUpdateInfos
.hasElements() )
271 rtl::Reference
< UpdateCheckConfig
> aConfig
= UpdateCheckConfig::get( rxContext
);
273 for ( sal_Int32 i
= rUpdateInfos
.getLength() - 1; i
>= 0; i
-- )
275 bNotify
|= aConfig
->storeExtensionVersion( rUpdateInfos
[i
][0], rUpdateInfos
[i
][1] );
281 //------------------------------------------------------------------------------
282 // Returns 'true' if there are updates for any extension
284 bool checkForExtensionUpdates( const uno::Reference
< uno::XComponentContext
> & rxContext
)
286 uno::Sequence
< uno::Sequence
< rtl::OUString
> > aUpdateList
;
288 uno::Reference
< deployment::XPackageInformationProvider
> xInfoProvider
;
291 uno::Any
aValue( rxContext
->getValueByName(
292 UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) );
293 OSL_VERIFY( aValue
>>= xInfoProvider
);
295 catch( const uno::Exception
& )
297 OSL_FAIL( "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
300 if ( !xInfoProvider
.is() ) return false;
302 aUpdateList
= xInfoProvider
->isUpdateAvailable( ::rtl::OUString() );
303 bool bNotify
= storeExtensionUpdateInfos( rxContext
, aUpdateList
);
308 //------------------------------------------------------------------------------
309 // Returns 'true' if there are any pending updates for any extension (offline check)
311 bool checkForPendingUpdates( const uno::Reference
< uno::XComponentContext
> & rxContext
)
313 uno::Sequence
< uno::Sequence
< rtl::OUString
> > aExtensionList
;
314 uno::Reference
< deployment::XPackageInformationProvider
> xInfoProvider
;
317 uno::Any
aValue( rxContext
->getValueByName(
318 UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) );
319 OSL_VERIFY( aValue
>>= xInfoProvider
);
321 catch( const uno::Exception
& )
323 OSL_FAIL( "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
326 if ( !xInfoProvider
.is() ) return false;
328 bool bPendingUpdateFound
= false;
330 aExtensionList
= xInfoProvider
->getExtensionList();
331 if ( aExtensionList
.hasElements() )
333 rtl::Reference
< UpdateCheckConfig
> aConfig
= UpdateCheckConfig::get( rxContext
);
335 for ( sal_Int32 i
= aExtensionList
.getLength() - 1; i
>= 0; i
-- )
337 bPendingUpdateFound
= aConfig
->checkExtensionVersion( aExtensionList
[i
][0], aExtensionList
[i
][1] );
338 if ( bPendingUpdateFound
)
343 return bPendingUpdateFound
;
346 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */