Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warning for duplicate URLs with Additional URLs list #9588

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions share/translations/keepassxc_en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3919,6 +3919,10 @@ Error: %1</source>
<source>Invalid URL</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Duplicate URL</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EntryView</name>
Expand Down
5 changes: 3 additions & 2 deletions src/gui/entry/EditEntryWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,17 +326,18 @@ void EditEntryWidget::insertURL()
{
Q_ASSERT(!m_history);

QString name("KP2A_URL");
QString name(BrowserService::ADDITIONAL_URL);
int i = 1;

while (m_entryAttributes->keys().contains(name)) {
name = QString("KP2A_URL_%1").arg(i);
name = QString("%1_%2").arg(BrowserService::ADDITIONAL_URL, QString::number(i));
i++;
}

m_entryAttributes->set(name, tr("<empty URL>"));
QModelIndex index = m_additionalURLsDataModel->indexByKey(name);

m_additionalURLsDataModel->setEntryUrl(m_entry->url());
m_browserUi->additionalURLsView->setCurrentIndex(index);
m_browserUi->additionalURLsView->edit(index);

Expand Down
38 changes: 25 additions & 13 deletions src/gui/entry/EntryURLModel.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
* 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
Expand All @@ -18,6 +18,7 @@

#include "EntryURLModel.h"

#include "browser/BrowserService.h"
#include "core/EntryAttributes.h"
#include "core/Tools.h"
#include "gui/Icons.h"
Expand Down Expand Up @@ -53,7 +54,7 @@ void EntryURLModel::setEntryAttributes(EntryAttributes* entryAttributes)

endResetModel();
}

#include <QDebug>
QVariant EntryURLModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid()) {
Expand All @@ -68,31 +69,42 @@ QVariant EntryURLModel::data(const QModelIndex& index, int role) const
const auto value = m_entryAttributes->value(key);
const auto urlValid = Tools::checkUrlValid(value);

if (role == Qt::BackgroundRole && !urlValid) {
// Check for duplicate URLs in the attribute list. Excludes the current key/value from the comparison.
auto customAttributeKeys = m_entryAttributes->customKeys();
customAttributeKeys.removeOne(key);
const auto duplicateUrl = m_entryAttributes->values(customAttributeKeys).contains(value) || value == m_entryUrl;

if (role == Qt::BackgroundRole && (!urlValid || duplicateUrl)) {
StateColorPalette statePalette;
return statePalette.color(StateColorPalette::ColorRole::Error);
} else if (role == Qt::DecorationRole && !urlValid) {
} else if (role == Qt::DecorationRole && (!urlValid || duplicateUrl)) {
return m_errorIcon;
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
return value;
} else if (role == Qt::ToolTipRole && duplicateUrl) {
return tr("Duplicate URL");
} else if (role == Qt::ToolTipRole && !urlValid) {
return tr("Invalid URL");
}

return {};
}

void EntryURLModel::setEntryUrl(const QString& entryUrl)
{
m_entryUrl = entryUrl;
}

bool EntryURLModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!index.isValid() || role != Qt::EditRole || value.type() != QVariant::String || value.toString().isEmpty()) {
return false;
}

const int row = index.row();
const QString key = m_urls.at(row).first;
const QString oldValue = m_urls.at(row).second;
const auto row = index.row();
const auto key = m_urls.at(row).first;

if (EntryAttributes::isDefaultAttribute(key) || m_entryAttributes->containsValue(value.toString())) {
if (EntryAttributes::isDefaultAttribute(key)) {
return false;
}

Expand All @@ -113,7 +125,7 @@ QModelIndex EntryURLModel::indexByKey(const QString& key) const
}

if (row == -1) {
return QModelIndex();
return {};
} else {
return index(row, 0);
}
Expand All @@ -122,7 +134,7 @@ QModelIndex EntryURLModel::indexByKey(const QString& key) const
QString EntryURLModel::keyByIndex(const QModelIndex& index) const
{
if (!index.isValid()) {
return QString();
return {};
} else {
return m_urls.at(index.row()).first;
}
Expand All @@ -133,9 +145,9 @@ void EntryURLModel::updateAttributes()
clear();
m_urls.clear();

const QList<QString> attributesKeyList = m_entryAttributes->keys();
for (const QString& key : attributesKeyList) {
if (!EntryAttributes::isDefaultAttribute(key) && key.contains("KP2A_URL")) {
const auto attributesKeyList = m_entryAttributes->keys();
for (const auto& key : attributesKeyList) {
if (!EntryAttributes::isDefaultAttribute(key) && key.contains(BrowserService::ADDITIONAL_URL)) {
const auto value = m_entryAttributes->value(key);
m_urls.append(qMakePair(key, value));

Expand Down
6 changes: 5 additions & 1 deletion src/gui/entry/EntryURLModel.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2023 KeePassXC Team <team@keepassxc.org>
* Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
* 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
Expand All @@ -19,6 +19,7 @@
#ifndef KEEPASSXC_ENTRYURLMODEL_H
#define KEEPASSXC_ENTRYURLMODEL_H

#include "core/Entry.h"
#include <QStandardItemModel>
#include <QStyledItemDelegate>

Expand All @@ -43,8 +44,10 @@ class EntryURLModel : public QStandardItemModel

public:
explicit EntryURLModel(QObject* parent = nullptr);

void setEntryAttributes(EntryAttributes* entryAttributes);
void insertRow(const QString& key, const QString& value);
void setEntryUrl(const QString& entryUrl);
droidmonkey marked this conversation as resolved.
Show resolved Hide resolved
bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
QVariant data(const QModelIndex& index, int role) const override;
QModelIndex indexByKey(const QString& key) const;
Expand All @@ -57,6 +60,7 @@ private slots:
QList<QPair<QString, QString>> m_urls;
EntryAttributes* m_entryAttributes;
QIcon m_errorIcon;
QString m_entryUrl;
};

#endif // KEEPASSXC_ENTRYURLMODEL_H