Blame clients/tui/nmt-connect-connection-list.c

Packit Service a1bd4f
/* SPDX-License-Identifier: GPL-2.0+ */
Packit 5756e2
/*
Packit 5756e2
 * Copyright (C) 2013 - 2017 Red Hat, Inc.
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * SECTION:nmt-connect-connection-list
Packit 5756e2
 * @short_description: Connection list for "nmtui connect"
Packit 5756e2
 *
Packit 5756e2
 * #NmtConnectConnectionList is the list of devices, connections, and
Packit 5756e2
 * access points displayed by "nmtui connect".
Packit 5756e2
 */
Packit 5756e2
Packit 5756e2
#include "nm-default.h"
Packit 5756e2
Packit 5756e2
#include <stdlib.h>
Packit 5756e2
Packit 5756e2
#include "nmtui.h"
Packit 5756e2
#include "nmt-connect-connection-list.h"
Packit 5756e2
#include "nm-client-utils.h"
Packit 5756e2
Packit Service a1bd4f
G_DEFINE_TYPE(NmtConnectConnectionList, nmt_connect_connection_list, NMT_TYPE_NEWT_LISTBOX)
Packit 5756e2
Packit Service a1bd4f
#define NMT_CONNECT_CONNECTION_LIST_GET_PRIVATE(o)                 \
Packit Service a1bd4f
    (G_TYPE_INSTANCE_GET_PRIVATE((o),                              \
Packit Service a1bd4f
                                 NMT_TYPE_CONNECT_CONNECTION_LIST, \
Packit Service a1bd4f
                                 NmtConnectConnectionListPrivate))
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    char *    name;
Packit Service a1bd4f
    NMDevice *device;
Packit 5756e2
Packit Service a1bd4f
    int sort_order;
Packit 5756e2
Packit Service a1bd4f
    GSList *conns;
Packit 5756e2
} NmtConnectDevice;
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    const char *name;
Packit Service a1bd4f
    char *      ssid;
Packit 5756e2
Packit Service a1bd4f
    NMConnection *      conn;
Packit Service a1bd4f
    NMAccessPoint *     ap;
Packit Service a1bd4f
    NMDevice *          device;
Packit Service a1bd4f
    NMActiveConnection *active;
Packit 5756e2
} NmtConnectConnection;
Packit 5756e2
Packit 5756e2
typedef struct {
Packit Service a1bd4f
    GSList *nmt_devices;
Packit 5756e2
} NmtConnectConnectionListPrivate;
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nmt_connect_connection_list_new:
Packit 5756e2
 *
Packit 5756e2
 * Creates a new #NmtConnectConnectionList
Packit 5756e2
 *
Packit 5756e2
 * Returns: a new #NmtConnectConnectionList
Packit 5756e2
 */
Packit 5756e2
NmtNewtWidget *
Packit Service a1bd4f
nmt_connect_connection_list_new(void)
Packit 5756e2
{
Packit Service a1bd4f
    return g_object_new(NMT_TYPE_CONNECT_CONNECTION_LIST,
Packit Service a1bd4f
                        "flags",
Packit Service a1bd4f
                        NMT_NEWT_LISTBOX_SCROLL | NMT_NEWT_LISTBOX_BORDER,
Packit Service a1bd4f
                        "skip-null-keys",
Packit Service a1bd4f
                        TRUE,
Packit Service a1bd4f
                        NULL);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_list_init(NmtConnectConnectionList *list)
Packit Service a1bd4f
{}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_free(NmtConnectConnection *nmtconn)
Packit 5756e2
{
Packit Service a1bd4f
    g_clear_object(&nmtconn->conn);
Packit Service a1bd4f
    g_clear_object(&nmtconn->ap);
Packit Service a1bd4f
    g_clear_object(&nmtconn->active);
Packit Service a1bd4f
    g_free(nmtconn->ssid);
Packit Service a1bd4f
    g_slice_free(NmtConnectConnection, nmtconn);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_device_free(NmtConnectDevice *nmtdev)
Packit 5756e2
{
Packit Service a1bd4f
    nm_clear_g_free(&nmtdev->name);
Packit Service a1bd4f
    g_clear_object(&nmtdev->device);
Packit 5756e2
Packit Service a1bd4f
    g_slist_free_full(nmtdev->conns, (GDestroyNotify) nmt_connect_connection_free);
Packit Service a1bd4f
    g_slice_free(NmtConnectDevice, nmtdev);
Packit 5756e2
}
Packit 5756e2
Packit Service a1bd4f
static const char *device_sort_order[]   = {"NMDeviceEthernet",
Packit Service a1bd4f
                                          "NMDeviceInfiniband",
Packit Service a1bd4f
                                          "NMDeviceWifi",
Packit Service a1bd4f
                                          NM_SETTING_VLAN_SETTING_NAME,
Packit Service a1bd4f
                                          NM_SETTING_BOND_SETTING_NAME,
Packit Service a1bd4f
                                          NM_SETTING_TEAM_SETTING_NAME,
Packit Service a1bd4f
                                          NM_SETTING_BRIDGE_SETTING_NAME,
Packit Service a1bd4f
                                          NM_SETTING_IP_TUNNEL_SETTING_NAME,
Packit Service a1bd4f
                                          "NMDeviceModem",
Packit Service a1bd4f
                                          "NMDeviceBt"};
Packit Service a1bd4f
static const int   device_sort_order_len = G_N_ELEMENTS(device_sort_order);
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
get_sort_order_for_device(NMDevice *device)
Packit 5756e2
{
Packit Service a1bd4f
    const char *type;
Packit Service a1bd4f
    int         i;
Packit 5756e2
Packit Service a1bd4f
    type = G_OBJECT_TYPE_NAME(device);
Packit Service a1bd4f
    for (i = 0; i < device_sort_order_len; i++) {
Packit Service a1bd4f
        if (!strcmp(type, device_sort_order[i]))
Packit Service a1bd4f
            return i;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return -1;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
get_sort_order_for_connection(NMConnection *conn)
Packit 5756e2
{
Packit Service a1bd4f
    NMSettingConnection *s_con;
Packit Service a1bd4f
    const char *         type;
Packit Service a1bd4f
    int                  i;
Packit 5756e2
Packit Service a1bd4f
    s_con = nm_connection_get_setting_connection(conn);
Packit Service a1bd4f
    type  = nm_setting_connection_get_connection_type(s_con);
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; i < device_sort_order_len; i++) {
Packit Service a1bd4f
        if (!strcmp(type, device_sort_order[i]))
Packit Service a1bd4f
            return i;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return -1;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
sort_connections(gconstpointer a, gconstpointer b)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnection *nmta = (NmtConnectConnection *) a;
Packit Service a1bd4f
    NmtConnectConnection *nmtb = (NmtConnectConnection *) b;
Packit 5756e2
Packit Service a1bd4f
    /* If nmta and nmtb both have NMConnections, sort them by timestamp */
Packit Service a1bd4f
    if (nmta->conn && nmtb->conn) {
Packit Service a1bd4f
        NMSettingConnection *s_con_a, *s_con_b;
Packit Service a1bd4f
        guint64              time_a, time_b;
Packit 5756e2
Packit Service a1bd4f
        s_con_a = nm_connection_get_setting_connection(nmta->conn);
Packit Service a1bd4f
        s_con_b = nm_connection_get_setting_connection(nmtb->conn);
Packit 5756e2
Packit Service a1bd4f
        time_a = nm_setting_connection_get_timestamp(s_con_a);
Packit Service a1bd4f
        time_b = nm_setting_connection_get_timestamp(s_con_b);
Packit 5756e2
Packit Service a1bd4f
        return (int) (time_b - time_a);
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    /* If one is an NMConnection and the other is an NMAccessPoint, the
Packit Service a1bd4f
     * connection comes first.
Packit Service a1bd4f
     */
Packit Service a1bd4f
    if (nmta->conn)
Packit Service a1bd4f
        return -1;
Packit Service a1bd4f
    else if (nmtb->conn)
Packit Service a1bd4f
        return 1;
Packit 5756e2
Packit Service a1bd4f
    g_return_val_if_fail(nmta->ap && nmtb->ap, 0);
Packit 5756e2
Packit Service a1bd4f
    /* If both are access points, then sort by strength */
Packit Service a1bd4f
    return nm_access_point_get_strength(nmtb->ap) - nm_access_point_get_strength(nmta->ap);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
add_connections_for_device(NmtConnectDevice *nmtdev, const GPtrArray *connections)
Packit 5756e2
{
Packit Service a1bd4f
    int i;
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; i < connections->len; i++) {
Packit Service a1bd4f
        NMConnection *       conn = connections->pdata[i];
Packit Service a1bd4f
        NMSettingConnection *s_con;
Packit 5756e2
Packit Service a1bd4f
        s_con = nm_connection_get_setting_connection(conn);
Packit Service a1bd4f
        if (nm_setting_connection_get_master(s_con))
Packit Service a1bd4f
            continue;
Packit 5756e2
Packit Service a1bd4f
        if (nm_device_connection_valid(nmtdev->device, conn)) {
Packit Service a1bd4f
            NmtConnectConnection *nmtconn = g_slice_new0(NmtConnectConnection);
Packit 5756e2
Packit Service a1bd4f
            nmtconn->name   = nm_connection_get_id(conn);
Packit Service a1bd4f
            nmtconn->device = nmtdev->device;
Packit Service a1bd4f
            nmtconn->conn   = g_object_ref(conn);
Packit Service a1bd4f
            nmtdev->conns   = g_slist_prepend(nmtdev->conns, nmtconn);
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/* stolen from nm-applet */
Packit 5756e2
static char *
Packit Service a1bd4f
hash_ap(NMAccessPoint *ap)
Packit 5756e2
{
Packit Service a1bd4f
    unsigned char input[66];
Packit Service a1bd4f
    GBytes *      ssid;
Packit Service a1bd4f
    NM80211Mode   mode;
Packit Service a1bd4f
    guint32       flags;
Packit Service a1bd4f
    guint32       wpa_flags;
Packit Service a1bd4f
    guint32       rsn_flags;
Packit Service a1bd4f
Packit Service a1bd4f
    memset(&input[0], 0, sizeof(input));
Packit Service a1bd4f
Packit Service a1bd4f
    ssid = nm_access_point_get_ssid(ap);
Packit Service a1bd4f
    if (ssid)
Packit Service a1bd4f
        memcpy(input, g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid));
Packit Service a1bd4f
Packit Service a1bd4f
    mode = nm_access_point_get_mode(ap);
Packit Service a1bd4f
    if (mode == NM_802_11_MODE_INFRA)
Packit Service a1bd4f
        input[32] |= (1 << 0);
Packit Service a1bd4f
    else if (mode == NM_802_11_MODE_ADHOC)
Packit Service a1bd4f
        input[32] |= (1 << 1);
Packit Service a1bd4f
    else
Packit Service a1bd4f
        input[32] |= (1 << 2);
Packit Service a1bd4f
Packit Service a1bd4f
    /* Separate out no encryption, WEP-only, and WPA-capable */
Packit Service a1bd4f
    flags     = nm_access_point_get_flags(ap);
Packit Service a1bd4f
    wpa_flags = nm_access_point_get_wpa_flags(ap);
Packit Service a1bd4f
    rsn_flags = nm_access_point_get_rsn_flags(ap);
Packit Service a1bd4f
    if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_flags == NM_802_11_AP_SEC_NONE)
Packit Service a1bd4f
        && (rsn_flags == NM_802_11_AP_SEC_NONE))
Packit Service a1bd4f
        input[32] |= (1 << 3);
Packit Service a1bd4f
    else if ((flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_flags == NM_802_11_AP_SEC_NONE)
Packit Service a1bd4f
             && (rsn_flags == NM_802_11_AP_SEC_NONE))
Packit Service a1bd4f
        input[32] |= (1 << 4);
Packit Service a1bd4f
    else if (!(flags & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_flags != NM_802_11_AP_SEC_NONE)
Packit Service a1bd4f
             && (rsn_flags != NM_802_11_AP_SEC_NONE))
Packit Service a1bd4f
        input[32] |= (1 << 5);
Packit Service a1bd4f
    else
Packit Service a1bd4f
        input[32] |= (1 << 6);
Packit Service a1bd4f
Packit Service a1bd4f
    /* duplicate it */
Packit Service a1bd4f
    memcpy(&input[33], &input[0], 32);
Packit Service a1bd4f
    return g_compute_checksum_for_data(G_CHECKSUM_MD5, input, sizeof(input));
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
add_connections_for_aps(NmtConnectDevice *nmtdev, const GPtrArray *connections)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnection *nmtconn;
Packit Service a1bd4f
    NMConnection *        conn;
Packit Service a1bd4f
    NMAccessPoint *       ap;
Packit Service a1bd4f
    const GPtrArray *     aps;
Packit Service a1bd4f
    GHashTable *          seen_ssids;
Packit Service a1bd4f
    GBytes *              ssid;
Packit Service a1bd4f
    char *                ap_hash;
Packit Service a1bd4f
    int                   i, c;
Packit Service a1bd4f
Packit Service a1bd4f
    aps = nm_device_wifi_get_access_points(NM_DEVICE_WIFI(nmtdev->device));
Packit Service a1bd4f
    if (!aps->len)
Packit Service a1bd4f
        return;
Packit Service a1bd4f
Packit Service a1bd4f
    seen_ssids = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, NULL);
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; i < aps->len; i++) {
Packit Service a1bd4f
        ap = aps->pdata[i];
Packit Service a1bd4f
Packit Service a1bd4f
        if (!nm_access_point_get_ssid(ap))
Packit Service a1bd4f
            continue;
Packit Service a1bd4f
Packit Service a1bd4f
        ap_hash = hash_ap(ap);
Packit Service a1bd4f
        if (g_hash_table_contains(seen_ssids, ap_hash)) {
Packit Service a1bd4f
            g_free(ap_hash);
Packit Service a1bd4f
            continue;
Packit Service a1bd4f
        }
Packit Service a1bd4f
        g_hash_table_add(seen_ssids, ap_hash);
Packit Service a1bd4f
Packit Service a1bd4f
        nmtconn         = g_slice_new0(NmtConnectConnection);
Packit Service a1bd4f
        nmtconn->device = nmtdev->device;
Packit Service a1bd4f
        nmtconn->ap     = g_object_ref(ap);
Packit Service a1bd4f
        ssid            = nm_access_point_get_ssid(ap);
Packit Service a1bd4f
        if (ssid)
Packit Service a1bd4f
            nmtconn->ssid =
Packit Service a1bd4f
                nm_utils_ssid_to_utf8(g_bytes_get_data(ssid, NULL), g_bytes_get_size(ssid));
Packit Service a1bd4f
Packit Service a1bd4f
        for (c = 0; c < connections->len; c++) {
Packit Service a1bd4f
            conn = connections->pdata[c];
Packit Service a1bd4f
            if (nm_device_connection_valid(nmtdev->device, conn)
Packit Service a1bd4f
                && nm_access_point_connection_valid(ap, conn)) {
Packit Service a1bd4f
                nmtconn->name = nm_connection_get_id(conn);
Packit Service a1bd4f
                nmtconn->conn = g_object_ref(conn);
Packit Service a1bd4f
                break;
Packit Service a1bd4f
            }
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        if (!nmtconn->name)
Packit Service a1bd4f
            nmtconn->name = nmtconn->ssid ?: "<unknown>";
Packit Service a1bd4f
Packit Service a1bd4f
        nmtdev->conns = g_slist_prepend(nmtdev->conns, nmtconn);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_hash_table_unref(seen_ssids);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static GSList *
Packit Service a1bd4f
append_nmt_devices_for_devices(GSList *         nmt_devices,
Packit Service a1bd4f
                               const GPtrArray *devices,
Packit Service a1bd4f
                               char **          names,
Packit Service a1bd4f
                               const GPtrArray *connections)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectDevice *nmtdev;
Packit Service a1bd4f
    NMDevice *        device;
Packit Service a1bd4f
    int               i, sort_order;
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; i < devices->len; i++) {
Packit Service a1bd4f
        device = devices->pdata[i];
Packit 5756e2
Packit Service a1bd4f
        sort_order = get_sort_order_for_device(device);
Packit Service a1bd4f
        if (sort_order == -1)
Packit Service a1bd4f
            continue;
Packit 5756e2
Packit Service a1bd4f
        nmtdev             = g_slice_new0(NmtConnectDevice);
Packit Service a1bd4f
        nmtdev->name       = g_strdup(names[i]);
Packit Service a1bd4f
        nmtdev->device     = g_object_ref(device);
Packit Service a1bd4f
        nmtdev->sort_order = sort_order;
Packit 5756e2
Packit Service a1bd4f
        if (NM_IS_DEVICE_WIFI(device))
Packit Service a1bd4f
            add_connections_for_aps(nmtdev, connections);
Packit Service a1bd4f
        else
Packit Service a1bd4f
            add_connections_for_device(nmtdev, connections);
Packit Service a1bd4f
        nmtdev->conns = g_slist_sort(nmtdev->conns, sort_connections);
Packit 5756e2
Packit Service a1bd4f
        nmt_devices = g_slist_prepend(nmt_devices, nmtdev);
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return nmt_devices;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static GSList *
Packit Service a1bd4f
append_nmt_devices_for_virtual_devices(GSList *nmt_devices, const GPtrArray *connections)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectDevice *    nmtdev = NULL;
Packit Service a1bd4f
    int                   i;
Packit Service a1bd4f
    GHashTable *          devices_by_name;
Packit Service a1bd4f
    char *                name;
Packit Service a1bd4f
    NMConnection *        conn;
Packit Service a1bd4f
    NmtConnectConnection *nmtconn;
Packit Service a1bd4f
    int                   sort_order;
Packit Service a1bd4f
Packit Service a1bd4f
    devices_by_name = g_hash_table_new(nm_str_hash, g_str_equal);
Packit Service a1bd4f
Packit Service a1bd4f
    for (i = 0; i < connections->len; i++) {
Packit Service a1bd4f
        conn       = connections->pdata[i];
Packit Service a1bd4f
        sort_order = get_sort_order_for_connection(conn);
Packit Service a1bd4f
        if (sort_order == -1)
Packit Service a1bd4f
            continue;
Packit Service a1bd4f
Packit Service a1bd4f
        name = nm_connection_get_virtual_device_description(conn);
Packit Service a1bd4f
        if (name)
Packit Service a1bd4f
            nmtdev = g_hash_table_lookup(devices_by_name, name);
Packit Service a1bd4f
        if (nmtdev)
Packit Service a1bd4f
            g_free(name);
Packit Service a1bd4f
        else {
Packit Service a1bd4f
            nmtdev             = g_slice_new0(NmtConnectDevice);
Packit Service a1bd4f
            nmtdev->name       = name ?: g_strdup("Unknown");
Packit Service a1bd4f
            nmtdev->sort_order = sort_order;
Packit Service a1bd4f
Packit Service a1bd4f
            g_hash_table_insert(devices_by_name, nmtdev->name, nmtdev);
Packit Service a1bd4f
            nmt_devices = g_slist_prepend(nmt_devices, nmtdev);
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        nmtconn       = g_slice_new0(NmtConnectConnection);
Packit Service a1bd4f
        nmtconn->name = nm_connection_get_id(conn);
Packit Service a1bd4f
        nmtconn->conn = g_object_ref(conn);
Packit Service a1bd4f
Packit Service a1bd4f
        nmtdev->conns = g_slist_insert_sorted(nmtdev->conns, nmtconn, sort_connections);
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    g_hash_table_destroy(devices_by_name);
Packit Service a1bd4f
    return nmt_devices;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static GSList *
Packit Service a1bd4f
append_nmt_devices_for_vpns(GSList *nmt_devices, const GPtrArray *connections)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectDevice *    nmtdev;
Packit Service a1bd4f
    int                   i;
Packit Service a1bd4f
    NMConnection *        conn;
Packit Service a1bd4f
    NmtConnectConnection *nmtconn;
Packit 5756e2
Packit Service a1bd4f
    nmtdev             = g_slice_new0(NmtConnectDevice);
Packit Service a1bd4f
    nmtdev->name       = g_strdup(_("VPN"));
Packit Service a1bd4f
    nmtdev->sort_order = 100;
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; i < connections->len; i++) {
Packit Service a1bd4f
        conn = connections->pdata[i];
Packit Service a1bd4f
        if (!nm_connection_is_type(conn, NM_SETTING_VPN_SETTING_NAME))
Packit Service a1bd4f
            continue;
Packit 5756e2
Packit Service a1bd4f
        nmtconn       = g_slice_new0(NmtConnectConnection);
Packit Service a1bd4f
        nmtconn->name = nm_connection_get_id(conn);
Packit Service a1bd4f
        nmtconn->conn = g_object_ref(conn);
Packit 5756e2
Packit Service a1bd4f
        nmtdev->conns = g_slist_insert_sorted(nmtdev->conns, nmtconn, sort_connections);
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    if (nmtdev->conns)
Packit Service a1bd4f
        nmt_devices = g_slist_prepend(nmt_devices, nmtdev);
Packit Service a1bd4f
    else
Packit Service a1bd4f
        nmt_connect_device_free(nmtdev);
Packit 5756e2
Packit Service a1bd4f
    return nmt_devices;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static int
Packit Service a1bd4f
sort_nmt_devices(gconstpointer a, gconstpointer b)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectDevice *nmta = (NmtConnectDevice *) a;
Packit Service a1bd4f
    NmtConnectDevice *nmtb = (NmtConnectDevice *) b;
Packit 5756e2
Packit Service a1bd4f
    if (nmta->sort_order != nmtb->sort_order)
Packit Service a1bd4f
        return nmta->sort_order - nmtb->sort_order;
Packit 5756e2
Packit Service a1bd4f
    return strcmp(nmta->name, nmtb->name);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static NMActiveConnection *
Packit Service a1bd4f
connection_find_ac(NMConnection *conn, const GPtrArray *acs)
Packit 5756e2
{
Packit Service a1bd4f
    NMActiveConnection *ac;
Packit Service a1bd4f
    NMRemoteConnection *ac_conn;
Packit Service a1bd4f
    int                 i;
Packit 5756e2
Packit Service a1bd4f
    for (i = 0; i < acs->len; i++) {
Packit Service a1bd4f
        ac      = acs->pdata[i];
Packit Service a1bd4f
        ac_conn = nm_active_connection_get_connection(ac);
Packit 5756e2
Packit Service a1bd4f
        if (conn == NM_CONNECTION(ac_conn))
Packit Service a1bd4f
            return ac;
Packit Service a1bd4f
    }
Packit 5756e2
Packit Service a1bd4f
    return NULL;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_list_rebuild(NmtConnectConnectionList *list)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnectionListPrivate *priv    = NMT_CONNECT_CONNECTION_LIST_GET_PRIVATE(list);
Packit Service a1bd4f
    NmtNewtListbox *                 listbox = NMT_NEWT_LISTBOX(list);
Packit Service a1bd4f
    const GPtrArray *                devices, *acs, *connections;
Packit Service a1bd4f
    int                              max_width;
Packit Service a1bd4f
    char **                          names, *row, active_col;
Packit Service a1bd4f
    const char *                     strength_col;
Packit Service a1bd4f
    GSList *                         nmt_devices, *diter, *citer;
Packit Service a1bd4f
    NmtConnectDevice *               nmtdev;
Packit Service a1bd4f
    NmtConnectConnection *           nmtconn;
Packit Service a1bd4f
Packit Service a1bd4f
    g_slist_free_full(priv->nmt_devices, (GDestroyNotify) nmt_connect_device_free);
Packit Service a1bd4f
    priv->nmt_devices = NULL;
Packit Service a1bd4f
    nmt_newt_listbox_clear(listbox);
Packit Service a1bd4f
Packit Service a1bd4f
    devices     = nm_client_get_devices(nm_client);
Packit Service a1bd4f
    acs         = nm_client_get_active_connections(nm_client);
Packit Service a1bd4f
    connections = nm_client_get_connections(nm_client);
Packit Service a1bd4f
Packit Service a1bd4f
    nmt_devices = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    names       = nm_device_disambiguate_names((NMDevice **) devices->pdata, devices->len);
Packit Service a1bd4f
    nmt_devices = append_nmt_devices_for_devices(nmt_devices, devices, names, connections);
Packit Service a1bd4f
    g_strfreev(names);
Packit Service a1bd4f
Packit Service a1bd4f
    nmt_devices = append_nmt_devices_for_virtual_devices(nmt_devices, connections);
Packit Service a1bd4f
    nmt_devices = append_nmt_devices_for_vpns(nmt_devices, connections);
Packit Service a1bd4f
Packit Service a1bd4f
    nmt_devices = g_slist_sort(nmt_devices, sort_nmt_devices);
Packit Service a1bd4f
Packit Service a1bd4f
    max_width = 0;
Packit Service a1bd4f
    for (diter = nmt_devices; diter; diter = diter->next) {
Packit Service a1bd4f
        nmtdev = diter->data;
Packit Service a1bd4f
        for (citer = nmtdev->conns; citer; citer = citer->next) {
Packit Service a1bd4f
            nmtconn = citer->data;
Packit Service a1bd4f
Packit Service a1bd4f
            max_width = MAX(max_width, nmt_newt_text_width(nmtconn->name));
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    for (diter = nmt_devices; diter; diter = diter->next) {
Packit Service a1bd4f
        nmtdev = diter->data;
Packit Service a1bd4f
Packit Service a1bd4f
        if (nmtdev->conns) {
Packit Service a1bd4f
            if (diter != nmt_devices)
Packit Service a1bd4f
                nmt_newt_listbox_append(listbox, "", NULL);
Packit Service a1bd4f
            nmt_newt_listbox_append(listbox, nmtdev->name, NULL);
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        for (citer = nmtdev->conns; citer; citer = citer->next) {
Packit Service a1bd4f
            nmtconn = citer->data;
Packit Service a1bd4f
Packit Service a1bd4f
            if (nmtconn->conn)
Packit Service a1bd4f
                nmtconn->active = connection_find_ac(nmtconn->conn, acs);
Packit Service a1bd4f
            if (nmtconn->active) {
Packit Service a1bd4f
                g_object_ref(nmtconn->active);
Packit Service a1bd4f
                active_col = '*';
Packit Service a1bd4f
            } else
Packit Service a1bd4f
                active_col = ' ';
Packit Service a1bd4f
Packit Service a1bd4f
            if (nmtconn->ap) {
Packit Service a1bd4f
                guint8 strength = nm_access_point_get_strength(nmtconn->ap);
Packit Service a1bd4f
Packit Service a1bd4f
                strength_col = nmc_wifi_strength_bars(strength);
Packit Service a1bd4f
            } else
Packit Service a1bd4f
                strength_col = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
            row = g_strdup_printf("%c %s%-*s%s%s",
Packit Service a1bd4f
                                  active_col,
Packit Service a1bd4f
                                  nmtconn->name,
Packit Service a1bd4f
                                  (int) (max_width - nmt_newt_text_width(nmtconn->name)),
Packit Service a1bd4f
                                  "",
Packit Service a1bd4f
                                  strength_col ? " " : "",
Packit Service a1bd4f
                                  strength_col ?: "");
Packit Service a1bd4f
Packit Service a1bd4f
            nmt_newt_listbox_append(listbox, row, nmtconn);
Packit Service a1bd4f
            g_free(row);
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    priv->nmt_devices = nmt_devices;
Packit Service a1bd4f
Packit Service a1bd4f
    g_object_notify(G_OBJECT(listbox), "active");
Packit Service a1bd4f
    g_object_notify(G_OBJECT(listbox), "active-key");
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
rebuild_on_property_changed(GObject *object, GParamSpec *spec, gpointer list)
Packit 5756e2
{
Packit Service a1bd4f
    nmt_connect_connection_list_rebuild(list);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_list_constructed(GObject *object)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnectionList *list = NMT_CONNECT_CONNECTION_LIST(object);
Packit Service a1bd4f
Packit Service a1bd4f
    g_signal_connect(nm_client,
Packit Service a1bd4f
                     "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
Packit Service a1bd4f
                     G_CALLBACK(rebuild_on_property_changed),
Packit Service a1bd4f
                     list);
Packit Service a1bd4f
    g_signal_connect(nm_client,
Packit Service a1bd4f
                     "notify::" NM_CLIENT_CONNECTIONS,
Packit Service a1bd4f
                     G_CALLBACK(rebuild_on_property_changed),
Packit Service a1bd4f
                     list);
Packit Service a1bd4f
    g_signal_connect(nm_client,
Packit Service a1bd4f
                     "notify::" NM_CLIENT_DEVICES,
Packit Service a1bd4f
                     G_CALLBACK(rebuild_on_property_changed),
Packit Service a1bd4f
                     list);
Packit Service a1bd4f
Packit Service a1bd4f
    nmt_connect_connection_list_rebuild(list);
Packit Service a1bd4f
Packit Service a1bd4f
    G_OBJECT_CLASS(nmt_connect_connection_list_parent_class)->constructed(object);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_list_finalize(GObject *object)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnectionListPrivate *priv = NMT_CONNECT_CONNECTION_LIST_GET_PRIVATE(object);
Packit 5756e2
Packit Service a1bd4f
    g_slist_free_full(priv->nmt_devices, (GDestroyNotify) nmt_connect_device_free);
Packit 5756e2
Packit Service a1bd4f
    g_signal_handlers_disconnect_by_func(nm_client,
Packit Service a1bd4f
                                         G_CALLBACK(rebuild_on_property_changed),
Packit Service a1bd4f
                                         object);
Packit 5756e2
Packit Service a1bd4f
    G_OBJECT_CLASS(nmt_connect_connection_list_parent_class)->finalize(object);
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
static void
Packit Service a1bd4f
nmt_connect_connection_list_class_init(NmtConnectConnectionListClass *list_class)
Packit 5756e2
{
Packit Service a1bd4f
    GObjectClass *object_class = G_OBJECT_CLASS(list_class);
Packit 5756e2
Packit Service a1bd4f
    g_type_class_add_private(list_class, sizeof(NmtConnectConnectionListPrivate));
Packit 5756e2
Packit Service a1bd4f
    /* virtual methods */
Packit Service a1bd4f
    object_class->constructed = nmt_connect_connection_list_constructed;
Packit Service a1bd4f
    object_class->finalize    = nmt_connect_connection_list_finalize;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nmt_connect_connection_list_get_connection:
Packit 5756e2
 * @list: an #NmtConnectConnectionList
Packit 5756e2
 * @identifier: a connection ID or UUID, or device name
Packit 5756e2
 * @connection: (out) (transfer none): the #NMConnection to be activated
Packit 5756e2
 * @device: (out) (transfer none): the #NMDevice to activate @connection on
Packit 5756e2
 * @specific_object: (out) (transfer none): the "specific object" to connect to
Packit 5756e2
 * @active: (out) (transfer none): the #NMActiveConnection corresponding
Packit 5756e2
 *   to the selection, if any.
Packit 5756e2
 *
Packit 5756e2
 * Gets information about the indicated connection.
Packit 5756e2
 *
Packit 5756e2
 * Returns: %TRUE if there was a match, %FALSE if not.
Packit 5756e2
 */
Packit 5756e2
gboolean
Packit Service a1bd4f
nmt_connect_connection_list_get_connection(NmtConnectConnectionList *list,
Packit Service a1bd4f
                                           const char *              identifier,
Packit Service a1bd4f
                                           NMConnection **           connection,
Packit Service a1bd4f
                                           NMDevice **               device,
Packit Service a1bd4f
                                           NMObject **               specific_object,
Packit Service a1bd4f
                                           NMActiveConnection **     active)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnectionListPrivate *priv = NMT_CONNECT_CONNECTION_LIST_GET_PRIVATE(list);
Packit Service a1bd4f
    GSList *                         diter, *citer;
Packit Service a1bd4f
    NmtConnectDevice *               nmtdev;
Packit Service a1bd4f
    NmtConnectConnection *           nmtconn = NULL;
Packit Service a1bd4f
    NMConnection *                   conn    = NULL;
Packit Service a1bd4f
Packit Service a1bd4f
    g_return_val_if_fail(identifier, FALSE);
Packit Service a1bd4f
Packit Service a1bd4f
    if (nm_utils_is_uuid(identifier))
Packit Service a1bd4f
        conn = NM_CONNECTION(nm_client_get_connection_by_uuid(nm_client, identifier));
Packit Service a1bd4f
    if (!conn)
Packit Service a1bd4f
        conn = NM_CONNECTION(nm_client_get_connection_by_id(nm_client, identifier));
Packit Service a1bd4f
Packit Service a1bd4f
    for (diter = priv->nmt_devices; diter; diter = diter->next) {
Packit Service a1bd4f
        nmtdev = diter->data;
Packit Service a1bd4f
        if (!nmtdev->conns)
Packit Service a1bd4f
            continue;
Packit Service a1bd4f
Packit Service a1bd4f
        for (citer = nmtdev->conns; citer; citer = citer->next) {
Packit Service a1bd4f
            nmtconn = citer->data;
Packit Service a1bd4f
            if (conn) {
Packit Service a1bd4f
                if (conn == nmtconn->conn)
Packit Service a1bd4f
                    goto found;
Packit Service a1bd4f
            } else if (nm_streq0(identifier, nmtconn->ssid))
Packit Service a1bd4f
                goto found;
Packit Service a1bd4f
        }
Packit Service a1bd4f
Packit Service a1bd4f
        if (!conn && nmtdev->device
Packit Service a1bd4f
            && nm_streq0(identifier, nm_device_get_ip_iface(nmtdev->device))) {
Packit Service a1bd4f
            nmtconn = nmtdev->conns->data;
Packit Service a1bd4f
            goto found;
Packit Service a1bd4f
        }
Packit Service a1bd4f
    }
Packit Service a1bd4f
Packit Service a1bd4f
    return FALSE;
Packit 5756e2
Packit 5756e2
found:
Packit Service a1bd4f
    if (connection)
Packit Service a1bd4f
        *connection = nmtconn->conn;
Packit Service a1bd4f
    if (device)
Packit Service a1bd4f
        *device = nmtconn->device;
Packit Service a1bd4f
    if (specific_object)
Packit Service a1bd4f
        *specific_object = NM_OBJECT(nmtconn->ap);
Packit Service a1bd4f
    if (active)
Packit Service a1bd4f
        *active = nmtconn->active;
Packit Service a1bd4f
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}
Packit 5756e2
Packit 5756e2
/**
Packit 5756e2
 * nmt_connect_connection_list_get_selection:
Packit 5756e2
 * @list: an #NmtConnectConnectionList
Packit 5756e2
 * @connection: (out) (transfer none): the #NMConnection to be activated
Packit 5756e2
 * @device: (out) (transfer none): the #NMDevice to activate @connection on
Packit 5756e2
 * @specific_object: (out) (transfer none): the "specific object" to connect to
Packit 5756e2
 * @active: (out) (transfer none): the #NMActiveConnection corresponding
Packit 5756e2
 *   to the selection, if any.
Packit 5756e2
 *
Packit 5756e2
 * Gets information about the selected row.
Packit 5756e2
 *
Packit 5756e2
 * Returns: %TRUE if there is a selection, %FALSE if not.
Packit 5756e2
 */
Packit 5756e2
gboolean
Packit Service a1bd4f
nmt_connect_connection_list_get_selection(NmtConnectConnectionList *list,
Packit Service a1bd4f
                                          NMConnection **           connection,
Packit Service a1bd4f
                                          NMDevice **               device,
Packit Service a1bd4f
                                          NMObject **               specific_object,
Packit Service a1bd4f
                                          NMActiveConnection **     active)
Packit 5756e2
{
Packit Service a1bd4f
    NmtConnectConnection *nmtconn;
Packit Service a1bd4f
Packit Service a1bd4f
    nmtconn = nmt_newt_listbox_get_active_key(NMT_NEWT_LISTBOX(list));
Packit Service a1bd4f
    if (!nmtconn)
Packit Service a1bd4f
        return FALSE;
Packit Service a1bd4f
Packit Service a1bd4f
    if (connection)
Packit Service a1bd4f
        *connection = nmtconn->conn;
Packit Service a1bd4f
    if (device)
Packit Service a1bd4f
        *device = nmtconn->device;
Packit Service a1bd4f
    if (specific_object)
Packit Service a1bd4f
        *specific_object = NM_OBJECT(nmtconn->ap);
Packit Service a1bd4f
    if (active)
Packit Service a1bd4f
        *active = nmtconn->active;
Packit Service a1bd4f
Packit Service a1bd4f
    return TRUE;
Packit 5756e2
}