Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 3.2.0 #312

Merged
merged 5 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(OTPClient VERSION "3.1.9" LANGUAGES "C")
project(OTPClient VERSION "3.2.0" LANGUAGES "C")
include(GNUInstallDirs)

configure_file("src/common/version.h.in" "version.h")
Expand Down
12 changes: 12 additions & 0 deletions data/com.github.paolostivanin.OTPClient.appdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@
</content_rating>

<releases>
<release version="3.2.0" date="2023-10-24">
<description>
<p>OTPClient 3.2.0 fixes a couple of issues.</p>
<ul>
<li>NEW: add file chooser dialog on export (#305)</li>
<li>FIX: overwrite exported file instead of appending it (#305)</li>
<li>FIX: exported file will be accessible only by the current user (#305)</li>
<li>FIX: multiple issues related to failed first launch (#303)</li>
<li>FIX: couple of issues with secret-service</li>
</ul>
</description>
</release>
<release version="3.1.9" date="2023-07-03">
<description>
<p>OTPClient 3.1.9 brings a couple of fixes:</p>
Expand Down
10 changes: 5 additions & 5 deletions src/app.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "show-qr-cb.h"
#include "dbinfo-cb.h"


#ifndef USE_FLATPAK_APP_FOLDER
static gchar *get_db_path (AppData *app_data);
#endif
Expand Down Expand Up @@ -214,8 +213,6 @@ activate (GtkApplication *app,
g_free (app_data);
g_application_quit (G_APPLICATION(app));
return;
} else {
goto retry;
}
}
}
Expand Down Expand Up @@ -606,12 +603,12 @@ get_db_path (AppData *app_data)
}
new_db: ; // empty statement workaround
GtkFileChooserNative *dialog = gtk_file_chooser_native_new (_("Select database location"),
GTK_WINDOW (app_data->main_window),
GTK_WINDOW(app_data->main_window),
app_data->open_db_file_action,
"OK",
"Cancel");

GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
gtk_file_chooser_set_select_multiple (chooser, FALSE);
if (app_data->open_db_file_action == GTK_FILE_CHOOSER_ACTION_SAVE) {
Expand All @@ -629,6 +626,9 @@ get_db_path (AppData *app_data)
}
}

// clear any password that may have been previously set, thus avoiding using a wrong password with a new database
secret_password_clear (OTPCLIENT_SCHEMA, NULL, on_password_cleared, NULL, "string", "main_pwd", NULL);

g_object_unref (dialog);

end:
Expand Down
3 changes: 3 additions & 0 deletions src/change-db-cb.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include <gtk/gtk.h>
#include <gcrypt.h>
#include <libsecret/secret.h>
#include "data.h"
#include "message-dialogs.h"
#include "db-misc.h"
#include "password-cb.h"
#include "db-actions.h"
#include "secret-schema.h"


void
Expand Down Expand Up @@ -36,6 +38,7 @@ change_db_cb (GSimpleAction *simple __attribute__((unused)),
update_cfg_file (app_data);
gcry_free (app_data->db_data->key);
app_data->db_data->key = prompt_for_password (app_data, NULL, NULL, FALSE);
secret_password_store (OTPCLIENT_SCHEMA, SECRET_COLLECTION_DEFAULT, "main_pwd", app_data->db_data->key, NULL, on_password_stored, NULL, "string", "main_pwd", NULL);
GError *err = NULL;
load_new_db (app_data, &err);
if (err != NULL) {
Expand Down
53 changes: 12 additions & 41 deletions src/change-file-cb.c
Original file line number Diff line number Diff line change
@@ -1,61 +1,32 @@
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "new-db-cb.h"
#include "change-db-cb.h"
#include "db-misc.h"
#include "message-dialogs.h"

gboolean
change_file (AppData *app_data)
{
gboolean res = FALSE;
GtkWidget *label = GTK_WIDGET(gtk_builder_get_object (app_data->builder, "diag_changefile_label_id"));
gchar *partial_msg_start = g_markup_printf_escaped ("%s <span font_family=\"monospace\">%s</span>", "The currently selected file is:\n", app_data->db_data->db_path);
const gchar *partial_msg_end = "\n\nDo you want to change it?\n\n"
"If you select <b>Yes</b>, you will be asked to pick another\n"
"database and then you will be prompted for the\n"
"decryption password.\n\n"
"\nIf you select <b>No</b>, then the app will close.";
const gchar *partial_msg_end = "\n\nWhat would you like to do?";
gchar *msg = g_strconcat (partial_msg_start, partial_msg_end, NULL);
gtk_label_set_markup (GTK_LABEL(label), msg);
g_free (msg);
g_free (partial_msg_start);

GtkFileChooserNative *fl_diag;
gboolean res = FALSE;
GtkWidget *diag_changefile = GTK_WIDGET(gtk_builder_get_object (app_data->builder, "diag_changefile_id"));
gint result = gtk_dialog_run (GTK_DIALOG(diag_changefile));
switch (result) {
case GTK_RESPONSE_ACCEPT:
// select an existing DB.
change_db_cb (NULL, NULL, app_data);
res = TRUE;
break;
case GTK_RESPONSE_OK:
fl_diag = gtk_file_chooser_native_new ("Open File",
GTK_WINDOW(app_data->main_window),
GTK_FILE_CHOOSER_ACTION_OPEN,
"Open",
"Cancel");

gint native_diag_res = gtk_native_dialog_run (GTK_NATIVE_DIALOG(fl_diag));
if (native_diag_res == GTK_RESPONSE_ACCEPT) {
GtkFileChooser *chooser = GTK_FILE_CHOOSER(fl_diag);
gchar *db_path = gtk_file_chooser_get_filename (chooser);
GKeyFile *kf = g_key_file_new ();
gchar *cfg_file_path;
#ifndef USE_FLATPAK_APP_FOLDER
cfg_file_path = g_build_filename (g_get_user_config_dir (), "otpclient.cfg", NULL);
#else
cfg_file_path = g_build_filename (g_get_user_data_dir (), "otpclient.cfg", NULL);
#endif
g_key_file_set_string (kf, "config", "db_path", db_path);
GError *err = NULL;
if (!g_key_file_save_to_file (kf, cfg_file_path, &err)) {
gchar *err_msg = g_strconcat (_("Couldn't save the config file: "), err->message, NULL);
show_message_dialog (app_data->main_window, err_msg, GTK_MESSAGE_ERROR);
g_free (err_msg);
g_clear_error (&err);
}
g_free (app_data->db_data->db_path);
app_data->db_data->db_path = g_strdup (db_path);
g_free (db_path);
g_free (cfg_file_path);
g_key_file_free (kf);
}
g_object_unref (fl_diag);
// create a new db.
new_db_cb (NULL, NULL, app_data);
res = TRUE;
break;
case GTK_RESPONSE_CANCEL:
Expand All @@ -65,4 +36,4 @@ change_file (AppData *app_data)
gtk_widget_hide (diag_changefile);

return res;
}
}
28 changes: 22 additions & 6 deletions src/common/aegis.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,20 +372,36 @@ export_aegis (const gchar *export_path,
gcry_cipher_close (hd);
}

FILE *fp = fopen (export_path, "w");
if (fp == NULL) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't create the file object");
} else {
if (json_dumpf (root, fp, JSON_COMPACT) == -1) {
GFile *out_gfile = g_file_new_for_path (export_path);
GFileOutputStream *out_stream = g_file_replace (out_gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION | G_FILE_CREATE_PRIVATE, NULL, &err);
if (err == NULL) {
gsize jbuf_size = json_dumpb (root, NULL, 0, 0);
if (jbuf_size == 0) {
goto cleanup_and_exit;
}
gchar *jbuf = g_malloc0 (jbuf_size);
if (json_dumpb (root, jbuf, jbuf_size, JSON_COMPACT) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to buffer");
g_free (jbuf);
goto cleanup_and_exit;
}
if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), jbuf, jbuf_size, NULL, &err) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to file");
g_free (jbuf);
goto cleanup_and_exit;
}
fclose (fp);
g_free (jbuf);
} else {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't create the file object");
}

cleanup_and_exit:
json_array_clear (array);
json_decref (aegis_db_obj);
json_decref (aegis_header_obj);
json_decref (root);
g_object_unref (out_stream);
g_object_unref (out_gfile);

return (err != NULL ? g_strdup (err->message) : NULL);
}
Expand Down
35 changes: 26 additions & 9 deletions src/common/andotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,33 @@ export_andotp (const gchar *export_path,

// if plaintext export is needed, then write the file and exit
if (password == NULL) {
FILE *fp = fopen (export_path, "w");
if (fp == NULL) {
GFile *out_gfile = g_file_new_for_path (export_path);
GFileOutputStream *out_stream = g_file_replace (out_gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION | G_FILE_CREATE_PRIVATE, NULL, &err);
if (err == NULL) {
gsize jbuf_size = json_dumpb (array, NULL, 0, 0);
if (jbuf_size == 0) {
g_object_unref (out_stream);
g_object_unref (out_gfile);
goto end;
}
gchar *jbuf = g_malloc0 (jbuf_size);
if (json_dumpb (array, jbuf, jbuf_size, JSON_COMPACT) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to buffer");
g_free (jbuf);
g_object_unref (out_stream);
g_object_unref (out_gfile);
goto end;
}
if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), jbuf, jbuf_size, NULL, &err) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to file");
}
g_free (jbuf);
g_object_unref (out_stream);
g_object_unref (out_gfile);
} else {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't create the file object");
goto end;
}
if (json_dumpf (array, fp, JSON_COMPACT) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to file");
g_object_unref (out_gfile);
}
fclose (fp);

goto end;
}

Expand Down Expand Up @@ -276,7 +293,7 @@ export_andotp (const gchar *export_path,
gcry_cipher_close (hd);

GFile *out_gfile = g_file_new_for_path (export_path);
GFileOutputStream *out_stream = g_file_append_to (out_gfile, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &err);
GFileOutputStream *out_stream = g_file_replace (out_gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION | G_FILE_CREATE_PRIVATE, NULL, &err);
if (err != NULL) {
goto cleanup_before_exiting;
}
Expand Down
28 changes: 17 additions & 11 deletions src/common/freeotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <time.h>
#include "../file-size.h"
#include "../parse-uri.h"
#include "../gquarks.h"


GSList *
Expand Down Expand Up @@ -38,18 +39,23 @@ export_freeotpplus (const gchar *export_path,
json_t *db_obj;
gsize index;

FILE *fp = fopen (export_path, "w");
if (fp == NULL) {
return g_strdup ("couldn't create the file object");
GError *err = NULL;
GFile *out_gfile = g_file_new_for_path (export_path);
GFileOutputStream *out_stream = g_file_replace (out_gfile, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION | G_FILE_CREATE_PRIVATE, NULL, &err);
if (err == NULL) {
json_array_foreach (json_db_data, index, db_obj) {
gchar *uri = get_otpauth_uri (NULL, db_obj);
if (g_output_stream_write (G_OUTPUT_STREAM(out_stream), uri, g_utf8_strlen (uri, -1) + 1, NULL, &err) == -1) {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't dump json data to file");
}
g_free (uri);
}
} else {
g_set_error (&err, generic_error_gquark (), GENERIC_ERRCODE, "couldn't create the file object");
}

json_array_foreach (json_db_data, index, db_obj) {
gchar *uri = get_otpauth_uri (NULL, db_obj);
fwrite (uri, strlen (uri), 1, fp);
g_free (uri);
}

fclose (fp);
g_object_unref (out_stream);
g_object_unref (out_gfile);

return NULL;
return (err != NULL ? g_strdup (err->message) : NULL);
}
Loading
Loading