OSCAR-code/oscar/updateparser.cpp
sawinglogz a80134e7db Remove redefinition of nullptr that caused compilation errors under Qt 5.14.
Thanks to mjphyi for tracking this down!

gcc didn't provide very useful error messages, saying that
error: invalid conversion from ‘long int’ to ‘QDebug::Stream*’
was in qglobal.h.

But it really had to do with a few scattered #defines in OSCAR changing
nullptr to NULL (an int). Since OSCAR now requires C++11, and nullptr
is a keyword in C++11, these #defines can go.

Resolves issue #5.
2020-02-18 15:22:51 -05:00

333 lines
11 KiB
C++

/* UpdateParser Implementation (Autoupdater component)
*
* Copyright (c) 2011-2018 Mark Watkins <mark@jedimark.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the source code
* for more details. */
#include <QDebug>
#include <QXmlStreamAttribute>
#include "updateparser.h"
Update::Update()
{
size = 0;
}
Update::Update(const Update &copy)
{
type = copy.type;
version = copy.version;
platform = copy.platform;
date = copy.date;
filename = copy.filename;
url = copy.url;
hash = copy.hash;
size = copy.size;
notes = copy.notes;
unzipped_path = copy.unzipped_path;
}
Update::Update(QString _type, QString _version, QString _platform, QDate _date)
{
type = _type;
version = _version;
platform = _platform;
date = _date;
size = 0;
}
bool UpdateParser::startDocument()
{
inRelease = false;
inUpdate = false;
inNotes = false;
inUpdateNotes = false;
release = nullptr;
update = nullptr;
return true;
}
bool UpdateParser::endElement(const QString &namespaceURI, const QString &localName,
const QString &qName)
{
Q_UNUSED(namespaceURI)
Q_UNUSED(localName)
QString name = qName.toLower();
if (name == "release") {
inRelease = false;
release = nullptr;
} else if (inRelease && name == "update") {
inUpdate = false;
update = nullptr;
} else if (inUpdate && name == "notes") {
inUpdateNotes = false;
} else if (inRelease && name == "notes") {
inNotes = false;
}
return true;
}
bool UpdateParser::characters(const QString &ch)
{
if (inUpdateNotes) {
update->notes = ch;
} else if (inNotes) {
release->notes[platform] = ch;
}
return true;
}
UpdateStatus lookupUpdateStatus(QString stat)
{
UpdateStatus status = UPDATE_TESTING;
if (stat == "testing") { status = UPDATE_TESTING; }
else if (stat == "beta") { status = UPDATE_BETA; }
else if (stat == "stable") { status = UPDATE_STABLE; }
else if (stat == "critical") { status = UPDATE_CRITICAL; }
return status;
}
bool UpdateParser::startElement(const QString &namespaceURI, const QString &localName,
const QString &qName, const QXmlAttributes &atts)
{
Q_UNUSED(namespaceURI)
Q_UNUSED(localName)
QString name = qName.toLower();
if (inRelease && name == "update") {
QString ver, type;
UpdateStatus updatestatus = UPDATE_TESTING;
for (int i = 0; i < atts.count(); i++) {
if (atts.localName(i) == "type") {
type = atts.value(i).toLower();
}
if (atts.localName(i) == "version") {
ver = atts.value(i).toLower();
}
if (atts.localName(i) == "platform") {
platform = atts.value(i).toLower();
}
if (atts.localName(i) == "release_date") {
release_date = atts.value(i);
}
if (atts.localName(i) == "status") {
updatestatus = lookupUpdateStatus(atts.value(i).toLower());
}
}
QDate date = QDate::fromString(release_date, "yyyy-MM-dd");
if (!date.isValid()) { date = QDate::currentDate(); }
release->updates[platform].push_back(Update(type, ver, platform, date));
update = &release->updates[platform][release->updates[platform].size() - 1];
update->status = updatestatus;
inUpdate = true;
} else if (inRelease && name == "info") {
QString tmp = atts.value("url");
if (tmp.isEmpty()) { return false; }
release->info_url = tmp;
} else if (inUpdate && name == "file") {
for (int i = 0; i < atts.count(); i++) {
if (atts.localName(i) == "name") {
update->filename = atts.value(i);
}
if (atts.localName(i) == "size") {
bool ok;
update->size = atts.value(i).toLongLong(&ok);
//if (!ok) return false;
}
if (atts.localName(i) == "url") {
update->url = atts.value(i);
}
if (atts.localName(i) == "hash") {
update->hash = atts.value(i).toLower();
}
}
} else if (inUpdate && name == "notes") {
inUpdateNotes = true;
} else if (inRelease && name == "notes") {
platform = "";
if (atts.count() >= 1) {
if (atts.localName(0) == "platform") {
platform = atts.value(0);
}
}
inNotes = true;
} else if (name == "release") {
inRelease = true;
QString codename;
UpdateStatus status = UPDATE_TESTING;
for (int i = 0; i < atts.count(); i++) {
if (atts.localName(i) == "version") {
version = atts.value(i).toLower();
}
if (atts.localName(i) == "codename") {
codename = atts.value(i);
}
if (atts.localName(i) == "status") {
status = lookupUpdateStatus(atts.value(i).toLower());
}
}
releases[version] = Release(version, codename, status);
release = &releases[version];
if (version > latest_version) { latest_version = version; }
}
return true;
}
bool UpdateParser::endDocument()
{
/*for (QHash<QString,Release>::iterator r=releases.begin();r!=releases.end();r++) {
Release & rel=r.value();
qDebug() << "New Version" << r.key() << rel.codename << rel.notes;
for (QHash<QString,Update>::iterator u=rel.files.begin();u!=rel.files.end();u++) {
Update & up=u.value();
qDebug() << "Platform:" << u.key() << up.filename << up.date;
}
}*/
return true;
}
/////////////////////////////////////////////////////////////////////
// Updates Parser implementation
/////////////////////////////////////////////////////////////////////
UpdatesParser::UpdatesParser()
{
}
QString UpdatesParser::errorString() const
{
return QObject::tr("%1\nLine %2, column %3")
.arg(xml.errorString())
.arg(xml.lineNumber())
.arg(xml.columnNumber());
}
bool UpdatesParser::read(QIODevice *device)
{
xml.setDevice(device);
if (xml.readNextStartElement()) {
if (xml.name() == "Updates") { // && xml.attributes().value("version") == "1.0")
readUpdates();
} else {
xml.raiseError(QObject::tr("Could not parse Updates.xml file."));
}
}
return !xml.error();
}
void UpdatesParser::readUpdates()
{
if (!xml.isStartElement() || (xml.name() != "Updates")) {
qWarning() << "UpdatesParser::readUpdates() condition check failed";
}
// Q_ ASSERT(xml.isStartElement() && xml.name() == "Updates");
while (xml.readNextStartElement()) {
if (xml.name().compare(QLatin1String("PackageUpdate"),Qt::CaseInsensitive)==0) {
readPackageUpdate();
} else {
qDebug() << "Skipping Updates.xml tag" << xml.name();
xml.skipCurrentElement();
}
}
}
void UpdatesParser::readPackageUpdate()
{
if (!xml.isStartElement() || (xml.name().compare(QLatin1String("PackageUpdate"),Qt::CaseInsensitive)!=0)) {
qWarning() << "UpdatesParser::readPackageUpdate() condition check failed";
return;
}
package = PackageUpdate();
while (xml.readNextStartElement()) {
if (xml.name().compare(QLatin1String("Name"),Qt::CaseInsensitive)==0) {
package.name = xml.readElementText().toLower();
} else if (xml.name().compare(QLatin1String("DisplayName"),Qt::CaseInsensitive)==0) {
package.displayName = xml.readElementText();
} else if (xml.name().compare(QLatin1String("Description"),Qt::CaseInsensitive)==0) {
package.description = xml.readElementText();
} else if (xml.name().compare(QLatin1String("Version"),Qt::CaseInsensitive)==0) {
package.versionString = xml.readElementText();
} else if (xml.name().compare(QLatin1String("ReleaseDate"),Qt::CaseInsensitive)==0) {
package.releaseDate = QDate().fromString(xml.readElementText(), "yyyy-MM-dd");
} else if (xml.name().compare(QLatin1String("Default"),Qt::CaseInsensitive)==0) {
package.defaultInstall = xml.readElementText().compare("true") == 0;
} else if (xml.name().compare(QLatin1String("ForcedInstallation"),Qt::CaseInsensitive)==0) {
package.forcedInstall = xml.readElementText().compare("true") == 0;
} else if (xml.name().compare(QLatin1String("Script"),Qt::CaseInsensitive)==0) {
package.script = xml.readElementText();
} else if (xml.name().compare(QLatin1String("Dependencies"),Qt::CaseInsensitive)==0) {
package.dependencies = xml.readElementText().split(",");
} else if (xml.name().compare(QLatin1String("UpdateFile"),Qt::CaseInsensitive)==0) {
for (int i=0; i<xml.attributes().size(); ++i) {
const QXmlStreamAttribute & at = xml.attributes().at(i);
if (at.name().compare(QLatin1String("CompressedSize"), Qt::CaseInsensitive)==0) {
package.compressedSize = at.value().toLong();
} else if (at.name().compare(QLatin1String("UncompressedSize"),Qt::CaseInsensitive)==0) {
package.uncompressedSize = at.value().toLong();
} else if (at.name().compare(QLatin1String("OS"),Qt::CaseInsensitive)==0) {
package.os = at.value().toString();
}
}
xml.skipCurrentElement();
} else if (xml.name().compare(QLatin1String("DownloadableArchives"))==0) {
package.downloadArchives = xml.readElementText().split(",");
} else if (xml.name().compare(QLatin1String("Licenses"),Qt::CaseInsensitive)==0) {
while (xml.readNextStartElement()) {
if (xml.name().compare(QLatin1String("License"),Qt::CaseInsensitive)==0) {
QString name;
QString file;
for (int i=0; i<xml.attributes().size(); ++i) {
const QXmlStreamAttribute & at = xml.attributes().at(i);
if (at.name().compare(QLatin1String("name"), Qt::CaseInsensitive)==0) {
name = at.value().toString();
} else if (at.name().compare(QLatin1String("file"),Qt::CaseInsensitive)==0) {
file = at.value().toString();
}
}
package.license[name]=file;
xml.skipCurrentElement();
} else {
qDebug() << "Lic Skipping Updates.xml tag" << xml.name();
xml.skipCurrentElement();
}
}
} else if (xml.name().compare(QLatin1String("SHA1"),Qt::CaseInsensitive)==0) {
package.sha1 = xml.readElementText();
} else {
qDebug() << "UP Skipping Updates.xml tag" << xml.name();
xml.skipCurrentElement();
}
};
packages[package.name] = package;
}