commit 2fe6e07cc51acfb3573b68da956dd54577859df2
parent 13c5869a7ddfe895f9104e5f28530930d28b8eca
Author: Jacki <jacki@thejackimonster.de>
Date: Sat, 17 Jan 2026 04:04:58 +0100
Implement using libsecret for automatic secret usage to encrypt/decrypt local keys
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
9 files changed, 695 insertions(+), 51 deletions(-)
diff --git a/meson.build b/meson.build
@@ -54,6 +54,7 @@ messenger_gtk_deps = [
dependency('libnotify'),
dependency('libqrencode'),
dependency('libpipewire-0.3'),
+ dependency('libsecret-1'),
declare_dependency(link_args: '-lunistring'),
]
diff --git a/src/application.c b/src/application.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2026 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -23,8 +23,6 @@
*/
#include "application.h"
-#include "request.h"
-#include "resources.h"
#include <glib-2.0/glib.h>
#include <gnunet/gnunet_common.h>
@@ -40,6 +38,10 @@
#include <libportal-gtk3/portal-gtk3.h>
#endif
+#include "request.h"
+#include "resources.h"
+#include "secret.h"
+
static void
_load_ui_stylesheets(MESSENGER_Application *app)
{
@@ -92,41 +94,69 @@ _application_accounts(gpointer user_data)
}
static void
-_application_init(MESSENGER_Application *app)
+_identity_secret_lookup(MESSENGER_Application *app,
+ const char *secret,
+ uint32_t secret_len,
+ gboolean success,
+ gboolean error,
+ gpointer user_data)
{
- g_assert(app);
-
- schedule_load_glib(&(app->ui.schedule));
+ g_assert((app) && (user_data));
- ui_messenger_init(app, &(app->ui.messenger));
+ char *identity = user_data;
-#ifndef MESSENGER_APPLICATION_NO_PORTAL
- if (app->portal)
- app->parent = xdp_parent_new_gtk(GTK_WINDOW(app->ui.messenger.main_window));
-#endif
+ if (error)
+ {
+ fprintf(stderr, "ERROR: Looking up secret failed\n");
+ }
+ else if ((success) && (secret) && (secret_len > 0))
+ {
+ struct GNUNET_CHAT_Account *account;
- GSourceFunc function = G_SOURCE_FUNC(_application_accounts);
+ application_chat_lock(app);
+ account = GNUNET_CHAT_find_account(app->chat.messenger.handle, identity);
+ GNUNET_CHAT_connect(app->chat.messenger.handle, account, secret, secret_len);
+ application_chat_unlock(app);
- if (app->chat.identity)
+ app->init = util_idle_add(G_SOURCE_FUNC(_application_main_window), app);
+ return;
+ }
+ else
{
struct GNUNET_CHAT_Account *account;
application_chat_lock(app);
- account = GNUNET_CHAT_find_account(
- app->chat.messenger.handle,
- app->chat.identity
- );
+ account = GNUNET_CHAT_find_account(app->chat.messenger.handle, identity);
+ application_chat_unlock(app);
if (account)
{
- GNUNET_CHAT_connect(app->chat.messenger.handle, account);
- function = G_SOURCE_FUNC(_application_main_window);
+ secret_operation_generate(app, identity, &_identity_secret_lookup, identity);
+ return;
}
-
- application_chat_unlock(app);
}
- app->init = util_idle_add(function, app);
+ app->init = util_idle_add(G_SOURCE_FUNC(_application_accounts), app);
+}
+
+static void
+_application_init(MESSENGER_Application *app)
+{
+ g_assert(app);
+
+ schedule_load_glib(&(app->ui.schedule));
+
+ ui_messenger_init(app, &(app->ui.messenger));
+
+#ifndef MESSENGER_APPLICATION_NO_PORTAL
+ if (app->portal)
+ app->parent = xdp_parent_new_gtk(GTK_WINDOW(app->ui.messenger.main_window));
+#endif
+
+ if (app->chat.identity)
+ secret_operation_lookup(app, app->chat.identity, &_identity_secret_lookup, app->chat.identity);
+ else
+ app->init = util_idle_add(G_SOURCE_FUNC(_application_accounts), app);
}
static void
@@ -235,6 +265,7 @@ application_init(MESSENGER_Application *app,
notify_init(MESSENGER_APPLICATION_NAME);
app->notifications = NULL;
app->requests = NULL;
+ app->secrets = NULL;
_load_ui_stylesheets(app);
@@ -372,6 +403,20 @@ application_run(MESSENGER_Application *app)
pthread_join(app->chat.tid, NULL);
GList *list;
+
+ // Get rid of open secret operations
+ list = app->secrets;
+
+ while (list)
+ {
+ if (list->data)
+ {
+ secret_operation_cancel((MESSENGER_SecretOperation*) list->data);
+ secret_operation_destroy((MESSENGER_SecretOperation*) list->data);
+ }
+
+ list = list->next;
+ }
// Get rid of open requests
list = app->requests;
@@ -398,6 +443,9 @@ application_run(MESSENGER_Application *app)
list = list->next;
}
+ if (app->secrets)
+ g_list_free(app->secrets);
+
if (app->requests)
g_list_free(app->requests);
diff --git a/src/application.h b/src/application.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2026 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -89,6 +89,7 @@ typedef struct MESSENGER_Application
GtkApplication *application;
GList *notifications;
GList *requests;
+ GList *secrets;
guint init;
#ifndef MESSENGER_APPLICATION_NO_PORTAL
diff --git a/src/event.c b/src/event.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2026 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -24,22 +24,23 @@
#include "event.h"
+#include <glib-2.0/glib.h>
+#include <gnunet/gnunet_chat_lib.h>
+#include <gnunet/gnunet_common.h>
+#include <stdio.h>
+
#include "account.h"
#include "application.h"
#include "contact.h"
#include "discourse.h"
#include "file.h"
+#include "secret.h"
#include "ui.h"
#include "ui/chat_entry.h"
#include "ui/chat_title.h"
#include "ui/message.h"
-#include <glib-2.0/glib.h>
-#include <gnunet/gnunet_chat_lib.h>
-#include <gnunet/gnunet_common.h>
-#include <stdio.h>
-
static void
_close_notification(NotifyNotification* notification,
gpointer user_data)
@@ -434,6 +435,40 @@ event_cleanup_profile(MESSENGER_Application *app)
GNUNET_CHAT_iterate_files(chat->handle, _cleanup_profile_files, NULL);
}
+static void
+_account_secret_lookup(MESSENGER_Application *app,
+ const char *secret,
+ uint32_t secret_len,
+ gboolean success,
+ gboolean error,
+ gpointer user_data)
+{
+ g_assert((app) && (user_data));
+
+ struct GNUNET_CHAT_Account *account = user_data;
+
+ if (error)
+ {
+ fprintf(stderr, "ERROR: Looking up secret failed\n");
+ }
+ else if ((success) && (secret) && (secret_len > 0))
+ {
+ application_chat_lock(app);
+ GNUNET_CHAT_connect(app->chat.messenger.handle, account, secret, secret_len);
+ application_chat_unlock(app);
+ }
+ else
+ {
+ const char *name;
+
+ application_chat_lock(app);
+ name = GNUNET_CHAT_account_get_name(account);
+ application_chat_unlock(app);
+
+ secret_operation_generate(app, name, &_account_secret_lookup, account);
+ }
+}
+
void
event_select_profile(MESSENGER_Application *app,
struct GNUNET_CHAT_Context *context,
@@ -441,12 +476,14 @@ event_select_profile(MESSENGER_Application *app,
{
g_assert((app) && (!context) && (msg));
- CHAT_MESSENGER_Handle *chat = &(app->chat.messenger);
-
struct GNUNET_CHAT_Account *account = GNUNET_CHAT_message_get_account(msg);
if (GNUNET_CHAT_KIND_CREATED_ACCOUNT == GNUNET_CHAT_message_get_kind(msg))
- GNUNET_CHAT_connect(chat->handle, account);
+ {
+ const char *name = GNUNET_CHAT_account_get_name(account);
+
+ secret_operation_lookup(app, name, &_account_secret_lookup, account);
+ }
}
gboolean
diff --git a/src/meson.build b/src/meson.build
@@ -1,6 +1,6 @@
#
# This file is part of GNUnet.
-# Copyright (C) 2023--2024 GNUnet e.V.
+# Copyright (C) 2023--2026 GNUnet e.V.
#
# GNUnet is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
@@ -32,6 +32,7 @@ messenger_gtk_sources = files([
'request.c', 'request.h',
'resources.c', 'resources.h',
'schedule.c', 'schedule.h',
+ 'secret.c', 'secret.h',
'ui.c', 'ui.h',
'util.c', 'util.h',
'messenger_gtk.c',
diff --git a/src/secret.c b/src/secret.c
@@ -0,0 +1,365 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2026 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file secret.c
+ */
+
+#include "secret.h"
+
+#include <glib-2.0/glib.h>
+#include <gnunet/gnunet_chat_lib.h>
+#include <gnunet/gnunet_common.h>
+#include <string.h>
+#include <libsecret/secret.h>
+#include <gnunet/gnunet_util_lib.h>
+
+#ifndef MESSENGER_APPLICATION_ID
+#define SECRET_APP_ID "org.gnunet.Messenger"
+#else
+#define SECRET_APP_ID MESSENGER_APPLICATION_ID
+#endif
+
+const SecretSchema *
+_secret_schema(void)
+{
+ static const SecretSchema schema = {
+ "org.gnunet.chat.AccountSecret", SECRET_SCHEMA_NONE,
+ {
+ { "name", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "app_id", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { "NULL", 0 },
+ }
+ };
+ return &schema;
+}
+
+char*
+_secret_description(const char *name)
+{
+ char *desc;
+
+ GNUNET_asprintf(
+ &desc,
+ "GNUnet Messenger account secret for identity %s",
+ name
+ );
+
+ return desc;
+}
+
+MESSENGER_SecretOperation*
+_secret_operation_new(MESSENGER_Application *application,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data)
+{
+ g_assert(application);
+
+ GCancellable *cancellable = g_cancellable_new();
+
+ if (!cancellable)
+ return NULL;
+
+ MESSENGER_SecretOperation* op = g_malloc(sizeof(MESSENGER_SecretOperation));
+
+ op->application = application;
+ op->callback = callback;
+ op->cancellable = cancellable;
+ op->user_data = user_data;
+ op->secret = NULL;
+ op->secret_len = 0;
+
+ application->secrets = g_list_append(
+ application->secrets,
+ op
+ );
+
+ return op;
+}
+
+void
+_secret_operation_callback(MESSENGER_SecretOperation *op,
+ gboolean success,
+ gboolean error)
+{
+ g_assert(op);
+
+ if (op->callback)
+ {
+ op->callback(
+ op->application,
+ op->secret,
+ op->secret_len,
+ success,
+ error,
+ op->user_data
+ );
+ }
+
+ secret_operation_drop(op);
+}
+
+void
+_secret_lookup_callback(GNUNET_UNUSED GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GError *error = NULL;
+ gchar *password;
+
+ MESSENGER_SecretOperation *op = data;
+
+ password = secret_password_lookup_finish(result, &error);
+
+ if (error)
+ _secret_operation_callback(op, FALSE, TRUE);
+ else if (password)
+ {
+ op->secret = GNUNET_strdup(password);
+ op->secret_len = g_utf8_strlen(password, -1);
+
+ _secret_operation_callback(op, TRUE, FALSE);
+
+ secret_password_free(password);
+ }
+ else
+ _secret_operation_callback(op, FALSE, FALSE);
+}
+
+MESSENGER_SecretOperation*
+secret_operation_lookup(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data)
+{
+ g_assert((application) && (name));
+
+ MESSENGER_SecretOperation *op = _secret_operation_new(
+ application,
+ callback,
+ user_data
+ );
+
+ if (!op)
+ return NULL;
+
+ secret_password_lookup(
+ _secret_schema(),
+ op->cancellable,
+ &_secret_lookup_callback,
+ op,
+ "name", name,
+ "app_id", SECRET_APP_ID,
+ NULL
+ );
+
+ return op;
+}
+
+void
+_secret_store_callback(GNUNET_UNUSED GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GError *error = NULL;
+ gboolean success;
+
+ MESSENGER_SecretOperation *op = data;
+
+ success = secret_password_store_finish(result, &error);
+
+ if (error)
+ _secret_operation_callback(op, FALSE, TRUE);
+ else
+ _secret_operation_callback(op, success, FALSE);
+}
+
+MESSENGER_SecretOperation*
+secret_operation_store(MESSENGER_Application *application,
+ const char *name,
+ const char *secret,
+ uint32_t secret_len,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data)
+{
+ g_assert((application) && (name) && (secret));
+
+ if (strlen(secret) != secret_len)
+ return NULL;
+
+ MESSENGER_SecretOperation *op = _secret_operation_new(
+ application,
+ callback,
+ user_data
+ );
+
+ if (!op)
+ return NULL;
+
+ op->secret = GNUNET_strndup(secret, secret_len + 1);
+ op->secret_len = secret_len;
+
+ secret_password_store(
+ _secret_schema(),
+ SECRET_COLLECTION_DEFAULT,
+ _secret_description(name),
+ secret,
+ op->cancellable,
+ &_secret_store_callback,
+ op,
+ "name", name,
+ "app_id", SECRET_APP_ID,
+ NULL
+ );
+
+ return op;
+}
+
+MESSENGER_SecretOperation*
+secret_operation_generate(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data)
+{
+ char new_secret [65];
+ uint32_t secret_len;
+
+ g_assert((application) && (name));
+
+ secret_len = 64;
+
+ if (GNUNET_OK != GNUNET_CHAT_generate_secret(new_secret, secret_len))
+ return NULL;
+
+ new_secret[secret_len] = '\0';
+
+ MESSENGER_SecretOperation *op = secret_operation_store(
+ application,
+ name,
+ new_secret,
+ secret_len,
+ callback,
+ user_data
+ );
+
+ secret_password_wipe(new_secret);
+ return op;
+}
+
+void
+_secret_delete_callback(GNUNET_UNUSED GObject *source_object,
+ GAsyncResult *result,
+ gpointer data)
+{
+ GError *error = NULL;
+ gboolean success;
+
+ MESSENGER_SecretOperation *op = data;
+
+ success = secret_password_clear_finish(result, &error);
+
+ if (error)
+ _secret_operation_callback(op, FALSE, TRUE);
+ else
+ _secret_operation_callback(op, success, FALSE);
+}
+
+MESSENGER_SecretOperation*
+secret_operation_delete(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data)
+{
+ g_assert((application) && (name));
+
+ MESSENGER_SecretOperation *op = _secret_operation_new(
+ application,
+ callback,
+ user_data
+ );
+
+ if (!op)
+ return NULL;
+
+ secret_password_clear(
+ _secret_schema(),
+ op->cancellable,
+ &_secret_delete_callback,
+ op,
+ "name", name,
+ "app_id", SECRET_APP_ID,
+ NULL
+ );
+
+ return op;
+}
+
+void
+secret_operation_cancel(MESSENGER_SecretOperation *op)
+{
+ g_assert(op);
+
+ if (!op->cancellable)
+ return;
+
+ if (!g_cancellable_is_cancelled(op->cancellable))
+ g_cancellable_cancel(op->cancellable);
+}
+
+void
+secret_operation_cleanup(MESSENGER_SecretOperation *op)
+{
+ g_assert(op);
+
+ if (op->secret)
+ {
+ secret_password_wipe(op->secret);
+ GNUNET_free(op->secret);
+ }
+
+ if (!op->cancellable)
+ return;
+
+ g_object_unref(op->cancellable);
+ op->cancellable = NULL;
+}
+
+void
+secret_operation_drop(MESSENGER_SecretOperation *op)
+{
+ g_assert(op);
+
+ if (op->application->secrets)
+ op->application->secrets = g_list_remove(
+ op->application->secrets,
+ op
+ );
+
+ secret_operation_destroy(op);
+}
+
+void
+secret_operation_destroy(MESSENGER_SecretOperation *op)
+{
+ g_assert(op);
+
+ secret_operation_cleanup(op);
+ g_free(op);
+}
diff --git a/src/secret.h b/src/secret.h
@@ -0,0 +1,114 @@
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2026 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/*
+ * @author Tobias Frisch
+ * @file secret.h
+ */
+
+#ifndef SECRET_H_
+#define SECRET_H_
+
+#include <gnunet/gnunet_chat_lib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "application.h"
+
+typedef void (*MESSENGER_SecretCallback)(
+ MESSENGER_Application *application,
+ const char *secret,
+ uint32_t secret_len,
+ gboolean success,
+ gboolean error,
+ gpointer user_data
+);
+
+typedef struct MESSENGER_SecretOperation {
+ MESSENGER_Application *application;
+ MESSENGER_SecretCallback callback;
+ GCancellable *cancellable;
+ gpointer user_data;
+ char *secret;
+ uint32_t secret_len;
+} MESSENGER_SecretOperation;
+
+/**
+ * Lookup a secret from identity with
+ * a given name.
+ *
+ * @param[in] name Identity name
+ * @param[out] secret_len Length of secret
+ * @return Secret or NULL
+ */
+MESSENGER_SecretOperation*
+secret_operation_lookup(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data);
+
+/**
+ * Stores a secret for identity with
+ * a given name.
+ *
+ * @param[in] name Identity name
+ * @param[in] secret Secret
+ * @param[in] secret_len Length of secret
+ * @return Whether the storage was successful
+ */
+MESSENGER_SecretOperation*
+secret_operation_store(MESSENGER_Application *application,
+ const char *name,
+ const char *secret,
+ uint32_t secret_len,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data);
+
+MESSENGER_SecretOperation*
+secret_operation_generate(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data);
+
+/**
+ * Delete a secret from identity with
+ * a given name.
+ *
+ * @param[in] name Identity name
+ * @return Whether the deletion was successful
+ */
+MESSENGER_SecretOperation*
+secret_operation_delete(MESSENGER_Application *application,
+ const char *name,
+ MESSENGER_SecretCallback callback,
+ gpointer user_data);
+
+void
+secret_operation_cancel(MESSENGER_SecretOperation *op);
+
+void
+secret_operation_cleanup(MESSENGER_SecretOperation *op);
+
+void
+secret_operation_drop(MESSENGER_SecretOperation *op);
+
+void
+secret_operation_destroy(MESSENGER_SecretOperation *op);
+
+#endif /* SECRET_H_ */
diff --git a/src/ui/accounts.c b/src/ui/accounts.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2022--2024 GNUnet e.V.
+ Copyright (C) 2022--2026 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -24,10 +24,13 @@
#include "accounts.h"
+#include <gnunet/gnunet_chat_lib.h>
+
#include "account_entry.h"
#include "../account.h"
#include "../application.h"
+#include "../secret.h"
#include "../ui.h"
static void
@@ -54,6 +57,40 @@ _open_new_account_dialog(gpointer user_data)
}
static void
+_account_secret_lookup(MESSENGER_Application *app,
+ const char *secret,
+ uint32_t secret_len,
+ gboolean success,
+ gboolean error,
+ gpointer user_data)
+{
+ g_assert((app) && (user_data));
+
+ struct GNUNET_CHAT_Account *account = user_data;
+
+ if (error)
+ {
+ fprintf(stderr, "ERROR: Looking up secret failed\n");
+ }
+ else if ((success) && (secret) && (secret_len > 0))
+ {
+ application_chat_lock(app);
+ GNUNET_CHAT_connect(app->chat.messenger.handle, account, secret, secret_len);
+ application_chat_unlock(app);
+ }
+ else
+ {
+ const char *name;
+
+ application_chat_lock(app);
+ name = GNUNET_CHAT_account_get_name(account);
+ application_chat_unlock(app);
+
+ secret_operation_generate(app, name, &_account_secret_lookup, account);
+ }
+}
+
+static void
handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
GtkListBoxRow* row,
gpointer user_data)
@@ -80,14 +117,18 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
goto close_dialog;
app->ui.state = MESSENGER_STATE_MAIN_WINDOW;
-
- application_chat_lock(app);
- GNUNET_CHAT_connect(app->chat.messenger.handle, account);
- application_chat_unlock(app);
gtk_list_box_unselect_all(app->ui.messenger.accounts_listbox);
gtk_widget_set_sensitive(GTK_WIDGET(app->ui.accounts.dialog), FALSE);
+ const char *name;
+
+ application_chat_lock(app);
+ name = GNUNET_CHAT_account_get_name(account);
+ application_chat_unlock(app);
+
+ secret_operation_lookup(app, name, &_account_secret_lookup, account);
+
close_dialog:
gtk_window_close(GTK_WINDOW(app->ui.accounts.dialog));
}
diff --git a/src/ui/messenger.c b/src/ui/messenger.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- Copyright (C) 2021--2024 GNUnet e.V.
+ Copyright (C) 2021--2026 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -24,7 +24,9 @@
#include "messenger.h"
+#include <gnunet/gnunet_chat_lib.h>
#include <gtk-3.0/gdk/gdkkeys.h>
+#include <stdio.h>
#include "account_entry.h"
#include "chat_entry.h"
@@ -39,6 +41,7 @@
#include "../account.h"
#include "../application.h"
+#include "../secret.h"
#include "../ui.h"
static void
@@ -186,6 +189,43 @@ handle_account_details_button_click(UNUSED GtkButton* button,
}
static void
+_account_secret_lookup(MESSENGER_Application *app,
+ const char *secret,
+ uint32_t secret_len,
+ gboolean success,
+ gboolean error,
+ gpointer user_data)
+{
+ g_assert((app) && (user_data));
+
+ struct GNUNET_CHAT_Account *account = user_data;
+
+ if (error)
+ {
+ fprintf(stderr, "ERROR: Looking up secret failed\n");
+ }
+ else if ((success) && (secret) && (secret_len > 0))
+ {
+ _switch_details_revealer_visibility(&(app->ui.messenger), FALSE);
+ hdy_flap_set_reveal_flap(HDY_FLAP(app->ui.messenger.flap_user_details), FALSE);
+
+ application_chat_lock(app);
+ GNUNET_CHAT_connect(app->chat.messenger.handle, account, secret, secret_len);
+ application_chat_unlock(app);
+ }
+ else
+ {
+ const char *name;
+
+ application_chat_lock(app);
+ name = GNUNET_CHAT_account_get_name(account);
+ application_chat_unlock(app);
+
+ secret_operation_generate(app, name, &_account_secret_lookup, account);
+ }
+}
+
+static void
handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
GtkListBoxRow* row,
gpointer user_data)
@@ -212,23 +252,19 @@ handle_accounts_listbox_row_activated(UNUSED GtkListBox* listbox,
if (!account)
return;
- application_chat_lock(app);
-
- const struct GNUNET_CHAT_Account *current = GNUNET_CHAT_get_connected(
- app->chat.messenger.handle
- );
+ const struct GNUNET_CHAT_Account *current;
+ const char *name;
+
+ application_chat_lock(app);
+ current = GNUNET_CHAT_get_connected(app->chat.messenger.handle);
+ name = GNUNET_CHAT_account_get_name(account);
application_chat_unlock(app);
if (account == current)
return;
- _switch_details_revealer_visibility(&(app->ui.messenger), FALSE);
- hdy_flap_set_reveal_flap(HDY_FLAP(app->ui.messenger.flap_user_details), FALSE);
-
- application_chat_lock(app);
- GNUNET_CHAT_connect(app->chat.messenger.handle, account);
- application_chat_unlock(app);
+ secret_operation_lookup(app, name, &_account_secret_lookup, account);
}
static void