CLI: do not display protected fields by default.

This commit is contained in:
louib 2019-10-28 13:27:29 -04:00 committed by Jonathan White
parent 98badfb4a2
commit f4d6b4d13a
4 changed files with 42 additions and 7 deletions

View File

@ -182,6 +182,10 @@ an error if no TOTP is configured for the entry.
Shows the named attributes. This option can be specified more than once, Shows the named attributes. This option can be specified more than once,
with each attribute shown one-per-line in the given order. If no attributes are with each attribute shown one-per-line in the given order. If no attributes are
specified and \fI-t\fP is not specified, a summary of the default attributes is given. specified and \fI-t\fP is not specified, a summary of the default attributes is given.
Protected attributes will be displayed in clear text if specified explicitly by this option.
.IP "-s, --show-protected"
Shows the protected attributes in clear text.
.IP "-t, --totp" .IP "-t, --totp"
Also shows the current TOTP, reporting an error if no TOTP is configured for Also shows the current TOTP, reporting an error if no TOTP is configured for

View File

@ -31,6 +31,11 @@ const QCommandLineOption Show::TotpOption = QCommandLineOption(QStringList() <<
<< "totp", << "totp",
QObject::tr("Show the entry's current TOTP.")); QObject::tr("Show the entry's current TOTP."));
const QCommandLineOption Show::ProtectedAttributesOption =
QCommandLineOption(QStringList() << "s"
<< "show-protected",
QObject::tr("Show the protected attributes in clear text."));
const QCommandLineOption Show::AttributesOption = QCommandLineOption( const QCommandLineOption Show::AttributesOption = QCommandLineOption(
QStringList() << "a" QStringList() << "a"
<< "attributes", << "attributes",
@ -46,6 +51,7 @@ Show::Show()
description = QObject::tr("Show an entry's information."); description = QObject::tr("Show an entry's information.");
options.append(Show::TotpOption); options.append(Show::TotpOption);
options.append(Show::AttributesOption); options.append(Show::AttributesOption);
options.append(Show::ProtectedAttributesOption);
positionalArguments.append({QString("entry"), QObject::tr("Name of the entry to show."), QString("")}); positionalArguments.append({QString("entry"), QObject::tr("Name of the entry to show."), QString("")});
} }
@ -57,6 +63,7 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
const QStringList args = parser->positionalArguments(); const QStringList args = parser->positionalArguments();
const QString& entryPath = args.at(1); const QString& entryPath = args.at(1);
bool showTotp = parser->isSet(Show::TotpOption); bool showTotp = parser->isSet(Show::TotpOption);
bool showProtectedAttributes = parser->isSet(Show::ProtectedAttributesOption);
QStringList attributes = parser->values(Show::AttributesOption); QStringList attributes = parser->values(Show::AttributesOption);
Entry* entry = database->rootGroup()->findEntryByPath(entryPath); Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
@ -78,16 +85,20 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
// Iterate over the attributes and output them line-by-line. // Iterate over the attributes and output them line-by-line.
bool sawUnknownAttribute = false; bool sawUnknownAttribute = false;
for (const QString& attribute : asConst(attributes)) { for (const QString& attributeName : asConst(attributes)) {
if (!entry->attributes()->contains(attribute)) { if (!entry->attributes()->contains(attributeName)) {
sawUnknownAttribute = true; sawUnknownAttribute = true;
errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attribute) << endl; errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attributeName) << endl;
continue; continue;
} }
if (showAttributeNames) { if (showAttributeNames) {
outputTextStream << attribute << ": "; outputTextStream << attributeName << ": ";
}
if (entry->attributes()->isProtected(attributeName) && showAttributeNames && !showProtectedAttributes) {
outputTextStream << "PROTECTED" << endl;
} else {
outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attributeName)) << endl;
} }
outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attribute)) << endl;
} }
if (showTotp) { if (showTotp) {

View File

@ -29,6 +29,7 @@ public:
static const QCommandLineOption TotpOption; static const QCommandLineOption TotpOption;
static const QCommandLineOption AttributesOption; static const QCommandLineOption AttributesOption;
static const QCommandLineOption ProtectedAttributesOption;
}; };
#endif // KEEPASSXC_SHOW_H #endif // KEEPASSXC_SHOW_H

View File

@ -1682,14 +1682,15 @@ void TestCli::testShow()
QCOMPARE(m_stdoutFile->readAll(), QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n" QByteArray("Title: Sample Entry\n"
"UserName: User Name\n" "UserName: User Name\n"
"Password: Password\n" "Password: PROTECTED\n"
"URL: http://www.somesite.com/\n" "URL: http://www.somesite.com/\n"
"Notes: Notes\n")); "Notes: Notes\n"));
qint64 pos = m_stdoutFile->pos(); qint64 pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"}); showCmd.execute({"show", "-s", m_dbFile->fileName(), "/Sample Entry"});
m_stdoutFile->seek(pos); m_stdoutFile->seek(pos);
m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n" QByteArray("Title: Sample Entry\n"
"UserName: User Name\n" "UserName: User Name\n"
@ -1697,6 +1698,17 @@ void TestCli::testShow()
"URL: http://www.somesite.com/\n" "URL: http://www.somesite.com/\n"
"Notes: Notes\n")); "Notes: Notes\n"));
pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a");
showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"});
m_stdoutFile->seek(pos);
QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n"
"UserName: User Name\n"
"Password: PROTECTED\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"));
pos = m_stdoutFile->pos(); pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"}); showCmd.execute({"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"});
@ -1704,6 +1716,13 @@ void TestCli::testShow()
m_stdoutFile->readLine(); // skip password prompt m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QByteArray("Sample Entry\n")); QCOMPARE(m_stdoutFile->readAll(), QByteArray("Sample Entry\n"));
pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Password", m_dbFile->fileName(), "/Sample Entry"});
m_stdoutFile->seek(pos);
m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QByteArray("Password\n"));
pos = m_stdoutFile->pos(); pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"}); showCmd.execute({"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"});