LibreOffice Module extensions (master) 1
updateprotocol.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 <config_folders.h>
21
22#include <com/sun/star/xml/xpath/XPathAPI.hpp>
23#include <com/sun/star/xml/xpath/XPathException.hpp>
24
25#include "updateprotocol.hxx"
26#include "updatecheckconfig.hxx"
27
28#include <com/sun/star/deployment/UpdateInformationEntry.hpp>
29#include <com/sun/star/deployment/XPackageInformationProvider.hpp>
30
31
32#include <rtl/ref.hxx>
33#include <rtl/bootstrap.hxx>
34#include <osl/diagnose.h>
35
36namespace container = css::container ;
37namespace deployment = css::deployment ;
38namespace uno = css::uno ;
39namespace task = css::task ;
40namespace xml = css::xml ;
41
42
43static bool
45 uno::Sequence< OUString > & rRepositoryList,
46 OUString & rGitID,
47 OUString & rInstallSetID)
48{
49 rGitID = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":buildid}";
50 rtl::Bootstrap::expandMacros( rGitID );
51 if ( rGitID.isEmpty() )
52 return false;
53
54 rInstallSetID = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":UpdateID}";
55 rtl::Bootstrap::expandMacros( rInstallSetID );
56 if ( rInstallSetID.isEmpty() )
57 return false;
58
59 OUString aValue( "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version") ":UpdateURL}" );
60 rtl::Bootstrap::expandMacros( aValue );
61
62 if( !aValue.isEmpty() )
63 {
64 rRepositoryList = { aValue };
65 }
66
67 return true;
68}
69
70
71// Returns 'true' if successfully connected to the update server
72bool
74 UpdateInfo& o_rUpdateInfo,
75 uno::Reference< uno::XComponentContext > const & rxContext,
76 uno::Reference< task::XInteractionHandler > const & rxInteractionHandler,
77 const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider)
78{
79 OUString myArch;
80 OUString myOS;
81
82 rtl::Bootstrap::get("_OS", myOS);
83 rtl::Bootstrap::get("_ARCH", myArch);
84
85 uno::Sequence< OUString > aRepositoryList;
86 OUString aGitID;
87 OUString aInstallSetID;
88
89 if( ! ( getBootstrapData(aRepositoryList, aGitID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) )
90 return false;
91
92 return checkForUpdates( o_rUpdateInfo, rxContext, rxInteractionHandler, rUpdateInfoProvider,
93 myOS, myArch,
94 aRepositoryList, aGitID, aInstallSetID );
95}
96
97bool
99 UpdateInfo& o_rUpdateInfo,
100 const uno::Reference< uno::XComponentContext > & rxContext,
101 const uno::Reference< task::XInteractionHandler > & rxInteractionHandler,
102 const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider,
103 std::u16string_view rOS,
104 std::u16string_view rArch,
105 const uno::Sequence< OUString > &rRepositoryList,
106 std::u16string_view rGitID,
107 const OUString &rInstallSetID )
108{
109 if( !rxContext.is() )
110 throw uno::RuntimeException( "checkForUpdates: empty component context" );
111
112 OSL_ASSERT( rxContext->getServiceManager().is() );
113
114 // XPath implementation
115 uno::Reference< xml::xpath::XXPathAPI > xXPath = xml::xpath::XPathAPI::create(rxContext);
116
117 xXPath->registerNS( "inst", "http://update.libreoffice.org/description" );
118
119 if( rxInteractionHandler.is() )
120 rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler);
121
122 try
123 {
124 uno::Reference< container::XEnumeration > aUpdateInfoEnumeration =
125 rUpdateInfoProvider->getUpdateInformationEnumeration( rRepositoryList, rInstallSetID );
126
127 if ( !aUpdateInfoEnumeration.is() )
128 return false; // something went wrong ..
129
130 OUString aXPathExpression =
131 OUString::Concat("/child::inst:description[inst:os=\'")+
132 rOS +
133 "\' and inst:arch=\'"+
134 rArch +
135 "\' and inst:gitid!=\'"+
136 rGitID +
137 "\']";
138
139
140 while( aUpdateInfoEnumeration->hasMoreElements() )
141 {
142 deployment::UpdateInformationEntry aEntry;
143
144 if( aUpdateInfoEnumeration->nextElement() >>= aEntry )
145 {
146 uno::Reference< xml::dom::XNode > xNode( aEntry.UpdateDocument );
147 uno::Reference< xml::dom::XNodeList > xNodeList;
148 try {
149 xNodeList = xXPath->selectNodeList(xNode, aXPathExpression
150 + "/inst:update/attribute::src");
151 } catch (const css::xml::xpath::XPathException &) {
152 // ignore
153 }
154
155 sal_Int32 i, imax = xNodeList->getLength();
156 for( i = 0; i < imax; ++i )
157 {
158 uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) );
159
160 if( xNode2.is() )
161 {
162 uno::Reference< xml::dom::XElement > xParent(xNode2->getParentNode(), uno::UNO_QUERY_THROW);
163 OUString aType = xParent->getAttribute("type");
164 bool bIsDirect = !aType.equalsIgnoreAsciiCase("text/html");
165
166 o_rUpdateInfo.Sources.push_back( DownloadSource(bIsDirect, xNode2->getNodeValue()) );
167 }
168 }
169
170 uno::Reference< xml::dom::XNode > xNode2;
171 try {
172 xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression
173 + "/inst:version/text()");
174 } catch (const css::xml::xpath::XPathException &) {
175 // ignore
176 }
177
178 if( xNode2.is() )
179 o_rUpdateInfo.Version = xNode2->getNodeValue();
180
181 try {
182 xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression
183 + "/inst:buildid/text()");
184 } catch (const css::xml::xpath::XPathException &) {
185 // ignore
186 }
187
188 if( xNode2.is() )
189 o_rUpdateInfo.BuildId = xNode2->getNodeValue();
190
191 o_rUpdateInfo.Description = aEntry.Description;
192
193 // Release Notes
194 try {
195 xNodeList = xXPath->selectNodeList(xNode, aXPathExpression
196 + "/inst:relnote");
197 } catch (const css::xml::xpath::XPathException &) {
198 // ignore
199 }
200 imax = xNodeList->getLength();
201 for( i = 0; i < imax; ++i )
202 {
203 uno::Reference< xml::dom::XElement > xRelNote(xNodeList->item(i), uno::UNO_QUERY);
204 if( xRelNote.is() )
205 {
206 sal_Int32 pos = xRelNote->getAttribute("pos").toInt32();
207
208 ReleaseNote aRelNote(static_cast<sal_uInt8>(pos), xRelNote->getAttribute("src"));
209
210 if( xRelNote->hasAttribute("src2") )
211 {
212 pos = xRelNote->getAttribute("pos2").toInt32();
213 aRelNote.Pos2 = static_cast<sal_Int8>(pos);
214 aRelNote.URL2 = xRelNote->getAttribute("src2");
215 }
216
217 o_rUpdateInfo.ReleaseNotes.push_back(aRelNote);
218 }
219 }
220
221 if( !o_rUpdateInfo.Sources.empty() )
222 return true;
223 }
224 }
225 }
226 catch( ... )
227 {
228 return false;
229 }
230
231 return true;
232}
233
234
235bool storeExtensionUpdateInfos( const uno::Reference< uno::XComponentContext > & rxContext,
236 const uno::Sequence< uno::Sequence< OUString > > &rUpdateInfos )
237{
238 bool bNotify = false;
239
240 if ( rUpdateInfos.hasElements() )
241 {
243
244 for ( sal_Int32 i = rUpdateInfos.getLength() - 1; i >= 0; i-- )
245 {
246 bNotify |= aConfig->storeExtensionVersion( rUpdateInfos[i][0], rUpdateInfos[i][1] );
247 }
248 }
249 return bNotify;
250}
251
252
253// Returns 'true' if there are updates for any extension
254
255bool checkForExtensionUpdates( const uno::Reference< uno::XComponentContext > & rxContext )
256{
257 uno::Sequence< uno::Sequence< OUString > > aUpdateList;
258
259 uno::Reference< deployment::XPackageInformationProvider > xInfoProvider;
260 try
261 {
262 uno::Any aValue( rxContext->getValueByName(
263 "/singletons/com.sun.star.deployment.PackageInformationProvider" ) );
264 OSL_VERIFY( aValue >>= xInfoProvider );
265 }
266 catch( const uno::Exception& )
267 {
268 OSL_FAIL( "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
269 }
270
271 if ( !xInfoProvider.is() ) return false;
272
273 aUpdateList = xInfoProvider->isUpdateAvailable( OUString() );
274 bool bNotify = storeExtensionUpdateInfos( rxContext, aUpdateList );
275
276 return bNotify;
277}
278
279
280// Returns 'true' if there are any pending updates for any extension (offline check)
281
282bool checkForPendingUpdates( const uno::Reference< uno::XComponentContext > & rxContext )
283{
284 uno::Sequence< uno::Sequence< OUString > > aExtensionList;
285 uno::Reference< deployment::XPackageInformationProvider > xInfoProvider;
286 try
287 {
288 uno::Any aValue( rxContext->getValueByName(
289 "/singletons/com.sun.star.deployment.PackageInformationProvider" ) );
290 OSL_VERIFY( aValue >>= xInfoProvider );
291 }
292 catch( const uno::Exception& )
293 {
294 OSL_FAIL( "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
295 }
296
297 if ( !xInfoProvider.is() ) return false;
298
299 bool bPendingUpdateFound = false;
300
301 aExtensionList = xInfoProvider->getExtensionList();
302 if ( aExtensionList.hasElements() )
303 {
305
306 for ( sal_Int32 i = aExtensionList.getLength() - 1; i >= 0; i-- )
307 {
308 bPendingUpdateFound = aConfig->checkExtensionVersion( aExtensionList[i][0], aExtensionList[i][1] );
309 if ( bPendingUpdateFound )
310 break;
311 }
312 }
313
314 return bPendingUpdateFound;
315}
316
317/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static ::rtl::Reference< UpdateCheckConfig > get(const css::uno::Reference< css::uno::XComponentContext > &xContext, const ::rtl::Reference< UpdateCheckConfigListener > &rListener=::rtl::Reference< UpdateCheckConfigListener >())
#define SAL_CONFIGFILE(name)
int i
OUString URL2
Definition: updateinfo.hxx:41
sal_uInt8 Pos2
Definition: updateinfo.hxx:40
std::vector< DownloadSource > Sources
Definition: updateinfo.hxx:54
OUString BuildId
Definition: updateinfo.hxx:51
OUString Version
Definition: updateinfo.hxx:52
std::vector< ReleaseNote > ReleaseNotes
Definition: updateinfo.hxx:55
OUString Description
Definition: updateinfo.hxx:53
unsigned char sal_uInt8
signed char sal_Int8
bool storeExtensionUpdateInfos(const uno::Reference< uno::XComponentContext > &rxContext, const uno::Sequence< uno::Sequence< OUString > > &rUpdateInfos)
bool checkForPendingUpdates(const uno::Reference< uno::XComponentContext > &rxContext)
static bool getBootstrapData(uno::Sequence< OUString > &rRepositoryList, OUString &rGitID, OUString &rInstallSetID)
bool checkForExtensionUpdates(const uno::Reference< uno::XComponentContext > &rxContext)
bool checkForUpdates(UpdateInfo &o_rUpdateInfo, uno::Reference< uno::XComponentContext > const &rxContext, uno::Reference< task::XInteractionHandler > const &rxInteractionHandler, const uno::Reference< deployment::XUpdateInformationProvider > &rUpdateInfoProvider)
size_t pos