1 /* ============================================================
2 * QuiteRSS is a open-source cross-platform RSS/Atom news feeds reader
3 * Copyright (C) 2011-2020 QuiteRSS Team <quiterssteam@gmail.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 * ============================================================ */
18 #include "updateappdialog.h"
19 
20 #include "mainapplication.h"
21 #include "VersionNo.h"
22 #include "settings.h"
23 
24 #include <QNetworkCookie>
25 #if defined(Q_OS_WIN)
26 #include <qt_windows.h>
27 #endif
28 
UpdateAppDialog(const QString & lang,QWidget * parent,bool show)29 UpdateAppDialog::UpdateAppDialog(const QString &lang, QWidget *parent, bool show)
30   : Dialog(parent)
31   , lang_(lang)
32   , showDialog_(show)
33   , page_(NULL)
34 {
35   Settings settings;
36 
37   networkManagerProxy_ = new NetworkManagerProxy(0, this);
38 
39   if (showDialog_) {
40     setWindowTitle(tr("Check for Updates"));
41     setWindowFlags (windowFlags() & ~Qt::WindowContextHelpButtonHint);
42     setObjectName("UpdateAppDialog");
43     resize(450, 350);
44 
45     infoLabel = new QLabel(tr("Checking for updates..."), this);
46     infoLabel->setOpenExternalLinks(true);
47 
48     history_ = new QTextBrowser(this);
49     history_->setObjectName("history_");
50     history_->setText(tr("Loading history..."));
51     history_->setOpenExternalLinks(true);
52 
53     remindAboutVersion_ = new QCheckBox(tr("Don't remind about this version"), this);
54     remindAboutVersion_->setChecked(settings.value("remindAboutVersion", false).toBool());
55     remindAboutVersion_->hide();
56 
57     pageLayout->addWidget(infoLabel, 0);
58     pageLayout->addWidget(history_, 1);
59     pageLayout->addWidget(remindAboutVersion_, 0);
60 
61     installButton_ = new QPushButton(tr("&Install"), this);
62     installButton_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
63     installButton_->hide();
64     buttonsLayout->insertWidget(0, installButton_, 1);
65     connect(installButton_, SIGNAL(clicked()), SLOT(updaterRun()));
66 
67     buttonBox->addButton(QDialogButtonBox::Close);
68 
69     renderStatistics();
70 
71     QString urlHistory;
72     if (lang_.contains("ru", Qt::CaseInsensitive))
73       urlHistory = "https://quiterss.org/files/updates_new/HISTORY_RU";
74     else urlHistory = "https://quiterss.org/files/updates_new/HISTORY_EN";
75     historyReply_ = networkManagerProxy_->get(QNetworkRequest(QUrl(urlHistory)));
76     connect(historyReply_, SIGNAL(finished()), this, SLOT(slotFinishHistoryReply()));
77 
78     connect(this, SIGNAL(finished(int)), this, SLOT(closeDialog()));
79 
80     restoreGeometry(settings.value("updateAppDlg/geometry").toByteArray());
81   } else {
82     renderStatistics();
83   }
84 }
85 
~UpdateAppDialog()86 UpdateAppDialog::~UpdateAppDialog()
87 {
88 
89 }
90 
disconnectObjects()91 void UpdateAppDialog::disconnectObjects()
92 {
93   disconnect(this);
94   networkManagerProxy_->disconnectObjects();
95 
96   if (page_ != NULL) {
97     QWebSettings::clearMemoryCaches();
98     page_->disconnect(this);
99     delete page_;
100   }
101 
102   delete networkManagerProxy_;
103 }
104 
closeDialog()105 void UpdateAppDialog::closeDialog()
106 {
107   Settings settings;
108   settings.setValue("remindAboutVersion", remindAboutVersion_->isChecked());
109   settings.setValue("updateAppDlg/geometry", saveGeometry());
110 }
111 
finishUpdatesChecking()112 void UpdateAppDialog::finishUpdatesChecking()
113 {
114   reply_->deleteLater();
115 
116   QString info;
117   QString newVersion = "";
118 
119   if (reply_->error() == QNetworkReply::NoError) {
120     QString version = STRPRODUCTVER;
121     QString date = STRDATE;
122 
123     QString str = QLatin1String(reply_->readAll());
124     QString curVersion = str.section('"', 5, 5).section('\\', 0, 0);
125     QString curDate = str.section('"', 3, 3).section('\\', 0, 0);
126 
127     if (version.contains(curVersion)) {
128       str =
129           tr("You already have the latest version");
130     } else {
131       QString urlDownloads;
132       if (lang_.contains("ru", Qt::CaseInsensitive))
133         urlDownloads = "https://quiterss.org/ru/download";
134       else urlDownloads = "https://quiterss.org/en/download";
135 
136       str =
137           tr("A new version of QuiteRSS is available!") +
138           "<p>" + QString("<a href=\"%1\">%2</a>").
139           arg(urlDownloads).
140           arg(tr("Click here to go to the download page"));
141       newVersion = curVersion;
142     }
143     info =
144         "<html><style>a { color: blue; text-decoration: none; }</style><body>"
145         "<table><tr><td>" + tr("Your version is:") + " </td><td>" +
146         "<B> " + version + "</B>" + QString(" (%1)").arg(date) + " </td></tr>" +
147         "<tr><td>" + tr("Current version is:") + " </td><td>" +
148         "<B>" + curVersion + "</B>" + QString(" (%1)").arg(curDate) +
149         "</td></tr></table><p>" + str +
150         "</body></html>";
151   } else {
152     qWarning() << "Error checking updates" << reply_->error() << reply_->errorString();
153     info = tr("Error checking updates");
154     if (showDialog_)
155       history_->setText("");
156   }
157 
158   Settings settings;
159   bool remind = settings.value("remindAboutVersion", false).toBool();
160   QString currentVersion = settings.value("currentVersionApp", "").toString();
161   if (!showDialog_) {
162     if (!newVersion.isEmpty()) {
163       if (currentVersion != newVersion) {
164         settings.setValue("currentVersionApp", newVersion);
165         settings.setValue("remindAboutVersion", false);
166       } else if (remind) {
167           newVersion = "";
168       }
169     }
170 
171     emit signalNewVersion(newVersion);
172   } else {
173     infoLabel->setText(info);
174 
175 #if defined(Q_OS_WIN)
176     if (QFile::exists(QCoreApplication::applicationDirPath() + "/Updater.exe") &&
177         !newVersion.isEmpty() && !mainApp->isPortableAppsCom())
178       installButton_->show();
179 #endif
180 
181     if (!newVersion.isEmpty()) {
182       if (currentVersion != newVersion) {
183         settings.setValue("currentVersionApp", newVersion);
184         settings.setValue("remindAboutVersion", false);
185         remindAboutVersion_->setChecked(false);
186         remindAboutVersion_->show();
187       } else if (!remind) {
188           remindAboutVersion_->show();
189       }
190     }
191   }
192 }
193 
slotFinishHistoryReply()194 void UpdateAppDialog::slotFinishHistoryReply()
195 {
196   historyReply_->deleteLater();
197   if (historyReply_->error() != QNetworkReply::NoError) {
198     qDebug() << "error retrieving " << historyReply_->url();
199     return;
200   }
201 
202   QString str = QString::fromUtf8(historyReply_->readAll());
203 
204   history_->setHtml(str);
205 }
206 
updaterRun()207 void UpdateAppDialog::updaterRun()
208 {
209   close();
210 #if defined(Q_OS_WIN)
211   QString updaterFile = QCoreApplication::applicationDirPath() + "/Updater.exe";
212   ShellExecute(0, 0, (wchar_t *)updaterFile.utf16(), 0, 0, SW_SHOWNORMAL);
213 #endif
214 }
215 
renderStatistics()216 void UpdateAppDialog::renderStatistics()
217 {
218   Settings settings;
219   bool updateCheckEnabled = settings.value("Settings/updateCheckEnabled", true).toBool();
220   if (updateCheckEnabled || showDialog_) {
221     QNetworkRequest request(QUrl("https://quiterss.org/files/updates_new/VersionNo.h"));
222     reply_ = networkManagerProxy_->get(request);
223     connect(reply_, SIGNAL(finished()), this, SLOT(finishUpdatesChecking()));
224   } else {
225     emit signalNewVersion();
226   }
227 }
228