This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch nm-vpn-username-capture
in repository enlightenment.
View the commit online.
commit 741379e593fc3fff1b50660bd171d6874b42c952
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 21 21:05:29 2026 -0600
networkmanager: inject VPN username field at connect time
Detect a missing username for username-auth VPNs from the already-parsed
vpn.data, add a Username row to the secrets dialog, and persist it to
vpn.data on OK (as a property, not a secret).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
---
src/modules/networkmanager/agent.c | 60 ++++++++++++++++++++++++---
src/modules/networkmanager/e_networkmanager.c | 19 ++++++++-
src/modules/networkmanager/e_networkmanager.h | 3 +-
3 files changed, 73 insertions(+), 9 deletions(-)
diff --git a/src/modules/networkmanager/agent.c b/src/modules/networkmanager/agent.c
index c1c85e058..0e1505a2b 100644
--- a/src/modules/networkmanager/agent.c
+++ b/src/modules/networkmanager/agent.c
@@ -9,6 +9,7 @@
#include "e.h"
#include "e_networkmanager.h"
+#include "e_networkmanager_vpn_username.h"
#include "e_mod_main.h"
/*
@@ -37,6 +38,11 @@ struct _E_NM_Agent_Dialog
char **field_names;
Evas_Object **field_entries;
unsigned int n_fields;
+ /* VPN mode: when set, username_entry holds a username *property* (not a
+ * secret) — persisted to vpn.data on OK instead of returned via reply. */
+ Eina_Bool has_username_field;
+ Evas_Object *username_entry;
+ char *conn_name; /* strdup; for username persistence */
};
static E_NM_Agent_Dialog *_current_dialog = NULL;
@@ -64,6 +70,17 @@ _dialog_send_ok(E_NM_Agent_Dialog *ad)
}
else
{
+ /* The username is a connection property, not a secret: persist it to
+ * vpn.data instead of returning it through the secrets reply. */
+ if (ad->has_username_field && ad->username_entry)
+ {
+ char *user = elm_entry_markup_to_utf8(
+ elm_entry_entry_get(ad->username_entry));
+ if (user && user[0] && ad->conn_name)
+ enm_vpn_username_set(ad->conn_name, user, NULL, NULL);
+ free(user);
+ }
+
const char **values = calloc(ad->n_fields, sizeof(*values));
char **utf8 = calloc(ad->n_fields, sizeof(*utf8));
if (!values || !utf8)
@@ -158,6 +175,7 @@ _dialog_del_cb(void *data)
free(ad->field_names);
}
free(ad->field_entries);
+ free(ad->conn_name);
free(ad);
}
@@ -357,7 +375,8 @@ _dialog_new(E_NM_Agent_Request *req, const char *ssid)
static E_NM_Agent_Dialog *
_vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
const char *service_type, const char *message,
- const char *const *fields, unsigned int n_fields)
+ const char *const *fields, unsigned int n_fields,
+ Eina_Bool need_username)
{
E_NM_Agent_Dialog *ad;
Evas_Object *frame, *box, *table;
@@ -374,6 +393,8 @@ _vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
ad->req = req;
ad->is_vpn = EINA_TRUE;
ad->n_fields = n_fields;
+ ad->has_username_field = need_username;
+ ad->conn_name = conn_name ? strdup(conn_name) : NULL;
ad->field_names = calloc(n_fields ?: 1, sizeof(*ad->field_names));
ad->field_entries = calloc(n_fields ?: 1, sizeof(*ad->field_entries));
used = calloc(n_fields ?: 1, sizeof(*used));
@@ -437,6 +458,31 @@ _vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
evas_object_show(table);
_field_column_min_width_set(table, 1);
+ unsigned int base = 0;
+ if (need_username)
+ {
+ Evas_Object *label, *entry;
+
+ label = elm_label_add(table);
+ elm_object_text_set(label, _("Username"));
+ evas_object_size_hint_weight_set(label, 0, 0);
+ evas_object_size_hint_align_set(label, 1.0, 0.5);
+ elm_table_pack(table, label, 0, 0, 1, 1);
+ evas_object_show(label);
+
+ entry = elm_entry_add(table);
+ elm_entry_single_line_set(entry, EINA_TRUE);
+ elm_entry_scrollable_set(entry, EINA_TRUE);
+ evas_object_size_hint_weight_set(entry, EVAS_HINT_EXPAND, 0);
+ evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
+ evas_object_smart_callback_add(entry, "activated",
+ _entry_activated_cb, ad);
+ elm_table_pack(table, entry, 1, 0, 1, 1);
+ evas_object_show(entry);
+ ad->username_entry = entry;
+ base = 1;
+ }
+
for (unsigned int i = 0; i < n_fields; i++)
{
Evas_Object *label, *entry;
@@ -446,7 +492,7 @@ _vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
elm_object_text_set(label, _vpn_field_label_get(field));
evas_object_size_hint_weight_set(label, 0, 0);
evas_object_size_hint_align_set(label, 1.0, 0.5);
- elm_table_pack(table, label, 0, i, 1, 1);
+ elm_table_pack(table, label, 0, base + i, 1, 1);
evas_object_show(label);
entry = elm_entry_add(table);
@@ -457,7 +503,7 @@ _vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
evas_object_size_hint_align_set(entry, EVAS_HINT_FILL, 0.5);
evas_object_smart_callback_add(entry, "activated",
_entry_activated_cb, ad);
- elm_table_pack(table, entry, 1, i, 1, 1);
+ elm_table_pack(table, entry, 1, base + i, 1, 1);
evas_object_show(entry);
ad->field_entries[i] = entry;
@@ -471,7 +517,8 @@ _vpn_dialog_new(E_NM_Agent_Request *req, const char *conn_name,
_dialog_key_down_cb, ad);
e_object_del_attach_func_set(E_OBJECT(dialog), _dialog_del_cb);
e_object_data_set(E_OBJECT(dialog), ad);
- if (n_fields > 0) elm_object_focus_set(ad->field_entries[0], EINA_TRUE);
+ if (ad->username_entry) elm_object_focus_set(ad->username_entry, EINA_TRUE);
+ else if (n_fields > 0) elm_object_focus_set(ad->field_entries[0], EINA_TRUE);
elm_win_center(dialog->win, 1, 1);
return ad;
}
@@ -521,7 +568,8 @@ static void
_agent_ui_vpn_request_cb(void *data EINA_UNUSED, E_NM_Agent_Request *req,
const char *conn_name, const char *service_type,
const char *message,
- const char *const *fields, unsigned int n_fields)
+ const char *const *fields, unsigned int n_fields,
+ Eina_Bool need_username)
{
if (_current_dialog)
{
@@ -531,7 +579,7 @@ _agent_ui_vpn_request_cb(void *data EINA_UNUSED, E_NM_Agent_Request *req,
}
_current_dialog = _vpn_dialog_new(req, conn_name, service_type,
message,
- fields, n_fields);
+ fields, n_fields, need_username);
if (!_current_dialog) { e_nm_agent_reply_cancel(req); return; }
}
diff --git a/src/modules/networkmanager/e_networkmanager.c b/src/modules/networkmanager/e_networkmanager.c
index b7dccbef0..560553d4e 100644
--- a/src/modules/networkmanager/e_networkmanager.c
+++ b/src/modules/networkmanager/e_networkmanager.c
@@ -1,5 +1,6 @@
#include "e_mod_main.h"
#include "e_networkmanager_vpn.h"
+#include "e_networkmanager_vpn_username.h"
#include <ctype.h>
/* -------------------------------------------------------------------------- */
@@ -3618,7 +3619,19 @@ _agent_get_secrets(const Eldbus_Service_Interface *iface,
return NULL;
}
- if (fields.len == 0)
+ /* The username is a connection *property* (vpn.data["username"]), never
+ * a secret, so NM never prompts for it. When it is missing for a
+ * username-auth VPN, inject a username field into the dialog and
+ * persist it back to vpn.data on OK. Pointers returned by
+ * _agent_vpn_data_find alias into `info`, valid until the clear below. */
+ {
+ const char *short_name = _agent_vpn_service_short_name(info.svc_type);
+ const char *conn_type = _agent_vpn_data_find(&info, "connection-type");
+ const char *cur_user = _agent_vpn_data_find(&info, "username");
+ Eina_Bool need_username =
+ enm_vpn_username_needed(short_name, conn_type, cur_user);
+
+ if (fields.len == 0 && !need_username)
{
printf("NM: _agent_get_secrets() fields.len == 0\n");
WRN("GetSecrets: no VPN secrets requested by hints or flags");
@@ -3635,13 +3648,15 @@ _agent_get_secrets(const Eldbus_Service_Interface *iface,
info.conn_id ?: "VPN", info.svc_type,
fields.message,
(const char *const *)fields.items,
- fields.len);
+ fields.len,
+ need_username);
}
else
{
WRN("No VPN SecretAgent UI callback; cancelling");
e_nm_agent_reply_cancel(req);
}
+ }
_agent_vpn_field_list_clear(&fields);
_agent_vpn_conn_info_clear(&info);
diff --git a/src/modules/networkmanager/e_networkmanager.h b/src/modules/networkmanager/e_networkmanager.h
index 9ed81d26f..46579890e 100644
--- a/src/modules/networkmanager/e_networkmanager.h
+++ b/src/modules/networkmanager/e_networkmanager.h
@@ -44,7 +44,8 @@ typedef void (*E_NM_Agent_VPN_Secrets_Request_Cb)(void *data,
const char *service_type,
const char *message,
const char *const *fields,
- unsigned int n_fields);
+ unsigned int n_fields,
+ Eina_Bool need_username);
typedef struct _E_NM_Agent_Callbacks E_NM_Agent_Callbacks;
struct _E_NM_Agent_Callbacks
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.