updatepackagefilter.cpp
1 //------------------------------------------------------------------------------
2 // updatepackagefilter.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2012 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "updatepackagefilter.h"
24 
25 #include "plugins/engineplugin.h"
26 #include "plugins/pluginloader.h"
27 #include "updater/autoupdater.h"
28 #include "strings.hpp"
29 #include "version.h"
30 #include <QCoreApplication>
31 #include <QFile>
32 #include <cassert>
33 #include <wadseeker/wadseekerversioninfo.h>
34 
35 class UpdatePackageFilter::PluginInfo
36 {
37  public:
38  QString name;
39  QString revision;
40 };
42 DClass<UpdatePackageFilter>
43 {
44  public:
45  bool bWasAnyUpdatePackageIgnored;
46  QMap<QString, QList<QString> > ignoredPackagesRevisions;
47  QMap<QString, UpdatePackageFilter::PluginInfo> plugins;
48 
49  bool hasMainProgramPackage(const QList<UpdatePackage> &packages) const
50  {
51  foreach (const UpdatePackage &pkg, packages)
52  {
54  {
55  return true;
56  }
57  }
58  return false;
59  }
60 };
61 
62 DPointered(UpdatePackageFilter)
65 
66 {
67  d->bWasAnyUpdatePackageIgnored = false;
68 }
69 
70 UpdatePackageFilter::~UpdatePackageFilter()
71 {
72 }
73 
74 QMap<QString, UpdatePackageFilter::PluginInfo> UpdatePackageFilter::collectPluginInfo()
75 {
76  QMap<QString, PluginInfo> infos;
77  const QList<PluginLoader::Plugin*> plugins = gPlugins->plugins();
78  foreach (const PluginLoader::Plugin* plugin, plugins)
79  {
80  PluginInfo pluginInfo;
81  pluginInfo.name = plugin->info()->data()->name;
82  pluginInfo.revision = QString::number(plugin->info()->data()->version);
83  QString prefixedName = AutoUpdater::PLUGIN_PREFIX + pluginInfo.name.toLower().replace(" ", "");
84  infos.insert(prefixedName, pluginInfo);
85  }
86  return infos;
87 }
88 
89 QList<UpdatePackage> UpdatePackageFilter::filter(const QList<UpdatePackage>& packages)
90 {
91  QList<UpdatePackage> filtered;
92  d->plugins = collectPluginInfo();
93  QList<UpdatePackage> packagesOnIgnoredList;
94  foreach (UpdatePackage pkg, packages)
95  {
96  if (isDifferentThanInstalled(pkg))
97  {
98  if (!isOnIgnoredList(pkg.name, pkg.revision))
99  {
100  filtered << pkg;
101  }
102  else
103  {
104  packagesOnIgnoredList << pkg;
105  }
106  }
107  }
108  if (!filtered.isEmpty())
109  {
110  // If we do an update of at least one package, we also need to update
111  // all packages that were previously ignored.
112  filtered.append(packagesOnIgnoredList);
113  packagesOnIgnoredList.clear();
114  }
115  d->bWasAnyUpdatePackageIgnored = !packagesOnIgnoredList.isEmpty();
116  return filtered;
117 }
118 
119 bool UpdatePackageFilter::isDifferentThanInstalled(UpdatePackage& pkg) const
120 {
122  {
123  QString localRevision = QString::number(Version::revisionNumber());
124  if (localRevision != pkg.revision)
125  {
127  return true;
128  }
129  }
130  else if (pkg.name == AutoUpdater::WADSEEKER_PACKAGE_NAME)
131  {
132  QString localRevision = WadseekerVersionInfo::version();
133  if (localRevision != pkg.revision)
134  {
135  pkg.currentlyInstalledDisplayVersion = localRevision;
136  return true;
137  }
138  }
139  else if (pkg.name == AutoUpdater::QT_PACKAGE_NAME)
140  {
141  // For OS X PowerPC is no longer getting Qt updates so it will
142  // always be on 4.8. Similarly i386 will be used as a legacy
143  // platform (the number of 32-bit only Intel Macs is tiny and
144  // the version of Qt5 we're launching with requires Lion or
145  // higher. Thus only 64-bit Intel Macs need to even bother
146  // checking this package.
147 #if !defined(Q_OS_MAC) || defined(__x86_64__)
148  if (QString(Version::qtPackageVersion()) != pkg.revision)
149  {
150  pkg.currentlyInstalledDisplayVersion = Version::qtPackageVersion();
151  return true;
152  }
153  // Workaround for auto-updater bug that made itself apparent
154  // in Doomseeker 1.1~beta builds. Bug caused every even
155  // numbered file in auxiliary packages not to be installed. As
156  // Qt is such auxiliary package in 1.1~beta, some files
157  // failed to install.
158  bool checkBrokenQt = false;
159 #ifdef Q_OS_WIN32
160  checkBrokenQt = true;
161 #endif
162  if (checkBrokenQt && !isQtInstallOk())
163  {
164  pkg.currentlyInstalledDisplayVersion = Version::qtPackageVersion() + tr("-BROKEN");
165  return true;
166  }
167 #endif
168  }
169  else
170  {
171  // Plugin node.
172  if (d->plugins.contains(pkg.name))
173  {
174  PluginInfo pluginInfo = d->plugins[pkg.name];
175  if (pluginInfo.revision != pkg.revision)
176  {
177  pkg.currentlyInstalledDisplayVersion = pluginInfo.revision;
178  return true;
179  }
180  }
181  }
182  return false;
183 }
184 
185 bool UpdatePackageFilter::isQtInstallOk() const
186 {
187  QStringList files;
188  files << "libeay32.dll" << "ssleay32.dll";
189  foreach (const QString &filename, files)
190  {
191  QString fileLocation = Strings::combinePaths(
192  QCoreApplication::applicationDirPath(), filename);
193  QFile file(fileLocation);
194  if (!file.exists())
195  {
196  return false;
197  }
198  }
199  return true;
200 }
201 
202 bool UpdatePackageFilter::isOnIgnoredList(const QString& package, const QString &revision) const
203 {
204  const QList<QString>& list = d->ignoredPackagesRevisions[package];
205  return list.contains(revision);
206 }
207 
208 void UpdatePackageFilter::setIgnoreRevisions(
209  const QMap<QString, QList<QString> >& packagesRevisions)
210 {
211  d->ignoredPackagesRevisions = packagesRevisions;
212 }
213 
215 {
216  return d->bWasAnyUpdatePackageIgnored;
217 }
static QString combinePaths(QString pathFront, QString pathEnd)
Definition: strings.cpp:147
static QString versionRevision()
Combines version and revision strings.
Definition: version.cpp:74
QString revision
Revision used for version comparison.
Definition: updatepackage.h:71
static const QString PLUGIN_PREFIX
Prefix for all plugins packages names.
Definition: autoupdater.h:125
EnginePlugin * info() const
Main plugin interface.
Filters UpdatePackage information basing on what is requested by the program.
bool wasAnyUpdatePackageIgnored() const
After filter() flag which says if any package was ignored.
static const QString MAIN_PROGRAM_PACKAGE_NAME
Package name for the main program.
Definition: autoupdater.h:131
QString currentlyInstalledDisplayVersion
Currently installed version, displayed to the user.
Definition: updatepackage.h:37
QString name
Name of the package (program name or plugin name).
Definition: updatepackage.h:63