Better SSL support for Windows
This commit is contained in:
parent
07fb53334f
commit
0a7107c414
0
License.txt → License-LGPL3.txt
Executable file → Normal file
0
License.txt → License-LGPL3.txt
Executable file → Normal file
BIN
QSimpleUpdater/dependencies/OpenSSL-Win32/bin/libeay32.dll
Normal file
BIN
QSimpleUpdater/dependencies/OpenSSL-Win32/bin/libeay32.dll
Normal file
Binary file not shown.
BIN
QSimpleUpdater/dependencies/OpenSSL-Win32/bin/ssleay32.dll
Normal file
BIN
QSimpleUpdater/dependencies/OpenSSL-Win32/bin/ssleay32.dll
Normal file
Binary file not shown.
BIN
QSimpleUpdater/dependencies/win32/libeay32.lib → QSimpleUpdater/dependencies/OpenSSL-Win32/lib/libeay32.lib
Executable file → Normal file
BIN
QSimpleUpdater/dependencies/win32/libeay32.lib → QSimpleUpdater/dependencies/OpenSSL-Win32/lib/libeay32.lib
Executable file → Normal file
Binary file not shown.
@ -23,8 +23,7 @@ macx || linux{
|
|||||||
}
|
}
|
||||||
|
|
||||||
win32* {
|
win32* {
|
||||||
CONFIG += openssl-linked
|
LIBS += -L$$PWD/dependencies/OpenSSL-Win32/lib -llibeay32
|
||||||
LIBS += -L$$PWD/dependencies/win32/ -llibeay32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RESOURCES += $$PWD/res/qsu_resources.qrc
|
RESOURCES += $$PWD/res/qsu_resources.qrc
|
||||||
|
31
QSimpleUpdater/readme.txt
Normal file
31
QSimpleUpdater/readme.txt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
--------------
|
||||||
|
PREFACE
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Many websites today use the HTTPS protocol, which means that you will need SSL in order to communicate with them. If your project needs to access such a webiste (for example GitHub), you will need to carefully read the following information in order to ensure that QSimpleUpdater works with those websites (both in your machine and in the final users' machine).
|
||||||
|
|
||||||
|
This readme guide is extremely important for any developer wishing to deploy his or her applications under the Windows platform, because the application will depend on the libraries provided by QSimpleUpdater.
|
||||||
|
|
||||||
|
--------------
|
||||||
|
LINUX
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Make sure that you have installed the following libraries in your system:
|
||||||
|
|
||||||
|
- lssl
|
||||||
|
- lcrypto
|
||||||
|
|
||||||
|
--------------
|
||||||
|
MAC OSX
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The libraries required by QSimpleUpdater are the same as Linux, however, these libraries are installed by default in most Mac OS X installations.
|
||||||
|
|
||||||
|
--------------
|
||||||
|
WINDOWS
|
||||||
|
--------------
|
||||||
|
|
||||||
|
QSimpleUpdater makes use of the OpenSSL-Win32 project, make sure that you deploy the following DLLs allong your application (the DLLs are provided with the source of QSimpleUpdater):
|
||||||
|
|
||||||
|
- dependencies/OpenSSL-Win32/bin/libeay32.dll
|
||||||
|
- dependencies/OpenSSL-Win32/bin/ssleay32.dll
|
@ -9,22 +9,22 @@
|
|||||||
#include "download_dialog.h"
|
#include "download_dialog.h"
|
||||||
#include "ui_download_dialog.h"
|
#include "ui_download_dialog.h"
|
||||||
|
|
||||||
DownloadDialog::DownloadDialog(QWidget *parent) :
|
DownloadDialog::DownloadDialog (QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget (parent),
|
||||||
ui(new Ui::DownloadDialog)
|
ui (new Ui::DownloadDialog)
|
||||||
{
|
{
|
||||||
// Setup the UI
|
// Setup the UI
|
||||||
ui->setupUi(this);
|
ui->setupUi (this);
|
||||||
|
|
||||||
// Connect SIGNALS/SLOTS
|
// Connect SIGNALS/SLOTS
|
||||||
connect(ui->stopButton, SIGNAL(clicked()), this, SLOT(cancelDownload()));
|
connect (ui->stopButton, SIGNAL (clicked()), this, SLOT (cancelDownload()));
|
||||||
|
|
||||||
// Initialize the network access manager
|
// Initialize the network access manager
|
||||||
m_manager = new QNetworkAccessManager(this);
|
m_manager = new QNetworkAccessManager (this);
|
||||||
|
|
||||||
// Avoid SSL issues
|
// Avoid SSL issues
|
||||||
connect(m_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
connect (m_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)),
|
||||||
this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
this, SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
||||||
}
|
}
|
||||||
|
|
||||||
DownloadDialog::~DownloadDialog()
|
DownloadDialog::~DownloadDialog()
|
||||||
@ -32,26 +32,26 @@ DownloadDialog::~DownloadDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadDialog::beginDownload(const QUrl &url)
|
void DownloadDialog::beginDownload (const QUrl &url)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!url.isEmpty());
|
Q_ASSERT (!url.isEmpty());
|
||||||
|
|
||||||
// Reset the UI
|
// Reset the UI
|
||||||
ui->progressBar->setValue(0);
|
ui->progressBar->setValue (0);
|
||||||
ui->stopButton->setText(tr("Stop"));
|
ui->stopButton->setText (tr ("Stop"));
|
||||||
ui->downloadLabel->setText(tr("Downloading updates"));
|
ui->downloadLabel->setText (tr ("Downloading updates"));
|
||||||
ui->timeLabel->setText(tr("Time remaining") + ": " + tr("unknown"));
|
ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown"));
|
||||||
|
|
||||||
// Begin the download
|
// Begin the download
|
||||||
m_reply = m_manager->get(QNetworkRequest(url));
|
m_reply = m_manager->get (QNetworkRequest (url));
|
||||||
m_start_time = QDateTime::currentDateTime().toTime_t();
|
m_start_time = QDateTime::currentDateTime().toTime_t();
|
||||||
|
|
||||||
// Update the progress bar value automatically
|
// Update the progress bar value automatically
|
||||||
connect(m_reply, SIGNAL(downloadProgress(qint64,qint64)),
|
connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)),
|
||||||
this, SLOT(updateProgress(qint64,qint64)));
|
this, SLOT (updateProgress (qint64, qint64)));
|
||||||
|
|
||||||
// Write the file to the hard disk once the download is finished
|
// Write the file to the hard disk once the download is finished
|
||||||
connect(m_reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
|
connect (m_reply, SIGNAL (finished()), this, SLOT (downloadFinished()));
|
||||||
|
|
||||||
// Show the dialog
|
// Show the dialog
|
||||||
showNormal();
|
showNormal();
|
||||||
@ -59,79 +59,84 @@ void DownloadDialog::beginDownload(const QUrl &url)
|
|||||||
|
|
||||||
void DownloadDialog::openDownload()
|
void DownloadDialog::openDownload()
|
||||||
{
|
{
|
||||||
if (!m_path.isEmpty()) {
|
if (!m_path.isEmpty())
|
||||||
|
{
|
||||||
QString url = m_path;
|
QString url = m_path;
|
||||||
|
|
||||||
if (url.startsWith("/"))
|
if (url.startsWith ("/"))
|
||||||
url = "file://" + url;
|
url = "file://" + url;
|
||||||
|
|
||||||
else
|
else
|
||||||
url = "file:///" + url;
|
url = "file:///" + url;
|
||||||
|
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl (url);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else
|
||||||
qWarning() << "QSimpleUpdater: cannot open downloaded file!";
|
qWarning() << "QSimpleUpdater: cannot open downloaded file!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadDialog::cancelDownload()
|
void DownloadDialog::cancelDownload()
|
||||||
{
|
{
|
||||||
if (!m_reply->isFinished()) {
|
if (!m_reply->isFinished())
|
||||||
|
{
|
||||||
QMessageBox _message;
|
QMessageBox _message;
|
||||||
_message.setWindowTitle(tr("Updater"));
|
_message.setWindowTitle (tr ("Updater"));
|
||||||
_message.setIcon(QMessageBox::Question);
|
_message.setIcon (QMessageBox::Question);
|
||||||
_message.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
_message.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
|
||||||
_message.setText(tr("Are you sure you want to cancel the download?"));
|
_message.setText (tr ("Are you sure you want to cancel the download?"));
|
||||||
|
|
||||||
if (_message.exec() == QMessageBox::Yes) {
|
if (_message.exec() == QMessageBox::Yes)
|
||||||
|
{
|
||||||
hide();
|
hide();
|
||||||
m_reply->abort();
|
m_reply->abort();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadDialog::downloadFinished()
|
void DownloadDialog::downloadFinished()
|
||||||
{
|
{
|
||||||
ui->stopButton->setText(tr("Close"));
|
ui->stopButton->setText (tr ("Close"));
|
||||||
ui->downloadLabel->setText(tr("Download complete!"));
|
ui->downloadLabel->setText (tr ("Download complete!"));
|
||||||
ui->timeLabel->setText(tr("The installer will open in a separate window..."));
|
ui->timeLabel->setText (tr ("The installer will open in a separate window..."));
|
||||||
|
|
||||||
QByteArray data = m_reply->readAll();
|
QByteArray data = m_reply->readAll();
|
||||||
|
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty())
|
||||||
QStringList list = m_reply->url().toString().split("/");
|
{
|
||||||
QFile file(QDir::tempPath() + "/" + list.at(list.count() - 1));
|
QStringList list = m_reply->url().toString().split ("/");
|
||||||
|
QFile file (QDir::tempPath() + "/" + list.at (list.count() - 1));
|
||||||
|
|
||||||
if (file.open(QIODevice::WriteOnly)) {
|
if (file.open (QIODevice::WriteOnly))
|
||||||
file.write(data);
|
{
|
||||||
|
file.write (data);
|
||||||
m_path = file.fileName();
|
m_path = file.fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else
|
||||||
qWarning() << "QSimpleUpdater: cannot write downloaded data!";
|
qWarning() << "QSimpleUpdater: cannot write downloaded data!";
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
openDownload();
|
openDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else
|
||||||
qWarning() << "QSimpleUpdater: invalid download data!";
|
qWarning() << "QSimpleUpdater: invalid download data!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownloadDialog::updateProgress(qint64 received, qint64 total)
|
void DownloadDialog::updateProgress (qint64 received, qint64 total)
|
||||||
{
|
{
|
||||||
// We know the size of the download, so we can calculate the progress....
|
// We know the size of the download, so we can calculate the progress....
|
||||||
if (total > 0 && received > 0) {
|
if (total > 0 && received > 0)
|
||||||
ui->progressBar->setMinimum(0);
|
{
|
||||||
ui->progressBar->setMaximum(100);
|
ui->progressBar->setMinimum (0);
|
||||||
|
ui->progressBar->setMaximum (100);
|
||||||
|
|
||||||
int _progress = (int) ((received * 100) / total);
|
int _progress = (int) ((received * 100) / total);
|
||||||
ui->progressBar->setValue(_progress);
|
ui->progressBar->setValue (_progress);
|
||||||
|
|
||||||
QString _total_string;
|
QString _total_string;
|
||||||
QString _received_string;
|
QString _received_string;
|
||||||
@ -139,61 +144,74 @@ void DownloadDialog::updateProgress(qint64 received, qint64 total)
|
|||||||
float _total = total;
|
float _total = total;
|
||||||
float _received = received;
|
float _received = received;
|
||||||
|
|
||||||
if (_total < 1024) {
|
if (_total < 1024)
|
||||||
_total_string = tr("%1 bytes").arg(_total);
|
_total_string = tr ("%1 bytes").arg (_total);
|
||||||
} else if (_total < 1024 * 1024) {
|
|
||||||
_total = roundNumber(_total / 1024);
|
else if (_total < 1024 * 1024)
|
||||||
_total_string = tr("%1 KB").arg(_total);
|
{
|
||||||
} else {
|
_total = roundNumber (_total / 1024);
|
||||||
_total = roundNumber(_total / (1024 * 1024));
|
_total_string = tr ("%1 KB").arg (_total);
|
||||||
_total_string = tr("%1 MB").arg(_total);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_received < 1024) {
|
else
|
||||||
_received_string = tr("%1 bytes").arg(_received);
|
{
|
||||||
} else if (received < 1024 * 1024) {
|
_total = roundNumber (_total / (1024 * 1024));
|
||||||
_received = roundNumber(_received / 1024);
|
_total_string = tr ("%1 MB").arg (_total);
|
||||||
_received_string = tr("%1 KB").arg(_received);
|
|
||||||
} else {
|
|
||||||
_received = roundNumber(_received / (1024 * 1024));
|
|
||||||
_received_string = tr("%1 MB").arg(_received);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->downloadLabel->setText(tr("Downloading updates") + " (" +
|
if (_received < 1024)
|
||||||
_received_string + " " + tr("of") + " " +
|
_received_string = tr ("%1 bytes").arg (_received);
|
||||||
_total_string + ")");
|
|
||||||
|
else if (received < 1024 * 1024)
|
||||||
|
{
|
||||||
|
_received = roundNumber (_received / 1024);
|
||||||
|
_received_string = tr ("%1 KB").arg (_received);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_received = roundNumber (_received / (1024 * 1024));
|
||||||
|
_received_string = tr ("%1 MB").arg (_received);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->downloadLabel->setText (tr ("Downloading updates") + " (" +
|
||||||
|
_received_string + " " + tr ("of") + " " +
|
||||||
|
_total_string + ")");
|
||||||
|
|
||||||
uint _diff = QDateTime::currentDateTime().toTime_t() - m_start_time;
|
uint _diff = QDateTime::currentDateTime().toTime_t() - m_start_time;
|
||||||
|
|
||||||
if (_diff > 0) {
|
if (_diff > 0)
|
||||||
|
{
|
||||||
QString _time_string;
|
QString _time_string;
|
||||||
float _time_remaining = total / (received / _diff);
|
float _time_remaining = total / (received / _diff);
|
||||||
|
|
||||||
if (_time_remaining > 7200) {
|
if (_time_remaining > 7200)
|
||||||
|
{
|
||||||
_time_remaining /= 3600;
|
_time_remaining /= 3600;
|
||||||
_time_string = tr("About %1 hours").arg(int(_time_remaining + 0.5));
|
_time_string = tr ("About %1 hours").arg (int (_time_remaining + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_time_remaining > 60) {
|
else if (_time_remaining > 60)
|
||||||
|
{
|
||||||
_time_remaining /= 60;
|
_time_remaining /= 60;
|
||||||
_time_string = tr("About %1 minutes").arg(int(_time_remaining + 0.5));
|
_time_string = tr ("About %1 minutes").arg (int (_time_remaining + 0.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_time_remaining <= 60) {
|
else if (_time_remaining <= 60)
|
||||||
_time_string = tr("%1 seconds").arg(int(_time_remaining + 0.5));
|
_time_string = tr ("%1 seconds").arg (int (_time_remaining + 0.5));
|
||||||
}
|
|
||||||
|
|
||||||
ui->timeLabel->setText(tr("Time remaining") + ": " + _time_string);
|
ui->timeLabel->setText (tr ("Time remaining") + ": " + _time_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do not know the size of the download, so we improvise...
|
// We do not know the size of the download, so we improvise...
|
||||||
else {
|
else
|
||||||
ui->progressBar->setValue(-1);
|
{
|
||||||
ui->progressBar->setMinimum(0);
|
ui->progressBar->setValue (-1);
|
||||||
ui->progressBar->setMaximum(0);
|
ui->progressBar->setMinimum (0);
|
||||||
ui->downloadLabel->setText(tr("Downloading updates"));
|
ui->progressBar->setMaximum (0);
|
||||||
ui->timeLabel->setText(tr("Time remaining") + ": " + tr("Unknown"));
|
ui->downloadLabel->setText (tr ("Downloading updates"));
|
||||||
|
ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("Unknown"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +220,7 @@ void DownloadDialog::ignoreSslErrors (QNetworkReply *reply, const QList<QSslErro
|
|||||||
reply->ignoreSslErrors (error);
|
reply->ignoreSslErrors (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
float DownloadDialog::roundNumber(const float &input)
|
float DownloadDialog::roundNumber (const float &input)
|
||||||
{
|
{
|
||||||
return roundf(input * 100) / 100;
|
return roundf (input * 100) / 100;
|
||||||
}
|
}
|
||||||
|
@ -13,38 +13,39 @@
|
|||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui
|
||||||
|
{
|
||||||
class DownloadDialog;
|
class DownloadDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DownloadDialog : public QWidget
|
class DownloadDialog : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DownloadDialog(QWidget *parent = 0);
|
explicit DownloadDialog (QWidget *parent = 0);
|
||||||
~DownloadDialog();
|
~DownloadDialog();
|
||||||
|
|
||||||
void beginDownload(const QUrl &url);
|
void beginDownload (const QUrl &url);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void openDownload();
|
void openDownload();
|
||||||
void cancelDownload();
|
void cancelDownload();
|
||||||
void downloadFinished();
|
void downloadFinished();
|
||||||
void updateProgress(qint64 received, qint64 total);
|
void updateProgress (qint64 received, qint64 total);
|
||||||
void ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &error);
|
void ignoreSslErrors (QNetworkReply *reply, const QList<QSslError> &error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::DownloadDialog *ui;
|
Ui::DownloadDialog *ui;
|
||||||
|
|
||||||
QString m_path;
|
QString m_path;
|
||||||
|
|
||||||
QNetworkReply *m_reply;
|
QNetworkReply *m_reply;
|
||||||
QNetworkAccessManager *m_manager;
|
QNetworkAccessManager *m_manager;
|
||||||
|
|
||||||
uint m_start_time;
|
uint m_start_time;
|
||||||
|
|
||||||
float roundNumber(const float &input);
|
float roundNumber (const float &input);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,80 +8,72 @@
|
|||||||
|
|
||||||
#include "qsimpleupdater.h"
|
#include "qsimpleupdater.h"
|
||||||
|
|
||||||
QSimpleUpdater::QSimpleUpdater(QObject *parent)
|
QSimpleUpdater::QSimpleUpdater (QObject *parent)
|
||||||
: QObject(parent)
|
: QObject (parent)
|
||||||
, m_changelog_downloaded(false)
|
, m_changelog_downloaded (false)
|
||||||
, m_version_check_finished(false)
|
, m_version_check_finished (false)
|
||||||
, m_new_version_available(false)
|
, m_new_version_available (false)
|
||||||
{
|
{
|
||||||
m_downloadDialog = new DownloadDialog();
|
m_downloadDialog = new DownloadDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString QSimpleUpdater::changeLog() const
|
||||||
// Return the contents of the downloaded changelog
|
{
|
||||||
QString QSimpleUpdater::changeLog() const {
|
if (m_changelog.isEmpty())
|
||||||
if (m_changelog.isEmpty()) {
|
{
|
||||||
qDebug() << "QSimpleUpdater: change log is empty,"
|
qDebug() << "QSimpleUpdater: change log is empty,"
|
||||||
<< "did you call setChangelogUrl() and checkForUpdates()?";
|
<< "did you call setChangelogUrl() and checkForUpdates()?";
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_changelog;
|
return m_changelog;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::checkForUpdates() {
|
void QSimpleUpdater::checkForUpdates()
|
||||||
// Only check for updates if we know which file should we download
|
{
|
||||||
if (!m_reference_url.isEmpty()) {
|
if (!m_reference_url.isEmpty())
|
||||||
|
{
|
||||||
|
QNetworkAccessManager *_manager = new QNetworkAccessManager (this);
|
||||||
|
|
||||||
// Create a new network access manager, which allows us to
|
connect (_manager, SIGNAL (finished (QNetworkReply *)),
|
||||||
// download our desired file
|
this, SLOT (checkDownloadedVersion (QNetworkReply *)));
|
||||||
QNetworkAccessManager *_manager = new QNetworkAccessManager(this);
|
|
||||||
|
|
||||||
// Compare the downloaded application version with the installed
|
connect (_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)),
|
||||||
// version when the download is finished
|
this, SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
||||||
connect(_manager, SIGNAL(finished(QNetworkReply*)),
|
|
||||||
this, SLOT(checkDownloadedVersion(QNetworkReply*)));
|
|
||||||
|
|
||||||
// Ignore any possible SSL errors
|
|
||||||
connect(_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
|
||||||
this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
|
||||||
|
|
||||||
// Finally, download the file
|
|
||||||
_manager->get (QNetworkRequest (m_reference_url));
|
_manager->get (QNetworkRequest (m_reference_url));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue a warning message in the case that the reference URL is empty...
|
else
|
||||||
else {
|
|
||||||
qDebug() << "QSimpleUpdater: Invalid reference URL";
|
qDebug() << "QSimpleUpdater: Invalid reference URL";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::openDownloadLink() {
|
void QSimpleUpdater::openDownloadLink()
|
||||||
// Open the download URL in a web browser
|
{
|
||||||
if (!m_download_url.isEmpty()) {
|
if (!m_download_url.isEmpty())
|
||||||
QDesktopServices::openUrl(m_download_url);
|
QDesktopServices::openUrl (m_download_url);
|
||||||
}
|
|
||||||
|
|
||||||
// The m_download_url is empty, so we issue another warning message
|
else
|
||||||
else {
|
{
|
||||||
qDebug() << "QSimpleUpdater: cannot download latest version,"
|
qDebug() << "QSimpleUpdater: cannot download latest version,"
|
||||||
<< "did you call setDownloadUrl() and checkForUpdates()?";
|
<< "did you call setDownloadUrl() and checkForUpdates()?";
|
||||||
// Return the application version referenced by the string
|
|
||||||
// that we downloaded
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the application version referenced by the string
|
QString QSimpleUpdater::latestVersion() const
|
||||||
// that we downloaded
|
{
|
||||||
QString QSimpleUpdater::latestVersion() const {
|
if (m_latest_version.isEmpty())
|
||||||
if (m_latest_version.isEmpty()) {
|
{
|
||||||
qDebug() << "QSimpleUpdater: latest version is empty,"
|
qDebug() << "QSimpleUpdater: latest version is empty,"
|
||||||
<< "did you call checkForUpdates() and setReferenceUrl()?";
|
<< "did you call checkForUpdates() and setReferenceUrl()?";
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_latest_version;
|
return m_latest_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the string issued by the user in the setApplicationVersion() function
|
QString QSimpleUpdater::installedVersion() const
|
||||||
QString QSimpleUpdater::installedVersion() const {
|
{
|
||||||
if (m_installed_version.isEmpty()) {
|
if (m_installed_version.isEmpty())
|
||||||
|
{
|
||||||
qDebug() << "QSimpleUpdater: installed version is empty,"
|
qDebug() << "QSimpleUpdater: installed version is empty,"
|
||||||
<< "did you call setApplicationVersion()?";
|
<< "did you call setApplicationVersion()?";
|
||||||
}
|
}
|
||||||
@ -89,123 +81,102 @@ QString QSimpleUpdater::installedVersion() const {
|
|||||||
return m_installed_version;
|
return m_installed_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::downloadLatestVersion() {
|
void QSimpleUpdater::downloadLatestVersion()
|
||||||
// Show the download dialog
|
{
|
||||||
if (!m_download_url.isEmpty()) {
|
if (!m_download_url.isEmpty())
|
||||||
m_downloadDialog->beginDownload(m_download_url);
|
m_downloadDialog->beginDownload (m_download_url);
|
||||||
}
|
|
||||||
|
|
||||||
// The m_download_url is empty, so we issue another warning message
|
else
|
||||||
else {
|
{
|
||||||
qDebug() << "QSimpleUpdater: cannot download latest version,"
|
qDebug() << "QSimpleUpdater: cannot download latest version,"
|
||||||
<< "did you call setDownloadUrl() and checkForUpdates()?";
|
<< "did you call setDownloadUrl() and checkForUpdates()?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QSimpleUpdater::newerVersionAvailable() const {
|
bool QSimpleUpdater::newerVersionAvailable() const
|
||||||
|
{
|
||||||
return m_new_version_available;
|
return m_new_version_available;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the download URL if the issued URL is valid
|
void QSimpleUpdater::setDownloadUrl (const QString &url)
|
||||||
void QSimpleUpdater::setDownloadUrl(const QString &url) {
|
{
|
||||||
Q_ASSERT(!url.isEmpty());
|
Q_ASSERT (!url.isEmpty());
|
||||||
|
|
||||||
if (!url.isEmpty()) {
|
if (!url.isEmpty())
|
||||||
m_download_url.setUrl(url);
|
m_download_url.setUrl (url);
|
||||||
} else {
|
|
||||||
|
else
|
||||||
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the reference URL if the issued URL is valid
|
void QSimpleUpdater::setReferenceUrl (const QString &url)
|
||||||
void QSimpleUpdater::setReferenceUrl(const QString &url) {
|
{
|
||||||
Q_ASSERT(!url.isEmpty());
|
Q_ASSERT (!url.isEmpty());
|
||||||
|
|
||||||
if (!url.isEmpty()) {
|
if (!url.isEmpty())
|
||||||
m_reference_url.setUrl(url);
|
m_reference_url.setUrl (url);
|
||||||
} else {
|
|
||||||
|
else
|
||||||
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the changelog URL if the issued URL is valid
|
void QSimpleUpdater::setChangelogUrl (const QString &url)
|
||||||
void QSimpleUpdater::setChangelogUrl(const QString &url) {
|
{
|
||||||
Q_ASSERT(!url.isEmpty());
|
Q_ASSERT (!url.isEmpty());
|
||||||
|
|
||||||
if (!url.isEmpty()) {
|
if (!url.isEmpty())
|
||||||
m_changelog_url.setUrl(url);
|
m_changelog_url.setUrl (url);
|
||||||
} else {
|
|
||||||
|
else
|
||||||
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
qDebug() << "QSimpleUpdater: input URL cannot be empty!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the installed application version if the issued string is valid
|
void QSimpleUpdater::setApplicationVersion (const QString &version)
|
||||||
void QSimpleUpdater::setApplicationVersion(const QString &version) {
|
{
|
||||||
Q_ASSERT(!version.isEmpty());
|
Q_ASSERT (!version.isEmpty());
|
||||||
|
|
||||||
if (!version.isEmpty()) {
|
if (!version.isEmpty())
|
||||||
m_installed_version = version;
|
m_installed_version = version;
|
||||||
} else {
|
|
||||||
|
else
|
||||||
qDebug() << "QSimpleUpdater: input string cannot be empty!";
|
qDebug() << "QSimpleUpdater: input string cannot be empty!";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::checkDownloadedVersion(QNetworkReply *reply) {
|
void QSimpleUpdater::checkDownloadedVersion (QNetworkReply *reply)
|
||||||
|
{
|
||||||
bool _new_update = false;
|
bool _new_update = false;
|
||||||
|
|
||||||
// Read the reply from the server and transform it
|
|
||||||
// to a QString
|
|
||||||
QString _reply = QString::fromUtf8 (reply->readAll());
|
QString _reply = QString::fromUtf8 (reply->readAll());
|
||||||
_reply.replace(" ", "");
|
_reply.replace (" ", "");
|
||||||
_reply.replace("\n", "");
|
_reply.replace ("\n", "");
|
||||||
|
|
||||||
// If the reply from the server is not empty, compare
|
if (!_reply.isEmpty() && _reply.contains ("."))
|
||||||
// the downloaded version with the installed version
|
{
|
||||||
if (!_reply.isEmpty() && _reply.contains(".")) {
|
|
||||||
|
|
||||||
// Replace the latest version string with the downloaded string
|
|
||||||
m_latest_version = _reply;
|
m_latest_version = _reply;
|
||||||
|
|
||||||
// Separate the downloaded and installed version
|
|
||||||
// string by their dots.
|
|
||||||
//
|
|
||||||
// For example, 0.9.1 would become:
|
|
||||||
// 1: 0
|
|
||||||
// 2: 9
|
|
||||||
// 3: 1
|
|
||||||
//
|
|
||||||
QStringList _download = m_latest_version.split (".");
|
QStringList _download = m_latest_version.split (".");
|
||||||
QStringList _installed = m_installed_version.split (".");
|
QStringList _installed = m_installed_version.split (".");
|
||||||
|
|
||||||
// Compare the major, minor, build, etc. numbers
|
for (int i = 0; i <= _download.count() - 1; ++i)
|
||||||
for (int i = 0; i <= _download.count() - 1; ++i) {
|
{
|
||||||
|
if (_download.count() - 1 >= i && _installed.count() - 1 >= i)
|
||||||
// Make sure that the number that we are goind to compare
|
{
|
||||||
// exists in both strings, for example, we will not compare
|
if (_download.at (i) > _installed.at (i))
|
||||||
// 1.2.3 and 1.2.3.1 because we would crash the program
|
{
|
||||||
if (_download.count() - 1 >= i && _installed.count() - 1 >= i) {
|
|
||||||
|
|
||||||
// The downloaded number is greater than the installed number
|
|
||||||
// in question. So there's a newer version of the application
|
|
||||||
// available.
|
|
||||||
if (_download.at (i) > _installed.at (i)) {
|
|
||||||
_new_update = true;
|
_new_update = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the number of dots are different, we can tell if
|
else
|
||||||
// there's a newer version by comparing the count of each
|
{
|
||||||
// version. For example, 1.2.3 is smaller than 1.2.3.1...
|
if (_installed.count() < _download.count())
|
||||||
// Also, we will only reach this code when we finish comparing
|
{
|
||||||
// the "3" in both the downloaded and the installed version.
|
|
||||||
else {
|
|
||||||
if (_installed.count() < _download.count()) {
|
|
||||||
|
|
||||||
if (_installed.at (i - 1) == _download.at (i - 1))
|
if (_installed.at (i - 1) == _download.at (i - 1))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
_new_update = true;
|
_new_update = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -214,56 +185,43 @@ void QSimpleUpdater::checkDownloadedVersion(QNetworkReply *reply) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the value of the m_new_version_avialable boolean
|
|
||||||
m_new_version_available = _new_update;
|
m_new_version_available = _new_update;
|
||||||
|
|
||||||
// Notify our parent that we have finished downloading and comparing
|
|
||||||
// the application version
|
|
||||||
emit versionCheckFinished();
|
emit versionCheckFinished();
|
||||||
|
|
||||||
// If the changelog URL is valid, download the change log ONLY if
|
if (!m_changelog_url.isEmpty() && newerVersionAvailable())
|
||||||
// there's a newer version available.
|
{
|
||||||
// Note that the processDownloadedChangeLog() function will
|
QNetworkAccessManager *_manager = new QNetworkAccessManager (this);
|
||||||
// notify our parent that we have finished checking for updates.
|
|
||||||
if (!m_changelog_url.isEmpty() && newerVersionAvailable()) {
|
|
||||||
QNetworkAccessManager *_manager = new QNetworkAccessManager(this);
|
|
||||||
|
|
||||||
connect(_manager, SIGNAL(finished(QNetworkReply*)),
|
connect (_manager, SIGNAL (finished (QNetworkReply *)),
|
||||||
this, SLOT(processDownloadedChangelog(QNetworkReply*)));
|
this, SLOT (processDownloadedChangelog (QNetworkReply *)));
|
||||||
|
|
||||||
connect(_manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
|
connect (_manager, SIGNAL (sslErrors (QNetworkReply *, QList<QSslError>)),
|
||||||
this, SLOT(ignoreSslErrors(QNetworkReply*,QList<QSslError>)));
|
this, SLOT (ignoreSslErrors (QNetworkReply *, QList<QSslError>)));
|
||||||
|
|
||||||
_manager->get (QNetworkRequest (m_changelog_url));
|
_manager->get (QNetworkRequest (m_changelog_url));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We did not download the changelog, so we notify our parent
|
else
|
||||||
// that we have finished checking for updates
|
|
||||||
else {
|
|
||||||
emit checkingFinished();
|
emit checkingFinished();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::processDownloadedChangelog(QNetworkReply *reply) {
|
void QSimpleUpdater::processDownloadedChangelog (QNetworkReply *reply)
|
||||||
// Read the downloaded file and transform it to a QString
|
{
|
||||||
QString _reply = QString::fromUtf8(reply->readAll());
|
QString _reply = QString::fromUtf8 (reply->readAll());
|
||||||
|
|
||||||
// Change the changelog string and notify our
|
if (!_reply.isEmpty())
|
||||||
// parent that the changelog was downlaoded
|
{
|
||||||
if (!_reply.isEmpty()) {
|
|
||||||
m_changelog = _reply;
|
m_changelog = _reply;
|
||||||
emit changelogDownloadFinished();
|
emit changelogDownloadFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue a warning in the case that the changelog is empty
|
else
|
||||||
else {
|
|
||||||
qDebug() << "QSimpleUpdater: downloaded change log is empty!";
|
qDebug() << "QSimpleUpdater: downloaded change log is empty!";
|
||||||
}
|
|
||||||
|
|
||||||
// Tell our parent that we are done checking for updates
|
|
||||||
emit checkingFinished();
|
emit checkingFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSimpleUpdater::ignoreSslErrors (QNetworkReply *reply, const QList<QSslError> &error) {
|
void QSimpleUpdater::ignoreSslErrors (QNetworkReply *reply, const QList<QSslError> &error)
|
||||||
|
{
|
||||||
reply->ignoreSslErrors (error);
|
reply->ignoreSslErrors (error);
|
||||||
}
|
}
|
@ -16,51 +16,89 @@
|
|||||||
|
|
||||||
#include "dialogs/download_dialog.h"
|
#include "dialogs/download_dialog.h"
|
||||||
|
|
||||||
class QSimpleUpdater : public QObject {
|
class QSimpleUpdater : public QObject
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QSimpleUpdater(QObject *parent = 0);
|
QSimpleUpdater (QObject *parent = 0);
|
||||||
|
|
||||||
QString changeLog() const;
|
/// Returns the downloaded change log
|
||||||
void checkForUpdates();
|
QString changeLog() const;
|
||||||
void openDownloadLink();
|
|
||||||
QString latestVersion() const;
|
/// Returns the downloaded version string
|
||||||
QString installedVersion() const;
|
QString latestVersion() const;
|
||||||
void downloadLatestVersion();
|
|
||||||
bool newerVersionAvailable() const;
|
/// Returns the local version, referenced by
|
||||||
|
/// the setApplicationVersion() function
|
||||||
|
QString installedVersion() const;
|
||||||
|
|
||||||
|
/// Returns \c true if there's a newer version available
|
||||||
|
bool newerVersionAvailable() const;
|
||||||
|
|
||||||
|
/// Checks for updates and calls the appropriate
|
||||||
|
/// signals when finished
|
||||||
|
void checkForUpdates();
|
||||||
|
|
||||||
|
/// Opens the download URL in a a web browser.
|
||||||
|
/// The URL is referenced by the \c setDownloadUrl() function
|
||||||
|
void openDownloadLink();
|
||||||
|
|
||||||
|
/// Shows a dialog that downloads the file in the
|
||||||
|
/// URL referenced by the \c setDownloadUrl() function
|
||||||
|
void downloadLatestVersion();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDownloadUrl(const QString &url);
|
|
||||||
void setReferenceUrl(const QString &url);
|
/// Changes the URL that we can open in a web browser or
|
||||||
void setChangelogUrl(const QString &url);
|
/// download. Its recommended to use fixed URLs if you
|
||||||
void setApplicationVersion(const QString &version);
|
/// want to automatically download and install your updates
|
||||||
|
void setDownloadUrl (const QString &url);
|
||||||
|
|
||||||
|
/// Changes the reference URL, which contains ONLY the latest
|
||||||
|
/// version of your application as a plain text file.
|
||||||
|
/// Examples include:
|
||||||
|
/// - 1.2.3
|
||||||
|
/// - 5.4.0
|
||||||
|
/// - 0.1.2
|
||||||
|
/// - etc.
|
||||||
|
void setReferenceUrl (const QString &url);
|
||||||
|
|
||||||
|
/// Changes the change log URL, which contains the change log
|
||||||
|
/// of your application. The change log can be any file you
|
||||||
|
/// like, however, its recommended to write it in plain text,
|
||||||
|
/// such as TXT, HTML and RTF files.
|
||||||
|
void setChangelogUrl (const QString &url);
|
||||||
|
|
||||||
|
/// Tells the updater the version of the installed
|
||||||
|
/// copy of your application.
|
||||||
|
void setApplicationVersion (const QString &version);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void checkDownloadedVersion(QNetworkReply *reply);
|
void checkDownloadedVersion (QNetworkReply *reply);
|
||||||
void processDownloadedChangelog(QNetworkReply *reply);
|
void processDownloadedChangelog (QNetworkReply *reply);
|
||||||
void ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &error);
|
void ignoreSslErrors (QNetworkReply *reply, const QList<QSslError> &error);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void checkingFinished();
|
void checkingFinished();
|
||||||
void versionCheckFinished();
|
void versionCheckFinished();
|
||||||
void changelogDownloadFinished();
|
void changelogDownloadFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_changelog;
|
QString m_changelog;
|
||||||
QString m_latest_version;
|
QString m_latest_version;
|
||||||
QString m_installed_version;
|
QString m_installed_version;
|
||||||
|
|
||||||
QUrl m_download_url;
|
QUrl m_download_url;
|
||||||
QUrl m_reference_url;
|
QUrl m_reference_url;
|
||||||
QUrl m_changelog_url;
|
QUrl m_changelog_url;
|
||||||
|
|
||||||
bool m_changelog_downloaded;
|
bool m_changelog_downloaded;
|
||||||
bool m_version_check_finished;
|
bool m_version_check_finished;
|
||||||
|
|
||||||
bool m_new_version_available;
|
bool m_new_version_available;
|
||||||
|
|
||||||
DownloadDialog *m_downloadDialog;
|
DownloadDialog *m_downloadDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user