Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package otpclient for openSUSE:Factory checked in at 2022-12-10 21:18:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/otpclient (Old) and /work/SRC/openSUSE:Factory/.otpclient.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "otpclient" Sat Dec 10 21:18:30 2022 rev:19 rq:1041889 version:3.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/otpclient/otpclient.changes 2022-11-30 18:53:51.740680940 +0100 +++ /work/SRC/openSUSE:Factory/.otpclient.new.1835/otpclient.changes 2022-12-10 21:18:31.153798872 +0100 @@ -1,0 +2,10 @@ +Fri Dec 9 14:01:32 UTC 2022 - Paolo Stivanin <i...@paolostivanin.com> + +- Update to 3.0.0: + * NEW: OTPClient is now translatable (#263). If you wish to translate it in your language, + you can find two templates (.pot) in the po/ directory. When you are done translating, either open a PR or send me an email so I can add the translation. + * NEW: secret is now editable too (#258) + * NEW: an About dialog has been added in the settings menu. + * CHANGED: removed Authenticator Plus support (#257) + +------------------------------------------------------------------- Old: ---- v2.6.4.tar.gz v2.6.4.tar.gz.asc New: ---- v3.0.0.tar.gz v3.0.0.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ otpclient.spec ++++++ --- /var/tmp/diff_new_pack.6GNDdw/_old 2022-12-10 21:18:31.829802825 +0100 +++ /var/tmp/diff_new_pack.6GNDdw/_new 2022-12-10 21:18:31.837802872 +0100 @@ -18,7 +18,7 @@ %define uclname OTPClient Name: otpclient -Version: 2.6.4 +Version: 3.0.0 Release: 0 Summary: Simple GTK+ client for managing TOTP and HOTP License: GPL-3.0-or-later @@ -43,7 +43,7 @@ BuildRequires: pkgconfig BuildRequires: protobuf-devel >= 3.6.0 BuildRequires: update-desktop-files -BuildRequires: pkgconfig(glib-2.0) >= 2.50 +BuildRequires: pkgconfig(glib-2.0) >= 2.64 BuildRequires: pkgconfig(gtk+-3.0) >= 3.20 %description ++++++ v2.6.4.tar.gz -> v3.0.0.tar.gz ++++++ ++++ 2071 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/CMakeLists.txt new/OTPClient-3.0.0/CMakeLists.txt --- old/OTPClient-2.6.4/CMakeLists.txt 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/CMakeLists.txt 2022-12-09 14:39:38.000000000 +0100 @@ -1,7 +1,11 @@ cmake_minimum_required(VERSION 3.10) -project(OTPClient VERSION "2.6.4" LANGUAGES "C") +project(OTPClient VERSION "3.0.0" LANGUAGES "C") +include(GNUInstallDirs) configure_file("src/common/version.h.in" "version.h") + +set (GETTEXT_PACKAGE ${CMAKE_PROJECT_NAME}) + include_directories(${PROJECT_BINARY_DIR}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -28,6 +32,7 @@ if(BUILD_CLI) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBUILD_CLI") endif() +add_definitions(-DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") @@ -47,8 +52,8 @@ pkg_check_modules(JANSSON REQUIRED jansson>=2.10.0) pkg_check_modules(ZBAR REQUIRED zbar>=0.20) pkg_check_modules(GTK3 REQUIRED gtk+-3.0>=3.20.0) -pkg_check_modules(GLIB2 REQUIRED glib-2.0>=2.48.0) -pkg_check_modules(GIO REQUIRED gio-2.0>=2.48.0) +pkg_check_modules(GLIB2 REQUIRED glib-2.0>=2.64.0) +pkg_check_modules(GIO REQUIRED gio-2.0>=2.64.0) pkg_check_modules(UUID REQUIRED uuid>=2.34.0) pkg_check_modules(PROTOC REQUIRED libprotobuf-c>=1.3.0) pkg_check_modules(LIBSECRET REQUIRED libsecret-1>=0.20.0) @@ -85,7 +90,6 @@ src/add-common.c src/common/andotp.c src/app.c - src/authplus.c src/gui-common.c src/db-misc.c src/edit-data.c @@ -115,7 +119,7 @@ src/db-actions.c src/change-file-cb.c src/google-migration.pb-c.c - src/secret-schema.c) + src/secret-schema.c src/about_diag_cb.c) set(CLI_HEADER_FILES src/cli/help.h @@ -152,7 +156,6 @@ src/gui-common.c src/add-common.c src/imports.c - src/authplus.c src/password-cb.c src/get-builder.c src/message-dialogs.c) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/README.md new/OTPClient-3.0.0/README.md --- old/OTPClient-2.6.4/README.md 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/README.md 2022-12-09 14:39:38.000000000 +0100 @@ -32,7 +32,6 @@ - support setting a custom period (between 10 and 120 seconds inclusive) - support SHA1, SHA256 and SHA512 algorithms - support for Steam codes (please read [THIS PAGE](https://github.com/paolostivanin/OTPClient/wiki/Steam-Support)) -- import encrypted [Authenticator Plus](https://www.authenticatorplus.com/) backup - import and export encrypted/plain [andOTP](https://github.com/flocke/andOTP) backup - import and export encrypted/plain [Aegis](https://github.com/beemdevelopment/Aegis) backup - import and export plain [FreeOTPPlus](https://github.com/helloworld1/FreeOTPPlus) backup (key URI format only) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/SECURITY.md new/OTPClient-3.0.0/SECURITY.md --- old/OTPClient-2.6.4/SECURITY.md 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/SECURITY.md 2022-12-09 14:39:38.000000000 +0100 @@ -5,8 +5,9 @@ The following list describes whether a version is eligible or not for security updates. | Version | Supported | EOL | -| ------- | ------------------ |-------------| -| 2.6.x | :heavy_check_mark: | - | +|---------| ------------------ |-------------| +| 3.0.x | :heavy_check_mark: | - | +| 2.6.x | :heavy_check_mark: | 15-Jan-2023 | | 2.5.x | :x: | 31-Aug-2022 | | 2.4.x | :x: | 15-May-2022 | | 2.3.x | :x: | 28-Feb-2021 | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/data/com.github.paolostivanin.OTPClient.appdata.xml new/OTPClient-3.0.0/data/com.github.paolostivanin.OTPClient.appdata.xml --- old/OTPClient-2.6.4/data/com.github.paolostivanin.OTPClient.appdata.xml 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/data/com.github.paolostivanin.OTPClient.appdata.xml 2022-12-09 14:39:38.000000000 +0100 @@ -83,6 +83,18 @@ </content_rating> <releases> + <release version="3.0.0" date="2022-12-09"> + <description> + <p>OTPClient 3.0.0 brings some exciting news:</p> + <ul> + <li>New feature (#263): OTPClient is now translatable (open a GitHub issue if you want to help translating it in your language).</li> + <li>New feature (#259): it's now possible to edit also the secret.</li> + <li>Improved: an About dialog has been added in the settings menu.</li> + <li>Removed (#257): Authenticator Plus support has been removed.</li> + <li>Various small fixes.</li> + </ul> + </description> + </release> <release version="2.6.4" date="2022-11-30"> <description> <p>OTPClient 2.6.4 fixes an import issue</p> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/po/generate_pot.txt new/OTPClient-3.0.0/po/generate_pot.txt --- old/OTPClient-2.6.4/po/generate_pot.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/OTPClient-3.0.0/po/generate_pot.txt 2022-12-09 14:39:38.000000000 +0100 @@ -0,0 +1,3 @@ +Note for myself: +$ xgettext -k_ -kN_ -o otpclient-cli.pot -L C -cTranslators ../src/cli/main.c ../src/cli/help.c ../src/cli/get-data.c +$ xgettext -k_ -kN_ -o otpclient.pot -L Glade ../src/ui/otpclient.ui diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/about_diag_cb.c new/OTPClient-3.0.0/src/about_diag_cb.c --- old/OTPClient-2.6.4/src/about_diag_cb.c 1970-01-01 01:00:00.000000000 +0100 +++ new/OTPClient-3.0.0/src/about_diag_cb.c 2022-12-09 14:39:38.000000000 +0100 @@ -0,0 +1,35 @@ +#include <gtk/gtk.h> +#include <glib/gi18n.h> +#include "version.h" +#include "data.h" + +void +about_diag_cb (GSimpleAction *simple __attribute__((unused)), + GVariant *parameter __attribute__((unused)), + gpointer user_data) +{ + AppData *app_data = (AppData *)user_data; + + const gchar *authors[] = {"Paolo Stivanin <i...@paolostivanin.com>", NULL}; + const gchar *artists[] = {"Paolo Stivanin <i...@paolostivanin.com>", NULL}; + const gchar *partial_path = "share/icons/hicolor/scalable/apps/com.github.paolostivanin.OTPClient.svg"; + gchar *icon_abs_path = g_strconcat (INSTALL_PREFIX, "/", partial_path, NULL); + + GtkWidget *ab_diag = gtk_about_dialog_new (); + gtk_window_set_transient_for (GTK_WINDOW(app_data->main_window), GTK_WINDOW(ab_diag)); + + gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(ab_diag), PROJECT_NAME); + gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(ab_diag), PROJECT_VER); + gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(ab_diag), "2017-2022"); + gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(ab_diag), _("Highly secure and easy to use GTK+ software for two-factor authentication that supports both Time-based One-time Passwords (TOTP) and HMAC-Based One-Time Passwords (HOTP).")); + gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(ab_diag), GTK_LICENSE_GPL_3_0); + gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(ab_diag), "https://github.com/paolostivanin/OTPClient"); + gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(ab_diag), authors); + gtk_about_dialog_set_artists (GTK_ABOUT_DIALOG(ab_diag), artists); + GdkPixbuf *logo = gdk_pixbuf_new_from_file (icon_abs_path, NULL); + gtk_about_dialog_set_logo (GTK_ABOUT_DIALOG(ab_diag), logo); + g_free (icon_abs_path); + g_signal_connect (ab_diag, "response", G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_widget_show_all (ab_diag); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/app.c new/OTPClient-3.0.0/src/app.c --- old/OTPClient-2.6.4/src/app.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/app.c 2022-12-09 14:39:38.000000000 +0100 @@ -438,7 +438,6 @@ gtk_window_set_default_size (GTK_WINDOW(app_data->main_window), (width >= 150) ? width : 500, (height >= 150) ? height : 300); GtkWidget *header_bar = GTK_WIDGET(gtk_builder_get_object (app_data->builder, "headerbar_id")); - gtk_header_bar_set_subtitle (GTK_HEADER_BAR(header_bar), PROJECT_VER); GtkWidget *lock_btn = GTK_WIDGET(gtk_builder_get_object (app_data->builder, "lock_btn_id")); g_signal_connect (lock_btn, "clicked", G_CALLBACK(lock_app), app_data); @@ -516,7 +515,6 @@ static GActionEntry settings_menu_entries[] = { { .name = ANDOTP_IMPORT_ACTION_NAME, .activate = select_file_cb }, { .name = ANDOTP_IMPORT_PLAIN_ACTION_NAME, .activate = select_file_cb }, - { .name = AUTHPLUS_IMPORT_ACTION_NAME, .activate = select_file_cb }, { .name = FREEOTPPLUS_IMPORT_ACTION_NAME, .activate = select_file_cb }, { .name = AEGIS_IMPORT_ACTION_NAME, .activate = select_file_cb }, { .name = AEGIS_IMPORT_ENC_ACTION_NAME, .activate = select_file_cb }, @@ -532,7 +530,8 @@ { .name = "change_pwd", .activate = change_password_cb }, { .name = "edit_row", .activate = edit_selected_row_cb }, { .name = "settings", .activate = settings_dialog_cb }, - { .name = "shortcuts", .activate = shortcuts_window_cb } + { .name = "shortcuts", .activate = shortcuts_window_cb }, + { .name = "about", .activate = about_diag_cb } }; static GActionEntry add_menu_entries[] = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/authplus.c new/OTPClient-3.0.0/src/authplus.c --- old/OTPClient-2.6.4/src/authplus.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/authplus.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,73 +0,0 @@ -#include <glib.h> -#include <zip.h> -#include <gcrypt.h> -#include "gquarks.h" -#include "parse-uri.h" - - -GSList * -get_authplus_data (const gchar *zip_path, - const gchar *password, - gint32 max_file_size, - GError **err) -{ - zip_t *zip_file; - struct zip_file *zf; - struct zip_stat sb; - - int zip_err; - if ((zip_file = zip_open (zip_path, ZIP_RDONLY, &zip_err)) == NULL) { - zip_error_t error; - zip_error_init_with_code (&error, zip_err); - gchar *msg = g_strdup_printf ("Couldn't open zip file '%s': %s", zip_path, zip_error_strerror (&error)); - g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "%s", msg); - g_free (msg); - zip_error_fini(&error); - return NULL; - } - - zip_set_default_password (zip_file, password); - - if (zip_stat (zip_file, "Accounts.txt", 0, &sb) < 0) { - g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "%s", "zip_stat failed"); - zip_discard (zip_file); - return NULL; - } - - if (sb.size > max_file_size) { - g_set_error (err, file_too_big_gquark (), FILE_TOO_BIG, "File is too big"); - zip_discard (zip_file); - return NULL; - } - gchar *sec_buf = gcry_calloc_secure (sb.size, 1); - if (sec_buf == NULL) { - g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Couldn't allocate secure memory"); - zip_discard (zip_file); - return NULL; - } - zf = zip_fopen (zip_file, "Accounts.txt", 0); - if (zf == NULL) { - g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "%s", "zip_fopen failed"); - zip_discard (zip_file); - return NULL; - } - - zip_int64_t len = zip_fread (zf, sec_buf, sb.size); - if (len < 0) { - g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "%s", "zip_fread failed"); - zip_fclose (zf); - zip_discard (zip_file); - return NULL; - } - - GSList *otps = NULL; - set_otps_from_uris (sec_buf, &otps); - - zip_fclose (zf); - - zip_discard (zip_file); - - gcry_free (sec_buf); - - return otps; -} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/cli/get-data.c new/OTPClient-3.0.0/src/cli/get-data.c --- old/OTPClient-2.6.4/src/cli/get-data.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/cli/get-data.c 2022-12-09 14:39:38.000000000 +0100 @@ -1,6 +1,7 @@ #include <glib.h> #include <jansson.h> #include <cotp.h> +#include <glib/gi18n.h> #include "../db-misc.h" #include "../common/common.h" @@ -54,9 +55,28 @@ } } if (!found) { - g_printerr ("Couldn't find the data. Either the given data is wrong or is not in the database.\n"); - g_printerr ("Given account: %s\n", account != NULL ? account : "<none>"); - g_printerr ("Given issuer: %s\n", issuer != NULL ? issuer : "<none>"); + g_printerr ("%s\n", _("Couldn't find the data. Either the given data is wrong or is not in the database.")); + + // Translators: please do not translate 'account' + GString *msg = g_string_new (_("Given account: %s")); +#if GLIB_CHECK_VERSION(2, 68, 0) + g_string_replace (msg, "%s", account != NULL ? account : "<none>", 0); +#else + g_string_replace_backported (msg, "%s", account != NULL ? account : "<none>", 0); +#endif + g_printerr ("%s\n", msg->str); + g_string_free (msg, TRUE); + + // Translators: please do not translate 'issuer' + msg = g_string_new (_("Given issuer: %s")); +#if GLIB_CHECK_VERSION(2, 68, 0) + g_string_replace (msg, "%s", issuer != NULL ? issuer : "<none>", 0); +#else + g_string_replace_backported (msg, "%s", issuer != NULL ? issuer : "<none>", 0); +#endif + g_printerr ("%s\n", msg->str); + g_string_free (msg, TRUE); + return; } } @@ -112,11 +132,11 @@ current_totp = get_totp_at (secret, current_ts, digits, period, algo, &cotp_err); if (show_next_token) next_totp = get_totp_at (secret, current_ts + period, digits, period, algo, &cotp_err); } - g_print ("Current TOTP (valid for %d more second(s)): %s\n", token_validity, current_totp); + g_print (_("Current TOTP (valid for %d more second(s)): %s\n"), token_validity, current_totp); if (show_next_token) g_print ("Next TOTP: %s\n", next_totp); } else { counter = json_integer_value (json_object_get (obj, "counter")); - g_print ("Current HOTP: %s\n", get_hotp (secret, counter, digits, algo, &cotp_err)); + g_print (_("Current HOTP: %s\n"), get_hotp (secret, counter, digits, algo, &cotp_err)); // counter must be updated every time it is accessed json_object_set (obj, "counter", json_integer (counter + 1)); GError *err = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/cli/help.c new/OTPClient-3.0.0/src/cli/help.c --- old/OTPClient-2.6.4/src/cli/help.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/cli/help.c 2022-12-09 14:39:38.000000000 +0100 @@ -1,18 +1,21 @@ #include <glib.h> +#include <glib/gi18n.h> #include "version.h" +#include "../common/common.h" -static void print_main_help (const gchar *prg_name); +static void print_main_help (const gchar *prg_name); -static void print_show_help (const gchar *prg_name); +static void print_show_help (const gchar *prg_name); -static void print_export_help (const gchar *prg_name); +static void print_export_help (const gchar *prg_name); gboolean show_help (const gchar *prg_name, const gchar *help_command) { gboolean help_displayed = FALSE; - if (g_strcmp0 (help_command, "-h") == 0 || g_strcmp0 (help_command, "--help") == 0 || g_strcmp0 (help_command, "help") == 0) { + if (g_strcmp0 (help_command, "-h") == 0 || g_strcmp0 (help_command, "--help") == 0 || g_strcmp0 (help_command, "help") == 0 || + help_command == NULL || g_utf8_strlen (help_command, -1) < 2) { print_main_help (prg_name); help_displayed = TRUE; } else if (g_strcmp0 (help_command, "-v") == 0 || g_strcmp0 (help_command, "--version") == 0) { @@ -24,9 +27,6 @@ } else if (g_strcmp0 (help_command, "--help-export") == 0 || g_strcmp0 (help_command, "help-export") == 0) { print_export_help (prg_name); help_displayed = TRUE; - } else if (help_command == NULL || g_utf8_strlen (help_command, -1) < 2) { - print_main_help (prg_name); - help_displayed = TRUE; } return help_displayed; @@ -36,44 +36,86 @@ static void print_main_help (const gchar *prg_name) { - g_print ("Usage:\n %s <main option> [option 1] [option 2] ...\n", prg_name); - g_print ("\n"); - g_print ("Help Options:\n"); - g_print (" -h, --help\t\tShow this help\n"); - g_print (" --help-show\t\tShow options\n"); - g_print (" --help-export\t\tExport options\n"); - g_print ("\n"); - g_print ("Main Options:\n"); - g_print (" -v, --version\t\t\t\tShow program version\n"); - g_print (" show <-a ..> [-i ..] [-m] [-n]\tShow a token\n"); - g_print (" list\t\t\t\t\tList all pairs of account and issuer\n"); - g_print (" export <-t ..> [-d ..]\t\tExport data\n"); - g_print ("\n"); + GString *msg = g_string_new (_("Usage:\n %s <main option> [option 1] [option 2] ...")); +#if GLIB_CHECK_VERSION(2, 68, 0) + g_string_replace (msg, "%s", prg_name, 0); +#else + g_string_replace_backported (msg, "%s", prg_name, 0); +#endif + g_print ("%s\n\n", msg->str); + g_string_free (msg, TRUE); + + // Translators: please do not translate 'help' + g_print ("%s\n", _("help command options:")); + + // Translators: please do not translate '-h, --help' + g_print ("%s\n", _(" -h, --help\t\tShow this help")); + + // Translators: please do not translate '--help-show' + g_print ("%s\n", _(" --help-show\t\tShow options")); + + // Translators: please do not translate '--help-export' + g_print ("%s\n\n", _(" --help-export\t\tExport options")); + g_print ("%s\n", _("Main options:")); + + // Translators: please do not translate '-v, --version' + g_print ("%s\n", _(" -v, --version\t\t\t\tShow program version")); + + // Translators: please do not translate 'show <-a ..> [-i ..] [-m] [-n]' + g_print ("%s\n", _(" show <-a ..> [-i ..] [-m] [-n]\tShow a token")); + + // Translators: please do not translate 'list' + g_print ("%s\n", _(" list\t\t\t\t\tList all pairs of account and issuer")); + + // Translators: please do not translate 'export <-t ..> [-d ..]' + g_print ("%s\n\n", _(" export <-t ..> [-d ..]\t\tExport data")); } static void print_show_help (const gchar *prg_name) { - g_print ("Usage:\n %s show <-a ..> [-i ..] [-m]\n", prg_name); - g_print ("\n"); - g_print ("Show Options:\n"); - g_print (" -a, --account\t\tThe account name (mandatory)\n"); - g_print (" -i, --issuer\t\tThe issuer name (optional)\n"); - g_print (" -m, --match-exactly\tShow the token only if it matches exactly the account and/or the issuer (optional)\n"); - g_print (" -n, --next\tShow also the next token, not only the current one (optional, valid only for TOTP)\n"); - g_print ("\n"); + // Translators: please do not translate '%s show' + GString *msg = g_string_new (_("Usage:\n %s show <-a ..> [-i ..] [-m]")); +#if GLIB_CHECK_VERSION(2, 68, 0) + g_string_replace (msg, "%s", prg_name, 0); +#else + g_string_replace_backported (msg, "%s", prg_name, 0); +#endif + g_print ("%s\n\n", msg->str); + g_string_free (msg, TRUE); + + // Translators: please do not translate 'show' + g_print ("%s\n", _("show command options:")); + // Translators: please do not translate '-a, --account' + g_print ("%s\n", _(" -a, --account\t\tThe account name (mandatory)")); + // Translators: please do not translate '-i, --issuer' + g_print ("%s\n", _(" -i, --issuer\t\tThe issuer name (optional)")); + // Translators: please do not translate '-m, --match-exactly' + g_print ("%s\n", _(" -m, --match-exactly\tShow the token only if it matches exactly the account and/or the issuer (optional)")); + // Translators: please do not translate '-n, --next' + g_print ("%s\n\n", _(" -n, --next\tShow also the next token, not only the current one (optional, valid only for TOTP)")); } static void print_export_help (const gchar *prg_name) { - g_print ("Usage:\n %s export <-t> <andotp | freeotpplus | aegis> [-d ..]\n", prg_name); - g_print ("\n"); - g_print ("Export Options:\n"); - g_print (" -t, --type\t\tExport format. Must be either one of: andotp_plain, andotp_encrypted, freeotpplus, aegis\n"); - g_print (" -d, --directory\tThe output directory where the exported file will be saved.\n"); - g_print ("\t\t\tIf nothing is specified OR flatpak is being used, the output folder will be the user's HOME directory.\n"); - g_print ("\n"); + // Translators: please do not translate '%s export' + GString *msg = g_string_new (_("Usage:\n %s export <-t> <andotp | freeotpplus | aegis> [-d ..]")); +#if GLIB_CHECK_VERSION(2, 68, 0) + g_string_replace (msg, "%s", prg_name, 0); +#else + g_string_replace_backported (msg, "%s", prg_name, 0); +#endif + g_print ("%s\n\n", msg->str); + g_string_free (msg, TRUE); + + // Translators: please do not translate 'export' + g_print ("%s\n", _("export command options:")); + // Translators: please do not translate '-t, --type' + g_print ("%s\n", _(" -t, --type\t\tExport format. Must be either one of: andotp_plain, andotp_encrypted, freeotpplus, aegis")); + // Translators: please do not translate '-d, --directory' + g_print ("%s\n", _(" -d, --directory\tThe output directory where the exported file will be saved.")); + g_print ("%s\n\n", _("\t\t\tIf nothing is specified OR flatpak is being used, the output folder will be the user's HOME directory.")); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/cli/main.c new/OTPClient-3.0.0/src/cli/main.c --- old/OTPClient-2.6.4/src/cli/main.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/cli/main.c 2022-12-09 14:39:38.000000000 +0100 @@ -3,6 +3,7 @@ #include <gcrypt.h> #include <termios.h> #include <libsecret/secret.h> +#include <glib/gi18n.h> #include "help.h" #include "get-data.h" #include "../common/common.h" @@ -32,10 +33,10 @@ db_data->key_stored = FALSE; db_data->max_file_size_from_memlock = get_max_file_size_from_memlock (); - gchar *msg = init_libs (db_data->max_file_size_from_memlock); - if (msg != NULL) { - g_printerr ("%s\n", msg); - g_free (msg); + gchar *init_msg = init_libs (db_data->max_file_size_from_memlock); + if (init_msg != NULL) { + g_printerr ("%s\n", init_msg); + g_free (init_msg); g_free (db_data); return -1; } @@ -68,7 +69,7 @@ } } else { get_pwd: - db_data->key = get_pwd ("Type the DB decryption password: "); + db_data->key = get_pwd (_("Type the DB decryption password: ")); if (db_data->key == NULL) { g_free (db_data); return -1; @@ -80,9 +81,12 @@ GError *err = NULL; load_db (db_data, &err); if (err != NULL) { - g_printerr ("Error while loading the database: %s\n", err->message); + const gchar *tmp_msg = _("Error while loading the database:"); + gchar *msg = g_strconcat (tmp_msg, " %s\n", err->message, NULL); + g_printerr ("%s\n", msg); gcry_free (db_data->key); g_free (db_data); + g_free (msg); return -1; } @@ -95,7 +99,8 @@ if (g_strcmp0 (argv[1], "show") == 0) { if (argc < 4 || argc > 8) { - g_printerr ("Wrong argument(s). Please type '%s --help-show' to see the available options.\n", argv[0]); + // Translators: please do not translate '%s --help-show' + g_printerr (_("Wrong argument(s). Please type '%s --help-show' to see the available options.\n"), argv[0]); g_free (db_data); return -1; } @@ -111,7 +116,8 @@ } } if (account == NULL) { - g_printerr ("[ERROR]: The account option (-a) must be specified and can not be empty.\n"); + // Translators: please do not translate 'account' + g_printerr ("%s\n", _("[ERROR]: The account option (-a) must be specified and can not be empty.")); goto end; } show_token (db_data, account, issuer, match_exactly, show_next_token); @@ -120,7 +126,8 @@ } else if (g_strcmp0 (argv[1], "export") == 0) { if (g_ascii_strcasecmp (argv[3], "andotp_plain") != 0 && g_ascii_strcasecmp (argv[3], "andotp_encrypted") != 0 && g_ascii_strcasecmp (argv[3], "freeotpplus") != 0 && g_ascii_strcasecmp (argv[3], "aegis") != 0) { - g_printerr ("Wrong argument(s). Please type '%s --help-export' to see the available options.\n", argv[0]); + // Translators: please do not translate '%s --help-export' + g_printerr (_("Wrong argument(s). Please type '%s --help-export' to see the available options.\n"), argv[0]); g_free (db_data); return -1; } @@ -131,13 +138,13 @@ } else { if (g_ascii_strcasecmp (argv[4], "-d") == 0 && argv[5] != NULL) { if (!g_file_test (argv[5], G_FILE_TEST_IS_DIR)) { - g_printerr ("%s is not a directory or the folder doesn't exist. The output will be saved into the HOME directory.\n", argv[5]); + g_printerr (_("%s is not a directory or the folder doesn't exist. The output will be saved into the HOME directory.\n"), argv[5]); base_dir = g_get_home_dir (); } else { base_dir = argv[5]; } } else { - g_printerr ("Incorrect parameters used for setting the output folder. Therefore, the exported file will be saved into the HOME directory.\n"); + g_printerr ("%s\n", _("Incorrect parameters used for setting the output folder. Therefore, the exported file will be saved into the HOME directory.")); base_dir = g_get_home_dir (); } } @@ -147,7 +154,7 @@ gchar *andotp_export_pwd = NULL, *exported_file_path = NULL, *ret_msg = NULL; if (g_ascii_strcasecmp (argv[3], "andotp_plain") == 0 || g_ascii_strcasecmp (argv[3], "andotp_encrypted") == 0) { if (g_ascii_strcasecmp (argv[3], "andotp_encrypted")) { - andotp_export_pwd = get_pwd ("Type the export encryption password: "); + andotp_export_pwd = get_pwd (_("Type the export encryption password: ")); if (andotp_export_pwd == NULL) { goto end; } @@ -165,10 +172,10 @@ ret_msg = export_aegis (exported_file_path, db_data->json_data, NULL); } if (ret_msg != NULL) { - g_printerr ("An error occurred while exporting the data: %s\n", ret_msg); + g_printerr (_("An error occurred while exporting the data: %s\n"), ret_msg); g_free (ret_msg); } else { - g_print ("Data successfully exported to: %s\n", exported_file_path); + g_print (_("Data successfully exported to: %s\n"), exported_file_path); } g_free (exported_file_path); } else { @@ -189,7 +196,7 @@ #ifndef USE_FLATPAK_APP_FOLDER static gchar * -get_db_path () +get_db_path (void) { gchar *db_path = NULL; GError *err = NULL; @@ -214,17 +221,17 @@ goto end; } type_db_path: ; // empty statement workaround - g_print ("Type the absolute path to the database: "); + g_print ("%s", _("Type the absolute path to the database: ")); db_path = g_malloc0 (MAX_ABS_PATH_LEN); if (fgets (db_path, MAX_ABS_PATH_LEN, stdin) == NULL) { - g_printerr ("Couldn't get db path from stdin\n"); + g_printerr ("%s\n", _("Couldn't get db path from stdin")); g_free (cfg_file_path); return NULL; } else { // remove the newline char db_path[g_utf8_strlen (db_path, -1) - 1] = '\0'; if (!g_file_test (db_path, G_FILE_TEST_EXISTS)) { - g_printerr ("File '%s' does not exist\n", db_path); + g_printerr (_("File '%s' does not exist\n"), db_path); g_free (cfg_file_path); return NULL; } @@ -246,19 +253,19 @@ struct termios old, new; if (tcgetattr (STDIN_FILENO, &old) != 0) { - g_printerr ("Couldn't get termios info\n"); + g_printerr ("%s\n", _("Couldn't get termios info")); gcry_free (pwd); return NULL; } new = old; new.c_lflag &= ~ECHO; if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &new) != 0) { - g_printerr ("Couldn't turn echoing off\n"); + g_printerr ("%s\n", _("Couldn't turn echoing off")); gcry_free (pwd); return NULL; } if (fgets (pwd, 256, stdin) == NULL) { - g_printerr ("Couldn't read password from stdin\n"); + g_printerr ("%s\n", _("Couldn't read password from stdin")); gcry_free (pwd); return NULL; } @@ -274,7 +281,7 @@ static gboolean -is_secretservice_disable () +is_secretservice_disable (void) { gboolean disable_secret_service = FALSE; GError *err = NULL; @@ -289,4 +296,4 @@ disable_secret_service = g_key_file_get_boolean (kf, "config", "disable_secret_service", NULL); } return disable_secret_service; -} \ No newline at end of file +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/common/common.c new/OTPClient-3.0.0/src/common/common.c --- old/OTPClient-2.6.4/src/common/common.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/common/common.c 2022-12-09 14:39:38.000000000 +0100 @@ -240,4 +240,47 @@ } return uris; -} \ No newline at end of file +} + + +// Backported from Glib 2.68 in order to support Debian "bullseye" and Ubuntu 20.04 +guint +g_string_replace_backported (GString *string, + const gchar *find, + const gchar *replace, + guint limit) +{ + gsize f_len, r_len, pos; + gchar *cur, *next; + guint n = 0; + + g_return_val_if_fail (string != NULL, 0); + g_return_val_if_fail (find != NULL, 0); + g_return_val_if_fail (replace != NULL, 0); + + f_len = strlen (find); + r_len = strlen (replace); + cur = string->str; + + while ((next = strstr (cur, find)) != NULL) + { + pos = next - string->str; + g_string_erase (string, pos, f_len); + g_string_insert (string, pos, replace); + cur = string->str + pos + r_len; + n++; + /* Only match the empty string once at any given position, to + * avoid infinite loops */ + if (f_len == 0) + { + if (cur[0] == '\0') + break; + else + cur++; + } + if (n == limit) + break; + } + + return n; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/common/common.h new/OTPClient-3.0.0/src/common/common.h --- old/OTPClient-2.6.4/src/common/common.h 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/common/common.h 2022-12-09 14:39:38.000000000 +0100 @@ -33,4 +33,9 @@ GSList *decode_migration_data (const gchar *encoded_uri); +guint g_string_replace_backported (GString *string, + const gchar *find, + const gchar *replace, + guint limit); + G_END_DECLS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/common/get-providers-data.h new/OTPClient-3.0.0/src/common/get-providers-data.h --- old/OTPClient-2.6.4/src/common/get-providers-data.h 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/common/get-providers-data.h 2022-12-09 14:39:38.000000000 +0100 @@ -4,11 +4,6 @@ G_BEGIN_DECLS -GSList *get_authplus_data (const gchar *zip_path, - const gchar *password, - gint32 max_file_size, - GError **err); - GSList *get_andotp_data (const gchar *path, const gchar *password, gint32 max_file_size, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/common/version.h.in new/OTPClient-3.0.0/src/common/version.h.in --- old/OTPClient-2.6.4/src/common/version.h.in 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/common/version.h.in 2022-12-09 14:39:38.000000000 +0100 @@ -3,3 +3,4 @@ #define PROJECT_NAME "@PROJECT_NAME@" #define PROJECT_VER "@PROJECT_VERSION@" #define INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@" +#define LOCALE_DIR "@SHARE_INSTALL_PREFIX@/locale" \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/edit-data.c new/OTPClient-3.0.0/src/edit-data.c --- old/OTPClient-2.6.4/src/edit-data.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/edit-data.c 2022-12-09 14:39:38.000000000 +0100 @@ -1,4 +1,5 @@ #include <gtk/gtk.h> +#include <gcrypt.h> #include "imports.h" #include "treeview.h" #include "db-misc.h" @@ -6,25 +7,35 @@ #include "message-dialogs.h" #include "gui-common.h" #include "gquarks.h" +#include "common/common.h" typedef struct edit_data_t { GtkListStore *list_store; GtkTreeIter iter; DatabaseData *db_data; + gchar *current_label; + gchar *new_label; + gchar *current_issuer; + gchar *new_issuer; + gchar *current_secret; + gchar *new_secret; } EditData; static void show_edit_dialog (EditData *edit_data, - AppData *app_data, - gchar *current_label, - gchar *current_issuer); + AppData *app_data); + +static void set_entry_editability (GtkToolButton *btn, + gpointer user_data); static gchar *get_parse_and_set_data_from_entries (EditData *edit_data, + GtkWidget *lab_ck_btn, GtkWidget *new_lab_entry, - GtkWidget *new_iss_entry); + GtkWidget *iss_ck_btn, + GtkWidget *new_iss_entry, + GtkWidget *sec_ck_btn, + GtkWidget *new_sec_entry); -static void set_data_in_lstore_and_json (EditData *edit_data, - const gchar *label, - const gchar *issuer); +static void set_data_in_lstore_and_json (EditData *edit_data); void @@ -40,12 +51,12 @@ edit_data->list_store = GTK_LIST_STORE(model); - gchar *current_label, *current_issuer; if (gtk_tree_selection_get_selected (gtk_tree_view_get_selection (app_data->tree_view), &model, &edit_data->iter)) { - gtk_tree_model_get (model, &edit_data->iter, COLUMN_ACC_LABEL, ¤t_label, COLUMN_ACC_ISSUER, ¤t_issuer, -1); - show_edit_dialog (edit_data, app_data, current_label, current_issuer); - g_free (current_label); - g_free (current_issuer); + gtk_tree_model_get (model, &edit_data->iter, COLUMN_ACC_LABEL, &edit_data->current_label, COLUMN_ACC_ISSUER, &edit_data->current_issuer, -1); + show_edit_dialog (edit_data, app_data); + g_free (edit_data->current_label); + g_free (edit_data->current_issuer); + gcry_free (edit_data->current_secret); } GError *err = NULL; @@ -53,49 +64,65 @@ if (err != NULL && !g_error_matches (err, missing_file_gquark (), MISSING_FILE_CODE)) { show_message_dialog (app_data->main_window, err->message, GTK_MESSAGE_ERROR); } + + g_free (edit_data->new_label); + g_free (edit_data->new_issuer); + if (edit_data->new_secret != NULL) { + gcry_free (edit_data->new_secret); + } g_free (edit_data); } static void show_edit_dialog (EditData *edit_data, - AppData *app_data, - gchar *current_label, - gchar *current_issuer) + AppData *app_data) { GtkBuilder *builder = get_builder_from_partial_path (UI_PARTIAL_PATH); GtkWidget *diag = GTK_WIDGET (gtk_builder_get_object (builder, "edit_diag_id")); gtk_window_set_transient_for (GTK_WINDOW(diag), GTK_WINDOW(app_data->main_window)); - GtkWidget *cur_lab_entry = GTK_WIDGET (gtk_builder_get_object (builder, "cur_label_entry")); - GtkWidget *cur_iss_entry = GTK_WIDGET (gtk_builder_get_object (builder, "cur_iss_entry")); - if (cur_lab_entry != NULL) { - gtk_entry_set_text (GTK_ENTRY (cur_lab_entry), current_label); - } - if (cur_iss_entry != NULL) { - gtk_entry_set_text (GTK_ENTRY (cur_iss_entry), current_issuer); - } - GtkWidget *new_lab_entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry_newlabel_id")); GtkWidget *new_iss_entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry_newissuer_id")); + GtkWidget *new_sec_entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry_newsec_id")); + g_signal_connect (new_sec_entry, "icon-press", G_CALLBACK (icon_press_cb), NULL); - if (current_label != NULL) { - gtk_entry_set_text (GTK_ENTRY(new_lab_entry), current_label); + if (edit_data->current_label != NULL) { + gtk_entry_set_text (GTK_ENTRY(new_lab_entry), edit_data->current_label); } - if (current_issuer != NULL) { - gtk_entry_set_text (GTK_ENTRY(new_iss_entry), current_issuer); + + if (edit_data->current_issuer != NULL) { + gtk_entry_set_text (GTK_ENTRY(new_iss_entry), edit_data->current_issuer); + if (g_ascii_strcasecmp (edit_data->current_issuer, "steam") == 0) { + gtk_widget_set_sensitive (new_iss_entry, FALSE); + } } - if (current_issuer != NULL && g_ascii_strcasecmp (current_issuer, "steam") == 0) { - gtk_widget_set_sensitive (new_iss_entry, FALSE); + guint row_number = get_row_number_from_iter (edit_data->list_store, edit_data->iter); + json_t *obj = json_array_get (edit_data->db_data->json_data, row_number); + edit_data->current_secret = secure_strdup (json_string_value (json_object_get (obj, "secret"))); + if (edit_data->current_secret != NULL) { + gtk_entry_set_text (GTK_ENTRY(new_sec_entry), edit_data->current_secret); } + GtkWidget *lab_ck_btn = GTK_WIDGET (gtk_builder_get_object (builder, "label_check_id")); + g_signal_connect (lab_ck_btn, "toggled", G_CALLBACK (set_entry_editability), new_lab_entry); + + GtkWidget *iss_ck_btn = GTK_WIDGET (gtk_builder_get_object (builder, "issuer_check_id")); + g_signal_connect (iss_ck_btn, "toggled", G_CALLBACK (set_entry_editability), new_iss_entry); + + GtkWidget *sec_ck_btn = GTK_WIDGET (gtk_builder_get_object (builder, "secret_check_id")); + g_signal_connect (sec_ck_btn, "toggled", G_CALLBACK (set_entry_editability), new_sec_entry); + gchar *err_msg = NULL; gint res = gtk_dialog_run (GTK_DIALOG (diag)); switch (res) { case GTK_RESPONSE_OK: - err_msg = get_parse_and_set_data_from_entries (edit_data, new_lab_entry, new_iss_entry); + err_msg = get_parse_and_set_data_from_entries (edit_data, + lab_ck_btn, new_lab_entry, + iss_ck_btn, new_iss_entry, + sec_ck_btn, new_sec_entry); if (err_msg != NULL) { show_message_dialog (app_data->main_window, err_msg, GTK_MESSAGE_ERROR); g_free (err_msg); @@ -111,40 +138,74 @@ } +static void +set_entry_editability (GtkToolButton *btn __attribute__((unused)), + gpointer user_data) +{ + gtk_editable_set_editable (GTK_EDITABLE (user_data), !gtk_editable_get_editable(user_data)); +} + + static gchar * -get_parse_and_set_data_from_entries (EditData *edit_data, - GtkWidget *new_lab_entry, - GtkWidget *new_iss_entry) +get_parse_and_set_data_from_entries (EditData *edit_data, + GtkWidget *lab_ck_btn, + GtkWidget *new_lab_entry, + GtkWidget *iss_ck_btn, + GtkWidget *new_iss_entry, + GtkWidget *sec_ck_btn, + GtkWidget *new_sec_entry) { - const gchar *new_label = gtk_entry_get_text (GTK_ENTRY (new_lab_entry)); - const gchar *new_issuer = gtk_entry_get_text (GTK_ENTRY (new_iss_entry)); + edit_data->new_label = g_strdup (gtk_entry_get_text (GTK_ENTRY (new_lab_entry))); + edit_data->new_issuer = g_strdup (gtk_entry_get_text (GTK_ENTRY (new_iss_entry))); + edit_data->new_secret = secure_strdup (gtk_entry_get_text (GTK_ENTRY (new_sec_entry))); - if (!g_str_is_ascii (new_label) || !g_str_is_ascii (new_issuer)) { - return g_strdup ("Only ASCII characters are supported at the moment."); + if (g_utf8_strlen (edit_data->new_issuer, -1) > 0) { + if (!g_str_is_ascii (edit_data->new_issuer)) { + return g_strdup ("Issuer entry must contain only ASCII characters."); + } } - if (g_utf8_strlen (new_label, -1) == 0) { - return g_strdup ("Label must not be empty"); + if (g_utf8_strlen (edit_data->new_label, -1) < 1 || !g_str_is_ascii (edit_data->new_label)) { + return g_strdup ("Label must not be empty and must contain only ASCII characters."); } - set_data_in_lstore_and_json (edit_data, new_label, new_issuer); + if (!g_str_is_ascii (edit_data->new_secret) || g_utf8_strlen (edit_data->new_secret, -1) < 6) { + return g_strdup ("The secret must be at least 6 characters long and must contain only ASCII characters."); + } + + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(lab_ck_btn)) || g_strcmp0 (edit_data->current_label, edit_data->new_label) == 0) { + g_free (edit_data->new_label); + edit_data->new_label = NULL; + } + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(iss_ck_btn)) || g_strcmp0 (edit_data->current_issuer, edit_data->new_issuer) == 0) { + g_free (edit_data->new_issuer); + edit_data->new_issuer = NULL; + } + if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(sec_ck_btn)) || g_strcmp0 (edit_data->current_secret, edit_data->new_secret) == 0) { + gcry_free (edit_data->new_secret); + edit_data->new_secret = NULL; + } + set_data_in_lstore_and_json (edit_data); return NULL; } static void -set_data_in_lstore_and_json (EditData *edit_data, - const gchar *label, - const gchar *issuer) +set_data_in_lstore_and_json (EditData *edit_data) { - gtk_list_store_set (edit_data->list_store, &edit_data->iter, - COLUMN_ACC_LABEL, label, - COLUMN_ACC_ISSUER, issuer, - -1); - guint row_number = get_row_number_from_iter (edit_data->list_store, edit_data->iter); json_t *obj = json_array_get (edit_data->db_data->json_data, row_number); - json_object_set (obj, "label", json_string (label)); - json_object_set (obj, "issuer", json_string (issuer)); -} + + if (edit_data->new_label != NULL) { + gtk_list_store_set (edit_data->list_store, &edit_data->iter, COLUMN_ACC_LABEL, edit_data->new_label, -1); + json_object_set (obj, "label", json_string (edit_data->new_label)); + } + if (edit_data->new_issuer != NULL) { + gtk_list_store_set (edit_data->list_store, &edit_data->iter, COLUMN_ACC_ISSUER, edit_data->new_issuer, -1); + json_object_set (obj, "issuer", json_string (edit_data->new_issuer)); + } + if (edit_data->new_secret != NULL) { + json_object_set (obj, "secret", json_string (edit_data->new_secret)); + } +} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/imports.c new/OTPClient-3.0.0/src/imports.c --- old/OTPClient-2.6.4/src/imports.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/imports.c 2022-12-09 14:39:38.000000000 +0100 @@ -106,8 +106,6 @@ if (g_strcmp0 (action_name, ANDOTP_IMPORT_ACTION_NAME) == 0 || g_strcmp0 (action_name, ANDOTP_IMPORT_PLAIN_ACTION_NAME) == 0) { content = get_andotp_data (filename, pwd, app_data->db_data->max_file_size_from_memlock, g_strcmp0 (action_name, ANDOTP_IMPORT_ACTION_NAME) == 0 ? TRUE : FALSE , &err); - } else if (g_strcmp0 (action_name, AUTHPLUS_IMPORT_ACTION_NAME) == 0) { - content = get_authplus_data (filename, pwd, app_data->db_data->max_file_size_from_memlock, &err); } else if (g_strcmp0 (action_name, FREEOTPPLUS_IMPORT_ACTION_NAME) == 0) { content = get_freeotpplus_data (filename, &err); } else if (g_strcmp0 (action_name, AEGIS_IMPORT_ACTION_NAME) == 0 || g_strcmp0 (action_name, AEGIS_IMPORT_ENC_ACTION_NAME) == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/imports.h new/OTPClient-3.0.0/src/imports.h --- old/OTPClient-2.6.4/src/imports.h 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/imports.h 2022-12-09 14:39:38.000000000 +0100 @@ -7,7 +7,6 @@ #define ANDOTP_IMPORT_ACTION_NAME "import_andotp" #define ANDOTP_IMPORT_PLAIN_ACTION_NAME "import_andotp_plain" -#define AUTHPLUS_IMPORT_ACTION_NAME "import_authplus" #define FREEOTPPLUS_IMPORT_ACTION_NAME "import_freeotpplus" #define AEGIS_IMPORT_ACTION_NAME "import_aegis" #define AEGIS_IMPORT_ENC_ACTION_NAME "import_aegis_enc" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/main.c new/OTPClient-3.0.0/src/main.c --- old/OTPClient-2.6.4/src/main.c 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/main.c 2022-12-09 14:39:38.000000000 +0100 @@ -1,4 +1,5 @@ #include <gtk/gtk.h> +#include <glib/gi18n.h> #include "otpclient.h" #include "version.h" @@ -6,7 +7,17 @@ main (gint argc, gchar **argv) { - GtkApplication *app = gtk_application_new ("com.github.paolostivanin.OTPClient", G_APPLICATION_FLAGS_NONE); + bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + GApplicationFlags flags; +#if GLIB_CHECK_VERSION(2, 74, 0) + flags = G_APPLICATION_DEFAULT_FLAGS; +#else + flags = G_APPLICATION_FLAGS_NONE; +#endif + GtkApplication *app = gtk_application_new ("com.github.paolostivanin.OTPClient", flags); g_set_application_name (PROJECT_NAME); g_signal_connect (app, "activate", G_CALLBACK (activate), NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/otpclient.h new/OTPClient-3.0.0/src/otpclient.h --- old/OTPClient-2.6.4/src/otpclient.h 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/otpclient.h 2022-12-09 14:39:38.000000000 +0100 @@ -41,6 +41,10 @@ GVariant *parameter, gpointer user_data); +void about_diag_cb (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data); + void destroy_cb (GtkWidget *window, gpointer user_data); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/OTPClient-2.6.4/src/ui/otpclient.ui new/OTPClient-3.0.0/src/ui/otpclient.ui --- old/OTPClient-2.6.4/src/ui/otpclient.ui 2022-11-30 17:07:46.000000000 +0100 +++ new/OTPClient-3.0.0/src/ui/otpclient.ui 2022-12-09 14:39:38.000000000 +0100 @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.38.2 --> +<!-- Generated with glade 3.40.0 --> <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkPopoverMenu" id="add_pop_id"> @@ -828,7 +828,7 @@ <object class="GtkBox"> <property name="can-focus">False</property> <property name="orientation">vertical</property> - <property name="spacing">10</property> + <property name="spacing">5</property> <child internal-child="action_area"> <object class="GtkButtonBox"> <property name="can-focus">False</property> @@ -870,9 +870,13 @@ <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Please note that "account" is <b>mandatory</b> and "issuer", while optional, is <b>highly recommended</b></property> + <property name="margin-bottom">5</property> + <property name="label" translatable="yes">Please note that: +- "account" is <b>mandatory</b> +- "issuer", while optional, is <b>highly recommended</b> +- when changing the "secret", be aware that <b>only the secret</b> itself can be changed, +but not the number of digits and/or the period/counter.</property> <property name="use-markup">True</property> - <property name="justify">center</property> <property name="wrap">True</property> </object> <packing> @@ -886,7 +890,7 @@ <property name="visible">True</property> <property name="can-focus">False</property> <property name="orientation">vertical</property> - <property name="spacing">10</property> + <property name="spacing">8</property> <child> <object class="GtkFrame"> <property name="visible">True</property> @@ -897,14 +901,42 @@ <object class="GtkAlignment"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="left-padding">12</property> + <property name="top-padding">7</property> + <property name="bottom-padding">12</property> + <property name="left-padding">10</property> + <property name="right-padding">10</property> <child> - <object class="GtkEntry" id="entry_newlabel_id"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="margin-right">5</property> - <property name="margin-bottom">5</property> - <property name="max-length">64</property> + <property name="can-focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkCheckButton" id="label_check_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Check if you want to edit the "Account"</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_newlabel_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="editable">False</property> + <property name="max-length">64</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> </object> </child> </object> @@ -913,7 +945,7 @@ <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">New account</property> + <property name="label" translatable="yes">Account</property> </object> </child> </object> @@ -933,14 +965,42 @@ <object class="GtkAlignment"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="left-padding">12</property> + <property name="top-padding">7</property> + <property name="bottom-padding">12</property> + <property name="left-padding">10</property> + <property name="right-padding">10</property> <child> - <object class="GtkEntry" id="entry_newissuer_id"> + <object class="GtkBox"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="margin-right">5</property> - <property name="margin-bottom">5</property> - <property name="max-length">64</property> + <property name="can-focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkCheckButton" id="issuer_check_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Check if you want to edit the "Issuer"</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_newissuer_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="editable">False</property> + <property name="max-length">64</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> </object> </child> </object> @@ -949,7 +1009,7 @@ <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">New issuer</property> + <property name="label" translatable="yes">Issuer</property> </object> </child> </object> @@ -959,6 +1019,72 @@ <property name="position">1</property> </packing> </child> + <child> + <object class="GtkFrame"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label-xalign">0</property> + <property name="shadow-type">in</property> + <child> + <object class="GtkAlignment"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="top-padding">7</property> + <property name="bottom-padding">12</property> + <property name="left-padding">10</property> + <property name="right-padding">10</property> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="spacing">5</property> + <child> + <object class="GtkCheckButton" id="secret_check_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Check if you want to edit the "Secret"</property> + <property name="draw-indicator">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_newsec_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="editable">False</property> + <property name="max-length">255</property> + <property name="visibility">False</property> + <property name="secondary-icon-name">dialog-password-symbolic</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Secret</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="expand">True</property> @@ -2097,6 +2223,20 @@ <property name="position">7</property> </packing> </child> + <child> + <object class="GtkModelButton" id="about_model_btn_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="action-name">settings_menu.about</property> + <property name="text" translatable="yes">About</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">8</property> + </packing> + </child> </object> <packing> <property name="submenu">main</property> @@ -2156,7 +2296,6 @@ <property name="orientation">vertical</property> <child> <object class="GtkInfoBar" id="info_bar_id"> - <property name="visible">False</property> <property name="can-focus">False</property> <property name="orientation">vertical</property> <child internal-child="action_area"> @@ -2238,6 +2377,11 @@ </object> </child> </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> </child> </object> </child> @@ -2246,6 +2390,7 @@ <property name="visible">True</property> <property name="can-focus">False</property> <property name="title" translatable="yes">OTPClient</property> + <property name="has-subtitle">False</property> <property name="show-close-button">True</property> <child> <object class="GtkBox" id="main_hbar"> @@ -2337,7 +2482,7 @@ <object class="GtkImage"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="icon-name">system-lock-screen-symbolic.symbolic</property> + <property name="icon-name">system-lock-screen-symbolic</property> </object> </child> </object>