Improve AutoOpen

* Add support for 'ifDevice' feature, closes #2871
* Resolve placeholders for username and password to support references, fixes #2078
* Add support for open databases from an entry when the url starts with 'kdbx://'. Uses the same syntax as AutoOpen. Closes #1536.
This commit is contained in:
Jonathan White 2020-06-04 08:10:55 -04:00
parent b7104be689
commit f129768f07
2 changed files with 67 additions and 29 deletions

View File

@ -25,6 +25,7 @@
#include <QFile> #include <QFile>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
#include <QHostInfo>
#include <QKeyEvent> #include <QKeyEvent>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
@ -891,6 +892,8 @@ void DatabaseWidget::openUrlForEntry(Entry* entry)
getMainWindow()->minimizeOrHide(); getMainWindow()->minimizeOrHide();
} }
} }
} else if (cmdString.startsWith("kdbx://")) {
openDatabaseFromEntry(entry, false);
} else { } else {
QUrl url = QUrl::fromUserInput(entry->resolveMultiplePlaceholders(entry->url())); QUrl url = QUrl::fromUserInput(entry->resolveMultiplePlaceholders(entry->url()));
if (!url.isEmpty()) { if (!url.isEmpty()) {
@ -2021,39 +2024,73 @@ void DatabaseWidget::processAutoOpen()
if (entry->url().isEmpty() || (entry->password().isEmpty() && entry->username().isEmpty())) { if (entry->url().isEmpty() || (entry->password().isEmpty() && entry->username().isEmpty())) {
continue; continue;
} }
QFileInfo filepath;
QFileInfo keyfile;
QString databaseUrl = entry->resolveMultiplePlaceholders(entry->url());
if (databaseUrl.startsWith("file://")) { // Support ifDevice advanced entry, a comma separated list of computer names
QUrl url(databaseUrl); // that control whether to perform AutoOpen on this entry or not. Can be
filepath.setFile(url.toLocalFile()); // negated using '!'
} else { auto ifDevice = entry->attribute("ifDevice");
filepath.setFile(databaseUrl); if (!ifDevice.isEmpty()) {
if (filepath.isRelative()) { bool loadDb = false;
QFileInfo currentpath(m_db->filePath()); auto hostName = QHostInfo::localHostName();
filepath.setFile(currentpath.absoluteDir(), databaseUrl); for (auto& dev : ifDevice.split(",")) {
} dev = dev.trimmed();
} if (dev.startsWith("!") && dev.mid(1).compare(hostName, Qt::CaseInsensitive) == 0) {
// Machine name matched an exclusion, don't load this database
if (!filepath.isFile()) { loadDb = false;
continue; break;
} } else if (dev.compare(hostName, Qt::CaseInsensitive) == 0) {
loadDb = true;
if (!entry->username().isEmpty()) {
if (entry->username().startsWith("file://")) {
QUrl keyfileUrl(entry->username());
keyfile.setFile(keyfileUrl.toLocalFile());
} else {
keyfile.setFile(entry->username());
if (keyfile.isRelative()) {
QFileInfo currentpath(m_db->filePath());
keyfile.setFile(currentpath.absoluteDir(), entry->username());
} }
} }
if (!loadDb) {
continue;
}
} }
// Request to open the database file in the background with a password and keyfile openDatabaseFromEntry(entry);
emit requestOpenDatabase(filepath.canonicalFilePath(), true, entry->password(), keyfile.canonicalFilePath());
} }
} }
void DatabaseWidget::openDatabaseFromEntry(const Entry* entry, bool inBackground)
{
auto keyFile = entry->resolveMultiplePlaceholders(entry->username());
auto password = entry->resolveMultiplePlaceholders(entry->password());
auto databaseUrl = entry->resolveMultiplePlaceholders(entry->url());
if (databaseUrl.startsWith("kdbx://")) {
databaseUrl = databaseUrl.mid(7);
}
QFileInfo dbFileInfo;
if (databaseUrl.startsWith("file://")) {
QUrl url(databaseUrl);
dbFileInfo.setFile(url.toLocalFile());
} else {
dbFileInfo.setFile(databaseUrl);
if (dbFileInfo.isRelative()) {
QFileInfo currentpath(m_db->filePath());
dbFileInfo.setFile(currentpath.absoluteDir(), databaseUrl);
}
}
if (!dbFileInfo.isFile()) {
showErrorMessage(tr("Could not find database file: %1").arg(databaseUrl));
return;
}
QFileInfo keyFileInfo;
if (!keyFile.isEmpty()) {
if (keyFile.startsWith("file://")) {
QUrl keyfileUrl(keyFile);
keyFileInfo.setFile(keyfileUrl.toLocalFile());
} else {
keyFileInfo.setFile(keyFile);
if (keyFileInfo.isRelative()) {
QFileInfo currentpath(m_db->filePath());
keyFileInfo.setFile(currentpath.absoluteDir(), keyFile);
}
}
}
// Request to open the database file in the background with a password and keyfile
emit requestOpenDatabase(dbFileInfo.canonicalFilePath(), inBackground, password, keyFileInfo.canonicalFilePath());
}

View File

@ -253,6 +253,7 @@ private:
int addChildWidget(QWidget* w); int addChildWidget(QWidget* w);
void setClipboardTextAndMinimize(const QString& text); void setClipboardTextAndMinimize(const QString& text);
void processAutoOpen(); void processAutoOpen();
void openDatabaseFromEntry(const Entry* entry, bool inBackground = true);
bool confirmDeleteEntries(QList<Entry*> entries, bool permanent); bool confirmDeleteEntries(QList<Entry*> entries, bool permanent);
void performIconDownloads(const QList<Entry*>& entries, bool force = false); void performIconDownloads(const QList<Entry*>& entries, bool force = false);
Entry* currentSelectedEntry(); Entry* currentSelectedEntry();