diff --git a/README.md b/README.md index 2390972..f6e66ff 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,18 @@ keyring](https://specifications.freedesktop.org/secret-service/latest/) using Usage ----- -With no arguments, all unlocked collections and items are shown, without secrets: +With no arguments, all unlocked collections and items are shown, without attributes or +secrets: lssecrets -To show secrets, use the argument `--secrets`: +To show item attributes, use the argument `--detail=3`: - lssecrets --secrets + lssecrets --detail=3 + +To show item attributes and secrets, use the argument `--detail=4`: + + lssecrets --detail=4 If there are collections or items locked, use the option `--unlock` to unlock everything: @@ -23,7 +28,7 @@ If there are collections or items locked, use the option `--unlock` to unlock ev Both options can be combined, to unlock and show the secrets: - lssecrets --secrets --unlock + lssecrets --detail=4 --unlock Dependencies diff --git a/configure.ac b/configure.ac index e45d31a..ed500d4 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.71]) AC_INIT([lssecrets], - [1.0], + [1.1], [https://github.com/dkosmari/lssecrets/issues], [lssecrets], [https://github.com/dkosmari/lssecrets]) diff --git a/main.cpp b/main.cpp index bbbb9c5..b077cc7 100644 --- a/main.cpp +++ b/main.cpp @@ -31,12 +31,22 @@ using std::cout; +using std::clog; using std::cerr; using std::endl; using namespace std::literals; +#if HAVE_GLIBMM_2_68 +#define AF_NON_UNIQUE Gio::Application::Flags::NON_UNIQUE +#define OEF_IN_MAIN Glib::OptionEntry::Flags::IN_MAIN +#else +#define AF_NON_UNIQUE Gio::ApplicationFlags::APPLICATION_NON_UNIQUE +#define OEF_IN_MAIN Glib::OptionEntry::Flags::FLAG_IN_MAIN +#endif + + template class GObjectWrapper { T* ptr = nullptr; @@ -295,70 +305,59 @@ throw_error(GError* raw_err) struct App : Gio::Application { - bool show_secrets = false; - bool do_unlock = false; + enum Detail : int { + Service = 0, + Collections = 1, + Items = 2, + Attributes = 3, + Secrets = 4 + }; + + + int detail = Detail::Items; + bool unlock_flag = false; + bool version_flag = false; + + Glib::OptionGroup main_group{"", ""}; + Glib::OptionEntry detail_opt; + Glib::OptionEntry unlock_opt; + Glib::OptionEntry version_opt; std::optional> service; App() : - Gio::Application{"lssecrets.dkosmari.github.com"} + Gio::Application{"lssecrets.dkosmari.github.com", AF_NON_UNIQUE} { set_option_context_summary("Show keyring secrets using libsecret."); set_option_context_description(PACKAGE_NAME " <" PACKAGE_URL ">\n" "Bug reports <" PACKAGE_BUGREPORT ">\n"); - - add_main_option_entry( -#if HAVE_GLIBMM_2_68 - OptionType::BOOL, -#else - OptionType::OPTION_TYPE_BOOL, -#endif - "secrets", - 's', - "Show secret values."); - add_main_option_entry( -#if HAVE_GLIBMM_2_68 - OptionType::BOOL, -#else - OptionType::OPTION_TYPE_BOOL, -#endif - "unlock", - 'u', - "Unlock secrets."); - - add_main_option_entry( -#if HAVE_GLIBMM_2_68 - OptionType::BOOL, -#else - OptionType::OPTION_TYPE_BOOL, -#endif - "version", - 'v', - "Print version number and exit."); - - signal_handle_local_options().connect(sigc::mem_fun(*this, &App::handle_local_options), - true); - } - - - - int - handle_local_options(const Glib::RefPtr& options) - { - if (options->contains("version")) { - cout << PACKAGE_STRING << endl; - return 0; - } - - if (options->contains("secrets")) - show_secrets = true; - - if (options->contains("unlock")) - do_unlock = true; - - return -1; // means "continue processing options" + detail_opt.set_flags(OEF_IN_MAIN); + detail_opt.set_long_name("detail"); + detail_opt.set_short_name('d'); + detail_opt.set_description("Set detail of detail, where N is:\n" + " 0 = service\n" + " 1 = collections\n" + " 2 = items (default)\n" + " 3 = attributes\n" + " 4 = secrets"); + detail_opt.set_arg_description("N"); + main_group.add_entry(detail_opt, detail); + + unlock_opt.set_flags(OEF_IN_MAIN); + unlock_opt.set_long_name("unlock"); + unlock_opt.set_short_name('u'); + unlock_opt.set_description("Unlock secrets."); + main_group.add_entry(unlock_opt, unlock_flag); + + version_opt.set_flags(OEF_IN_MAIN); + version_opt.set_long_name("version"); + version_opt.set_short_name('v'); + version_opt.set_description("Print version number and exit."); + main_group.add_entry(version_opt, version_flag); + + add_option_group(main_group); } @@ -366,6 +365,11 @@ struct App : Gio::Application { on_activate() override { + if (version_flag) { + cout << PACKAGE_STRING << endl; + return; + } + try { print(); } @@ -383,7 +387,7 @@ struct App : Gio::Application { GError* service_error = nullptr; int flags = SECRET_SERVICE_LOAD_COLLECTIONS; - if (show_secrets) + if (detail >= Detail::Secrets) flags |= SECRET_SERVICE_OPEN_SESSION; service = take(secret_service_get_sync(SecretServiceFlags(flags), @@ -398,7 +402,6 @@ struct App : Gio::Application { << g_dbus_proxy_get_object_path(*service) << '\n'; - // check known aliases const std::vector known_aliases{ "default", "login", "session" @@ -427,6 +430,9 @@ struct App : Gio::Application { cout << '\n'; + if (detail < Detail::Collections) + return; + auto collections = to_vector(secret_service_get_collections(*service)); for (auto& col : collections) { print(col, reverse_aliases, " "); @@ -475,15 +481,19 @@ struct App : Gio::Application { << timestamp_to_string(modified).value() << '\n'; - bool locked = secret_collection_get_locked(col); - if (locked && do_unlock) { + if (unlock_flag && secret_collection_get_locked(col)) { auto error = unlock(col); if (error) cout << indent << " Error: " << error->what() << endl; } + bool locked = secret_collection_get_locked(col); + cout << indent << " Locked: " << locked << '\n'; cout << '\n'; + if (detail < Detail::Items) + return; + auto items = to_vector(secret_collection_get_items(col)); for (auto& item : items) { print(item, indent + " "); @@ -522,6 +532,9 @@ struct App : Gio::Application { << timestamp_to_string(modified).value() << '\n'; + if (detail < Detail::Attributes) + return; + auto attributes = to_map(secret_item_get_attributes(item)); if (!attributes.empty()) { static const std::string attrib_indent = indent + " "; @@ -536,16 +549,22 @@ struct App : Gio::Application { } } - bool locked = secret_item_get_locked(item); - if (locked && do_unlock) { + auto print_locked = [&item, indent] { + bool locked = secret_item_get_locked(item); + cout << indent << " Locked: " << locked << '\n'; + }; + + if (unlock_flag && secret_item_get_locked(item)) { auto error = unlock(item); + print_locked(); if (error) { cout << indent << " Error: " << error->what() << endl; return; } - } + } else + print_locked(); - if (!show_secrets) + if (detail < Detail::Secrets) return; GError* error = nullptr;