Page MenuHome GnuPG

passwordviewer.cpp
No OneTemporary

passwordviewer.cpp

// SPDX-FileCopyrightText: 2014-2023 Anne Jan Brouwer <brouwer@annejan.com>
// SPDX-FileCopyrightText: 2016-2017 tezeb <tezeb+github@outoftheblue.pl>
// SPDX-FileCopyrightText: 2018 Lukas Vogel <lukedirtwalker@gmail.com>
// SPDX-FileCopyrightText: 2018 Claudio Maradonna <penguyman@stronzi.org>
// SPDX-FileCopyrightText: 2019 Maciej S. Szmigiero <mail@maciej.szmigiero.name>
// SPDX-FileCopyrightText: 2023 g10 Code GmbH
// SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>
// SPDX-License-Identifier: GPL-3.0-or-later
#include "passwordviewer.h"
#include "clipboardhelper.h"
#include "passentry.h"
#include "qpushbuttonfactory.h"
#include "settings.h"
#include "util.h"
#include <QDialog>
#include <QFormLayout>
#include <QLabel>
#include <QMainWindow>
#include <QPushButton>
#include <QTextBrowser>
#include <QVBoxLayout>
#include <KLocalizedString>
#include <KPasswordLineEdit>
#include <KTitleWidget>
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
#include <Prison/Barcode>
#else
#include <Prison/AbstractBarcode>
#include <Prison/prison.h>
#endif
namespace
{
std::unique_ptr<QTextBrowser> createTextBrowserForNotes()
{
auto textBrowser = std::make_unique<QTextBrowser>();
if (Settings::isNoLineWrapping()) {
textBrowser->setLineWrapMode(QTextBrowser::NoWrap);
}
textBrowser->setOpenExternalLinks(true);
textBrowser->setContextMenuPolicy(Qt::DefaultContextMenu);
textBrowser->document()->setDocumentMargin(0);
return textBrowser;
}
}
PasswordViewer::PasswordViewer(ClipboardHelper *clipboardHelper, QWidget *parent)
: QWidget(parent)
, m_titleWidget(new KTitleWidget(this))
, m_clipboardHelper(clipboardHelper)
, m_contentLayout(new QFormLayout)
, m_copyPasswordNameButton(new QPushButton(QIcon::fromTheme(QStringLiteral("edit-copy-symbolic")), {}, this))
{
auto layout = new QVBoxLayout(this);
// Setup ui
m_copyPasswordNameButton->setAccessibleName(i18nc("@action:button", "Copy to clipboard"));
m_copyPasswordNameButton->setToolTip(i18nc("@info:tooltip", "Copy title to clipboard"));
auto titleLayout = new QHBoxLayout;
titleLayout->addWidget(m_titleWidget);
titleLayout->insertStretch(1);
titleLayout->addWidget(m_copyPasswordNameButton);
connect(m_copyPasswordNameButton, &QPushButton::clicked, this, [this]() {
m_clipboardHelper->copyTextToClipboard(m_titleWidget->text().trimmed());
});
layout->addLayout(titleLayout);
layout->addLayout(m_contentLayout);
setPanelTimer();
clearPanelTimer.setSingleShot(true);
connect(&clearPanelTimer, &QTimer::timeout, this, &PasswordViewer::clear);
}
void PasswordViewer::setPassEntry(const PassEntry &entry, const QString &content)
{
QString password = entry.password();
QString output = content;
m_clipboardHelper->setClippedText(password);
// first clear the current view:
clear();
m_titleWidget->setText(entry.name());
m_titleWidget->show();
m_copyPasswordNameButton->show();
// show what is needed:
if (!Settings::isDisplayAsIs()) {
if (!password.isEmpty()) {
// set the password, it is hidden if needed in addToGridLayout
addToGridLayout(i18n("Password:"), password);
}
const auto namedValues = entry.namedValues();
for (const auto &nv : namedValues) {
addToGridLayout(i18nc("Field label", "%1:", nv.name), nv.value);
}
output = entry.remainingDataForDisplay();
}
if (Settings::isUseAutoclearPanel()) {
clearPanelTimer.start();
}
if (!output.isEmpty()) {
output = output.toHtmlEscaped();
output.replace(Util::protocolRegex(), QStringLiteral(R"(<a href="\1">\1</a>)"));
output.replace(QLatin1Char('\n'), QStringLiteral("<br />"));
auto textBrowser = createTextBrowserForNotes();
textBrowser->setHtml(output);
m_contentLayout->addRow(new QLabel(i18nc("@label", "Notes:")), textBrowser.release());
}
}
void PasswordViewer::clearTemplateWidgets()
{
while (m_contentLayout->count() > 0) {
m_contentLayout->removeRow(m_contentLayout->rowCount() - 1);
}
}
void PasswordViewer::addToGridLayout(const QString &field, const QString &value)
{
QString trimmedField = field.trimmed();
QString trimmedValue = value.trimmed();
// Combine the Copy button and the line edit in one widget
auto rowLayout = new QHBoxLayout();
rowLayout->setContentsMargins(0, 2, 0, 2);
if (trimmedField == i18n("Password:")) {
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
auto *line = new KPasswordLineEdit();
line->setRevealPasswordMode(KPassword::RevealMode::Always);
line->setReadOnly(true);
line->setPassword(trimmedValue);
#else
auto *line = new QLineEdit();
line->setText(trimmedValue);
auto iconOn = QIcon::fromTheme(QStringLiteral("password-show-on"));
auto iconOff = QIcon::fromTheme(QStringLiteral("password-show-off"));
auto action = line->addAction(iconOn, QLineEdit::TrailingPosition);
action->setCheckable(true);
action->setText(i18n("Toggle password visibility"));
connect(action, &QAction::triggered, this, [line, action, iconOn, iconOff]() {
if (line->echoMode() == QLineEdit::Password) {
line->setEchoMode(QLineEdit::Normal);
action->setIcon(iconOff);
} else {
line->setEchoMode(QLineEdit::Password);
action->setIcon(iconOn);
}
});
#endif
line->setObjectName(trimmedField);
line->setContentsMargins(0, 0, 0, 0);
line->setEchoMode(QLineEdit::Password);
rowLayout->addWidget(line);
} else {
auto *line = new QLabel();
line->setOpenExternalLinks(true);
line->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
line->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum));
line->setObjectName(trimmedField);
trimmedValue.replace(Util::protocolRegex(), QStringLiteral(R"(<a href="\1">\1</a>)"));
line->setText(trimmedValue);
line->setContentsMargins(5, 0, 0, 0);
rowLayout->addWidget(line);
}
auto fieldName = trimmedField;
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
fieldName.removeLast(); // remove ':' from the end of the label
#else
fieldName.remove(fieldName.count() - 1, 1); // remove ':' from the end of the label
#endif
auto fieldLabel =
createPushButton(QIcon::fromTheme(QStringLiteral("edit-copy")), i18n("Copy '%1' to clipboard", fieldName), m_clipboardHelper, [this, trimmedValue] {
m_clipboardHelper->copyTextToClipboard(trimmedValue);
});
rowLayout->addWidget(fieldLabel.release());
auto qrButton =
createPushButton(QIcon::fromTheme(QStringLiteral("view-barcode-qr")), i18n("View '%1' QR Code", fieldName), m_clipboardHelper, [this, trimmedValue]() {
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
auto barcode = Prison::Barcode::create(Prison::QRCode);
#else
auto barcode = Prison::createBarcode(Prison::BarcodeType::QRCode);
#endif
if (!barcode) {
return;
}
barcode->setData(trimmedValue);
auto image = barcode->toImage(barcode->preferredSize(window()->devicePixelRatioF()));
QDialog popup(nullptr, Qt::Popup | Qt::FramelessWindowHint);
QVBoxLayout *layout = new QVBoxLayout;
QLabel *popupLabel = new QLabel();
layout->addWidget(popupLabel);
popupLabel->setPixmap(QPixmap::fromImage(image));
popupLabel->setScaledContents(true);
popupLabel->show();
popup.setLayout(layout);
popup.move(QCursor::pos());
popup.exec();
});
rowLayout->addWidget(qrButton.release());
// set into the layout
m_contentLayout->addRow(trimmedField, rowLayout);
}
/**
* @brief MainWindow::clearPanel hide the information from shoulder surfers
*/
void PasswordViewer::clear()
{
clearTemplateWidgets();
m_titleWidget->setText(QString{});
m_copyPasswordNameButton->hide();
}
void PasswordViewer::setPanelTimer()
{
clearPanelTimer.setInterval(1000 * Settings::getAutoclearPanelSeconds());
}

File Metadata

Mime Type
text/x-c
Expires
Sat, Nov 29, 7:11 AM (6 h, 26 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
91/37/c84b8fe114846fe26ab482e1e537

Event Timeline