Line data Source code
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 "dp_update.hxx"
23 : #include "dp_version.hxx"
24 : #include "dp_identifier.hxx"
25 : #include "dp_descriptioninfoset.hxx"
26 :
27 : #include <osl/diagnose.h>
28 : #include <rtl/bootstrap.hxx>
29 :
30 : using namespace ::com::sun::star;
31 : using namespace ::com::sun::star::uno;
32 :
33 :
34 : namespace dp_misc {
35 : namespace {
36 :
37 0 : int determineHighestVersion(
38 : OUString const & userVersion,
39 : OUString const & sharedVersion,
40 : OUString const & bundledVersion,
41 : OUString const & onlineVersion)
42 : {
43 0 : int index = 0;
44 0 : OUString greatest = userVersion;
45 0 : if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER)
46 : {
47 0 : index = 1;
48 0 : greatest = sharedVersion;
49 : }
50 0 : if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER)
51 : {
52 0 : index = 2;
53 0 : greatest = bundledVersion;
54 : }
55 0 : if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER)
56 : {
57 0 : index = 3;
58 : }
59 0 : return index;
60 : }
61 :
62 : Sequence< Reference< xml::dom::XElement > >
63 0 : getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation,
64 : Sequence< OUString > const & urls,
65 : OUString const & identifier,
66 : uno::Any & out_error)
67 : {
68 : try {
69 0 : return updateInformation->getUpdateInformation(urls, identifier);
70 0 : } catch (const uno::RuntimeException &) {
71 0 : throw;
72 0 : } catch (const ucb::CommandFailedException & e) {
73 0 : out_error = e.Reason;
74 0 : } catch (const ucb::CommandAbortedException &) {
75 0 : } catch (const uno::Exception & e) {
76 0 : out_error = uno::makeAny(e);
77 : }
78 : return
79 0 : Sequence<Reference< xml::dom::XElement > >();
80 : }
81 :
82 0 : void getOwnUpdateInfos(
83 : Reference<uno::XComponentContext> const & xContext,
84 : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
85 : UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors,
86 : bool & out_allFound)
87 : {
88 0 : bool allHaveOwnUpdateInformation = true;
89 0 : for (UpdateInfoMap::iterator i = inout_map.begin(); i != inout_map.end(); ++i)
90 : {
91 : OSL_ASSERT(i->second.extension.is());
92 0 : Sequence<OUString> urls(i->second.extension->getUpdateInformationURLs());
93 0 : if (urls.getLength())
94 : {
95 0 : const OUString id = dp_misc::getIdentifier(i->second.extension);
96 0 : uno::Any anyError;
97 : //It is unclear from the idl if there can be a null reference returned.
98 : //However all valid information should be the same
99 : Sequence<Reference< xml::dom::XElement > >
100 0 : infos(getUpdateInformation(updateInformation, urls, id, anyError));
101 0 : if (anyError.hasValue())
102 0 : out_errors.push_back(std::make_pair(i->second.extension, anyError));
103 :
104 0 : for (sal_Int32 j = 0; j < infos.getLength(); ++j)
105 : {
106 : dp_misc::DescriptionInfoset infoset(
107 : xContext,
108 0 : Reference< xml::dom::XNode >(infos[j], UNO_QUERY_THROW));
109 0 : if (!infoset.hasDescription())
110 0 : continue;
111 0 : boost::optional< OUString > id2(infoset.getIdentifier());
112 0 : if (!id2)
113 0 : continue;
114 : OSL_ASSERT(*id2 == id);
115 0 : if (*id2 == id)
116 : {
117 0 : i->second.version = infoset.getVersion();
118 0 : i->second.info = Reference< xml::dom::XNode >(
119 0 : infos[j], UNO_QUERY_THROW);
120 : }
121 0 : break;
122 0 : }
123 : }
124 : else
125 : {
126 0 : allHaveOwnUpdateInformation &= false;
127 : }
128 0 : }
129 0 : out_allFound = allHaveOwnUpdateInformation;
130 0 : }
131 :
132 0 : void getDefaultUpdateInfos(
133 : Reference<uno::XComponentContext> const & xContext,
134 : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
135 : UpdateInfoMap& inout_map,
136 : std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors)
137 : {
138 0 : const OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL());
139 : OSL_ASSERT(!sDefaultURL.isEmpty());
140 :
141 0 : Any anyError;
142 : Sequence< Reference< xml::dom::XElement > >
143 : infos(
144 : getUpdateInformation(
145 : updateInformation,
146 0 : Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError));
147 0 : if (anyError.hasValue())
148 0 : out_errors.push_back(std::make_pair(Reference<deployment::XPackage>(), anyError));
149 0 : for (sal_Int32 i = 0; i < infos.getLength(); ++i)
150 : {
151 0 : Reference< xml::dom::XNode > node(infos[i], UNO_QUERY_THROW);
152 0 : dp_misc::DescriptionInfoset infoset(xContext, node);
153 0 : boost::optional< OUString > id(infoset.getIdentifier());
154 0 : if (!id) {
155 0 : continue;
156 : }
157 0 : UpdateInfoMap::iterator j = inout_map.find(*id);
158 0 : if (j != inout_map.end())
159 : {
160 : //skip those extension which provide its own update urls
161 0 : if (j->second.extension->getUpdateInformationURLs().getLength())
162 0 : continue;
163 0 : OUString v(infoset.getVersion());
164 : //look for the highest version in the online repository
165 0 : if (dp_misc::compareVersions(v, j->second.version) ==
166 : dp_misc::GREATER)
167 : {
168 0 : j->second.version = v;
169 0 : j->second.info = node;
170 0 : }
171 : }
172 0 : }
173 0 : }
174 :
175 0 : bool containsBundledOnly(Sequence<Reference<deployment::XPackage> > const & sameIdExtensions)
176 : {
177 : OSL_ASSERT(sameIdExtensions.getLength() == 3);
178 0 : return !sameIdExtensions[0].is() && !sameIdExtensions[1].is() && sameIdExtensions[2].is();
179 : }
180 :
181 : /** Returns true if the list of extensions are bundled extensions and there are no
182 : other extensions with the same identifier in the shared or user repository.
183 : If extensionList is NULL, then it is checked if there are only bundled extensions.
184 : */
185 0 : bool onlyBundledExtensions(
186 : Reference<deployment::XExtensionManager> const & xExtMgr,
187 : std::vector< Reference<deployment::XPackage > > const * extensionList)
188 : {
189 : OSL_ASSERT(xExtMgr.is());
190 0 : bool onlyBundled = true;
191 0 : if (extensionList)
192 : {
193 : typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT;
194 0 : for (CIT i(extensionList->begin()), aEnd(extensionList->end()); onlyBundled && i != aEnd; ++i)
195 : {
196 0 : Sequence<Reference<deployment::XPackage> > seqExt = xExtMgr->getExtensionsWithSameIdentifier(
197 0 : dp_misc::getIdentifier(*i), (*i)->getName(), Reference<ucb::XCommandEnvironment>());
198 :
199 0 : onlyBundled = containsBundledOnly(seqExt);
200 0 : }
201 : }
202 : else
203 : {
204 : const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt =
205 0 : xExtMgr->getAllExtensions(Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
206 :
207 0 : for (int pos(0), nLen(seqAllExt.getLength()); onlyBundled && pos != nLen; ++pos)
208 : {
209 0 : onlyBundled = containsBundledOnly(seqAllExt[pos]);
210 0 : }
211 : }
212 0 : return onlyBundled;
213 : }
214 :
215 : } // anon namespace
216 :
217 :
218 0 : OUString getExtensionDefaultUpdateURL()
219 : {
220 : OUString sUrl(
221 : "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version")
222 0 : ":Version:ExtensionUpdateURL}");
223 0 : ::rtl::Bootstrap::expandMacros(sUrl);
224 0 : return sUrl;
225 : }
226 :
227 : /* returns the index of the greatest version, starting with 0
228 :
229 : */
230 0 : UPDATE_SOURCE isUpdateUserExtension(
231 : bool bReadOnlyShared,
232 : OUString const & userVersion,
233 : OUString const & sharedVersion,
234 : OUString const & bundledVersion,
235 : OUString const & onlineVersion)
236 : {
237 0 : UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
238 0 : if (bReadOnlyShared)
239 : {
240 0 : if (!userVersion.isEmpty())
241 : {
242 : int index = determineHighestVersion(
243 0 : userVersion, sharedVersion, bundledVersion, onlineVersion);
244 0 : if (index == 1)
245 0 : retVal = UPDATE_SOURCE_SHARED;
246 0 : else if (index == 2)
247 0 : retVal = UPDATE_SOURCE_BUNDLED;
248 0 : else if (index == 3)
249 0 : retVal = UPDATE_SOURCE_ONLINE;
250 : }
251 0 : else if (!sharedVersion.isEmpty())
252 : {
253 : int index = determineHighestVersion(
254 0 : OUString(), sharedVersion, bundledVersion, onlineVersion);
255 0 : if (index == 2)
256 0 : retVal = UPDATE_SOURCE_BUNDLED;
257 0 : else if (index == 3)
258 0 : retVal = UPDATE_SOURCE_ONLINE;
259 :
260 : }
261 : }
262 : else
263 : {
264 0 : if (!userVersion.isEmpty())
265 : {
266 : int index = determineHighestVersion(
267 0 : userVersion, sharedVersion, bundledVersion, onlineVersion);
268 0 : if (index == 1)
269 0 : retVal = UPDATE_SOURCE_SHARED;
270 0 : else if (index == 2)
271 0 : retVal = UPDATE_SOURCE_BUNDLED;
272 0 : else if (index == 3)
273 0 : retVal = UPDATE_SOURCE_ONLINE;
274 : }
275 : }
276 :
277 0 : return retVal;
278 : }
279 :
280 0 : UPDATE_SOURCE isUpdateSharedExtension(
281 : bool bReadOnlyShared,
282 : OUString const & sharedVersion,
283 : OUString const & bundledVersion,
284 : OUString const & onlineVersion)
285 : {
286 0 : if (bReadOnlyShared)
287 0 : return UPDATE_SOURCE_NONE;
288 0 : UPDATE_SOURCE retVal = UPDATE_SOURCE_NONE;
289 :
290 0 : if (!sharedVersion.isEmpty())
291 : {
292 : int index = determineHighestVersion(
293 0 : OUString(), sharedVersion, bundledVersion, onlineVersion);
294 0 : if (index == 2)
295 0 : retVal = UPDATE_SOURCE_BUNDLED;
296 0 : else if (index == 3)
297 0 : retVal = UPDATE_SOURCE_ONLINE;
298 : }
299 0 : return retVal;
300 : }
301 :
302 : Reference<deployment::XPackage>
303 0 : getExtensionWithHighestVersion(
304 : Sequence<Reference<deployment::XPackage> > const & seqExt)
305 : {
306 0 : if (seqExt.getLength() == 0)
307 0 : return Reference<deployment::XPackage>();
308 :
309 0 : Reference<deployment::XPackage> greatest;
310 0 : sal_Int32 len = seqExt.getLength();
311 :
312 0 : for (sal_Int32 i = 0; i < len; i++)
313 : {
314 0 : if (!greatest.is())
315 : {
316 0 : greatest = seqExt[i];
317 0 : continue;
318 : }
319 0 : Reference<deployment::XPackage> const & current = seqExt[i];
320 : //greatest has a value
321 0 : if (! current.is())
322 0 : continue;
323 :
324 0 : if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER)
325 0 : greatest = current;
326 : }
327 0 : return greatest;
328 : }
329 :
330 0 : UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext):
331 0 : extension(ext)
332 : {
333 0 : }
334 :
335 :
336 :
337 0 : UpdateInfoMap getOnlineUpdateInfos(
338 : Reference<uno::XComponentContext> const &xContext,
339 : Reference<deployment::XExtensionManager> const & xExtMgr,
340 : Reference<deployment::XUpdateInformationProvider > const & updateInformation,
341 : std::vector<Reference<deployment::XPackage > > const * extensionList,
342 : std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors)
343 : {
344 : OSL_ASSERT(xExtMgr.is());
345 0 : UpdateInfoMap infoMap;
346 0 : if (!xExtMgr.is() || onlyBundledExtensions(xExtMgr, extensionList))
347 0 : return infoMap;
348 :
349 0 : if (!extensionList)
350 : {
351 0 : const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions(
352 0 : Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
353 :
354 : //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo
355 0 : for (int pos = seqAllExt.getLength(); pos --; )
356 : {
357 0 : uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos];
358 :
359 0 : Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt);
360 : OSL_ASSERT(extension.is());
361 :
362 : std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
363 : UpdateInfoMap::value_type(
364 0 : dp_misc::getIdentifier(extension), UpdateInfo(extension)));
365 : OSL_ASSERT(insertRet.second);
366 : (void)insertRet;
367 0 : }
368 : }
369 : else
370 : {
371 : typedef std::vector<Reference<deployment::XPackage > >::const_iterator CIT;
372 0 : for (CIT i = extensionList->begin(); i != extensionList->end(); ++i)
373 : {
374 : OSL_ASSERT(i->is());
375 : std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.insert(
376 : UpdateInfoMap::value_type(
377 0 : dp_misc::getIdentifier(*i), UpdateInfo(*i)));
378 : OSL_ASSERT(insertRet.second);
379 : (void)insertRet;
380 : }
381 : }
382 :
383 : //Now find the update information for the extensions which provide their own
384 : //URLs to update information.
385 0 : bool allInfosObtained = false;
386 0 : getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, allInfosObtained);
387 :
388 0 : if (!allInfosObtained)
389 0 : getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors);
390 0 : return infoMap;
391 : }
392 0 : OUString getHighestVersion(
393 : OUString const & userVersion,
394 : OUString const & sharedVersion,
395 : OUString const & bundledVersion,
396 : OUString const & onlineVersion)
397 : {
398 0 : int index = determineHighestVersion(userVersion, sharedVersion, bundledVersion, onlineVersion);
399 0 : switch (index)
400 : {
401 0 : case 0: return userVersion;
402 0 : case 1: return sharedVersion;
403 0 : case 2: return bundledVersion;
404 0 : case 3: return onlineVersion;
405 : default: OSL_ASSERT(false);
406 : }
407 :
408 0 : return OUString();
409 : }
410 : } //namespace dp_misc
411 :
412 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|