/* Copyright (C) 2015 Srivats P. This file is part of "Ostinato" This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ #include "updater.h" #include #include #include #include extern const char* version; Updater::Updater() { http_ = NULL; file_ = NULL; #if 1 // Tests! Q_ASSERT(isVersionNewer("1.1", "1") == true); Q_ASSERT(isVersionNewer("10.1", "2") == true); Q_ASSERT(isVersionNewer("0.10", "0.2") == true); Q_ASSERT(isVersionNewer("1.10.1", "1.2.3") == true); Q_ASSERT(isVersionNewer("0.7.1", "0.8") == false); #endif } Updater::~Updater() { delete http_; delete file_; } void Updater::checkForNewVersion() { QString host("update.ostinato.org"); QHttpRequestHeader reqHdr("GET", "/update/pad.xml"); http_ = new QHttp(host); file_ = new QTemporaryFile(); reqHdr.setValue("Host", host); reqHdr.setValue("User-Agent", userAgent()); connect(http_, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(responseReceived(QHttpResponseHeader))); connect(http_, SIGNAL(requestFinished(int, bool)), this, SLOT(parseXml(int, bool))); connect(http_, SIGNAL(stateChanged(int)), this, SLOT(stateUpdate(int))); file_->open(); qDebug("Updater: PAD XML file - %s", qPrintable(file_->fileName())); http_->request(reqHdr, NULL, file_); qDebug("Updater: %s", qPrintable(http_->currentRequest().toString() .replace("\r\n", "\nUpdater: "))); } void Updater::stateUpdate(int state) { qDebug("Updater: state %d", state); } void Updater::responseReceived(QHttpResponseHeader response) { qDebug("Updater: HTTP/%d.%d %d %s", response.majorVersion(), response.minorVersion(), response.statusCode(), qPrintable(response.reasonPhrase())); } void Updater::parseXml(int /*id*/, bool error) { QXmlStreamReader xml; QString newVersion; if (error) { qDebug("Updater: %s", qPrintable(http_->errorString())); goto _exit; } // Close and reopen the file so that we read from the top file_->close(); file_->open(); xml.setDevice(file_); while (!xml.atEnd()) { xml.readNext(); if (xml.isStartElement() && (xml.name() == "Program_Version")) newVersion = xml.readElementText(); } qDebug("Updater: latest version = %s", qPrintable(newVersion)); if (!newVersion.isEmpty() && isVersionNewer(newVersion, QString(version))) emit newVersionAvailable(newVersion); _exit: // Job done, time to self-destruct deleteLater(); } bool Updater::isVersionNewer(QString newVersion, QString curVersion) { QStringList curVer = QString(curVersion).split('.'); QStringList newVer = QString(newVersion).split('.'); for (int i = 0; i < qMin(curVer.size(), newVer.size()); i++) { bool isOk; uint n = newVer.at(i).toUInt(&isOk); uint c = curVer.at(i).toUInt(&isOk); if (n > c) return true; else if (n < c) return false; } if (newVer.size() > curVer.size()) return true; return false; } QString Updater::userAgent() { QString ua = QString("Mozilla/5.0 (%1) %2/%3 (Qt/%6)") .arg(sysInfo()) .arg(QCoreApplication::instance()->applicationName()) .arg(version) .arg(qVersion()); return ua; } QString Updater::sysInfo() { #if defined(Q_OS_WIN32) return QString("Windows/0x%1").arg(QSysInfo::WindowsVersion, 0, 16); #elif defined(Q_OS_LINUX) return QString("Linux"); #elif defined(Q_OS_MAC) return QString("MacOSX/0x%1").arg(QSysInfo::MacintoshVersion, 0, 16); #elif defined(Q_OS_BSD4) return QString("BSD"); #elif defined(Q_OS_UNIX) return QString("Unix"); #else return QString("Unknown"); #endif }