diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 0e27f2060..1f7ab25d9 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -16,6 +16,8 @@ set(cli_SOURCES Clip.cpp Clip.h + Command.cpp + Command.h EntropyMeter.cpp EntropyMeter.h Extract.cpp diff --git a/src/cli/Clip.cpp b/src/cli/Clip.cpp index 70d97c0e2..7571bc194 100644 --- a/src/cli/Clip.cpp +++ b/src/cli/Clip.cpp @@ -21,7 +21,6 @@ #include "Clip.h" #include -#include #include #include #include @@ -32,30 +31,41 @@ #include "core/Group.h" #include "gui/Clipboard.h" +Clip::Clip() +{ + this->name = QString("clip"); + this->description = QObject::tr("Copy an entry's password to the clipboard."); +} + +Clip::~Clip() +{ +} + int Clip::execute(int argc, char** argv) { - QStringList arguments; - for (int i = 0; i < argc; ++i) { + // Skipping the first argument (keepassxc). + for (int i = 1; i < argc; ++i) { arguments << QString(argv[i]); } + QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "Copy a password to the clipboard")); - parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); - QCommandLineOption guiPrompt( - QStringList() << "g" - << "gui-prompt", - QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + parser.setApplicationDescription(this->description); + parser.addPositionalArgument("database", QObject::tr("Path of the database.")); + QCommandLineOption guiPrompt(QStringList() << "g" + << "gui-prompt", + QObject::tr("Use a GUI prompt unlocking the database.")); parser.addOption(guiPrompt); - parser.addPositionalArgument("entry", QCoreApplication::translate("main", "Name of the entry to clip.")); + parser.addPositionalArgument("entry", QObject::tr("Path of the entry to clip.")); parser.process(arguments); const QStringList args = parser.positionalArguments(); if (args.size() != 2) { QCoreApplication app(argc, argv); - parser.showHelp(EXIT_FAILURE); + out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli clip"); + return EXIT_FAILURE; } Database* db = nullptr; @@ -69,14 +79,20 @@ int Clip::execute(int argc, char** argv) if (!db) { return EXIT_FAILURE; } + return this->clipEntry(db, args.at(1)); +} - QString entryId = args.at(1); - Entry* entry = db->rootGroup()->findEntry(entryId); +int Clip::clipEntry(Database* database, QString entryPath) +{ + + QTextStream outputTextStream(stdout, QIODevice::WriteOnly); + Entry* entry = database->rootGroup()->findEntry(entryPath); if (!entry) { - qCritical("Entry %s not found.", qPrintable(entryId)); + qCritical("Entry %s not found.", qPrintable(entryPath)); return EXIT_FAILURE; } Clipboard::instance()->setText(entry->password()); return EXIT_SUCCESS; + } diff --git a/src/cli/Clip.h b/src/cli/Clip.h index cb72e4299..195976355 100644 --- a/src/cli/Clip.h +++ b/src/cli/Clip.h @@ -18,10 +18,15 @@ #ifndef KEEPASSXC_CLIP_H #define KEEPASSXC_CLIP_H -class Clip +#include "Command.h" + +class Clip : public Command { public: - static int execute(int argc, char** argv); + Clip(); + ~Clip(); + int execute(int argc, char** argv); + int clipEntry(Database* database, QString entryPath); }; #endif // KEEPASSXC_CLIP_H diff --git a/src/cli/Command.cpp b/src/cli/Command.cpp new file mode 100644 index 000000000..443208c7e --- /dev/null +++ b/src/cli/Command.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * 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 + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include + +#include "Command.h" + +#include "Clip.h" +#include "EntropyMeter.h" +#include "Extract.h" +#include "List.h" +#include "Merge.h" +#include "Show.h" + +QMap commands; + +Command::~Command() +{ +} + +int Command::execute(int, char**) +{ + return EXIT_FAILURE; +} + +QString Command::getDescriptionLine() +{ + + QString response = this->name; + QString space(" "); + QString spaces = space.repeated(15 - this->name.length()); + response = response.append(spaces); + response = response.append(this->description); + response = response.append("\n"); + return response; +} + +void populateCommands() +{ + if (commands.isEmpty()) { + commands.insert(QString("clip"), new Clip()); + commands.insert(QString("entropy-meter"), new EntropyMeter()); + commands.insert(QString("extract"), new Extract()); + commands.insert(QString("ls"), new List()); + commands.insert(QString("merge"), new Merge()); + commands.insert(QString("show"), new Show()); + } +} + +Command* Command::getCommand(QString commandName) +{ + populateCommands(); + if (commands.contains(commandName)) { + return commands[commandName]; + } + return nullptr; +} + +QList Command::getCommands() +{ + populateCommands(); + return commands.values(); +} diff --git a/src/cli/Command.h b/src/cli/Command.h new file mode 100644 index 000000000..adc4aad0d --- /dev/null +++ b/src/cli/Command.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * 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 + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_COMMAND_H +#define KEEPASSXC_COMMAND_H + +#include +#include +#include +#include + +#include "core/Database.h" + +class Command +{ +public: + virtual ~Command(); + virtual int execute(int argc, char** argv); + QString name; + QString description; + QString getDescriptionLine(); + + static QList getCommands(); + static Command* getCommand(QString commandName); +}; + +#endif // KEEPASSXC_COMMAND_H diff --git a/src/cli/EntropyMeter.cpp b/src/cli/EntropyMeter.cpp index 5c531af5e..62bd973f8 100644 --- a/src/cli/EntropyMeter.cpp +++ b/src/cli/EntropyMeter.cpp @@ -18,8 +18,8 @@ #include "EntropyMeter.h" #include -#include #include +#include #include /* For pre-compiled headers under windows */ @@ -29,6 +29,16 @@ #endif #endif +EntropyMeter::EntropyMeter() +{ + this->name = QString("entropy-meter"); + this->description = QObject::tr("Calculate password entropy."); +} + +EntropyMeter::~EntropyMeter() +{ +} + static void calculate(const char *pwd, int advanced) { double e; diff --git a/src/cli/EntropyMeter.h b/src/cli/EntropyMeter.h index d160115bf..b1508f172 100644 --- a/src/cli/EntropyMeter.h +++ b/src/cli/EntropyMeter.h @@ -18,10 +18,14 @@ #ifndef KEEPASSXC_ENTROPYMETER_H #define KEEPASSXC_ENTROPYMETER_H -class EntropyMeter +#include "Command.h" + +class EntropyMeter : public Command { public: - static int execute(int argc, char** argv); + EntropyMeter(); + ~EntropyMeter(); + int execute(int argc, char** argv); }; #endif // KEEPASSXC_ENTROPYMETER_H diff --git a/src/cli/Extract.cpp b/src/cli/Extract.cpp index b9433801c..0073acba5 100644 --- a/src/cli/Extract.cpp +++ b/src/cli/Extract.cpp @@ -26,25 +26,41 @@ #include #include +#include "cli/PasswordInput.h" #include "core/Database.h" #include "format/KeePass2Reader.h" #include "keys/CompositeKey.h" -#include "cli/PasswordInput.h" + +Extract::Extract() +{ + this->name = QString("extract"); + this->description = QObject::tr("Extract and print the content of a database."); +} + +Extract::~Extract() +{ +} int Extract::execute(int argc, char** argv) { + QStringList arguments; + // Skipping the first argument (keepassxc). + for (int i = 1; i < argc; ++i) { + arguments << QString(argv[i]); + } + QCoreApplication app(argc, argv); QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription( - QCoreApplication::translate("main", "Extract and print the content of a database.")); - parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database to extract.")); - parser.process(app); + parser.setApplicationDescription(this->description); + parser.addPositionalArgument("database", QObject::tr("Path of the database to extract.")); + parser.process(arguments); const QStringList args = parser.positionalArguments(); if (args.size() != 1) { - parser.showHelp(EXIT_FAILURE); + out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli extract"); + return EXIT_FAILURE; } out << "Insert the database password\n> "; diff --git a/src/cli/Extract.h b/src/cli/Extract.h index e1b0672ec..eadbb9e34 100644 --- a/src/cli/Extract.h +++ b/src/cli/Extract.h @@ -18,10 +18,14 @@ #ifndef KEEPASSXC_EXTRACT_H #define KEEPASSXC_EXTRACT_H -class Extract +#include "Command.h" + +class Extract : public Command { public: - static int execute(int argc, char** argv); + Extract(); + ~Extract(); + int execute(int argc, char** argv); }; #endif // KEEPASSXC_EXTRACT_H diff --git a/src/cli/List.cpp b/src/cli/List.cpp index de6bd5ef5..f3f22f6e3 100644 --- a/src/cli/List.cpp +++ b/src/cli/List.cpp @@ -26,43 +26,47 @@ #include #include -#include "gui/UnlockDatabaseDialog.h" #include "core/Database.h" #include "core/Entry.h" #include "core/Group.h" -#include "keys/CompositeKey.h" +#include "gui/UnlockDatabaseDialog.h" +List::List() +{ + this->name = QString("ls"); + this->description = QObject::tr("List database entries."); +} + +List::~List() +{ +} int List::execute(int argc, char** argv) { QStringList arguments; - for (int i = 0; i < argc; ++i) { + // Skipping the first argument (keepassxc). + for (int i = 1; i < argc; ++i) { arguments << QString(argv[i]); } + QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "List database entries.")); - parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); - parser.addPositionalArgument("group", - QCoreApplication::translate("main", "Path of the group to list. Default is /"), - QString("[group]")); - QCommandLineOption printUuidsOption( - QStringList() << "u" - << "print-uuids", - QCoreApplication::translate("main", "Print the UUIDs of the entries and groups.")); - parser.addOption(printUuidsOption); - QCommandLineOption guiPrompt( - QStringList() << "g" - << "gui-prompt", - QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + parser.setApplicationDescription(this->description); + parser.addPositionalArgument("database", QObject::tr("Path of the database.")); + parser.addPositionalArgument( + "group", QObject::tr("Path of the group to list. Default is /"), QString("[group]")); + QCommandLineOption guiPrompt(QStringList() << "g" + << "gui-prompt", + QObject::tr("Use a GUI prompt unlocking the database.")); parser.addOption(guiPrompt); parser.process(arguments); const QStringList args = parser.positionalArguments(); if (args.size() != 1 && args.size() != 2) { QCoreApplication app(argc, argv); - parser.showHelp(EXIT_FAILURE); + out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli ls"); + return EXIT_FAILURE; } Database* db = nullptr; @@ -78,17 +82,28 @@ int List::execute(int argc, char** argv) return EXIT_FAILURE; } - Group* group = db->rootGroup(); if (args.size() == 2) { - QString groupPath = args.at(1); - group = db->rootGroup()->findGroupByPath(groupPath); - if (group == nullptr) { - qCritical("Cannot find group %s.", qPrintable(groupPath)); - return EXIT_FAILURE; - } + return this->listGroup(db, args.at(1)); + } + return this->listGroup(db); +} + +int List::listGroup(Database* database, QString groupPath) +{ + QTextStream outputTextStream(stdout, QIODevice::WriteOnly); + if (groupPath.isEmpty()) { + outputTextStream << database->rootGroup()->print(); + outputTextStream.flush(); + return EXIT_SUCCESS; } - out << group->print(parser.isSet("print-uuids")); - out.flush(); + Group* group = database->rootGroup()->findGroupByPath(groupPath); + if (group == nullptr) { + qCritical("Cannot find group %s.", qPrintable(groupPath)); + return EXIT_FAILURE; + } + + outputTextStream << group->print(); + outputTextStream.flush(); return EXIT_SUCCESS; } diff --git a/src/cli/List.h b/src/cli/List.h index 18528bd78..cd9f8d1df 100644 --- a/src/cli/List.h +++ b/src/cli/List.h @@ -18,10 +18,15 @@ #ifndef KEEPASSXC_LIST_H #define KEEPASSXC_LIST_H -class List +#include "Command.h" + +class List : public Command { public: - static int execute(int argc, char** argv); + List(); + ~List(); + int execute(int argc, char** argv); + int listGroup(Database* database, QString groupPath = QString("")); }; #endif // KEEPASSXC_LIST_H diff --git a/src/cli/Merge.cpp b/src/cli/Merge.cpp index a179d69be..7567029c6 100644 --- a/src/cli/Merge.cpp +++ b/src/cli/Merge.cpp @@ -28,31 +28,39 @@ #include "core/Database.h" #include "gui/UnlockDatabaseDialog.h" +Merge::Merge() +{ + this->name = QString("merge"); + this->description = QObject::tr("Merge two databases."); +} + +Merge::~Merge() +{ +} + int Merge::execute(int argc, char** argv) { - QStringList arguments; - for (int i = 0; i < argc; ++i) { + // Skipping the first argument (keepassxc). + for (int i = 1; i < argc; ++i) { arguments << QString(argv[i]); } + QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "Merge two databases.")); - parser.addPositionalArgument("database1", - QCoreApplication::translate("main", "Path of the database to merge into.")); - parser.addPositionalArgument("database2", - QCoreApplication::translate("main", "Path of the database to merge from.")); + parser.setApplicationDescription(this->description); + parser.addPositionalArgument("database1", QObject::tr("Path of the database to merge into.")); + parser.addPositionalArgument("database2", QObject::tr("Path of the database to merge from.")); QCommandLineOption samePasswordOption( QStringList() << "s" << "same-password", - QCoreApplication::translate("main", "Use the same password for both database files.")); + QObject::tr("Use the same password for both database files.")); - QCommandLineOption guiPrompt( - QStringList() << "g" - << "gui-prompt", - QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + QCommandLineOption guiPrompt(QStringList() << "g" + << "gui-prompt", + QObject::tr("Use a GUI prompt unlocking the database.")); parser.addOption(guiPrompt); parser.addOption(samePasswordOption); @@ -61,7 +69,8 @@ int Merge::execute(int argc, char** argv) const QStringList args = parser.positionalArguments(); if (args.size() != 2) { QCoreApplication app(argc, argv); - parser.showHelp(EXIT_FAILURE); + out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli merge"); + return EXIT_FAILURE; } Database* db1; @@ -100,5 +109,4 @@ int Merge::execute(int argc, char** argv) out << "Successfully merged the database files.\n"; return EXIT_SUCCESS; - } diff --git a/src/cli/Merge.h b/src/cli/Merge.h index 95da7af81..bb121f579 100644 --- a/src/cli/Merge.h +++ b/src/cli/Merge.h @@ -18,10 +18,14 @@ #ifndef KEEPASSXC_MERGE_H #define KEEPASSXC_MERGE_H -class Merge +#include "Command.h" + +class Merge : public Command { public: - static int execute(int argc, char** argv); + Merge(); + ~Merge(); + int execute(int argc, char** argv); }; #endif // KEEPASSXC_MERGE_H diff --git a/src/cli/Show.cpp b/src/cli/Show.cpp index c212a9d61..55da87515 100644 --- a/src/cli/Show.cpp +++ b/src/cli/Show.cpp @@ -28,43 +28,64 @@ #include "core/Database.h" #include "core/Entry.h" #include "core/Group.h" -#include "keys/CompositeKey.h" -#include "cli/PasswordInput.h" + +Show::Show() +{ + this->name = QString("show"); + this->description = QObject::tr("Show an entry's information."); +} + +Show::~Show() +{ +} int Show::execute(int argc, char** argv) { + QStringList arguments; + // Skipping the first argument (keepassxc). + for (int i = 1; i < argc; ++i) { + arguments << QString(argv[i]); + } + QCoreApplication app(argc, argv); QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "Show a password.")); - parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); - parser.addPositionalArgument("entry", QCoreApplication::translate("main", "Name of the entry to show.")); - parser.process(app); + parser.setApplicationDescription(this->description); + parser.addPositionalArgument("database", QObject::tr("Path of the database.")); + parser.addPositionalArgument("entry", QObject::tr("Name of the entry to show.")); + parser.process(arguments); const QStringList args = parser.positionalArguments(); if (args.size() != 2) { - parser.showHelp(EXIT_FAILURE); + out << parser.helpText().replace("keepassxc-cli", "keepassxc-cli show"); + return EXIT_FAILURE; } - out << "Insert the database password\n> "; - out.flush(); - - QString line = PasswordInput::getPassword(); - CompositeKey key = CompositeKey::readFromLine(line); - - Database* db = Database::openDatabaseFile(args.at(0), key); + Database* db = Database::unlockFromStdin(args.at(0)); if (db == nullptr) { return EXIT_FAILURE; } - QString entryId = args.at(1); - Entry* entry = db->rootGroup()->findEntry(entryId); + return this->showEntry(db, args.at(1)); +} + +int Show::showEntry(Database* database, QString entryPath) +{ + + QTextStream inputTextStream(stdin, QIODevice::ReadOnly); + QTextStream outputTextStream(stdout, QIODevice::WriteOnly); + + Entry* entry = database->rootGroup()->findEntry(entryPath); if (!entry) { - qCritical("Entry %s not found.", qPrintable(entryId)); + qCritical("Could not find entry with path %s.", qPrintable(entryPath)); return EXIT_FAILURE; } - out << entry->password() << "\n"; + outputTextStream << " title: " << entry->title() << endl; + outputTextStream << "username: " << entry->username() << endl; + outputTextStream << "password: " << entry->password() << endl; + outputTextStream << " URL: " << entry->url() << endl; + outputTextStream << " Notes: " << entry->notes() << endl; return EXIT_SUCCESS; } diff --git a/src/cli/Show.h b/src/cli/Show.h index 630b18f80..b10e6bf0a 100644 --- a/src/cli/Show.h +++ b/src/cli/Show.h @@ -18,10 +18,15 @@ #ifndef KEEPASSXC_SHOW_H #define KEEPASSXC_SHOW_H -class Show +#include "Command.h" + +class Show : public Command { public: - static int execute(int argc, char** argv); + Show(); + ~Show(); + int execute(int argc, char** argv); + int showEntry(Database* database, QString entryPath); }; #endif // KEEPASSXC_SHOW_H diff --git a/src/cli/keepassxc-cli.cpp b/src/cli/keepassxc-cli.cpp index 18bb224ec..37210b6a1 100644 --- a/src/cli/keepassxc-cli.cpp +++ b/src/cli/keepassxc-cli.cpp @@ -22,12 +22,7 @@ #include #include -#include -#include -#include -#include -#include -#include +#include #include "config-keepassx.h" #include "core/Tools.h" @@ -48,6 +43,7 @@ int main(int argc, char** argv) return EXIT_FAILURE; } + QTextStream out(stdout); QStringList arguments; for (int i = 0; i < argc; ++i) { arguments << QString(argv[i]); @@ -55,16 +51,13 @@ int main(int argc, char** argv) QCommandLineParser parser; QString description("KeePassXC command line interface."); - description = description.append(QString("\n\nAvailable commands:")); - description = description.append(QString("\n clip\t\tCopy a password to the clipboard.")); - description = description.append(QString("\n extract\tExtract and print the content of a database.")); - description = description.append(QString("\n entropy-meter\tCalculate password entropy.")); - description = description.append(QString("\n list\t\tList database entries.")); - description = description.append(QString("\n merge\t\tMerge two databases.")); - description = description.append(QString("\n show\t\tShow a password.")); - parser.setApplicationDescription(QCoreApplication::translate("main", qPrintable(description))); + description = description.append(QObject::tr("\n\nAvailable commands:\n")); + for (Command* command : Command::getCommands()) { + description = description.append(command->getDescriptionLine()); + } + parser.setApplicationDescription(description); - parser.addPositionalArgument("command", QCoreApplication::translate("main", "Name of the command to execute.")); + parser.addPositionalArgument("command", QObject::tr("Name of the command to execute.")); parser.addHelpOption(); parser.addVersionOption(); @@ -78,50 +71,16 @@ int main(int argc, char** argv) app.setApplicationVersion(KEEPASSX_VERSION); if (parser.isSet("version")) { // Switch to parser.showVersion() when available (QT 5.4). - QTextStream out(stdout); - out << KEEPASSX_VERSION << "\n"; - out.flush(); + out << KEEPASSX_VERSION << endl; return EXIT_SUCCESS; } parser.showHelp(); } QString commandName = parser.positionalArguments().at(0); + Command* command = Command::getCommand(commandName); - int exitCode = EXIT_FAILURE; - - if (commandName == "clip") { - // Removing the first cli argument before dispatching. - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli clip"); - exitCode = Clip::execute(argc, argv); - } else if (commandName == "entropy-meter") { - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli entropy-meter"); - exitCode = EntropyMeter::execute(argc, argv); - } else if (commandName == "extract") { - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli extract"); - exitCode = Extract::execute(argc, argv); - } else if (commandName == "list") { - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli list"); - exitCode = List::execute(argc, argv); - } else if (commandName == "merge") { - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli merge"); - exitCode = Merge::execute(argc, argv); - } else if (commandName == "show") { - ++argv; - --argc; - argv[0] = const_cast("keepassxc-cli show"); - exitCode = Show::execute(argc, argv); - } else { + if (command == nullptr) { qCritical("Invalid command %s.", qPrintable(commandName)); QCoreApplication app(argc, argv); app.setApplicationVersion(KEEPASSX_VERSION); @@ -130,6 +89,8 @@ int main(int argc, char** argv) parser.showHelp(EXIT_FAILURE); } + int exitCode = command->execute(argc, argv); + #if defined(WITH_ASAN) && defined(WITH_LSAN) // do leak check here to prevent massive tail of end-of-process leak errors from third-party libraries __lsan_do_leak_check(); diff --git a/src/core/Group.cpp b/src/core/Group.cpp index edbed947e..008755510 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -578,7 +578,7 @@ Group* Group::findGroupByPath(QString groupPath, QString basePath) } -QString Group::print(bool printUuids, QString baseName, int depth) +QString Group::print(bool recursive, int depth) { QString response; @@ -590,21 +590,14 @@ QString Group::print(bool printUuids, QString baseName, int depth) } for (Entry* entry : entries()) { - response += indentation + entry->title(); - if (printUuids) { - response += " " + entry->uuid().toHex(); - } - response += "\n"; + response += indentation + entry->title() + "\n"; } for (Group* innerGroup : children()) { - QString newBaseName = baseName + innerGroup->name() + "/"; - response += indentation + newBaseName; - if (printUuids) { - response += " " + innerGroup->uuid().toHex(); + response += indentation + innerGroup->name() + "/\n"; + if (recursive) { + response += innerGroup->print(recursive, depth + 1); } - response += "\n"; - response += innerGroup->print(printUuids, newBaseName, depth + 1); } return response; diff --git a/src/core/Group.h b/src/core/Group.h index f8c976eeb..10313b488 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -125,7 +125,7 @@ public: Group* clone(Entry::CloneFlags entryFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo) const; void copyDataFrom(const Group* other); void merge(const Group* other); - QString print(bool printUuids = false, QString baseName = QString(""), int depth = 0); + QString print(bool recursive = false, int depth = 0); signals: void dataChanged(Group* group); diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index 50997dcca..14956618e 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -728,10 +728,6 @@ void TestGroup::testPrint() output = db->rootGroup()->print(); QCOMPARE(output, QString("entry1\n")); - output = db->rootGroup()->print(true); - QCOMPARE(output, QString("entry1 " + entry1->uuid().toHex() + "\n")); - - Group* group1 = new Group(); group1->setName("group1"); @@ -746,11 +742,16 @@ void TestGroup::testPrint() output = db->rootGroup()->print(); QVERIFY(output.contains(QString("entry1\n"))); QVERIFY(output.contains(QString("group1/\n"))); - QVERIFY(output.contains(QString(" entry2\n"))); + QVERIFY(!output.contains(QString(" entry2\n"))); output = db->rootGroup()->print(true); - QVERIFY(output.contains(QString("entry1 " + entry1->uuid().toHex() + "\n"))); - QVERIFY(output.contains(QString("group1/ " + group1->uuid().toHex() + "\n"))); - QVERIFY(output.contains(QString(" entry2 " + entry2->uuid().toHex() + "\n"))); + QVERIFY(output.contains(QString("entry1\n"))); + QVERIFY(output.contains(QString("group1/\n"))); + QVERIFY(output.contains(QString(" entry2\n"))); + + output = group1->print(); + QVERIFY(!output.contains(QString("group1/\n"))); + QVERIFY(output.contains(QString("entry2\n"))); + delete db; }