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 152be889ed0785f21f28bdcda1d83632a4f25fac
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 21 21:01:00 2026 -0600

    networkmanager: prompt for VPN username after import
    
    Capture nmcli stdout, parse the imported connection name, and trigger the
    username probe for username-auth VPNs that have no stored username.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
---
 src/modules/networkmanager/e_mod_main.c            | 14 ++++-
 .../networkmanager/e_networkmanager_import.c       | 68 ++++++++++++++++++----
 .../networkmanager/e_networkmanager_import.h       |  7 ++-
 3 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/src/modules/networkmanager/e_mod_main.c b/src/modules/networkmanager/e_mod_main.c
index 56bb02991..8d626f4b6 100644
--- a/src/modules/networkmanager/e_mod_main.c
+++ b/src/modules/networkmanager/e_mod_main.c
@@ -3,6 +3,7 @@
 #include "e_networkmanager.h"
 #include "e_networkmanager_vpn.h"
 #include "e_networkmanager_import.h"
+#include "e_networkmanager_vpn_username.h"
 
 E_Module *networkmanager_mod = NULL;
 E_NM_Config *networkmanager_config = NULL;
@@ -406,10 +407,16 @@ _enm_itc_bt_content_get(void *data, Evas_Object *obj, const char *part)
 /* ---- VPN item class callbacks --------------------------------------------- */
 
 static void
-_enm_vpn_import_done_cb(void *data EINA_UNUSED, Eina_Bool ok, const char *err)
+_enm_vpn_import_done_cb(void *data EINA_UNUSED, Eina_Bool ok, const char *err,
+                        const char *conn_name)
 {
    E_Dialog *err_dlg;
-   if (ok) { INF("VPN import succeeded"); return; }
+   if (ok)
+     {
+        INF("VPN import succeeded");
+        if (conn_name) enm_vpn_username_maybe_prompt(conn_name);
+        return;
+     }
 
    ERR("VPN import failed: %s", err ?: "(no output)");
 
@@ -452,7 +459,8 @@ _enm_vpn_fs_done_cb(void *data, Evas_Object *fs EINA_UNUSED, void *event)
      {
         _enm_vpn_import_done_cb(NULL, EINA_FALSE,
               _("Could not detect VPN type from file extension. "
-                "Use a .conf (WireGuard) or .ovpn (OpenVPN) file."));
+                "Use a .conf (WireGuard) or .ovpn (OpenVPN) file."),
+              NULL);
      }
    else
      {
diff --git a/src/modules/networkmanager/e_networkmanager_import.c b/src/modules/networkmanager/e_networkmanager_import.c
index 0b5d2487b..1808c8e39 100644
--- a/src/modules/networkmanager/e_networkmanager_import.c
+++ b/src/modules/networkmanager/e_networkmanager_import.c
@@ -73,11 +73,13 @@ enm_import_detect_type(const char *file_path)
 
 typedef struct _Import_Ctx
 {
-   Enm_Import_Done_Cb  done_cb;
-   void               *data;
-   Ecore_Exe          *exe;
-   Eina_Strbuf        *stderr_buf;
+   Enm_Import_Done_Cb   done_cb;
+   void                *data;
+   Ecore_Exe           *exe;
+   Eina_Strbuf         *stderr_buf;
+   Eina_Strbuf         *stdout_buf;
    Ecore_Event_Handler *handler_err;
+   Ecore_Event_Handler *handler_out;
    Ecore_Event_Handler *handler_del;
 } Import_Ctx;
 
@@ -86,8 +88,10 @@ _import_ctx_free(Import_Ctx *ctx)
 {
    if (!ctx) return;
    if (ctx->handler_err) ecore_event_handler_del(ctx->handler_err);
+   if (ctx->handler_out) ecore_event_handler_del(ctx->handler_out);
    if (ctx->handler_del) ecore_event_handler_del(ctx->handler_del);
    if (ctx->stderr_buf)  eina_strbuf_free(ctx->stderr_buf);
+   if (ctx->stdout_buf)  eina_strbuf_free(ctx->stdout_buf);
    /* exe is already gone by the time _del fires; don't del it here */
    free(ctx);
 }
@@ -124,6 +128,33 @@ _on_stderr(void *data, int type EINA_UNUSED, void *event)
    return ECORE_CALLBACK_DONE;
 }
 
+static Eina_Bool
+_on_stdout(void *data, int type EINA_UNUSED, void *event)
+{
+   Import_Ctx *ctx = data;
+   Ecore_Exe_Event_Data *ev = event;
+
+   if (!ev || !ev->exe || ev->exe != ctx->exe)
+     return ECORE_CALLBACK_PASS_ON;
+   if (ev->data && ev->size > 0)
+     eina_strbuf_append_length(ctx->stdout_buf, ev->data, ev->size);
+   return ECORE_CALLBACK_DONE;
+}
+
+/* Parse `Connection 'NAME' (uuid) successfully added.` -> malloc'd NAME. */
+static char *
+_import_parse_conn_name(const char *out)
+{
+   const char *a, *b;
+   if (!out) return NULL;
+   a = strchr(out, '\'');
+   if (!a) return NULL;
+   a++;
+   b = strchr(a, '\'');
+   if (!b) return NULL;
+   return strndup(a, (size_t)(b - a));
+}
+
 static Eina_Bool
 _on_del(void *data, int type EINA_UNUSED, void *event)
 {
@@ -136,13 +167,18 @@ _on_del(void *data, int type EINA_UNUSED, void *event)
    /* Prevent double-free: clear handlers before freeing ctx */
    ecore_event_handler_del(ctx->handler_err);
    ctx->handler_err = NULL;
+   if (ctx->handler_out)
+     { ecore_event_handler_del(ctx->handler_out); ctx->handler_out = NULL; }
    ecore_event_handler_del(ctx->handler_del);
    ctx->handler_del = NULL;
 
    Eina_Bool ok = (ev->exited && ev->exit_code == 0);
    const char *stderr_text = eina_strbuf_string_get(ctx->stderr_buf);
+   char *conn_name = ok ? _import_parse_conn_name(
+                              eina_strbuf_string_get(ctx->stdout_buf)) : NULL;
 
-   ctx->done_cb(ctx->data, ok, stderr_text);
+   ctx->done_cb(ctx->data, ok, stderr_text, conn_name);
+   free(conn_name);
 
    _import_ctx_free(ctx);
    return ECORE_CALLBACK_DONE;
@@ -159,7 +195,7 @@ enm_import_run(const char *type, const char *file_path,
    const char *nmcli = enm_import_nmcli_path();
    if (!nmcli)
      {
-        done_cb(data, EINA_FALSE, "nmcli not found on PATH");
+        done_cb(data, EINA_FALSE, "nmcli not found on PATH", NULL);
         return;
      }
 
@@ -172,7 +208,7 @@ enm_import_run(const char *type, const char *file_path,
         free(esc_nmcli);
         free(esc_type);
         free(esc_filepath);
-        done_cb(data, EINA_FALSE, "out of memory");
+        done_cb(data, EINA_FALSE, "out of memory", NULL);
         return;
      }
 
@@ -188,7 +224,7 @@ enm_import_run(const char *type, const char *file_path,
    Import_Ctx *ctx = calloc(1, sizeof(Import_Ctx));
    if (!ctx)
      {
-        done_cb(data, EINA_FALSE, "out of memory");
+        done_cb(data, EINA_FALSE, "out of memory", NULL);
         return;
      }
 
@@ -197,12 +233,22 @@ enm_import_run(const char *type, const char *file_path,
    ctx->stderr_buf = eina_strbuf_new();
    if (!ctx->stderr_buf)
      {
-        done_cb(data, EINA_FALSE, "out of memory");
+        done_cb(data, EINA_FALSE, "out of memory", NULL);
+        free(ctx);
+        return;
+     }
+   ctx->stdout_buf = eina_strbuf_new();
+   if (!ctx->stdout_buf)
+     {
+        done_cb(data, EINA_FALSE, "out of memory", NULL);
+        eina_strbuf_free(ctx->stderr_buf);
         free(ctx);
         return;
      }
 
    ctx->exe = ecore_exe_pipe_run(cmd,
+                                 ECORE_EXE_PIPE_READ |
+                                 ECORE_EXE_PIPE_READ_LINE_BUFFERED |
                                  ECORE_EXE_PIPE_ERROR |
                                  ECORE_EXE_PIPE_ERROR_LINE_BUFFERED |
                                  ECORE_EXE_NOT_LEADER |
@@ -210,11 +256,13 @@ enm_import_run(const char *type, const char *file_path,
                                  ctx);
    if (!ctx->exe)
      {
-        done_cb(data, EINA_FALSE, "failed to spawn nmcli");
+        done_cb(data, EINA_FALSE, "failed to spawn nmcli", NULL);
         _import_ctx_free(ctx);
         return;
      }
 
+   ctx->handler_out = ecore_event_handler_add(ECORE_EXE_EVENT_DATA,
+                                              _on_stdout, ctx);
    ctx->handler_err = ecore_event_handler_add(ECORE_EXE_EVENT_ERROR,
                                                _on_stderr, ctx);
    ctx->handler_del = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
diff --git a/src/modules/networkmanager/e_networkmanager_import.h b/src/modules/networkmanager/e_networkmanager_import.h
index d34087023..8bf9a11ba 100644
--- a/src/modules/networkmanager/e_networkmanager_import.h
+++ b/src/modules/networkmanager/e_networkmanager_import.h
@@ -28,12 +28,17 @@ const char *enm_import_detect_type(const char *file_path);
  * stderr_text points into an internal buffer that is freed immediately
  * after the callback returns; copy it if you need to retain.
  *
+ * conn_name is the imported connection's name parsed from nmcli stdout
+ * (NULL on failure or when it cannot be parsed); it too is freed right
+ * after the callback returns.
+ *
  * data must remain valid until done_cb fires.  enm_import_run does not
  * return a cancellation handle, so the caller is responsible for
  * ensuring it does not deallocate data while a call is in flight.
  */
 typedef void (*Enm_Import_Done_Cb)(void *data, Eina_Bool ok,
-                                   const char *stderr_text);
+                                   const char *stderr_text,
+                                   const char *conn_name);
 
 /* Run nmcli connection import asynchronously.  done_cb is invoked exactly
  * once. */

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to