mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-09 03:08:32 -05:00
Update checking feature (#2648)
* Check on startup (toggleable setting) and manually * Option to check for pre-releases (eg, 2.4.0-beta1) * Only included if WITH_XC_NETWORKING is enabled
This commit is contained in:
parent
5c9b062f13
commit
779b529da2
@ -61,9 +61,9 @@ if(WITH_XC_ALL)
|
|||||||
set(WITH_XC_YUBIKEY ON)
|
set(WITH_XC_YUBIKEY ON)
|
||||||
set(WITH_XC_SSHAGENT ON)
|
set(WITH_XC_SSHAGENT ON)
|
||||||
set(WITH_XC_KEESHARE ON)
|
set(WITH_XC_KEESHARE ON)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(WITH_XC_TOUCHID ON)
|
set(WITH_XC_TOUCHID ON)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_XC_KEESHARE_SECURE)
|
if(WITH_XC_KEESHARE_SECURE)
|
||||||
|
@ -102,9 +102,7 @@ These steps place the compiled KeePassXC binary inside the `./build/src/` direct
|
|||||||
-DWITH_XC_KEESHARE=[ON|OFF] Enable/Disable KeeShare group syncronization extension (default: OFF)
|
-DWITH_XC_KEESHARE=[ON|OFF] Enable/Disable KeeShare group syncronization extension (default: OFF)
|
||||||
-DWITH_XC_TOUCHID=[ON|OFF] (macOS Only) Enable/Disable Touch ID unlock (default:OFF)
|
-DWITH_XC_TOUCHID=[ON|OFF] (macOS Only) Enable/Disable Touch ID unlock (default:OFF)
|
||||||
-DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF)
|
-DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF)
|
||||||
|
|
||||||
-DWITH_XC_KEESHARE_SECURE=[ON|OFF] Enable/Disable KeeShare secure containers, requires libquazip5 (default: OFF)
|
-DWITH_XC_KEESHARE_SECURE=[ON|OFF] Enable/Disable KeeShare secure containers, requires libquazip5 (default: OFF)
|
||||||
|
|
||||||
-DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON)
|
-DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON)
|
||||||
-DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF)
|
-DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF)
|
||||||
-DWITH_DEV_BUILD=[ON|OFF] Enable/Disable deprecated method warnings (default: OFF)
|
-DWITH_DEV_BUILD=[ON|OFF] Enable/Disable deprecated method warnings (default: OFF)
|
||||||
|
@ -257,6 +257,10 @@ else()
|
|||||||
list(APPEND keepassx_SOURCES keys/drivers/YubiKey.h keys/drivers/YubiKeyStub.cpp)
|
list(APPEND keepassx_SOURCES keys/drivers/YubiKey.h keys/drivers/YubiKeyStub.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_XC_NETWORKING)
|
||||||
|
list(APPEND keepassx_SOURCES updatecheck/UpdateChecker.cpp gui/UpdateCheckDialog.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_XC_TOUCHID)
|
if(WITH_XC_TOUCHID)
|
||||||
list(APPEND keepassx_SOURCES touchid/TouchID.mm)
|
list(APPEND keepassx_SOURCES touchid/TouchID.mm)
|
||||||
endif()
|
endif()
|
||||||
|
@ -92,6 +92,7 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
#ifndef WITH_XC_NETWORKING
|
#ifndef WITH_XC_NETWORKING
|
||||||
|
m_generalUi->checkForUpdatesOnStartupCheckBox->setVisible(false);
|
||||||
m_secUi->privacy->setVisible(false);
|
m_secUi->privacy->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -174,6 +175,8 @@ void ApplicationSettingsWidget::loadSettings()
|
|||||||
m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool());
|
m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool());
|
||||||
m_generalUi->minimizeOnCloseCheckBox->setChecked(config()->get("GUI/MinimizeOnClose").toBool());
|
m_generalUi->minimizeOnCloseCheckBox->setChecked(config()->get("GUI/MinimizeOnClose").toBool());
|
||||||
m_generalUi->systrayMinimizeOnStartup->setChecked(config()->get("GUI/MinimizeOnStartup").toBool());
|
m_generalUi->systrayMinimizeOnStartup->setChecked(config()->get("GUI/MinimizeOnStartup").toBool());
|
||||||
|
m_generalUi->checkForUpdatesOnStartupCheckBox->setChecked(config()->get("GUI/CheckForUpdates").toBool());
|
||||||
|
m_generalUi->checkForUpdatesIncludeBetasCheckBox->setChecked(config()->get("GUI/CheckForUpdatesIncludeBetas").toBool());
|
||||||
m_generalUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool());
|
m_generalUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool());
|
||||||
|
|
||||||
if (autoType()->isAvailable()) {
|
if (autoType()->isAvailable()) {
|
||||||
@ -256,6 +259,8 @@ void ApplicationSettingsWidget::saveSettings()
|
|||||||
config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked());
|
config()->set("GUI/MinimizeToTray", m_generalUi->systrayMinimizeToTrayCheckBox->isChecked());
|
||||||
config()->set("GUI/MinimizeOnClose", m_generalUi->minimizeOnCloseCheckBox->isChecked());
|
config()->set("GUI/MinimizeOnClose", m_generalUi->minimizeOnCloseCheckBox->isChecked());
|
||||||
config()->set("GUI/MinimizeOnStartup", m_generalUi->systrayMinimizeOnStartup->isChecked());
|
config()->set("GUI/MinimizeOnStartup", m_generalUi->systrayMinimizeOnStartup->isChecked());
|
||||||
|
config()->set("GUI/CheckForUpdates", m_generalUi->checkForUpdatesOnStartupCheckBox->isChecked());
|
||||||
|
config()->set("GUI/CheckForUpdatesIncludeBetas", m_generalUi->checkForUpdatesIncludeBetasCheckBox->isChecked());
|
||||||
|
|
||||||
config()->set("security/autotypeask", m_generalUi->autoTypeAskCheckBox->isChecked());
|
config()->set("security/autotypeask", m_generalUi->autoTypeAskCheckBox->isChecked());
|
||||||
|
|
||||||
|
@ -83,6 +83,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkForUpdatesOnStartupCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for updates at application startup</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -179,6 +186,13 @@
|
|||||||
<string>General</string>
|
<string>General</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkForUpdatesIncludeBetasCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Include pre-releases when checking for updates</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="toolbarHideCheckBox">
|
<widget class="QCheckBox" name="toolbarHideCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
@ -41,6 +41,12 @@
|
|||||||
#include "keys/FileKey.h"
|
#include "keys/FileKey.h"
|
||||||
#include "keys/PasswordKey.h"
|
#include "keys/PasswordKey.h"
|
||||||
|
|
||||||
|
#ifdef WITH_XC_NETWORKING
|
||||||
|
#include "updatecheck/UpdateChecker.h"
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
|
#include "gui/UpdateCheckDialog.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_XC_SSHAGENT
|
#ifdef WITH_XC_SSHAGENT
|
||||||
#include "sshagent/AgentSettingsPage.h"
|
#include "sshagent/AgentSettingsPage.h"
|
||||||
#include "sshagent/SSHAgent.h"
|
#include "sshagent/SSHAgent.h"
|
||||||
@ -282,6 +288,7 @@ MainWindow::MainWindow()
|
|||||||
m_ui->actionPasswordGenerator->setIcon(filePath()->icon("actions", "password-generator"));
|
m_ui->actionPasswordGenerator->setIcon(filePath()->icon("actions", "password-generator"));
|
||||||
|
|
||||||
m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about"));
|
m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about"));
|
||||||
|
m_ui->actionCheckForUpdates->setIcon(filePath()->icon("actions", "system-software-update"));
|
||||||
|
|
||||||
m_actionMultiplexer.connect(
|
m_actionMultiplexer.connect(
|
||||||
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
|
SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode)));
|
||||||
@ -364,6 +371,15 @@ MainWindow::MainWindow()
|
|||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
setUnifiedTitleAndToolBarOnMac(true);
|
setUnifiedTitleAndToolBarOnMac(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_XC_NETWORKING
|
||||||
|
connect(m_ui->actionCheckForUpdates, SIGNAL(triggered()), SLOT(showUpdateCheckDialog()));
|
||||||
|
connect(UpdateChecker::instance(), SIGNAL(updateCheckFinished(bool, QString, bool)), SLOT(hasUpdateAvailable(bool, QString, bool)));
|
||||||
|
QTimer::singleShot(3000, this, SLOT(showUpdateCheckStartup()));
|
||||||
|
#else
|
||||||
|
m_ui->actionCheckForUpdates->setVisible(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
connect(m_ui->tabWidget,
|
connect(m_ui->tabWidget,
|
||||||
SIGNAL(messageGlobal(QString,MessageWidget::MessageType)),
|
SIGNAL(messageGlobal(QString,MessageWidget::MessageType)),
|
||||||
@ -661,6 +677,48 @@ void MainWindow::showAboutDialog()
|
|||||||
aboutDialog->open();
|
aboutDialog->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showUpdateCheckStartup()
|
||||||
|
{
|
||||||
|
#ifdef WITH_XC_NETWORKING
|
||||||
|
if (!config()->get("UpdateCheckMessageShown", false).toBool()) {
|
||||||
|
auto result = MessageBox::question(this,
|
||||||
|
tr("Check for updates on startup?"),
|
||||||
|
tr("Would you like KeePassXC to check for updates on startup?") + "\n\n" +
|
||||||
|
tr("You can always check for updates manually from the application menu."),
|
||||||
|
MessageBox::Yes | MessageBox::No,
|
||||||
|
MessageBox::Yes);
|
||||||
|
|
||||||
|
config()->set("GUI/CheckForUpdates", (result == MessageBox::Yes));
|
||||||
|
config()->set("UpdateCheckMessageShown", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config()->get("GUI/CheckForUpdates", false).toBool()) {
|
||||||
|
updateCheck()->checkForUpdates(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested)
|
||||||
|
{
|
||||||
|
#ifdef WITH_XC_NETWORKING
|
||||||
|
if (hasUpdate && !isManuallyRequested) {
|
||||||
|
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
||||||
|
updateCheckDialog->showUpdateCheckResponse(hasUpdate, version);
|
||||||
|
updateCheckDialog->show();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showUpdateCheckDialog()
|
||||||
|
{
|
||||||
|
#ifdef WITH_XC_NETWORKING
|
||||||
|
updateCheck()->checkForUpdates(true);
|
||||||
|
auto* updateCheckDialog = new UpdateCheckDialog(this);
|
||||||
|
updateCheckDialog->show();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::openDonateUrl()
|
void MainWindow::openDonateUrl()
|
||||||
{
|
{
|
||||||
QDesktopServices::openUrl(QUrl("https://keepassxc.org/donate"));
|
QDesktopServices::openUrl(QUrl("https://keepassxc.org/donate"));
|
||||||
|
@ -83,6 +83,9 @@ private slots:
|
|||||||
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::Mode::None);
|
void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::Mode::None);
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
void showAboutDialog();
|
void showAboutDialog();
|
||||||
|
void showUpdateCheckStartup();
|
||||||
|
void showUpdateCheckDialog();
|
||||||
|
void hasUpdateAvailable(bool hasUpdate, const QString& version, bool isManuallyRequested);
|
||||||
void openDonateUrl();
|
void openDonateUrl();
|
||||||
void openBugReportUrl();
|
void openBugReportUrl();
|
||||||
void switchToDatabases();
|
void switchToDatabases();
|
||||||
|
@ -223,6 +223,7 @@
|
|||||||
<string>&Help</string>
|
<string>&Help</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionAbout"/>
|
<addaction name="actionAbout"/>
|
||||||
|
<addaction name="actionCheckForUpdates"/>
|
||||||
<addaction name="actionDonate"/>
|
<addaction name="actionDonate"/>
|
||||||
<addaction name="actionBugReport"/>
|
<addaction name="actionBugReport"/>
|
||||||
</widget>
|
</widget>
|
||||||
@ -348,6 +349,14 @@
|
|||||||
<enum>QAction::AboutRole</enum>
|
<enum>QAction::AboutRole</enum>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionCheckForUpdates">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check for Updates...</string>
|
||||||
|
</property>
|
||||||
|
<property name="menuRole">
|
||||||
|
<enum>QAction::ApplicationSpecificRole</enum>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionDatabaseOpen">
|
<action name="actionDatabaseOpen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Open database...</string>
|
<string>&Open database...</string>
|
||||||
|
68
src/gui/UpdateCheckDialog.cpp
Normal file
68
src/gui/UpdateCheckDialog.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "UpdateCheckDialog.h"
|
||||||
|
#include "ui_UpdateCheckDialog.h"
|
||||||
|
#include "updatecheck/UpdateChecker.h"
|
||||||
|
#include "core/FilePath.h"
|
||||||
|
|
||||||
|
UpdateCheckDialog::UpdateCheckDialog(QWidget* parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_ui(new Ui::UpdateCheckDialog())
|
||||||
|
{
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
setWindowFlags(Qt::Window);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48));
|
||||||
|
|
||||||
|
connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close()));
|
||||||
|
connect(UpdateChecker::instance(), SIGNAL(updateCheckFinished(bool, QString, bool)), SLOT(showUpdateCheckResponse(bool, QString)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateCheckDialog::showUpdateCheckResponse(bool status, const QString& version) {
|
||||||
|
m_ui->progressBar->setVisible(false);
|
||||||
|
m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close"));
|
||||||
|
|
||||||
|
if (version == QString("error")) {
|
||||||
|
setWindowTitle(tr("Update Error!"));
|
||||||
|
|
||||||
|
m_ui->statusLabel->setText(
|
||||||
|
"<strong>" + tr("Update Error!") + "</strong><br><br>" +
|
||||||
|
tr("An error occurred in retrieving update information.") + "<br>" +
|
||||||
|
tr("Please try again later."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
setWindowTitle(tr("Software Update"));
|
||||||
|
m_ui->statusLabel->setText(
|
||||||
|
"<strong>" + tr("A new version of KeePassXC is available!") + "</strong><br><br>" +
|
||||||
|
tr("KeePassXC %1 is now available — you have %2.").arg(version, KEEPASSXC_VERSION) + "<br><br>" +
|
||||||
|
"<a href='https://keepassxc.org/download/'>" +
|
||||||
|
tr("Download it at keepassxc.org") +
|
||||||
|
"</a>");
|
||||||
|
} else {
|
||||||
|
setWindowTitle(tr("You're up-to-date!"));
|
||||||
|
m_ui->statusLabel->setText(tr(
|
||||||
|
"KeePassXC %1 is currently the newest version available").arg(KEEPASSXC_VERSION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCheckDialog::~UpdateCheckDialog()
|
||||||
|
{
|
||||||
|
}
|
50
src/gui/UpdateCheckDialog.h
Normal file
50
src/gui/UpdateCheckDialog.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSXC_UPDATECHECKDIALOG_H
|
||||||
|
#define KEEPASSXC_UPDATECHECKDIALOG_H
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
|
#include "config-keepassx.h"
|
||||||
|
#include "core/Global.h"
|
||||||
|
#include "updatecheck/UpdateChecker.h"
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class UpdateCheckDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateCheckDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit UpdateCheckDialog(QWidget* parent = nullptr);
|
||||||
|
~UpdateCheckDialog() override;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void showUpdateCheckResponse(bool status, const QString& version);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QScopedPointer<Ui::UpdateCheckDialog> m_ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //KEEPASSXC_UPDATECHECKDIALOG_H
|
175
src/gui/UpdateCheckDialog.ui
Normal file
175
src/gui/UpdateCheckDialog.ui
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>UpdateCheckDialog</class>
|
||||||
|
<widget class="QDialog" name="UpdateCheckDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>375</width>
|
||||||
|
<height>136</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Checking for updates</string>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="iconLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>60</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="statusLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>50</weight>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Checking for updates...</string>
|
||||||
|
</property>
|
||||||
|
<property name="textFormat">
|
||||||
|
<enum>Qt::RichText</enum>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>UpdateCheckDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>UpdateCheckDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
148
src/updatecheck/UpdateChecker.cpp
Normal file
148
src/updatecheck/UpdateChecker.cpp
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "UpdateChecker.h"
|
||||||
|
#include "core/Config.h"
|
||||||
|
#include "config-keepassx.h"
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QtNetwork>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
|
||||||
|
UpdateChecker* UpdateChecker::m_instance(nullptr);
|
||||||
|
|
||||||
|
UpdateChecker::UpdateChecker(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_netMgr(new QNetworkAccessManager(this))
|
||||||
|
, m_reply(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateChecker::~UpdateChecker()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateChecker::checkForUpdates(bool manuallyRequested)
|
||||||
|
{
|
||||||
|
m_isManuallyRequested = manuallyRequested;
|
||||||
|
m_bytesReceived.clear();
|
||||||
|
|
||||||
|
QString apiUrlStr = QString("https://api.github.com/repos/keepassxreboot/keepassxc/releases");
|
||||||
|
|
||||||
|
if (!config()->get("GUI/CheckForUpdatesIncludeBetas", false).toBool()) {
|
||||||
|
apiUrlStr += "/latest";
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl apiUrl = QUrl(apiUrlStr);
|
||||||
|
|
||||||
|
QNetworkRequest request(apiUrl);
|
||||||
|
request.setRawHeader("Accept", "application/json");
|
||||||
|
|
||||||
|
m_reply = m_netMgr->get(request);
|
||||||
|
|
||||||
|
connect(m_reply, &QNetworkReply::finished, this, &UpdateChecker::fetchFinished);
|
||||||
|
connect(m_reply, &QIODevice::readyRead, this, &UpdateChecker::fetchReadyRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateChecker::fetchReadyRead()
|
||||||
|
{
|
||||||
|
m_bytesReceived += m_reply->readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateChecker::fetchFinished()
|
||||||
|
{
|
||||||
|
bool error = (m_reply->error() != QNetworkReply::NoError);
|
||||||
|
bool hasNewVersion = false;
|
||||||
|
QUrl url = m_reply->url();
|
||||||
|
QString version = "";
|
||||||
|
|
||||||
|
m_reply->deleteLater();
|
||||||
|
m_reply = nullptr;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(m_bytesReceived);
|
||||||
|
QJsonObject jsonObject = jsonResponse.object();
|
||||||
|
|
||||||
|
if (config()->get("GUI/CheckForUpdatesIncludeBetas", false).toBool()) {
|
||||||
|
QJsonArray jsonArray = jsonResponse.array();
|
||||||
|
jsonObject = jsonArray.at(0).toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jsonObject.value("tag_name").isUndefined()) {
|
||||||
|
version = jsonObject.value("tag_name").toString();
|
||||||
|
hasNewVersion = compareVersions(version, QString(KEEPASSXC_VERSION));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
version = "error";
|
||||||
|
}
|
||||||
|
|
||||||
|
emit updateCheckFinished(hasNewVersion, version, m_isManuallyRequested);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdateChecker::compareVersions(const QString& remoteVersion, const QString& localVersion)
|
||||||
|
{
|
||||||
|
if (localVersion == remoteVersion) {
|
||||||
|
return false; // Currently using updated version
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegularExpression verRegex("^(\\d+(\\.\\d+){0,2})(-\\w+)?$", QRegularExpression::CaseInsensitiveOption);
|
||||||
|
|
||||||
|
QRegularExpressionMatch lmatch = verRegex.match(localVersion);
|
||||||
|
QRegularExpressionMatch rmatch = verRegex.match(remoteVersion);
|
||||||
|
|
||||||
|
if (!lmatch.captured(1).isNull() && !rmatch.captured(1).isNull()) {
|
||||||
|
if (lmatch.captured(1) == rmatch.captured(1) && !lmatch.captured(3).isNull()) {
|
||||||
|
// Same version, but installed version has snapshot/beta suffix and should be updated to stable
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList lparts = lmatch.captured(1).split(".");
|
||||||
|
QStringList rparts = rmatch.captured(1).split(".");
|
||||||
|
|
||||||
|
if (lparts.length() < 3)
|
||||||
|
lparts << "0";
|
||||||
|
|
||||||
|
if (rparts.length() < 3)
|
||||||
|
rparts << "0";
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
int l = lparts[i].toInt();
|
||||||
|
int r = rparts[i].toInt();
|
||||||
|
|
||||||
|
if (l == r)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (l > r) {
|
||||||
|
return false; // Installed version is newer than release
|
||||||
|
} else {
|
||||||
|
return true; // Installed version is outdated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Installed version is the same
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Invalid version string
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateChecker* UpdateChecker::instance()
|
||||||
|
{
|
||||||
|
if (!m_instance) {
|
||||||
|
m_instance = new UpdateChecker();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_instance;
|
||||||
|
}
|
60
src/updatecheck/UpdateChecker.h
Normal file
60
src/updatecheck/UpdateChecker.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSXC_UPDATECHECK_H
|
||||||
|
#define KEEPASSXC_UPDATECHECK_H
|
||||||
|
#include <QString>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
class UpdateChecker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
UpdateChecker(QObject* parent = nullptr);
|
||||||
|
~UpdateChecker() override;
|
||||||
|
|
||||||
|
void checkForUpdates(bool manuallyRequested);
|
||||||
|
static bool compareVersions(const QString& remoteVersion, const QString& localVersion);
|
||||||
|
static UpdateChecker* instance();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void updateCheckFinished(bool hasNewVersion, QString version, bool isManuallyRequested);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void fetchFinished();
|
||||||
|
void fetchReadyRead();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QNetworkAccessManager* m_netMgr;
|
||||||
|
QNetworkReply* m_reply;
|
||||||
|
QByteArray m_bytesReceived;
|
||||||
|
bool m_isManuallyRequested;
|
||||||
|
|
||||||
|
static UpdateChecker* m_instance;
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(UpdateChecker)
|
||||||
|
};
|
||||||
|
|
||||||
|
inline UpdateChecker* updateCheck()
|
||||||
|
{
|
||||||
|
return UpdateChecker::instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //KEEPASSXC_UPDATECHECK_H
|
@ -162,6 +162,11 @@ add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp
|
|||||||
add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp
|
add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp
|
||||||
LIBS ${TEST_LIBRARIES})
|
LIBS ${TEST_LIBRARIES})
|
||||||
|
|
||||||
|
if(WITH_XC_NETWORKING)
|
||||||
|
add_unit_test(NAME testupdatecheck SOURCES TestUpdateCheck.cpp
|
||||||
|
LIBS ${TEST_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_XC_AUTOTYPE)
|
if(WITH_XC_AUTOTYPE)
|
||||||
add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
|
add_unit_test(NAME testautotype SOURCES TestAutoType.cpp
|
||||||
LIBS ${TEST_LIBRARIES})
|
LIBS ${TEST_LIBRARIES})
|
||||||
|
41
tests/TestUpdateCheck.cpp
Normal file
41
tests/TestUpdateCheck.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TestUpdateCheck.h"
|
||||||
|
#include "TestGlobal.h"
|
||||||
|
#include "updatecheck/UpdateChecker.h"
|
||||||
|
#include "crypto/Crypto.h"
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN(TestUpdateCheck)
|
||||||
|
|
||||||
|
void TestUpdateCheck::initTestCase()
|
||||||
|
{
|
||||||
|
QVERIFY(Crypto::init());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestUpdateCheck::testCompareVersion()
|
||||||
|
{
|
||||||
|
// Remote Version , Installed Version
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.4.0"), QString("2.3.4")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.4.0")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0"), QString("2.3.0-beta1")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.0-beta2"), QString("2.3.0-beta1")), true);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("2.3.4"), QString("2.4.0-snapshot")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString("invalid"), QString("2.4.0")), false);
|
||||||
|
QCOMPARE(UpdateChecker::compareVersions(QString(""), QString("2.4.0")), false);
|
||||||
|
}
|
32
tests/TestUpdateCheck.h
Normal file
32
tests/TestUpdateCheck.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
|
||||||
|
*
|
||||||
|
* This program 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 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSX_TESTUPDATECHECK_H
|
||||||
|
#define KEEPASSX_TESTUPDATECHECK_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class TestUpdateCheck : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();
|
||||||
|
void testCompareVersion();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // #define KEEPASSX_TESTUPDATECHECK_H
|
@ -86,6 +86,8 @@ void TestGui::initTestCase()
|
|||||||
config()->set("GUI/ShowTrayIcon", true);
|
config()->set("GUI/ShowTrayIcon", true);
|
||||||
// Disable advanced settings mode (activate within individual tests to test advanced settings)
|
// Disable advanced settings mode (activate within individual tests to test advanced settings)
|
||||||
config()->set("GUI/AdvancedSettings", false);
|
config()->set("GUI/AdvancedSettings", false);
|
||||||
|
// Disable the update check first time alert
|
||||||
|
config()->set("UpdateCheckMessageShown", true);
|
||||||
|
|
||||||
m_mainWindow.reset(new MainWindow());
|
m_mainWindow.reset(new MainWindow());
|
||||||
Bootstrap::restoreMainWindowState(*m_mainWindow);
|
Bootstrap::restoreMainWindowState(*m_mainWindow);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user