Skip to content

Commit

Permalink
Adding top-level fields to CLI commands
Browse files Browse the repository at this point in the history
The top-level fields are currently not accessible from the CLI, which
makes it impossible to select entries or groups based on the UUID.
There are other top-level fields I believe, like the expiry date, but
I only added the two most critical fields for now. I also considered
defining the constants in `Entry` instead of `EntryAttributes`, because
they are not attributes per se. I'm not sure which choice is better tbh.
  • Loading branch information
louib committed Aug 4, 2022
1 parent a6d3f97 commit 09df862
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/cli/Clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<

found = true;
value = entry->totp();
} else if (Utils::EntryFieldNames.contains(selectedAttribute)) {
value = Utils::getTopLevelField(entry, selectedAttribute);
found = true;
} else {
QStringList attrs = Utils::findAttributes(*entry->attributes(), selectedAttribute);
if (attrs.size() > 1) {
Expand Down
11 changes: 11 additions & 0 deletions src/cli/Show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,22 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
bool showDefaultAttributes = attributes.isEmpty() && !showTotp;
if (showDefaultAttributes) {
attributes = EntryAttributes::DefaultAttributes;
for (QString fieldName : Utils::EntryFieldNames) {
attributes.append(fieldName);
}
}

// Iterate over the attributes and output them line-by-line.
bool encounteredError = false;
for (const QString& attributeName : asConst(attributes)) {
if (Utils::EntryFieldNames.contains(attributeName)) {
if (showDefaultAttributes) {
out << attributeName << ": ";
}
out << Utils::getTopLevelField(entry, attributeName) << endl;
continue;
}

QStringList attrs = Utils::findAttributes(*entry->attributes(), attributeName);
if (attrs.isEmpty()) {
encounteredError = true;
Expand Down
12 changes: 12 additions & 0 deletions src/cli/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "Utils.h"

#include "core/Database.h"
#include "core/Entry.h"
#include "core/EntryAttributes.h"
#include "keys/FileKey.h"
#ifdef WITH_XC_YUBIKEY
Expand Down Expand Up @@ -368,6 +369,17 @@ namespace Utils
return result;
}

QString getTopLevelField(const Entry* entry, const QString& fieldName)
{
if (fieldName == UuidFieldName) {
return entry->uuid().toString();
}
if (fieldName == TagsFieldName) {
return entry->tags();
}
return QString("");
}

QStringList findAttributes(const EntryAttributes& attributes, const QString& name)
{
QStringList result;
Expand Down
9 changes: 9 additions & 0 deletions src/cli/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

class CompositeKey;
class Database;
class Entry;
class EntryAttributes;
class FileKey;
class PasswordKey;
Expand All @@ -33,6 +34,10 @@ namespace Utils
extern QTextStream STDIN;
extern QTextStream DEVNULL;

static const QString UuidFieldName = "Uuid";
static const QString TagsFieldName = "Tags";
static const QStringList EntryFieldNames(QStringList() << UuidFieldName << TagsFieldName);

void setDefaultTextStreams();

void setStdinEcho(bool enable);
Expand All @@ -55,6 +60,10 @@ namespace Utils
* (case-insensitive).
*/
QStringList findAttributes(const EntryAttributes& attributes, const QString& name);
/**
* Get the value of a top-level Entry field using its name.
*/
QString getTopLevelField(const Entry* entry, const QString& fieldName);
}; // namespace Utils

#endif // KEEPASSXC_UTILS_H
1 change: 0 additions & 1 deletion src/core/EntryAttributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ const QString EntryAttributes::URLKey = "URL";
const QString EntryAttributes::NotesKey = "Notes";
const QStringList EntryAttributes::DefaultAttributes(QStringList()
<< TitleKey << UserNameKey << PasswordKey << URLKey << NotesKey);

const QString EntryAttributes::WantedFieldGroupName = "WantedField";
const QString EntryAttributes::SearchInGroupName = "SearchIn";
const QString EntryAttributes::SearchTextGroupName = "SearchText";
Expand Down
25 changes: 22 additions & 3 deletions tests/TestCli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,11 @@ void TestCli::testClip()
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "-a", "username"});
QTRY_COMPARE(clipboard->text(), QString("User Name"));

// Uuid (top-level field)
setInput("a");
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "-a", "Uuid"});
QTRY_COMPARE(clipboard->text(), QString("{9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}"));

// TOTP
setInput("a");
execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "--totp"});
Expand Down Expand Up @@ -1937,7 +1942,9 @@ void TestCli::testShow()
"UserName: User Name\n"
"Password: PROTECTED\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"));
"Notes: Notes\n"
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
"Tags: \n"));

setInput("a");
execCmd(showCmd, {"show", "-s", m_dbFile->fileName(), "/Sample Entry"});
Expand All @@ -1946,7 +1953,9 @@ void TestCli::testShow()
"UserName: User Name\n"
"Password: Password\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"));
"Notes: Notes\n"
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
"Tags: \n"));

setInput("a");
execCmd(showCmd, {"show", m_dbFile->fileName(), "-q", "/Sample Entry"});
Expand All @@ -1956,7 +1965,9 @@ void TestCli::testShow()
"UserName: User Name\n"
"Password: PROTECTED\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"));
"Notes: Notes\n"
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
"Tags: \n"));

setInput("a");
execCmd(showCmd, {"show", m_dbFile->fileName(), "--show-attachments", "/Sample Entry"});
Expand All @@ -1968,6 +1979,8 @@ void TestCli::testShow()
"Password: PROTECTED\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"
"Uuid: {9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"
"Tags: \n"
"\n"
"Attachments:\n"
" Sample attachment.txt (15.0 B)\n"));
Expand All @@ -1982,6 +1995,8 @@ void TestCli::testShow()
"Password: PROTECTED\n"
"URL: https://www.bank.com\n"
"Notes: Important note\n"
"Uuid: {20b183fd-6878-4506-a50b-06d30792aa10}\n"
"Tags: \n"
"\n"
"No attachments present.\n"));

Expand All @@ -1993,6 +2008,10 @@ void TestCli::testShow()
execCmd(showCmd, {"show", "-a", "Password", m_dbFile->fileName(), "/Sample Entry"});
QCOMPARE(m_stdout->readAll(), QByteArray("Password\n"));

setInput("a");
execCmd(showCmd, {"show", "-a", "Uuid", m_dbFile->fileName(), "/Sample Entry"});
QCOMPARE(m_stdout->readAll(), QByteArray("{9f4544c2-ab00-c74a-8a1a-6eaf26cf57e9}\n"));

setInput("a");
execCmd(showCmd, {"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"});
QCOMPARE(m_stdout->readAll(),
Expand Down

0 comments on commit 09df862

Please sign in to comment.