From 8a7be101e443a9d85b77da1ebdd74db1811b8894 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sun, 18 Apr 2021 16:11:57 -0400 Subject: [PATCH] CLI Improvements * Fix #6001 - only use `--notes` in Add/Edit commands to prevent clash with password generator option `-n`. * Fix #6119 - Send Unicode to clip command; Windows only understands UTF-16 encoding. * Fix #6128 - `clip` command will default to clearing the clipboard after 10 seconds. To disable clearing set timeout to 0. --- docs/man/keepassxc-cli.1.adoc | 4 ++-- src/cli/Add.cpp | 6 ++--- src/cli/Clip.cpp | 44 +++++++++++++++++----------------- src/cli/Utils.cpp | 9 ++++++- tests/TestCli.cpp | 36 ++++++++++++++-------------- tests/data/NewDatabase2.kdbx | Bin 8350 -> 10750 bytes 6 files changed, 52 insertions(+), 47 deletions(-) diff --git a/docs/man/keepassxc-cli.1.adoc b/docs/man/keepassxc-cli.1.adoc index d3aba6120..906e45e05 100644 --- a/docs/man/keepassxc-cli.1.adoc +++ b/docs/man/keepassxc-cli.1.adoc @@ -45,7 +45,7 @@ It provides the ability to query and modify the entries of a KeePass database, d If no attribute name is specified using the *-a* option, the password is copied. If multiple entries with the same name exist in different groups, only the attribute for the first one is copied. For copying the attribute of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. - Optionally, a timeout in seconds can be specified to automatically clear the clipboard. + Optionally, a timeout in seconds can be specified to automatically clear the clipboard, the default timeout is 10 seconds, set to 0 to disable. *close*:: In interactive mode, closes the currently opened database (see *open*). @@ -182,7 +182,7 @@ The same password generation options as documented for the generate command can *--url* <__url__>:: Specifies the URL of the entry. -*-n*, *--notes* <__notes__>:: +*--notes* <__notes__>:: Specifies the notes of the entry. *-p*, *--password-prompt*:: diff --git a/src/cli/Add.cpp b/src/cli/Add.cpp index 2f4f14d69..6ff4fa36a 100644 --- a/src/cli/Add.cpp +++ b/src/cli/Add.cpp @@ -30,10 +30,8 @@ const QCommandLineOption Add::UsernameOption = QCommandLineOption(QStringList() const QCommandLineOption Add::UrlOption = QCommandLineOption(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL")); -const QCommandLineOption Add::NotesOption = QCommandLineOption(QStringList() << "n" - << "notes", - QObject::tr("Notes for the entry."), - QObject::tr("Notes")); +const QCommandLineOption Add::NotesOption = + QCommandLineOption(QStringList() << "notes", QObject::tr("Notes for the entry."), QObject::tr("Notes")); const QCommandLineOption Add::PasswordPromptOption = QCommandLineOption(QStringList() << "p" diff --git a/src/cli/Clip.cpp b/src/cli/Clip.cpp index 1096d4ff6..10865092f 100644 --- a/src/cli/Clip.cpp +++ b/src/cli/Clip.cpp @@ -22,6 +22,8 @@ #include "core/Group.h" #include "core/Tools.h" +#define CLI_DEFAULT_CLIP_TIMEOUT 10 + const QCommandLineOption Clip::AttributeOption = QCommandLineOption( QStringList() << "a" << "attribute", @@ -50,7 +52,10 @@ Clip::Clip() positionalArguments.append( {QString("entry"), QObject::tr("Path of the entry to clip.", "clip = copy to clipboard"), QString("")}); optionalArguments.append( - {QString("timeout"), QObject::tr("Timeout in seconds before clearing the clipboard."), QString("[timeout]")}); + {QString("timeout"), + QObject::tr("Timeout before clearing the clipboard (default is %1 seconds, set to 0 for unlimited).") + .arg(CLI_DEFAULT_CLIP_TIMEOUT), + QString("[timeout]")}); } int Clip::executeWithDatabase(QSharedPointer database, QSharedPointer parser) @@ -59,13 +64,18 @@ int Clip::executeWithDatabase(QSharedPointer database, QSharedPointer< auto& err = Utils::STDERR; const QStringList args = parser->positionalArguments(); - QString bestEntryPath; - QString timeout; + auto timeout = CLI_DEFAULT_CLIP_TIMEOUT; if (args.size() == 3) { - timeout = args.at(2); + bool ok; + timeout = args.at(2).toInt(&ok); + if (!ok) { + err << QObject::tr("Invalid timeout value %1.").arg(args.at(2)) << endl; + return EXIT_FAILURE; + } } + QString entryPath; if (parser->isSet(Clip::BestMatchOption)) { QStringList results = database->rootGroup()->locate(args.at(1)); if (results.count() > 1) { @@ -75,24 +85,14 @@ int Clip::executeWithDatabase(QSharedPointer database, QSharedPointer< } return EXIT_FAILURE; } else { - bestEntryPath = (results.isEmpty()) ? args.at(1) : results[0]; - out << QObject::tr("Used matching entry: %1").arg(bestEntryPath) << endl; + entryPath = (results.isEmpty()) ? args.at(1) : results[0]; + out << QObject::tr("Used matching entry: %1").arg(entryPath) << endl; } } else { - bestEntryPath = args.at(1); + entryPath = args.at(1); } - const QString& entryPath = bestEntryPath; - - int timeoutSeconds = 0; - if (!timeout.isEmpty() && timeout.toInt() <= 0) { - err << QObject::tr("Invalid timeout value %1.").arg(timeout) << endl; - return EXIT_FAILURE; - } else if (!timeout.isEmpty()) { - timeoutSeconds = timeout.toInt(); - } - - Entry* entry = database->rootGroup()->findEntryByPath(entryPath); + auto* entry = database->rootGroup()->findEntryByPath(entryPath); if (!entry) { err << QObject::tr("Entry %1 not found.").arg(entryPath) << endl; return EXIT_FAILURE; @@ -140,17 +140,17 @@ int Clip::executeWithDatabase(QSharedPointer database, QSharedPointer< out << QObject::tr("Entry's \"%1\" attribute copied to the clipboard!").arg(selectedAttribute) << endl; - if (!timeoutSeconds) { + if (timeout <= 0) { return exitCode; } QString lastLine = ""; - while (timeoutSeconds > 0) { + while (timeout > 0) { out << '\r' << QString(lastLine.size(), ' ') << '\r'; - lastLine = QObject::tr("Clearing the clipboard in %1 second(s)…", "", timeoutSeconds).arg(timeoutSeconds); + lastLine = QObject::tr("Clearing the clipboard in %1 second(s)...", "", timeout).arg(timeout); out << lastLine << flush; Tools::sleep(1000); - --timeoutSeconds; + --timeout; } Utils::clipText(""); out << '\r' << QString(lastLine.size(), ' ') << '\r'; diff --git a/src/cli/Utils.cpp b/src/cli/Utils.cpp index b1c6ca645..44ed10c56 100644 --- a/src/cli/Utils.cpp +++ b/src/cli/Utils.cpp @@ -308,7 +308,14 @@ namespace Utils continue; } - if (clipProcess->write(text.toLatin1()) == -1) { +#ifdef Q_OS_WIN + // Windows clip command only understands Unicode written as UTF-16 + auto data = QByteArray::fromRawData(reinterpret_cast(text.utf16()), text.size() * 2); + if (clipProcess->write(data) == -1) { +#else + // Other platforms understand UTF-8 + if (clipProcess->write(text.toUtf8()) == -1) { +#endif qDebug("Unable to write to process : %s", qPrintable(clipProcess->errorString())); } clipProcess->waitForBytesWritten(); diff --git a/tests/TestCli.cpp b/tests/TestCli.cpp index b01e9576e..8a14cb88b 100644 --- a/tests/TestCli.cpp +++ b/tests/TestCli.cpp @@ -284,7 +284,7 @@ void TestCli::testAdd() "-g", "-L", "20", - "-n", + "--notes", "some notes", m_dbFile->fileName(), "/newuser-entry"}); @@ -360,7 +360,7 @@ void TestCli::testAdd() QVERIFY(!defaultPasswordClassesRegex.match(entry->password()).hasMatch()); setInput("a"); - execCmd(addCmd, {"add", "-u", "newuser5", "-n", "test\\nnew line", m_dbFile->fileName(), "/newuser-entry5"}); + execCmd(addCmd, {"add", "-u", "newuser5", "--notes", "test\\nnew line", m_dbFile->fileName(), "/newuser-entry5"}); m_stderr->readLine(); // skip password prompt QCOMPARE(m_stderr->readAll(), QByteArray("")); QCOMPARE(m_stdout->readAll(), QByteArray("Successfully added entry newuser-entry5.\n")); @@ -446,7 +446,7 @@ void TestCli::testClip() // Password setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry"}); + execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0"}); QString errorOutput(m_stderr->readAll()); if (QProcessEnvironment::systemEnvironment().contains("WAYLAND_DISPLAY")) { @@ -465,22 +465,26 @@ void TestCli::testClip() // Quiet option setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "-q"}); + execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "-q"}); QCOMPARE(m_stderr->readAll(), QByteArray()); QCOMPARE(m_stdout->readAll(), QByteArray()); QTRY_COMPARE(clipboard->text(), QString("Password")); // Username setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "-a", "username"}); + execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "-a", "username"}); QTRY_COMPARE(clipboard->text(), QString("User Name")); // TOTP setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "--totp"}); - + execCmd(clipCmd, {"clip", m_dbFile->fileName(), "/Sample Entry", "0", "--totp"}); QTRY_VERIFY(isTotp(clipboard->text())); + // Test Unicode + setInput("a"); + execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "/General/Unicode", "0", "-a", "username"}); + QTRY_COMPARE(clipboard->text(), QString(R"(¯\_(ツ)_/¯)")); + // Password with timeout setInput("a"); // clang-format off @@ -505,35 +509,31 @@ void TestCli::testClip() future.waitForFinished(); - setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "--totp", "/Sample Entry", "0"}); - QVERIFY(m_stderr->readAll().contains("Invalid timeout value 0.\n")); - setInput("a"); execCmd(clipCmd, {"clip", m_dbFile->fileName(), "--totp", "/Sample Entry", "bleuh"}); QVERIFY(m_stderr->readAll().contains("Invalid timeout value bleuh.\n")); setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "--totp", "/Sample Entry"}); + execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "--totp", "/Sample Entry", "0"}); QVERIFY(m_stderr->readAll().contains("Entry with path /Sample Entry has no TOTP set up.\n")); setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile->fileName(), "-a", "TESTAttribute1", "/Sample Entry"}); + execCmd(clipCmd, {"clip", m_dbFile->fileName(), "-a", "TESTAttribute1", "/Sample Entry", "0"}); QVERIFY(m_stderr->readAll().contains("ERROR: attribute TESTAttribute1 is ambiguous")); setInput("a"); - execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "--attribute", "Username", "--totp", "/Sample Entry"}); + execCmd(clipCmd, {"clip", m_dbFile2->fileName(), "--attribute", "Username", "--totp", "/Sample Entry", "0"}); QVERIFY(m_stderr->readAll().contains("ERROR: Please specify one of --attribute or --totp, not both.\n")); // Best option setInput("a"); - execCmd(clipCmd, {"clip", m_dbFileMulti->fileName(), "Multi", "-b"}); + execCmd(clipCmd, {"clip", m_dbFileMulti->fileName(), "Multi", "0", "-b"}); QByteArray errorChoices = m_stderr->readAll(); QVERIFY(errorChoices.contains("Multi Entry 1")); QVERIFY(errorChoices.contains("Multi Entry 2")); setInput("a"); - execCmd(clipCmd, {"clip", m_dbFileMulti->fileName(), "Entry 2", "-b"}); + execCmd(clipCmd, {"clip", m_dbFileMulti->fileName(), "Entry 2", "0", "-b"}); QTRY_COMPARE(clipboard->text(), QString("Password2")); } @@ -750,7 +750,7 @@ void TestCli::testEdit() "newuser", "--url", "https://otherurl.example.com/", - "-n", + "--notes", "newnotes", "-t", "newtitle", @@ -825,7 +825,7 @@ void TestCli::testEdit() // with line break in notes setInput("a"); - execCmd(editCmd, {"edit", m_dbFile->fileName(), "-n", "testing\\nline breaks", "/evennewertitle"}); + execCmd(editCmd, {"edit", m_dbFile->fileName(), "--notes", "testing\\nline breaks", "/evennewertitle"}); db = readDatabase(); entry = db->rootGroup()->findEntryByPath("/evennewertitle"); QVERIFY(entry); diff --git a/tests/data/NewDatabase2.kdbx b/tests/data/NewDatabase2.kdbx index 4e77724c7e8cfdf22bcd951ccfcaa4ae7f49d460..2ff491cc70ea87b77d0ae3f5d062819e3edff8f0 100644 GIT binary patch literal 10750 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 H_$CGbEb8x@