Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package otpclient for openSUSE:Factory checked in at 2024-03-08 18:10:15 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/otpclient (Old) and /work/SRC/openSUSE:Factory/.otpclient.new.1770 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "otpclient" Fri Mar 8 18:10:15 2024 rev:35 rq:1156324 version:3.5.2 Changes: -------- --- /work/SRC/openSUSE:Factory/otpclient/otpclient.changes 2024-03-05 18:51:59.603943557 +0100 +++ /work/SRC/openSUSE:Factory/.otpclient.new.1770/otpclient.changes 2024-03-08 18:10:26.224913431 +0100 @@ -1,0 +2,10 @@ +Fri Mar 8 10:32:23 UTC 2024 - Paolo Stivanin <i...@paolostivanin.com> + +- Update to 3.5.2: + * NEW: add possibility to export plain/encrypted + Authenticator Pro/2FAS backups using the CLI. + * FIX: improve popover layout. + * FIX: exporting plaing Aegis via CLI. + * FIX: cleanup code. + +------------------------------------------------------------------- Old: ---- v3.5.1.tar.gz v3.5.1.tar.gz.asc New: ---- v3.5.2.tar.gz v3.5.2.tar.gz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ otpclient.spec ++++++ --- /var/tmp/diff_new_pack.WoGfr7/_old 2024-03-08 18:10:26.920939008 +0100 +++ /var/tmp/diff_new_pack.WoGfr7/_new 2024-03-08 18:10:26.924939155 +0100 @@ -18,7 +18,7 @@ %define uclname OTPClient Name: otpclient -Version: 3.5.1 +Version: 3.5.2 Release: 0 Summary: Simple GTK+ client for managing TOTP and HOTP License: GPL-3.0-or-later ++++++ v3.5.1.tar.gz -> v3.5.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/.circleci/config.yml new/OTPClient-3.5.2/.circleci/config.yml --- old/OTPClient-3.5.1/.circleci/config.yml 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/.circleci/config.yml 2024-03-08 11:29:39.000000000 +0100 @@ -1,21 +1,12 @@ version: 2.0 jobs: - ubuntu2404: - docker: - - image: ubuntu:24.04 - steps: - - checkout - - run: apt update && DEBIAN_FRONTEND=noninteractive apt -y install git gcc clang cmake libgcrypt20-dev libgtk-3-dev libzip-dev libjansson-dev libpng-dev libzbar-dev libprotobuf-c-dev libsecret-1-dev uuid-dev libprotobuf-dev libqrencode-dev - - run: chmod +x .ci/install_deps.sh && .ci/install_deps.sh - - run: chmod +x .ci/install_otpclient.sh && .ci/install_otpclient.sh - - ubuntuLatestRolling: + archlinux: docker: - - image: ubuntu:rolling + - image: archlinux:latest steps: - checkout - - run: apt update && DEBIAN_FRONTEND=noninteractive apt -y install git gcc clang cmake libgcrypt20-dev libgtk-3-dev libzip-dev libjansson-dev libpng-dev libzbar-dev libprotobuf-c-dev libsecret-1-dev uuid-dev libprotobuf-dev libqrencode-dev + - run: pacman -Syu --noconfirm && pacman -S --noconfirm pkg-config git gtk3 libgcrypt zbar gcc clang cmake make libzip jansson libpng protobuf-c libsecret util-linux-libs qrencode - run: chmod +x .ci/install_deps.sh && .ci/install_deps.sh - run: chmod +x .ci/install_otpclient.sh && .ci/install_otpclient.sh @@ -37,12 +28,12 @@ - run: chmod +x .ci/install_deps.sh && .ci/install_deps.sh - run: chmod +x .ci/install_otpclient.sh && .ci/install_otpclient.sh - archlinux: + ubuntu2404: docker: - - image: archlinux:latest + - image: ubuntu:24.04 steps: - checkout - - run: pacman -Syu --noconfirm && pacman -S --noconfirm pkg-config git gtk3 libgcrypt zbar gcc clang cmake make libzip jansson libpng protobuf-c libsecret util-linux-libs qrencode + - run: apt update && DEBIAN_FRONTEND=noninteractive apt -y install git gcc clang cmake libgcrypt20-dev libgtk-3-dev libzip-dev libjansson-dev libpng-dev libzbar-dev libprotobuf-c-dev libsecret-1-dev uuid-dev libprotobuf-dev libqrencode-dev - run: chmod +x .ci/install_deps.sh && .ci/install_deps.sh - run: chmod +x .ci/install_otpclient.sh && .ci/install_otpclient.sh @@ -50,8 +41,7 @@ version: 2 build: jobs: - - ubuntu2404 - - ubuntuLatestRolling + - archlinux - debianLatestStable - fedoraLatestStable - - archlinux + - ubuntu2404 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/CMakeLists.txt new/OTPClient-3.5.2/CMakeLists.txt --- old/OTPClient-3.5.1/CMakeLists.txt 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/CMakeLists.txt 2024-03-08 11:29:39.000000000 +0100 @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.16) -project(OTPClient VERSION "3.5.1" LANGUAGES "C") +project(OTPClient VERSION "3.5.2" LANGUAGES "C") include(GNUInstallDirs) configure_file("src/common/version.h.in" "version.h") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/data/com.github.paolostivanin.OTPClient.appdata.xml new/OTPClient-3.5.2/data/com.github.paolostivanin.OTPClient.appdata.xml --- old/OTPClient-3.5.1/data/com.github.paolostivanin.OTPClient.appdata.xml 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/data/com.github.paolostivanin.OTPClient.appdata.xml 2024-03-08 11:29:39.000000000 +0100 @@ -89,7 +89,18 @@ </content_rating> <releases> - <release version="3.5.0" date="2024-03-05"> + <release version="3.5.2" date="2024-03-08"> + <description> + <p>OTPClient 3.5.2 brings some small improvements:</p> + <ul> + <li>NEW: add possibility to export plain/encrypted Authenticator Pro/2FAS backups using the CLI</li> + <li>FIX: improve popover layout</li> + <li>FIX: exporting plaing Aegis via CLI</li> + <li>FIX: cleanup code</li> + </ul> + </description> + </release> + <release version="3.5.1" date="2024-03-05"> <description> <p>OTPClient 3.5.1 brings a small improvement and some code clean-up:</p> <ul> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/cli/exec-action.c new/OTPClient-3.5.2/src/cli/exec-action.c --- old/OTPClient-3.5.1/src/cli/exec-action.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/cli/exec-action.c 2024-03-08 11:29:39.000000000 +0100 @@ -124,6 +124,32 @@ gcry_free (export_pwd); exported = TRUE; } + if (g_ascii_strcasecmp (cmdline_opts->export_type, "twofas_plain") == 0 || g_ascii_strcasecmp (cmdline_opts->export_type, "twofas_encrypted") == 0) { + if (g_ascii_strcasecmp (cmdline_opts->export_type, "twofas_encrypted") == 0) { + export_pwd = get_pwd (_("Type the export encryption password: ")); + if (export_pwd == NULL) { + free_dbdata (db_data); + return FALSE; + } + } + exported_file_path = g_build_filename (export_directory, export_pwd != NULL ? "twofas_encrypted_v4.2fas" : "twofas_plain_v4.2fas", NULL); + ret_msg = export_twofas (exported_file_path, export_pwd, db_data->json_data); + gcry_free (export_pwd); + exported = TRUE; + } + if (g_ascii_strcasecmp (cmdline_opts->export_type, "authpro_plain") == 0 || g_ascii_strcasecmp (cmdline_opts->export_type, "authpro_encrypted") == 0) { + if (g_ascii_strcasecmp (cmdline_opts->export_type, "authpro_encrypted") == 0) { + export_pwd = get_pwd (_("Type the export encryption password: ")); + if (export_pwd == NULL) { + free_dbdata (db_data); + return FALSE; + } + } + exported_file_path = g_build_filename (export_directory, export_pwd != NULL ? "authpro_encrypted.bin" : "authpro_plain.json", NULL); + ret_msg = export_authpro (exported_file_path, export_pwd, db_data->json_data); + gcry_free (export_pwd); + exported = TRUE; + } if (ret_msg != NULL) { g_printerr (_("An error occurred while exporting the data: %s\n"), ret_msg); g_free (ret_msg); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/cli/main.c new/OTPClient-3.5.2/src/cli/main.c --- old/OTPClient-3.5.1/src/cli/main.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/cli/main.c 2024-03-08 11:29:39.000000000 +0100 @@ -34,7 +34,7 @@ { "show-next", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show also next OTP (to be used with --show, optional)", NULL}, { "list", 'l', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "List all accounts and issuers for a given database.", NULL }, { "export", 'e', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Export a database.", NULL }, - { "type", 't', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL, "The export type for the database. Must be either one of: andotp_plain, andotp_encrypted, freeotpplus, aegis, aegis_encrypted (to be used with --export, mandatory)", NULL }, + { "type", 't', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL, "The export type for the database. Must be either one of: andotp_plain, andotp_encrypted, freeotpplus, aegis_plain, aegis_encrypted, twofas_plain, twofas_encrypted, authpro_plain, authpro_encrypted (to be used with --export, mandatory)", NULL }, #ifndef USE_FLATPAK_APP_FOLDER { "output-dir", 'o', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL, "The output directory (defaults to the user's home. To be used with --export, optional)", NULL }, #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/db-misc.c new/OTPClient-3.5.2/src/db-misc.c --- old/OTPClient-3.5.1/src/db-misc.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/db-misc.c 2024-03-08 11:29:39.000000000 +0100 @@ -14,25 +14,41 @@ guint8 salt[KDF_SALT_SIZE]; } HeaderData; -static void reload_db (DatabaseData *db_data, GError **err); +static void reload_db (DatabaseData *db_data, + GError **err); -static void update_db (DatabaseData *db_data, GError **err); +static void update_db (DatabaseData *db_data, + GError **err); -static gpointer encrypt_db (const gchar *db_path, const gchar *in_memory_json, const gchar *password, GError **err); +static gpointer encrypt_db (const gchar *db_path, + const gchar *in_memory_json, + const gchar *password, + GError **err); -static inline void add_to_json (gpointer list_elem, gpointer json_array); +static inline void add_to_json (gpointer list_elem, + gpointer json_array); -static gchar *decrypt_db (const gchar *db_path, const gchar *password); +static gchar *decrypt_db (const gchar *db_path, + const gchar *password); -static guchar *get_derived_key (const gchar *pwd, HeaderData *header_data); +static guchar *get_derived_key (const gchar *pwd, + HeaderData *header_data); -static void backup_db (const gchar *path); +static void backup_db (const gchar *path); -static void restore_db (const gchar *path); +static void restore_db (const gchar *path); -static inline void json_free (gpointer data); +static inline void json_free (gpointer data); -static void cleanup (GFile *, gpointer, HeaderData *, GError *); +static void cleanup_gfile (GFile *file, + gpointer stream, + GError *err); + +static void free_resources (gcry_cipher_hd_t hd, + guchar *derived_key, + guchar *enc_buf, + gchar *dec_buf, + HeaderData *header_data); void @@ -213,20 +229,23 @@ if (local_err != NULL) { g_printerr ("%s\n", local_err->message); g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed to replace existing file"); - cleanup (out_file, NULL, header_data, local_err); + cleanup_gfile (out_file, NULL, local_err); + g_free (header_data); return GENERIC_ERROR; } if (g_output_stream_write (G_OUTPUT_STREAM (out_stream), header_data, sizeof (HeaderData), NULL, &local_err) == -1) { g_printerr ("%s\n", local_err->message); g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed while writing header data to file"); - cleanup (out_file, out_stream, header_data, local_err); + cleanup_gfile (out_file, out_stream, local_err); + g_free (header_data); return GENERIC_ERROR; } guchar *derived_key = get_derived_key (password, header_data); if (derived_key == SECURE_MEMORY_ALLOC_ERR || derived_key == KEY_DERIV_ERR) { - cleanup (out_file, out_stream, header_data, local_err); g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed to derive key.\nPlease check <a href=\"https://github.com/paolostivanin/OTPClient/wiki/Secure-Memory-Limitations\">Secure Memory wiki page</a>"); + cleanup_gfile (out_file, out_stream, local_err); + g_free (header_data); return (gpointer)derived_key; } @@ -235,28 +254,23 @@ gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, header_data->iv, IV_SIZE); if (hd == NULL) { - gcry_free (derived_key); - g_free (header_data); - g_free (enc_buffer); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (NULL, derived_key, enc_buffer, NULL, header_data); return NULL; } gpg_error_t gpg_err = gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData)); if (gpg_err) { g_printerr ("%s\n", _("Error while processing the authenticated data.")); - gcry_free (derived_key); - g_free (header_data); - g_free (enc_buffer); - gcry_cipher_close (hd); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); return GENERIC_ERROR; } gpg_err = gcry_cipher_encrypt (hd, enc_buffer, input_data_len, in_memory_json, input_data_len); if (gpg_err) { g_printerr ("%s\n", _("Error while encrypting the data.")); - gcry_free (derived_key); - g_free (enc_buffer); - g_free (header_data); - gcry_cipher_close (hd); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); return GENERIC_ERROR; } @@ -264,34 +278,26 @@ gpg_err = gcry_cipher_gettag (hd, tag, TAG_SIZE); //append tag to outfile if (gpg_err) { g_printerr ("%s\n", _("Error while getting the tag.")); - gcry_free (derived_key); - g_free (enc_buffer); - g_free (header_data); - gcry_cipher_close (hd); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); return GENERIC_ERROR; } if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), enc_buffer, input_data_len, NULL, &local_err) == -1) { g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed while writing encrypted buffer to file"); - cleanup (out_file, out_stream, header_data, local_err); - g_free (enc_buffer); - gcry_free (derived_key); - gcry_cipher_close (hd); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); return GENERIC_ERROR; } if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), tag, TAG_SIZE, NULL, &local_err) == -1) { g_set_error (err, generic_error_gquark (), GENERIC_ERRCODE, "Failed while writing tag data to file"); - cleanup (out_file, out_stream, header_data, local_err); - g_free (enc_buffer); - gcry_free (derived_key); - gcry_cipher_close (hd); + cleanup_gfile (out_file, out_stream, local_err); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); return GENERIC_ERROR; } - g_free (enc_buffer); - gcry_free (derived_key); - gcry_cipher_close (hd); - cleanup (out_file, out_stream, header_data, NULL); + free_resources (hd, derived_key, enc_buffer, NULL, header_data); + cleanup_gfile (out_file, out_stream, NULL); return NULL; } @@ -310,24 +316,28 @@ GFileInputStream *in_stream = g_file_read (in_file, NULL, &err); if (err != NULL) { g_printerr ("%s\n", err->message); - cleanup (in_file, NULL, header_data, err); + cleanup_gfile (in_file, NULL, err); + g_free (header_data); return GENERIC_ERROR; } if (g_input_stream_read (G_INPUT_STREAM (in_stream), header_data, sizeof (HeaderData), NULL, &err) == -1) { g_printerr ("%s\n", err->message); - cleanup (in_file, in_stream, header_data, err); + cleanup_gfile (in_file, in_stream, err); + g_free (header_data); return GENERIC_ERROR; } guchar tag[TAG_SIZE]; if (!g_seekable_seek (G_SEEKABLE (in_stream), input_file_size - TAG_SIZE, G_SEEK_SET, NULL, &err)) { g_printerr ("%s\n", err->message); - cleanup (in_file, in_stream, header_data, err); + cleanup_gfile (in_file, in_stream, err); + g_free (header_data); return GENERIC_ERROR; } if (g_input_stream_read (G_INPUT_STREAM (in_stream), tag, TAG_SIZE, NULL, &err) == -1) { g_printerr ("%s\n", err->message); - cleanup (in_file, in_stream, header_data, err); + cleanup_gfile (in_file, in_stream, err); + g_free (header_data); return GENERIC_ERROR; } @@ -336,14 +346,14 @@ if (!g_seekable_seek (G_SEEKABLE (in_stream), sizeof (HeaderData), G_SEEK_SET, NULL, &err)) { g_printerr ("%s\n", err->message); - cleanup (in_file, in_stream, header_data, err); - g_free (enc_buf); + cleanup_gfile (in_file, in_stream, err); + return GENERIC_ERROR; } if (g_input_stream_read (G_INPUT_STREAM (in_stream), enc_buf, enc_buf_size, NULL, &err) == -1) { g_printerr ("%s\n", err->message); - cleanup (in_file, in_stream, header_data, err); - g_free (enc_buf); + cleanup_gfile (in_file, in_stream, err); + free_resources (NULL, NULL, enc_buf, NULL, header_data); return GENERIC_ERROR; } g_object_unref (in_stream); @@ -351,61 +361,41 @@ guchar *derived_key = get_derived_key (password, header_data); if (derived_key == SECURE_MEMORY_ALLOC_ERR || derived_key == KEY_DERIV_ERR) { - g_free (header_data); - g_free (enc_buf); + free_resources (NULL, NULL, enc_buf, NULL, header_data); return (gpointer)derived_key; } gcry_cipher_hd_t hd = open_cipher_and_set_data (derived_key, header_data->iv, IV_SIZE); if (hd == NULL) { - gcry_free (derived_key); - g_free (enc_buf); - g_free (header_data); + free_resources (NULL, derived_key, enc_buf, NULL, header_data); return GENERIC_ERROR; } gpg_error_t gpg_err = gcry_cipher_authenticate (hd, header_data, sizeof (HeaderData)); if (gpg_err) { g_printerr ("%s\n", _("Error while processing the authenticated data.")); - gcry_free (derived_key); - g_free (header_data); - g_free (enc_buf); - gcry_cipher_close (hd); + free_resources (hd, derived_key, enc_buf, NULL, header_data); return GENERIC_ERROR; } gchar *dec_buf = gcry_calloc_secure (enc_buf_size, 1); if (dec_buf == NULL) { g_printerr ("%s\n", _("Error while allocating secure memory.")); - gcry_free (derived_key); - g_free (header_data); - g_free (enc_buf); - gcry_cipher_close (hd); + free_resources (hd, derived_key, enc_buf, NULL, header_data); return GENERIC_ERROR; } gpg_err = gcry_cipher_decrypt (hd, dec_buf, enc_buf_size, enc_buf, enc_buf_size); if (gpg_err) { g_printerr ("%s\n", _("Error while decrypting the data.")); - gcry_free (derived_key); - gcry_free (dec_buf); - g_free (header_data); - g_free (enc_buf); - gcry_cipher_close (hd); + free_resources (hd, derived_key, enc_buf, dec_buf, header_data); return GENERIC_ERROR; } if (gcry_err_code (gcry_cipher_checktag (hd, tag, TAG_SIZE)) == GPG_ERR_CHECKSUM) { - gcry_cipher_close (hd); - gcry_free (derived_key); - gcry_free (dec_buf); - g_free (header_data); - g_free (enc_buf); + free_resources (hd, derived_key, enc_buf, dec_buf, header_data); return TAG_MISMATCH; } - gcry_cipher_close (hd); - gcry_free (derived_key); - g_free (header_data); - g_free (enc_buf); + free_resources (hd, derived_key, enc_buf, NULL, header_data); return dec_buf; } @@ -435,38 +425,42 @@ static void -backup_db (const gchar *path) +perform_backup_restore (const gchar *path, + gboolean is_backup) { GError *err = NULL; - GFile *src = g_file_new_for_path (path); - gchar *dst_path = g_strconcat (path, ".bak", NULL); + gchar *src_path = is_backup ? g_strdup (path) : g_strconcat (path, ".bak", NULL); + gchar *dst_path = is_backup ? g_strconcat (path, ".bak", NULL) : g_strdup (path); + + GFile *src = g_file_new_for_path (src_path); GFile *dst = g_file_new_for_path (dst_path); + + g_free (src_path); g_free (dst_path); + if (!g_file_copy (src, dst, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, &err)) { - g_printerr ("Couldn't create the backup file: %s\n", err->message); + g_printerr ("Couldn't %s: %s\n", is_backup ? "create the backup" : "restore the backup", err->message); g_clear_error (&err); + } else { + g_print("%s\n", is_backup ? _("Backup copy successfully created.") : _("Backup copy successfully restored.")); } + g_object_unref (src); g_object_unref (dst); } static void +backup_db (const gchar *path) +{ + perform_backup_restore (path, TRUE); +} + + +static void restore_db (const gchar *path) { - GError *err = NULL; - gchar *src_path = g_strconcat (path, ".bak", NULL); - GFile *src = g_file_new_for_path (src_path); - GFile *dst = g_file_new_for_path (path); - g_free (src_path); - if (!g_file_copy (src, dst, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, NULL, NULL, NULL, &err)) { - g_printerr ("Couldn't restore the backup file: %s\n", err->message); - g_clear_error (&err); - } else { - g_print ("%s\n", _("Backup copy successfully restored.")); - } - g_object_unref (src); - g_object_unref (dst); + perform_backup_restore (path, FALSE); } @@ -478,16 +472,32 @@ static void -cleanup (GFile *in_file, - gpointer in_stream, - HeaderData *header_data, - GError *err) +cleanup_gfile (GFile *file, + gpointer stream, + GError *err) { - g_object_unref (in_file); - if (in_stream != NULL) - g_object_unref (in_stream); - if (header_data != NULL) - g_free (header_data); - if (err != NULL) - g_clear_error (&err); + g_object_unref (file); + g_clear_error (&err); + + if (stream != NULL) + g_object_unref (stream); } + + +static void +free_resources (gcry_cipher_hd_t hd, + guchar *derived_key, + guchar *enc_buf, + gchar *dec_buf, + HeaderData *header_data) +{ + g_free (enc_buf); + g_free (header_data); + + if (hd != NULL) + gcry_cipher_close (hd); + if (derived_key != NULL) + gcry_free (derived_key); + if (dec_buf != NULL) + gcry_free (dec_buf); +} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/dbinfo-cb.c new/OTPClient-3.5.2/src/dbinfo-cb.c --- old/OTPClient-3.5.1/src/dbinfo-cb.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/dbinfo-cb.c 2024-03-08 11:29:39.000000000 +0100 @@ -3,8 +3,8 @@ void dbinfo_cb (GSimpleAction *simple __attribute__((unused)), - GVariant *parameter __attribute__((unused)), - gpointer user_data) + GVariant *parameter __attribute__((unused)), + gpointer user_data) { AppData *app_data = (AppData *)user_data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/dbinfo-cb.h new/OTPClient-3.5.2/src/dbinfo-cb.h --- old/OTPClient-3.5.1/src/dbinfo-cb.h 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/dbinfo-cb.h 2024-03-08 11:29:39.000000000 +0100 @@ -4,8 +4,8 @@ G_BEGIN_DECLS -void dbinfo_cb (GSimpleAction *simple, - GVariant *parameter, - gpointer user_data); +void dbinfo_cb (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data); G_END_DECLS \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/edit-row-cb.h new/OTPClient-3.5.2/src/edit-row-cb.h --- old/OTPClient-3.5.1/src/edit-row-cb.h 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/edit-row-cb.h 2024-03-08 11:29:39.000000000 +0100 @@ -4,11 +4,11 @@ G_BEGIN_DECLS -void edit_row_cb (GSimpleAction *simple, - GVariant *parameter, - gpointer user_data); +void edit_row_cb (GSimpleAction *simple, + GVariant *parameter, + gpointer user_data); -void edit_row_cb_shortcut (GtkWidget *w, - gpointer user_data); +void edit_row_cb_shortcut (GtkWidget *w, + gpointer user_data); G_END_DECLS \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/password-cb.c new/OTPClient-3.5.2/src/password-cb.c --- old/OTPClient-3.5.1/src/password-cb.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/password-cb.c 2024-03-08 11:29:39.000000000 +0100 @@ -3,7 +3,6 @@ #include "gui-common.h" #include "message-dialogs.h" #include "get-builder.h" -#include "otpclient.h" #include "common/common.h" typedef struct entrywidgets_t { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/qrcode-parser.c new/OTPClient-3.5.2/src/qrcode-parser.c --- old/OTPClient-3.5.1/src/qrcode-parser.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/qrcode-parser.c 2024-03-08 11:29:39.000000000 +0100 @@ -19,7 +19,6 @@ parse_qrcode (const gchar *png_path, gchar **otpauth_uri) { - zbar_image_scanner_t *scanner = zbar_image_scanner_create (); zbar_image_scanner_set_config (scanner, ZBAR_NONE, ZBAR_CFG_ENABLE, 1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/setup-signals-shortcuts.c new/OTPClient-3.5.2/src/setup-signals-shortcuts.c --- old/OTPClient-3.5.1/src/setup-signals-shortcuts.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/setup-signals-shortcuts.c 2024-03-08 11:29:39.000000000 +0100 @@ -9,6 +9,12 @@ #include "show-qr-cb.h" #include "change-db-cb.h" +static const char *signal_names[] = { + "toggle-reorder-button", "toggle-delete-button", "lock-app", + "change-db", "change-pwd", "show-settings", "show-kb-shortcuts", + "scan-webcam", "manual-add", "edit-row", "show-qr" +}; + static void setup_signals (void); static void connect_signals (AppData *app_data); @@ -24,51 +30,52 @@ GtkBindingSet *mw_binding_set = gtk_binding_set_by_class (GTK_APPLICATION_WINDOW_GET_CLASS(app_data->main_window)); - gtk_binding_entry_add_signal(mw_binding_set, GDK_KEY_r, GDK_CONTROL_MASK, "toggle-reorder-button", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_d, GDK_CONTROL_MASK, "toggle-delete-button", 0); + gtk_binding_entry_add_signal(mw_binding_set, GDK_KEY_r, GDK_CONTROL_MASK, signal_names[0], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_d, GDK_CONTROL_MASK, signal_names[1], 0); if (app_data->auto_lock == TRUE || app_data->inactivity_timeout > 0) { // auto-lock is enabled, so secret service is disabled, therefore we allow the shortcut - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_l, GDK_CONTROL_MASK, "lock-app", 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_l, GDK_CONTROL_MASK, signal_names[2], 0); } - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_b, GDK_CONTROL_MASK, "change-db", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_o, GDK_CONTROL_MASK, "change-pwd", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_s, GDK_CONTROL_MASK, "show-settings", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_k, GDK_CONTROL_MASK, "show-kb-shortcuts", 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_b, GDK_CONTROL_MASK, signal_names[3], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_o, GDK_CONTROL_MASK, signal_names[4], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_s, GDK_CONTROL_MASK, signal_names[5], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_k, GDK_CONTROL_MASK, signal_names[6], 0); // GDM_MOD1_MASK: the fourth modifier key (it depends on the modifier mapping of the X server which key is interpreted as this modifier, but normally it is the Alt key). - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_w, GDK_MOD1_MASK, "scan-webcam", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_m, GDK_MOD1_MASK, "manual-add", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_e, GDK_MOD1_MASK, "edit-row", 0); - gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_q, GDK_MOD1_MASK, "show-qr", 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_w, GDK_MOD1_MASK, signal_names[7], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_m, GDK_MOD1_MASK, signal_names[8], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_e, GDK_MOD1_MASK, signal_names[9], 0); + gtk_binding_entry_add_signal (mw_binding_set, GDK_KEY_q, GDK_MOD1_MASK, signal_names[10], 0); } static void setup_signals (void) { - g_signal_new ("toggle-reorder-button", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("toggle-delete-button", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("lock-app", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("change-db", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("change-pwd", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("show-settings", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("show-kb-shortcuts", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("scan-webcam", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("manual-add", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("edit-row", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - g_signal_new ("show-qr", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + for (int i = 0; i < G_N_ELEMENTS(signal_names); ++i) { + g_signal_new (signal_names[i], G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 0, NULL, NULL, NULL, G_TYPE_NONE, 0); + } } static void connect_signals (AppData *app_data) { - g_signal_connect (app_data->main_window, "change-db", G_CALLBACK(change_db_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "change-pwd", G_CALLBACK(change_pwd_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "show-settings", G_CALLBACK(show_settings_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "show-kb-shortcuts", G_CALLBACK(show_kbs_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "scan-webcam", G_CALLBACK(webcam_add_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "manual-add", G_CALLBACK(manual_add_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "edit-row", G_CALLBACK(edit_row_cb_shortcut), app_data); - g_signal_connect (app_data->main_window, "show-qr", G_CALLBACK(show_qr_cb_shortcut), app_data); + struct { + const char *signal_name; + GCallback callback; + } signal_connections[] = { + {"change-db", G_CALLBACK(change_db_cb_shortcut)}, + {"change-pwd", G_CALLBACK(change_pwd_cb_shortcut)}, + {"show-settings", G_CALLBACK(show_settings_cb_shortcut)}, + {"show-kb-shortcuts", G_CALLBACK(show_kbs_cb_shortcut)}, + {"scan-webcam", G_CALLBACK(webcam_add_cb_shortcut)}, + {"manual-add", G_CALLBACK(manual_add_cb_shortcut)}, + {"edit-row", G_CALLBACK(edit_row_cb_shortcut)}, + {"show-qr", G_CALLBACK(show_qr_cb_shortcut)} + }; + + for (int i = 0; i < G_N_ELEMENTS(signal_connections); ++i) { + g_signal_connect (app_data->main_window, signal_connections[i].signal_name, signal_connections[i].callback, app_data); + } } \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/treeview.c new/OTPClient-3.5.2/src/treeview.c --- old/OTPClient-3.5.1/src/treeview.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/treeview.c 2024-03-08 11:29:39.000000000 +0100 @@ -277,9 +277,9 @@ ParsedData *pjd) { gsize array_len = json_array_size (array); - pjd->types = (gchar **) g_malloc0 ((array_len + 1) * sizeof (gchar *)); - pjd->labels = (gchar **) g_malloc0 ((array_len + 1) * sizeof (gchar *)); - pjd->issuers = (gchar **) g_malloc0 ((array_len + 1) * sizeof (gchar *)); + pjd->types = (gchar **)g_malloc0 ((array_len + 1) * sizeof(gchar *)); + pjd->labels = (gchar **)g_malloc0 ((array_len + 1) * sizeof(gchar *)); + pjd->issuers = (gchar **)g_malloc0 ((array_len + 1) * sizeof(gchar *)); pjd->periods = g_array_new (FALSE, FALSE, sizeof(gint)); for (guint i = 0; i < array_len; i++) { json_t *obj = json_array_get (array, i); @@ -323,51 +323,33 @@ static void -add_columns (GtkTreeView *tree_view) +add_column_with_attributes (GtkTreeView *tree_view, + const gchar *title, + gint column_id, + gboolean visible) { GtkCellRenderer *renderer = gtk_cell_renderer_text_new (); - GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes ("Type", renderer, "text", COLUMN_TYPE, NULL); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Account", renderer, "text", COLUMN_ACC_LABEL, NULL); - gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Issuer", renderer, "text", COLUMN_ACC_ISSUER, NULL); - gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("OTP Value", renderer, "text", COLUMN_OTP, NULL); - gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Validity", renderer, "text", COLUMN_VALIDITY, NULL); - gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Period", renderer, "text", COLUMN_PERIOD, NULL); - gtk_tree_view_column_set_visible (column, FALSE); - gtk_tree_view_append_column (tree_view, column); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Updated", renderer, "text", COLUMN_UPDATED, NULL); - gtk_tree_view_column_set_visible (column, FALSE); + GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes (title, renderer, "text", column_id, NULL); + gtk_tree_view_column_set_visible (column, visible); gtk_tree_view_append_column (tree_view, column); +} - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Less Than a Minute", renderer, "text", COLUMN_LESS_THAN_A_MINUTE, NULL); - gtk_tree_view_column_set_visible (column, FALSE); - gtk_tree_view_append_column (tree_view, column); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes ("Position in Database", renderer, "text", COLUMN_POSITION_IN_DB, NULL); - gtk_tree_view_column_set_visible (column, FALSE); - gtk_tree_view_append_column (tree_view, column); +static void +add_columns (GtkTreeView *tree_view) +{ + // Main columns + add_column_with_attributes (tree_view, "Type", COLUMN_TYPE, TRUE); + add_column_with_attributes (tree_view, "Account", COLUMN_ACC_LABEL, TRUE); + add_column_with_attributes (tree_view, "Issuer", COLUMN_ACC_ISSUER, TRUE); + add_column_with_attributes (tree_view, "OTP Value", COLUMN_OTP, TRUE); + add_column_with_attributes (tree_view, "Validity", COLUMN_VALIDITY, TRUE); + + // Additional columns (hidden by default) + add_column_with_attributes (tree_view, "Period", COLUMN_PERIOD, FALSE); + add_column_with_attributes (tree_view, "Updated", COLUMN_UPDATED, FALSE); + add_column_with_attributes (tree_view, "Less Than a Minute", COLUMN_LESS_THAN_A_MINUTE, FALSE); + add_column_with_attributes (tree_view, "Position in Database", COLUMN_POSITION_IN_DB, FALSE); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/ui/settings_popover.ui new/OTPClient-3.5.2/src/ui/settings_popover.ui --- old/OTPClient-3.5.1/src/ui/settings_popover.ui 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/ui/settings_popover.ui 2024-03-08 11:29:39.000000000 +0100 @@ -168,7 +168,7 @@ </object> <packing> <property name="submenu">import_menu</property> - <property name="position">1</property> + <property name="position">0</property> </packing> </child> <child> @@ -321,7 +321,7 @@ </object> <packing> <property name="submenu">export_menu</property> - <property name="position">2</property> + <property name="position">1</property> </packing> </child> <child> @@ -330,12 +330,14 @@ <property name="can-focus">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkModelButton" id="import_model_btn_id"> + <object class="GtkModelButton" id="db_submenu_back_btn_id"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">True</property> - <property name="text" translatable="yes">Import</property> - <property name="menu-name">import_menu</property> + <property name="inverted">True</property> + <property name="centered">True</property> + <property name="menu-name">main</property> + <property name="text" translatable="yes">Back</property> </object> <packing> <property name="expand">False</property> @@ -344,12 +346,12 @@ </packing> </child> <child> - <object class="GtkModelButton" id="export_model_btn_id"> + <object class="GtkModelButton" id="newdb_model_btn_id"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">True</property> - <property name="text" translatable="yes">Export</property> - <property name="menu-name">export_menu</property> + <property name="action-name">settings_menu.create_newdb</property> + <property name="text" translatable="yes">New DB</property> </object> <packing> <property name="expand">False</property> @@ -358,12 +360,12 @@ </packing> </child> <child> - <object class="GtkModelButton" id="newdb_model_btn_id"> + <object class="GtkModelButton" id="change_db_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.create_newdb</property> - <property name="text" translatable="yes">New database</property> + <property name="action-name">settings_menu.change_db</property> + <property name="text" translatable="yes">Change DB</property> </object> <packing> <property name="expand">False</property> @@ -372,12 +374,12 @@ </packing> </child> <child> - <object class="GtkModelButton" id="change_db_model_btn_id"> + <object class="GtkModelButton" id="change_pwd_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.change_db</property> - <property name="text" translatable="yes">Change database</property> + <property name="action-name">settings_menu.change_pwd</property> + <property name="text" translatable="yes">Change DB password</property> </object> <packing> <property name="expand">False</property> @@ -386,12 +388,12 @@ </packing> </child> <child> - <object class="GtkModelButton" id="change_pwd_model_btn_id"> + <object class="GtkModelButton" id="dbinfo_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.change_pwd</property> - <property name="text" translatable="yes">Change password</property> + <property name="action-name">settings_menu.dbinfo</property> + <property name="text" translatable="yes">DB info</property> </object> <packing> <property name="expand">False</property> @@ -399,18 +401,45 @@ <property name="position">4</property> </packing> </child> + </object> + <packing> + <property name="submenu">db_menu</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> + <child> + <object class="GtkModelButton" id="row_submenu_back_btn_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="inverted">True</property> + <property name="centered">True</property> + <property name="menu-name">main</property> + <property name="text" translatable="yes">Back</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> <child> <object class="GtkModelButton" id="edit_row_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.edit_row</property> - <property name="text" translatable="yes">Edit row</property> + <property name="text" translatable="yes">Edit data</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">5</property> + <property name="position">1</property> </packing> </child> <child> @@ -424,21 +453,74 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">6</property> + <property name="position">2</property> </packing> </child> + </object> + <packing> + <property name="submenu">row_menu</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> <child> - <object class="GtkModelButton" id="settings_model_btn_id"> + <object class="GtkModelButton" id="import_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.settings</property> - <property name="text" translatable="yes">Settings</property> + <property name="text" translatable="yes">Import</property> + <property name="menu-name">import_menu</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">7</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkModelButton" id="export_model_btn_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="text" translatable="yes">Export</property> + <property name="menu-name">export_menu</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkModelButton" id="db_model_btn_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="text" translatable="yes">Database Mgmt</property> + <property name="menu-name">db_menu</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkModelButton" id="row_model_btn_id"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="receives-default">True</property> + <property name="text" translatable="yes">Row Mgmt</property> + <property name="menu-name">row_menu</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> </packing> </child> <child> @@ -452,21 +534,21 @@ <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">8</property> + <property name="position">7</property> </packing> </child> <child> - <object class="GtkModelButton" id="dbinfo_model_btn_id"> + <object class="GtkModelButton" id="settings_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.dbinfo</property> - <property name="text" translatable="yes">Database info</property> + <property name="action-name">settings_menu.settings</property> + <property name="text" translatable="yes">Settings</property> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> - <property name="position">9</property> + <property name="position">8</property> </packing> </child> <child> @@ -545,4 +627,4 @@ </packing> </child> </object> -</interface> \ No newline at end of file +</interface> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/OTPClient-3.5.1/src/webcam-add-cb.c new/OTPClient-3.5.2/src/webcam-add-cb.c --- old/OTPClient-3.5.1/src/webcam-add-cb.c 2024-03-05 10:53:41.000000000 +0100 +++ new/OTPClient-3.5.2/src/webcam-add-cb.c 2024-03-08 11:29:39.000000000 +0100 @@ -2,7 +2,6 @@ #include <zbar.h> #include <gcrypt.h> #include "imports.h" -#include "parse-uri.h" #include "message-dialogs.h" #include "get-builder.h" #include "common/common.h"