Merge branch 'release/2.2.1' into develop

This commit is contained in:
Janek Bevendorff 2017-07-20 14:15:14 +02:00
commit 90468e8095
No known key found for this signature in database
GPG key ID: CFEC2F6850BFFA53
17 changed files with 303 additions and 113 deletions

View file

@ -107,6 +107,7 @@ void Config::init(const QString& fileName)
{
m_settings.reset(new QSettings(fileName, QSettings::IniFormat));
m_defaults.insert("SingleInstance", true);
m_defaults.insert("RememberLastDatabases", true);
m_defaults.insert("RememberLastKeyFiles", true);
m_defaults.insert("OpenPreviousDatabasesOnStartup", true);

View file

@ -17,6 +17,8 @@
*/
#include "Entry.h"
#include "config-keepassx.h"
#include "core/Database.h"
#include "core/DatabaseIcons.h"
#include "core/Group.h"
@ -237,6 +239,11 @@ QString Entry::url() const
return m_attributes->value(EntryAttributes::URLKey);
}
QString Entry::webUrl() const
{
return resolveUrl(m_attributes->value(EntryAttributes::URLKey));
}
QString Entry::username() const
{
return m_attributes->value(EntryAttributes::UserNameKey);
@ -784,3 +791,31 @@ QString Entry::resolvePlaceholder(const QString& str) const
return result;
}
QString Entry::resolveUrl(const QString& url) const
{
#ifdef WITH_XC_HTTP
QString newUrl = url;
if (!url.contains("://")) {
// URL doesn't have a protocol, add https by default
newUrl.prepend("https://");
}
QUrl tempUrl = QUrl(newUrl);
if (tempUrl.isValid()) {
if (tempUrl.scheme() == "cmd") {
// URL is a cmd, hopefully the second argument is an URL
QStringList cmd = newUrl.split(" ");
if (cmd.size() > 1) {
return resolveUrl(cmd[1].remove("'").remove("\""));
}
} else if (tempUrl.scheme() == "http" || tempUrl.scheme() == "https") {
// URL is nice
return tempUrl.url();
}
}
#else
Q_UNUSED(url);
#endif
return QString("");
}

View file

@ -78,6 +78,7 @@ public:
const AutoTypeAssociations* autoTypeAssociations() const;
QString title() const;
QString url() const;
QString webUrl() const;
QString username() const;
QString password() const;
QString notes() const;
@ -143,6 +144,7 @@ public:
void copyDataFrom(const Entry* other);
QString resolveMultiplePlaceholders(const QString& str) const;
QString resolvePlaceholder(const QString& str) const;
QString resolveUrl(const QString& url) const;
/**
* Call before and after set*() methods to create a history item

View file

@ -73,7 +73,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke
quint32 signature2 = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok);
if (ok && signature2 == KeePass1::SIGNATURE_2) {
raiseError(tr("The selected file is an old KeePass 1 database (.kdb).\n\n"
"You can import it by clicking on Database > 'Import KeePass 1 database'.\n"
"You can import it by clicking on Database > 'Import KeePass 1 database...'.\n"
"This is a one-way migration. You won't be able to open the imported "
"database with the old KeePassX 0.4 version."));
return nullptr;

View file

@ -19,6 +19,7 @@
#include "Application.h"
#include "MainWindow.h"
#include "core/Config.h"
#include <QAbstractNativeEventFilter>
#include <QFileOpenEvent>
@ -100,6 +101,10 @@ Application::Application(int& argc, char** argv)
if (!userName.isEmpty()) {
identifier.append("-");
identifier.append(userName);
#ifdef QT_DEBUG
// In DEBUG mode don't interfere with Release instances
identifier.append("-DEBUG");
#endif
}
QString socketName = identifier + ".socket";
QString lockName = identifier + ".lock";
@ -119,12 +124,14 @@ Application::Application(int& argc, char** argv)
alreadyRunning = true;
// notify the other instance
// try several times, in case the other instance is still starting up
QLocalSocket client;
for (int i = 0; i < 3; i++) {
client.connectToServer(socketName);
if (client.waitForConnected(150)) {
client.abort();
break;
if (config()->get("SingleInstance").toBool()) {
QLocalSocket client;
for (int i = 0; i < 3; i++) {
client.connectToServer(socketName);
if (client.waitForConnected(150)) {
client.abort();
break;
}
}
}
break;
@ -232,6 +239,10 @@ void Application::quitBySignal()
bool Application::isAlreadyRunning() const
{
return alreadyRunning;
#ifdef QT_DEBUG
// In DEBUG mode we can run unlimited instances
return false;
#endif
return config()->get("SingleInstance").toBool() && alreadyRunning;
}

View file

@ -19,7 +19,7 @@
<item>
<widget class="QCheckBox" name="titleClone">
<property name="text">
<string>Append ' - Copy' to title</string>
<string>Append ' - Clone' to title</string>
</property>
<property name="checked">
<bool>true</bool>

View file

@ -223,8 +223,16 @@ void EditWidgetIcons::fetchFavicon(const QUrl& url)
}
m_httpClient->setConnectingTimeOut(5000, [this]() {
resetFaviconDownload();
MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon."));
QUrl tempurl = QUrl(m_url);
if (tempurl.scheme() == "http") {
resetFaviconDownload();
MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon.") + "\n" + tr("Hint: You can enable Google as a fallback under Tools>Settings>Security"));
} else {
tempurl.setScheme("http");
m_url = tempurl.url();
tempurl.setPath("/favicon.ico");
fetchFavicon(tempurl);
}
});
m_ui->faviconButton->setDisabled(true);
@ -235,7 +243,9 @@ void EditWidgetIcons::fetchFaviconFromGoogle(const QString& domain)
if (config()->get("security/IconDownloadFallbackToGoogle", false).toBool() && m_fallbackToGoogle) {
resetFaviconDownload();
m_fallbackToGoogle = false;
fetchFavicon(QUrl("http://www.google.com/s2/favicons?domain=" + domain));
QUrl faviconUrl = QUrl("https://www.google.com/s2/favicons");
faviconUrl.setQuery("domain=" + QUrl::toPercentEncoding(domain));
fetchFavicon(faviconUrl);
} else {
resetFaviconDownload();
MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon."));

View file

@ -200,7 +200,7 @@
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>He&amp;lp</string>
<string>&amp;Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
@ -309,7 +309,7 @@
</action>
<action name="actionDatabaseOpen">
<property name="text">
<string>&amp;Open database</string>
<string>&amp;Open database...</string>
</property>
</action>
<action name="actionDatabaseSave">
@ -391,7 +391,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Sa&amp;ve database as</string>
<string>Sa&amp;ve database as...</string>
</property>
</action>
<action name="actionChangeMasterKey">
@ -399,7 +399,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Change &amp;master key</string>
<string>Change &amp;master key...</string>
</property>
</action>
<action name="actionChangeDatabaseSettings">
@ -517,22 +517,22 @@
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Export to CSV file</string>
<string>&amp;Export to CSV file...</string>
</property>
</action>
<action name="actionImportKeePass1">
<property name="text">
<string>Import KeePass 1 database</string>
<string>Import KeePass 1 database...</string>
</property>
</action>
<action name="actionImportCsv">
<property name="text">
<string>Import CSV file</string>
<string>Import CSV file...</string>
</property>
</action>
<action name="actionRepairDatabase">
<property name="text">
<string>Re&amp;pair database</string>
<string>Re&amp;pair database...</string>
</property>
</action>
<action name="actionEntryTotp">
@ -542,7 +542,7 @@
</action>
<action name="actionEntrySetupTotp">
<property name="text">
<string>Setup TOTP</string>
<string>Set up TOTP...</string>
</property>
</action>
<action name="actionEntryCopyTotp">

View file

@ -2,32 +2,12 @@
<ui version="4.0">
<class>PasswordGeneratorWidget</class>
<widget class="QWidget" name="PasswordGeneratorWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>575</width>
<height>305</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>284</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string/>
</property>
@ -188,17 +168,11 @@ QProgressBar::chunk {
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="tabPosition">
<enum>QTabWidget::North</enum>
</property>
@ -225,12 +199,6 @@ QProgressBar::chunk {
<layout class="QHBoxLayout" name="alphabetLayout" stretch="0,0,0,0,1,0">
<item>
<widget class="QToolButton" name="checkBoxUpper">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
@ -256,12 +224,6 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxLower">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
@ -287,12 +249,6 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxNumbers">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
@ -318,12 +274,6 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxSpecialChars">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
@ -349,12 +299,6 @@ QProgressBar::chunk {
</item>
<item>
<widget class="QToolButton" name="checkBoxExtASCII">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
@ -578,7 +522,7 @@ QProgressBar::chunk {
<item row="2" column="1">
<widget class="QLineEdit" name="editWordSeparator">
<property name="text">
<string> </string>
<string/>
</property>
</widget>
</item>

View file

@ -107,6 +107,10 @@ void SettingsWidget::loadSettings()
tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error);
}
#ifdef QT_DEBUG
m_generalUi->singleInstanceCheckBox->setEnabled(false);
#endif
m_generalUi->singleInstanceCheckBox->setChecked(config()->get("SingleInstance").toBool());
m_generalUi->rememberLastDatabasesCheckBox->setChecked(config()->get("RememberLastDatabases").toBool());
m_generalUi->rememberLastKeyFilesCheckBox->setChecked(config()->get("RememberLastKeyFiles").toBool());
m_generalUi->openPreviousDatabasesOnStartupCheckBox->setChecked(
@ -177,6 +181,7 @@ void SettingsWidget::saveSettings()
return;
}
config()->set("SingleInstance", m_generalUi->singleInstanceCheckBox->isChecked());
config()->set("RememberLastDatabases", m_generalUi->rememberLastDatabasesCheckBox->isChecked());
config()->set("RememberLastKeyFiles", m_generalUi->rememberLastKeyFilesCheckBox->isChecked());
config()->set("OpenPreviousDatabasesOnStartup",

View file

@ -33,6 +33,16 @@
<string>Basic Settings</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="singleInstanceCheckBox">
<property name="text">
<string>Start only a single instance of KeePassXC</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="rememberLastDatabasesCheckBox">
<property name="text">

View file

@ -363,7 +363,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore)
IconStruct iconStruct;
iconStruct.uuid = entry->iconUuid();
iconStruct.number = entry->iconNumber();
m_iconsWidget->load(entry->uuid(), m_database, iconStruct, entry->url());
m_iconsWidget->load(entry->uuid(), m_database, iconStruct, entry->webUrl());
connect(m_mainUi->urlEdit, SIGNAL(textChanged(QString)), m_iconsWidget, SLOT(setUrl(QString)));
m_autoTypeUi->enableButton->setChecked(entry->autoTypeEnabled());

View file

@ -2,20 +2,6 @@
<ui version="4.0">
<class>EditEntryWidgetMain</class>
<widget class="QWidget" name="EditEntryWidgetMain">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>692</width>
<height>323</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="topMargin">
<number>0</number>
@ -34,20 +20,7 @@
</widget>
</item>
<item row="4" column="1">
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
<widget class="PasswordGeneratorWidget" name="passwordGenerator" native="true"/>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="passwordLabel">

View file

@ -203,7 +203,7 @@ QList<Entry*> Service::searchEntries(Database* db, const QString& hostname)
const auto results = EntrySearcher().search(hostname, rootGroup, Qt::CaseInsensitive);
for (Entry* entry: results) {
QString title = entry->title();
QString url = entry->url();
QString url = entry->webUrl();
//Filter to match hostname in Title and Url fields
if ( (!title.isEmpty() && hostname.contains(title))

View file

@ -57,13 +57,11 @@ int main(int argc, char** argv)
// don't set organizationName as that changes the return value of
// QStandardPaths::writableLocation(QDesktopServices::DataLocation)
#ifndef QT_DEBUG
if (app.isAlreadyRunning()) {
qWarning() << QCoreApplication::translate("Main", "Another instance of KeePassXC is already running.").toUtf8().constData();
return 0;
}
#endif
QApplication::setQuitOnLastWindowClosed(false);
if (!Crypto::init()) {