// SPDX-License-Identifier: GPL-2.0+
/* NetworkManager Applet -- allow user control over networking
*
* Dan Williams <dcbw@redhat.com>
*
* Copyright 2008 - 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <NetworkManager.h>
#include "applet-dialogs.h"
#include "utils.h"
#include "nma-bar-code-widget.h"
static void
info_dialog_show_error (const char *err)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s", _("Error displaying connection information:"), err);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_present (GTK_WINDOW (dialog));
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_destroy), dialog);
}
static char *
ip4_address_as_string (guint32 ip)
{
char *ip_string;
struct in_addr tmp_addr;
tmp_addr.s_addr = ip;
ip_string = g_malloc0 (INET_ADDRSTRLEN + 1);
if (!inet_ntop (AF_INET, &tmp_addr, ip_string, INET_ADDRSTRLEN))
strcpy (ip_string, "(none)");
return ip_string;
}
static char *
get_eap_label (NMSettingWirelessSecurity *sec,
NMSetting8021x *s_8021x)
{
GString *str = NULL;
char *phase2_str = NULL;
if (sec) {
const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (sec);
const char *auth_alg = nm_setting_wireless_security_get_auth_alg (sec);
if (!strcmp (key_mgmt, "ieee8021x")) {
if (auth_alg && !strcmp (auth_alg, "leap"))
str = g_string_new (_("LEAP"));
else
str = g_string_new (_("Dynamic WEP"));
} else if (!strcmp (key_mgmt, "wpa-eap"))
str = g_string_new (_("WPA/WPA2"));
else
return NULL;
} else if (s_8021x)
str = g_string_new ("802.1x");
if (!s_8021x)
goto out;
if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
char *eap_str = g_ascii_strup (nm_setting_802_1x_get_eap_method (s_8021x, 0), -1);
g_string_append_printf (str, ", EAP-%s", eap_str);
g_free (eap_str);
}
if (nm_setting_802_1x_get_phase2_auth (s_8021x))
phase2_str = g_ascii_strup (nm_setting_802_1x_get_phase2_auth (s_8021x), -1);
else if (nm_setting_802_1x_get_phase2_autheap (s_8021x))
phase2_str = g_ascii_strup (nm_setting_802_1x_get_phase2_autheap (s_8021x), -1);
if (phase2_str) {
g_string_append (str, ", ");
g_string_append (str, phase2_str);
g_free (phase2_str);
}
out:
return g_string_free (str, FALSE);
}
static NMConnection *
get_connection_for_active_path (NMApplet *applet, const char *active_path)
{
NMActiveConnection *active = NULL;
const GPtrArray *connections;
int i;
if (active_path == NULL)
return NULL;
connections = nm_client_get_active_connections (applet->nm_client);
for (i = 0; connections && (i < connections->len); i++) {
NMActiveConnection *candidate = g_ptr_array_index (connections, i);
const char *ac_path = nm_object_get_path (NM_OBJECT (candidate));
if (g_strcmp0 (ac_path, active_path) == 0) {
active = candidate;
break;
}
}
return active ? (NMConnection *) nm_active_connection_get_connection (active) : NULL;
}
static GtkWidget *
create_info_label (const char *text)
{
GtkWidget *label;
label = gtk_label_new (text ? text : "");
gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.0);
gtk_style_context_add_class (gtk_widget_get_style_context (label),
"dim-label");
return label;
}
static GtkWidget *
create_info_value (const char *text)
{
GtkWidget *label;
label = gtk_label_new (text ? text : "");
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
gtk_label_set_selectable (GTK_LABEL (label), TRUE);
return label;
}
static GtkWidget *
create_info_group_label (const char *text, gboolean selectable)
{
GtkWidget *label;
char *markup;
markup = g_markup_printf_escaped ("<span weight=\"bold\">%s</span>", text);
label = gtk_label_new (markup);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
g_free (markup);
return label;
}
static GtkWidget *
create_more_addresses_widget (const GPtrArray *addresses)
{
GtkWidget *expander, *label, *text_view, *child;
GtkTextBuffer *buffer;
GtkWidget *scrolled_window;
int i;
/* Create the expander */
expander = gtk_expander_new (_("More addresses"));
gtk_widget_set_halign (expander, GTK_ALIGN_START);
label = gtk_expander_get_label_widget (GTK_EXPANDER (expander));
gtk_widget_set_margin_top (label, 2);
/* Create the text view widget and add additional addresses to it */
text_view = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), FALSE);
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (text_view), 20);
gtk_expander_set_spacing (GTK_EXPANDER (expander), 4);
child = text_view;
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
for (i = 1; addresses && (i < addresses->len); i++) {
NMIPAddress *addr = (NMIPAddress *) g_ptr_array_index (addresses, i);
char *addr_text = g_strdup_printf ("%s / %d",
nm_ip_address_get_address (addr),
nm_ip_address_get_prefix (addr));
if (i != 1)
gtk_text_buffer_insert_at_cursor (buffer, "\n", -1);
gtk_text_buffer_insert_at_cursor (buffer, addr_text, -1);
g_free (addr_text);
}
if (addresses->len > 5) {
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
gtk_widget_set_size_request (scrolled_window, -1, 80);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
child = scrolled_window;
}
gtk_container_add (GTK_CONTAINER (expander), child);
return expander;
}
static GtkWidget *
create_info_label_security (NMConnection *connection)
{
NMSettingConnection *s_con;
char *label = NULL;
GtkWidget *w = NULL;
const char *connection_type;
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
connection_type = nm_setting_connection_get_connection_type (s_con);
if (!strcmp (connection_type, NM_SETTING_WIRELESS_SETTING_NAME)) {
NMSettingWirelessSecurity *s_wireless_sec;
NMSetting8021x *s_8021x;
s_wireless_sec = nm_connection_get_setting_wireless_security (connection);
s_8021x = nm_connection_get_setting_802_1x (connection);
if (s_wireless_sec) {
const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
if (!strcmp (key_mgmt, "none"))
label = g_strdup (_("WEP"));
else if (!strcmp (key_mgmt, "wpa-none"))
label = g_strdup (_("WPA/WPA2"));
else if (!strcmp (key_mgmt, "wpa-psk"))
label = g_strdup (_("WPA/WPA2"));
else if (!strcmp (key_mgmt, "sae"))
label = g_strdup (_("WPA3"));
else
label = get_eap_label (s_wireless_sec, s_8021x);
} else {
label = g_strdup (C_("Wi-Fi/Ethernet security", "None"));
}
} else if (!strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME)) {
NMSetting8021x *s_8021x;
s_8021x = nm_connection_get_setting_802_1x (connection);
if (s_8021x)
label = get_eap_label (NULL, s_8021x);
else
label = g_strdup (C_("Wi-Fi/Ethernet security", "None"));
}
if (label)
w = create_info_value (label);
g_free (label);
return w;
}
typedef struct {
NMDevice *device;
GtkWidget *label;
guint32 id;
} LabelInfo;
static void
device_destroyed (gpointer data, GObject *device_ptr)
{
LabelInfo *info = data;
/* Device is destroyed, notify handler won't fire
* anymore anyway. Let the label destroy handler
* know it doesn't have to disconnect the callback.
*/
info->device = NULL;
info->id = 0;
}
static void
label_destroyed (gpointer data, GObject *label_ptr)
{
LabelInfo *info = data;
/* Remove the notify handler from the device */
if (info->device) {
if (info->id)
g_signal_handler_disconnect (info->device, info->id);
/* destroy our info data */
g_object_weak_unref (G_OBJECT (info->device), device_destroyed, info);
memset (info, 0, sizeof (LabelInfo));
g_free (info);
}
}
static void
label_info_new (NMDevice *device,
GtkWidget *label,
const char *notify_prop,
GCallback callback)
{
LabelInfo *info;
info = g_malloc0 (sizeof (LabelInfo));
info->device = device;
info->label = label;
info->id = g_signal_connect (device, notify_prop, callback, label);
g_object_weak_ref (G_OBJECT (label), label_destroyed, info);
g_object_weak_ref (G_OBJECT (device), device_destroyed, info);
}
static void
bitrate_changed_cb (GObject *device, GParamSpec *pspec, gpointer user_data)
{
GtkWidget *speed_label = GTK_WIDGET (user_data);
guint32 bitrate = 0;
char *str = NULL;
bitrate = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device)) / 1000;
if (bitrate)
str = g_strdup_printf (_("%u Mb/s"), bitrate);
gtk_label_set_text (GTK_LABEL (speed_label), str ? str : C_("Speed", "Unknown"));
g_free (str);
}
static void
display_ip4_info (NMIPAddress *def_addr, const GPtrArray *addresses, GtkGrid *grid, int *row)
{
GtkWidget *desc_widget, *data_widget = NULL;
AtkObject *desc_object, *data_object = NULL;
guint32 hostmask, network, bcast, netmask;
const char *addr;
char *str;
/* Address */
addr = def_addr ? nm_ip_address_get_address (def_addr) : C_("Address", "Unknown");
desc_widget = create_info_label (_("IP Address"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (addr);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, *row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
(*row)++;
/* Broadcast */
if (def_addr) {
guint32 addr_bin;
nm_ip_address_get_address_binary (def_addr, &addr_bin);
netmask = nm_utils_ip4_prefix_to_netmask (nm_ip_address_get_prefix (def_addr));
network = addr_bin & netmask;
hostmask = ~netmask;
bcast = network | hostmask;
}
str = def_addr ? ip4_address_as_string (bcast) : g_strdup (C_("Address", "Unknown"));
desc_widget = create_info_label (_("Broadcast Address"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (str);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, *row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
g_free (str);
(*row)++;
/* Prefix */
str = def_addr ? ip4_address_as_string (netmask) : g_strdup (C_("Subnet Mask", "Unknown"));
desc_widget = create_info_label (_("Subnet Mask"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (str);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, *row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
g_free (str);
(*row)++;
/* More Addresses */
if (addresses && addresses->len > 1) {
data_widget = create_more_addresses_widget (addresses);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
(*row)++;
}
}
static void
display_ip6_info (NMIPAddress *def6_addr,
const GPtrArray *addresses,
const char *method,
GtkGrid *grid,
int *row)
{
GtkWidget *desc_widget, *data_widget = NULL;
AtkObject *desc_object, *data_object = NULL;
char *str;
if (!def6_addr)
return;
/* Address */
str = g_strdup_printf ("%s/%d",
nm_ip_address_get_address (def6_addr),
nm_ip_address_get_prefix (def6_addr));
desc_widget = create_info_label (_("IP Address"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (str);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, *row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
g_free (str);
(*row)++;
/* More Addresses */
if (addresses && addresses->len > 1) {
data_widget = create_more_addresses_widget (addresses);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
(*row)++;
}
}
static void
display_dns_info (const char * const *dns, GtkGrid *grid, int *row)
{
GtkWidget *desc_widget, *data_widget = NULL;
AtkObject *desc_object, *data_object = NULL;
char *label[] = { N_("Primary DNS"), N_("Secondary DNS"), N_("Tertiary DNS") };
int i;
for (i = 0; dns && dns[i] && i < 3; i++) {
desc_widget = create_info_label (_(label[i]));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (dns[i]);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, *row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, *row, 1, 1);
(*row)++;
}
}
static void
_got_wsec_secrets (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
NMRemoteConnection *connection = NM_REMOTE_CONNECTION (source_object);
gs_unref_object GtkWidget *data_widget = GTK_WIDGET (user_data);
gs_unref_variant GVariant *secrets = NULL;
NMSettingWirelessSecurity *s_wsec;
secrets = nm_remote_connection_get_secrets_finish (connection, res, NULL);
if (!secrets)
return;
if (!nm_connection_update_secrets (NM_CONNECTION (connection),
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
secrets,
NULL)) {
return;
}
s_wsec = nm_connection_get_setting_wireless_security (NM_CONNECTION (connection));
if (!s_wsec)
return;
gtk_label_set_text (GTK_LABEL (data_widget),
nm_setting_wireless_security_get_psk (s_wsec));
}
static void
info_dialog_add_page (GtkNotebook *notebook,
NMConnection *connection,
NMDevice *device)
{
GtkGrid *grid;
guint32 speed = 0;
char *str;
const char *iface, *method = NULL;
NMIPConfig *ip4_config;
NMIPConfig *ip6_config = NULL;
const char * const *dns;
const char * const *dns6;
NMIPAddress *def_addr = NULL;
NMIPAddress *def6_addr = NULL;
const char *gateway;
NMSettingIPConfig *s_ip;
int row = 0;
GtkWidget* speed_label, *sec_label, *desc_widget, *data_widget = NULL;
GPtrArray *addresses;
gboolean show_security = FALSE;
gboolean is_hotspot = FALSE;
NMSettingWireless *s_wireless;
GBytes *ssid = NULL;
gs_free char *ssid_utf8 = NULL;
AtkObject *desc_object, *data_object = NULL;
grid = GTK_GRID (gtk_grid_new ());
gtk_grid_set_column_spacing (grid, 12);
gtk_grid_set_row_spacing (grid, 6);
gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
gtk_grid_set_column_homogeneous (grid, TRUE);
/* Interface */
iface = nm_device_get_iface (device);
if (NM_IS_DEVICE_ETHERNET (device)) {
str = g_strdup_printf (_("Ethernet (%s)"), iface);
show_security = TRUE;
} else if (NM_IS_DEVICE_WIFI (device)) {
str = g_strdup_printf (_("802.11 Wi-Fi (%s)"), iface);
show_security = TRUE;
} else if (NM_IS_DEVICE_MODEM (device)) {
NMDeviceModemCapabilities caps;
caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
if (caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS)
str = g_strdup_printf (_("GSM (%s)"), iface);
else if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO)
str = g_strdup_printf (_("CDMA (%s)"), iface);
else
str = g_strdup_printf (_("Mobile Broadband (%s)"), iface);
} else
str = g_strdup (iface);
/*--- General ---*/
gtk_grid_attach (grid, create_info_group_label (_("General"), FALSE), 0, row, 2, 1);
row++;
desc_widget = create_info_label (_("Interface"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (str);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
g_free (str);
row++;
/* Hardware address */
str = g_strdup (nm_device_get_hw_address (device));
if (str) {
desc_widget = create_info_label (_("Hardware Address"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (str);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
g_free (str);
row++;
}
/* Driver */
desc_widget = create_info_label (_("Driver"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (nm_device_get_driver (device));
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
row++;
speed_label = create_info_value ("");
/* Speed */
str = NULL;
if (NM_IS_DEVICE_ETHERNET (device)) {
/* Ethernet speed in Mb/s */
speed = nm_device_ethernet_get_speed (NM_DEVICE_ETHERNET (device));
} else if (NM_IS_DEVICE_WIFI (device)) {
/* Wi-Fi speed in Kb/s */
speed = nm_device_wifi_get_bitrate (NM_DEVICE_WIFI (device)) / 1000;
label_info_new (device,
speed_label,
"notify::" NM_DEVICE_WIFI_BITRATE,
G_CALLBACK (bitrate_changed_cb));
}
if (speed)
str = g_strdup_printf (_("%u Mb/s"), speed);
gtk_label_set_text (GTK_LABEL(speed_label), str ? str : C_("Speed", "Unknown"));
g_free (str);
desc_widget = create_info_label (_("Speed"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_object = gtk_widget_get_accessible (speed_label);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, speed_label, 1, row, 1, 1);
row++;
/* Security */
if (show_security) {
sec_label = create_info_label_security (connection);
if (sec_label) {
desc_widget = create_info_label (_("Security"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_object = gtk_widget_get_accessible (sec_label);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget,
0, row, 1, 1);
gtk_grid_attach (grid, sec_label,
1, row, 1, 1);
row++;
}
}
/* Empty line */
gtk_grid_attach (grid, gtk_label_new (""), 0, row, 2, 1);
row++;
/*--- IPv4 ---*/
s_ip = nm_connection_get_setting_ip4_config (connection);
if (s_ip) {
method = nm_setting_ip_config_get_method (s_ip);
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
is_hotspot = TRUE;
}
gtk_grid_attach (grid, create_info_group_label (_("IPv4"), FALSE), 0, row, 2, 1);
row++;
ip4_config = nm_device_get_ip4_config (device);
if (ip4_config) {
addresses = nm_ip_config_get_addresses (ip4_config);
gateway = nm_ip_config_get_gateway (ip4_config);
} else {
addresses = NULL;
gateway = NULL;
}
if (addresses && addresses->len > 0)
def_addr = (NMIPAddress *) g_ptr_array_index (addresses, 0);
display_ip4_info (def_addr, addresses, grid, &row);
/* Gateway */
if (gateway && *gateway) {
desc_widget = create_info_label (_("Default Route"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (gateway);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
row++;
}
/* DNS */
dns = def_addr ? nm_ip_config_get_nameservers (ip4_config) : NULL;
display_dns_info (dns, grid, &row);
/* Empty line */
gtk_grid_attach (grid, gtk_label_new (""), 0, row, 2, 1);
row++;
/*--- IPv6 ---*/
s_ip = nm_connection_get_setting_ip6_config (connection);
if (s_ip) {
method = nm_setting_ip_config_get_method (s_ip);
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0)
is_hotspot = TRUE;
}
if (method && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0) {
gtk_grid_attach (grid, create_info_group_label (_("IPv6"), FALSE), 0, row, 2, 1);
row++;
ip6_config = nm_device_get_ip6_config (device);
if (ip6_config) {
addresses = nm_ip_config_get_addresses (ip6_config);
gateway = nm_ip_config_get_gateway (ip6_config);
} else {
addresses = NULL;
gateway = NULL;
}
if (addresses && addresses->len > 0)
def6_addr = (NMIPAddress *) g_ptr_array_index (addresses, 0);
display_ip6_info (def6_addr, addresses, method, grid, &row);
}
/* Gateway */
if (gateway && *gateway) {
desc_widget = create_info_label (_("Default Route"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (gateway);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
row++;
}
/* DNS */
dns6 = def6_addr ? nm_ip_config_get_nameservers (ip6_config) : NULL;
display_dns_info (dns6, grid, &row);
/* Wi-Fi */
if (!NM_IS_DEVICE_WIFI (device))
is_hotspot = FALSE;
if (is_hotspot) {
gtk_grid_attach (grid, gtk_label_new (""), 0, row, 2, 1);
row++;
gtk_grid_attach (grid, create_info_group_label (_("Hotspot"), FALSE), 0, row, 2, 1);
row++;
s_wireless = nm_connection_get_setting_wireless (connection);
ssid = nm_setting_wireless_get_ssid (s_wireless);
ssid_utf8 = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid));
desc_widget = create_info_label (_("Network"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value (ssid_utf8);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
row++;
if (nm_connection_get_setting_wireless_security (connection)) {
desc_widget = create_info_label (_("Password"));
desc_object = gtk_widget_get_accessible (desc_widget);
data_widget = create_info_value ("\xe2\x80\x94" /* em dash */);
data_object = gtk_widget_get_accessible (data_widget);
atk_object_add_relationship (desc_object, ATK_RELATION_LABEL_FOR, data_object);
gtk_grid_attach (grid, desc_widget, 0, row, 1, 1);
gtk_grid_attach (grid, data_widget, 1, row, 1, 1);
row++;
nm_remote_connection_get_secrets_async (NM_REMOTE_CONNECTION (connection),
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NULL,
_got_wsec_secrets,
g_object_ref (data_widget));
}
gtk_grid_attach (grid, nma_bar_code_widget_new (connection), 0, row, 2, 1);
row++;
}
desc_widget = NULL;
desc_object = NULL;
data_widget = NULL;
data_object = NULL;
gtk_notebook_append_page (notebook, GTK_WIDGET (grid),
gtk_label_new (nm_connection_get_id (connection)));
gtk_widget_show_all (GTK_WIDGET (grid));
}
static char *
get_vpn_connection_type (NMConnection *connection)
{
const char *type, *p;
/* The service type is in format of "org.freedesktop.NetworkManager.vpnc".
* Extract end part after last dot, e.g. "vpnc" */
type = nm_setting_vpn_get_service_type (nm_connection_get_setting_vpn (connection));
p = strrchr (type, '.');
return g_strdup (p ? p + 1 : type);
}
/* VPN parameters can be found at:
* http://git.gnome.org/browse/network-manager-openvpn/tree/src/nm-openvpn-service.h
* http://git.gnome.org/browse/network-manager-vpnc/tree/src/nm-vpnc-service.h
* http://git.gnome.org/browse/network-manager-pptp/tree/src/nm-pptp-service.h
* http://git.gnome.org/browse/network-manager-openconnect/tree/src/nm-openconnect-service.h
* http://git.gnome.org/browse/network-manager-openswan/tree/src/nm-openswan-service.h
* See also 'properties' directory in these plugins.
*/
static const gchar *
find_vpn_gateway_key (const char *vpn_type)
{
if (g_strcmp0 (vpn_type, "openvpn") == 0) return "remote";
if (g_strcmp0 (vpn_type, "vpnc") == 0) return "IPSec gateway";
if (g_strcmp0 (vpn_type, "pptp") == 0) return "gateway";
if (g_strcmp0 (vpn_type, "openconnect") == 0) return "gateway";
if (g_strcmp0 (vpn_type, "openswan") == 0) return "right";
return "";
}
static const gchar *
find_vpn_username_key (const char *vpn_type)
{
if (g_strcmp0 (vpn_type, "openvpn") == 0) return "username";
if (g_strcmp0 (vpn_type, "vpnc") == 0) return "Xauth username";
if (g_strcmp0 (vpn_type, "pptp") == 0) return "user";
if (g_strcmp0 (vpn_type, "openconnect") == 0) return "username";
if (g_strcmp0 (vpn_type, "openswan") == 0) return "leftxauthusername";
return "";
}
enum VpnDataItem {
VPN_DATA_ITEM_GATEWAY,
VPN_DATA_ITEM_USERNAME
};
static const gchar *
get_vpn_data_item (NMConnection *connection, enum VpnDataItem vpn_data_item)
{
const char *key;
char *type = get_vpn_connection_type (connection);
switch (vpn_data_item) {
case VPN_DATA_ITEM_GATEWAY:
key = find_vpn_gateway_key (type);
break;
case VPN_DATA_ITEM_USERNAME:
key = find_vpn_username_key (type);
break;
default:
key = "";
break;
}
g_free (type);
return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (connection), key);
}
static void
info_dialog_add_page_for_vpn (GtkNotebook *notebook,
NMConnection *connection,
NMActiveConnection *active,
NMConnection *parent_con)
{
GtkGrid *grid;
char *str;
int row = 0;
NMIPConfig *ip4_config;
NMIPConfig *ip6_config;
const char * const *dns;
const char * const *dns6;
NMIPAddress *def_addr = NULL;
NMIPAddress *def6_addr = NULL;
GPtrArray *addresses;
NMSettingIPConfig *s_ip6;
const char *method = NULL;
grid = GTK_GRID (gtk_grid_new ());
gtk_grid_set_column_spacing (grid, 12);
gtk_grid_set_row_spacing (grid, 6);
gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
/*--- General ---*/
gtk_grid_attach (grid, create_info_group_label (_("General"), FALSE), 0, row, 2, 1);
row++;
str = get_vpn_connection_type (connection);
gtk_grid_attach (grid, create_info_label (_("VPN Type")), 0, row, 1, 1);
gtk_grid_attach (grid, create_info_value (str), 1, row, 1, 1);
g_free (str);
row++;
gtk_grid_attach (grid, create_info_label (_("VPN Gateway")), 0, row, 1, 1);
gtk_grid_attach (grid, create_info_value (get_vpn_data_item (connection, VPN_DATA_ITEM_GATEWAY)), 1, row, 1, 1);
row++;
gtk_grid_attach (grid, create_info_label (_("VPN Username")), 0, row, 1, 1);
gtk_grid_attach (grid, create_info_value (get_vpn_data_item (connection, VPN_DATA_ITEM_USERNAME)), 1, row, 1, 1);
row++;
gtk_grid_attach (grid, create_info_label (_("VPN Banner")), 0, row, 1, 1);
gtk_grid_attach (grid, create_info_value (nm_vpn_connection_get_banner (NM_VPN_CONNECTION (active))), 1, row, 1, 1);
row++;
gtk_grid_attach (grid, create_info_label (_("Base Connection")), 0, row, 1, 1);
gtk_grid_attach (grid, create_info_value (parent_con ? nm_connection_get_id (parent_con) : _("Unknown")), 1, row, 1, 1);
row++;
/* Empty line */
gtk_grid_attach (grid, gtk_label_new (""), 0, row, 2, 1);
row++;
/*--- IPv4 ---*/
gtk_grid_attach (grid, create_info_group_label (_("IPv4"), FALSE), 0, row, 2, 1);
row++;
ip4_config = nm_active_connection_get_ip4_config (active);
addresses = nm_ip_config_get_addresses (ip4_config);
if (addresses && addresses->len > 0)
def_addr = (NMIPAddress *) g_ptr_array_index (addresses, 0);
display_ip4_info (def_addr, addresses, grid, &row);
/* DNS */
dns = def_addr ? nm_ip_config_get_nameservers (ip4_config) : NULL;
display_dns_info (dns, grid, &row);
/* Empty line */
gtk_grid_attach (grid, gtk_label_new (""), 0, row, 2, 1);
row++;
/*--- IPv6 ---*/
ip6_config = nm_active_connection_get_ip6_config (active);
if (ip6_config) {
s_ip6 = nm_connection_get_setting_ip6_config (connection);
if (s_ip6)
method = nm_setting_ip_config_get_method (s_ip6);
}
if (method && strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0) {
gtk_grid_attach (grid, create_info_group_label (_("IPv6"), FALSE), 0, row, 2, 1);
row++;
addresses = nm_ip_config_get_addresses (ip6_config);
if (addresses && addresses->len > 0)
def6_addr = (NMIPAddress *) g_ptr_array_index (addresses, 0);
/* IPv6 Address */
display_ip6_info (def6_addr, addresses, method, grid, &row);
/* DNS */
dns6 = def6_addr ? nm_ip_config_get_nameservers (ip6_config) : NULL;
display_dns_info (dns6, grid, &row);
}
gtk_notebook_append_page (notebook, GTK_WIDGET (grid),
gtk_label_new (nm_connection_get_id (connection)));
gtk_widget_show_all (GTK_WIDGET (grid));
}
#ifndef NM_REMOTE_CONNECTION_FLAGS
/*
* NetworkManager < 1.12 compatibility.
* If you look outside and see flying cars, remove this.
*/
typedef enum {
NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED = 2,
} NMSettingsConnectionFlags;
static NMSettingsConnectionFlags
nm_remote_connection_get_flags (NMRemoteConnection *connection)
{
NMSettingsConnectionFlags flags;
if (!g_object_class_find_property (G_OBJECT_GET_CLASS (connection), "flags"))
return 0;
g_object_get (connection, "flags", &flags, NULL);
return flags;
}
#else
#define nm_remote_connection_get_flags(conn) \
NM_LIBNM_COMPAT_UNDEPRECATE (nm_remote_connection_get_flags (conn))
#endif
static int
_compare_active_connections (gconstpointer a, gconstpointer b)
{
NMActiveConnection *ac_a = NM_ACTIVE_CONNECTION(*(NMActiveConnection **)a);
NMActiveConnection *ac_b = NM_ACTIVE_CONNECTION(*(NMActiveConnection **)b);
NMRemoteConnection *con_a = nm_active_connection_get_connection (ac_a);
NMRemoteConnection *con_b = nm_active_connection_get_connection (ac_b);
NMSettingIPConfig *s_ip;
int cmp = 0;
if (con_a && nm_remote_connection_get_visible (con_a))
cmp--;
if (con_b && nm_remote_connection_get_visible (con_b))
cmp++;
if (cmp || !con_a || !con_b)
return cmp;
s_ip = nm_connection_get_setting_ip6_config (NM_CONNECTION (con_a));
if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0)
cmp--;
s_ip = nm_connection_get_setting_ip6_config (NM_CONNECTION (con_b));
if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0)
cmp++;
if (cmp)
return cmp;
s_ip = nm_connection_get_setting_ip4_config (NM_CONNECTION (con_a));
if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
cmp--;
s_ip = nm_connection_get_setting_ip4_config (NM_CONNECTION (con_b));
if (s_ip && strcmp (nm_setting_ip_config_get_method (s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
cmp++;
if (cmp)
return cmp;
if (nm_active_connection_get_default (ac_a))
cmp--;
if (nm_active_connection_get_default (ac_b))
cmp++;
if (cmp)
return cmp;
if (nm_active_connection_get_default6 (ac_a))
cmp--;
if (nm_active_connection_get_default6 (ac_b))
cmp++;
if (cmp)
return cmp;
if (nm_remote_connection_get_flags (con_a) & NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED)
cmp++;
if (nm_remote_connection_get_flags (con_b) & NM_SETTINGS_CONNECTION_FLAG_NM_GENERATED)
cmp--;
return cmp;
}
static GtkWidget *
info_dialog_update (NMApplet *applet)
{
GtkNotebook *notebook;
const GPtrArray *connections;
gs_unref_ptrarray GPtrArray *sorted_connections = NULL;
int i;
int pages = 0;
notebook = GTK_NOTEBOOK (GTK_WIDGET (gtk_builder_get_object (applet->info_dialog_ui, "info_notebook")));
/* Remove old pages */
for (i = gtk_notebook_get_n_pages (notebook); i > 0; i--)
gtk_notebook_remove_page (notebook, -1);
/* Add new pages */
connections = nm_client_get_active_connections (applet->nm_client);
sorted_connections = g_ptr_array_new_full (connections->len, NULL);
memcpy (sorted_connections->pdata, connections->pdata,
sizeof (void *) * connections->len);
sorted_connections->len = connections->len;
g_ptr_array_sort (sorted_connections, _compare_active_connections);
for (i = 0; i < sorted_connections->len; i++) {
NMActiveConnection *active_connection = g_ptr_array_index (sorted_connections, i);
NMConnection *connection;
const GPtrArray *devices;
if (nm_active_connection_get_state (active_connection) != NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
continue;
connection = (NMConnection *) nm_active_connection_get_connection (active_connection);
if (!connection) {
g_warning ("%s: couldn't find the default active connection's NMConnection!", __func__);
continue;
}
devices = nm_active_connection_get_devices (active_connection);
if (NM_IS_VPN_CONNECTION (active_connection)) {
const char *spec_object = nm_active_connection_get_specific_object_path (active_connection);
NMConnection *parent_con = get_connection_for_active_path (applet, spec_object);
info_dialog_add_page_for_vpn (notebook, connection, active_connection, parent_con);
} else if (devices && devices->len > 0) {
info_dialog_add_page (notebook,
connection,
g_ptr_array_index (devices, 0));
} else {
g_warning ("Active connection %s had no devices and was not a VPN!",
nm_object_get_path (NM_OBJECT (active_connection)));
continue;
}
pages++;
}
if (pages == 0) {
/* Shouldn't really happen but ... */
info_dialog_show_error (_("No valid active connections found!"));
return NULL;
}
return GTK_WIDGET (gtk_builder_get_object (applet->info_dialog_ui, "info_dialog"));
}
void
applet_info_dialog_show (NMApplet *applet)
{
GtkWidget *dialog;
dialog = info_dialog_update (applet);
if (!dialog)
return;
g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), dialog);
g_signal_connect_swapped (dialog, "response", G_CALLBACK (gtk_widget_hide), dialog);
gtk_widget_realize (dialog);
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_present (GTK_WINDOW (dialog));
}
void
applet_about_dialog_show (NMApplet *applet)
{
const char *authors[] = {
"Michael Biebl <biebl@debian.org>",
"Matthias Clasen <mclasen@redhat.com>",
"Piotr Drąg <piotrdrag@gmail.com>",
"Pavel Šimerda <psimerda@redhat.com>",
"Alexander Sack <asac@ubuntu.com>",
"Aleksander Morgado <aleksander@lanedo.com>",
"Christian Persch <chpe@gnome.org>",
"Tambet Ingo <tambet@gmail.com>",
"Beniamino Galvani <bgalvani@redhat.com>",
"Lubomir Rintel <lkundrak@v3.sk>",
"Dan Winship <danw@gnome.org>",
"Dan Williams <dcbw@src.gnome.org>",
"Thomas Haller <thaller@redhat.com>",
"Jiří Klimeš <jklimes@redhat.com>",
"Dan Williams <dcbw@redhat.com>",
NULL
};
gtk_show_about_dialog (NULL,
"version", VERSION,
"copyright", _("Copyright \xc2\xa9 2004-2017 Red Hat, Inc.\n"
"Copyright \xc2\xa9 2005-2008 Novell, Inc.\n"
"and many other community contributors and translators"),
"comments", _("Notification area applet for managing your network devices and connections."),
"website", "http://www.gnome.org/projects/NetworkManager/",
"website-label", _("NetworkManager Website"),
"logo-icon-name", "network-workgroup",
"license-type", GTK_LICENSE_GPL_2_0,
"authors", authors,
"translator-credits", _("translator-credits"),
NULL);
}
GtkWidget *
applet_missing_ui_warning_dialog_show (void)
{
GtkWidget *dialog;
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
_("The NetworkManager Applet could not find some required resources (the .ui file was not found)."));
/* Bash focus-stealing prevention in the face */
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_icon_name (GTK_WINDOW (dialog), "dialog-error");
gtk_window_set_title (GTK_WINDOW (dialog), _("Missing resources"));
gtk_widget_realize (dialog);
gtk_widget_show (dialog);
gtk_window_present (GTK_WINDOW (dialog));
g_signal_connect_swapped (dialog, "response",
G_CALLBACK (gtk_widget_destroy),
dialog);
return dialog;
}
GtkWidget *
applet_mobile_password_dialog_new (NMConnection *connection,
GtkEntry **out_secret_entry)
{
GtkDialog *dialog;
GtkWidget *w;
GtkBox *box = NULL, *vbox = NULL;
NMSettingConnection *s_con;
char *tmp;
const char *id;
dialog = GTK_DIALOG (gtk_dialog_new ());
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_title (GTK_WINDOW (dialog), _("Mobile broadband network password"));
gtk_dialog_add_button (dialog, _("_Cancel"), GTK_RESPONSE_REJECT);
w = gtk_dialog_add_button (dialog, _("_OK"), GTK_RESPONSE_OK);
gtk_window_set_default (GTK_WINDOW (dialog), w);
s_con = nm_connection_get_setting_connection (connection);
id = nm_setting_connection_get_id (s_con);
g_assert (id);
tmp = g_strdup_printf (_("A password is required to connect to “%s”."), id);
w = gtk_label_new (tmp);
g_free (tmp);
vbox = GTK_BOX (gtk_dialog_get_content_area (dialog));
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
w = gtk_alignment_new (0.5, 0.5, 0, 1.0);
gtk_box_pack_start (vbox, w, TRUE, TRUE, 0);
box = GTK_BOX (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6));
gtk_container_set_border_width (GTK_CONTAINER (box), 6);
gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (box));
gtk_box_pack_start (box, gtk_label_new (_("Password:")), FALSE, FALSE, 0);
w = gtk_entry_new ();
*out_secret_entry = GTK_ENTRY (w);
gtk_entry_set_activates_default (GTK_ENTRY (w), TRUE);
gtk_box_pack_start (box, w, FALSE, FALSE, 0);
gtk_widget_show_all (GTK_WIDGET (vbox));
return GTK_WIDGET (dialog);
}
/**********************************************************************/
static void
mpd_entry_changed (GtkWidget *widget, gpointer user_data)
{
GtkWidget *dialog = GTK_WIDGET (user_data);
GtkBuilder *builder = g_object_get_data (G_OBJECT (dialog), "builder");
GtkWidget *entry;
guint32 minlen;
gboolean valid = FALSE;
const char *text, *text2 = NULL, *text3 = NULL;
gboolean match23;
g_return_if_fail (builder != NULL);
entry = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
if (g_object_get_data (G_OBJECT (entry), "active")) {
minlen = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (entry), "minlen"));
text = gtk_entry_get_text (GTK_ENTRY (entry));
if (text && (strlen (text) < minlen))
goto done;
}
entry = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
if (g_object_get_data (G_OBJECT (entry), "active")) {
minlen = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (entry), "minlen"));
text2 = gtk_entry_get_text (GTK_ENTRY (entry));
if (text2 && (strlen (text2) < minlen))
goto done;
}
entry = GTK_WIDGET (gtk_builder_get_object (builder, "code3_entry"));
if (g_object_get_data (G_OBJECT (entry), "active")) {
minlen = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (entry), "minlen"));
text3 = gtk_entry_get_text (GTK_ENTRY (entry));
if (text3 && (strlen (text3) < minlen))
goto done;
}
/* Validate 2 & 3 if they are supposed to be the same */
match23 = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (dialog), "match23"));
if (match23) {
if (!text2 || !text3 || strcmp (text2, text3))
goto done;
}
valid = TRUE;
done:
/* Clear any error text in the progress label now that the user has changed something */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progress_label"));
gtk_label_set_text (GTK_LABEL (widget), "");
widget = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_button"));
g_warn_if_fail (widget != NULL);
gtk_widget_set_sensitive (widget, valid);
if (valid)
gtk_widget_grab_default (widget);
}
static void
mpd_cancel_dialog (GtkDialog *dialog)
{
gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
}
static void
show_toggled_cb (GtkWidget *button, gpointer user_data)
{
GtkWidget *dialog = GTK_WIDGET (user_data);
gboolean show;
GtkWidget *widget;
GtkBuilder *builder;
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_if_fail (builder != NULL);
show = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
gtk_entry_set_visibility (GTK_ENTRY (widget), show);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
gtk_entry_set_visibility (GTK_ENTRY (widget), show);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code3_entry"));
gtk_entry_set_visibility (GTK_ENTRY (widget), show);
}
static void
mpd_entry_filter (GtkEditable *editable,
gchar *text,
gint length,
gint *position,
gpointer user_data)
{
utils_filter_editable_on_insert_text (editable,
text, length, position, user_data,
utils_char_is_ascii_digit,
mpd_entry_filter);
}
const char *
applet_mobile_pin_dialog_get_entry1 (GtkWidget *dialog)
{
GtkBuilder *builder;
GtkWidget *widget;
g_return_val_if_fail (dialog != NULL, NULL);
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_val_if_fail (builder != NULL, NULL);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
return gtk_entry_get_text (GTK_ENTRY (widget));
}
const char *
applet_mobile_pin_dialog_get_entry2 (GtkWidget *dialog)
{
GtkBuilder *builder;
GtkWidget *widget;
g_return_val_if_fail (dialog != NULL, NULL);
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_val_if_fail (builder != NULL, NULL);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
return gtk_entry_get_text (GTK_ENTRY (widget));
}
gboolean
applet_mobile_pin_dialog_get_auto_unlock (GtkWidget *dialog)
{
GtkBuilder *builder;
GtkWidget *widget;
g_return_val_if_fail (dialog != NULL, FALSE);
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_val_if_fail (builder != NULL, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "save_checkbutton"));
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
}
void
applet_mobile_pin_dialog_start_spinner (GtkWidget *dialog, const char *text)
{
GtkBuilder *builder;
GtkWidget *spinner, *widget, *hbox, *vbox;
g_return_if_fail (dialog != NULL);
g_return_if_fail (text != NULL);
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_if_fail (builder != NULL);
spinner = gtk_spinner_new ();
g_return_if_fail (spinner != NULL);
g_object_set_data (G_OBJECT (dialog), "spinner", spinner);
vbox = GTK_WIDGET (gtk_builder_get_object (builder, "spinner_vbox"));
gtk_container_add (GTK_CONTAINER (vbox), spinner);
gtk_widget_set_halign (spinner, GTK_ALIGN_FILL);
gtk_spinner_start (GTK_SPINNER (spinner));
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progress_label"));
gtk_label_set_text (GTK_LABEL (widget), text);
gtk_widget_show (widget);
hbox = GTK_WIDGET (gtk_builder_get_object (builder, "progress_hbox"));
gtk_widget_show_all (hbox);
/* Desensitize everything while spinning */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
gtk_widget_set_sensitive (widget, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
gtk_widget_set_sensitive (widget, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code3_entry"));
gtk_widget_set_sensitive (widget, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_button"));
gtk_widget_set_sensitive (widget, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_cancel_button"));
gtk_widget_set_sensitive (widget, FALSE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "show_password_checkbutton"));
gtk_widget_set_sensitive (widget, FALSE);
}
void
applet_mobile_pin_dialog_stop_spinner (GtkWidget *dialog, const char *text)
{
GtkBuilder *builder;
GtkWidget *spinner, *widget, *vbox;
g_return_if_fail (dialog != NULL);
builder = g_object_get_data (G_OBJECT (dialog), "builder");
g_return_if_fail (builder != NULL);
spinner = g_object_get_data (G_OBJECT (dialog), "spinner");
g_return_if_fail (spinner != NULL);
gtk_spinner_stop (GTK_SPINNER (spinner));
g_object_set_data (G_OBJECT (dialog), "spinner", NULL);
/* Remove it from the vbox */
vbox = GTK_WIDGET (gtk_builder_get_object (builder, "spinner_vbox"));
gtk_container_remove (GTK_CONTAINER (vbox), spinner);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progress_label"));
if (text) {
gtk_label_set_text (GTK_LABEL (widget), text);
gtk_widget_show (widget);
} else
gtk_widget_hide (widget);
/* Resensitize stuff */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code3_entry"));
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_button"));
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_cancel_button"));
gtk_widget_set_sensitive (widget, TRUE);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "show_password_checkbutton"));
gtk_widget_set_sensitive (widget, TRUE);
}
GtkWidget *
applet_mobile_pin_dialog_new (const char *unlock_required,
const char *device_description)
{
char *str;
GtkWidget *dialog;
GtkWidget *widget;
GtkWidget *label;
GError *error = NULL;
GtkBuilder *builder;
const char *header = NULL;
const char *title = NULL;
const char *show_password_label = NULL;
char *desc = NULL;
const char *label1 = NULL, *label2 = NULL, *label3 = NULL;
gboolean match23 = FALSE;
guint32 label1_min = 0, label2_min = 0, label3_min = 0;
guint32 label1_max = 0, label2_max = 0, label3_max = 0;
gboolean puk = FALSE;
g_return_val_if_fail (unlock_required != NULL, NULL);
g_return_val_if_fail (!strcmp (unlock_required, "sim-pin") || !strcmp (unlock_required, "sim-puk"), NULL);
builder = gtk_builder_new ();
if (!gtk_builder_add_from_resource (builder, "/org/freedesktop/network-manager-applet/gsm-unlock.ui", &error)) {
g_warning ("Couldn't load builder resource: %s", error->message);
g_error_free (error);
g_object_unref (builder);
return NULL;
}
dialog = GTK_WIDGET (gtk_builder_get_object (builder, "unlock_dialog"));
if (!dialog) {
g_object_unref (builder);
g_return_val_if_fail (dialog != NULL, NULL);
}
g_object_set_data_full (G_OBJECT (dialog), "builder", builder, (GDestroyNotify) g_object_unref);
/* Figure out the dialog text based on the required unlock code */
if (!strcmp (unlock_required, "sim-pin")) {
title = _("SIM PIN unlock required");
header = _("SIM PIN Unlock Required");
/* FIXME: some warning about # of times you can enter incorrect PIN */
desc = g_strdup_printf (_("The mobile broadband device “%s” requires a SIM PIN code before it can be used."), device_description);
/* Translators: PIN code entry label */
label1 = _("PIN code:");
label1_min = 4;
label1_max = 8;
/* Translators: Show/obscure PIN checkbox label */
show_password_label = _("Show PIN code");
} else if (!strcmp (unlock_required, "sim-puk")) {
title = _("SIM PUK unlock required");
header = _("SIM PUK Unlock Required");
/* FIXME: some warning about # of times you can enter incorrect PUK */
desc = g_strdup_printf (_("The mobile broadband device “%s” requires a SIM PUK code before it can be used."), device_description);
/* Translators: PUK code entry label */
label1 = _("PUK code:");
label1_min = label1_max = 8;
/* Translators: New PIN entry label */
label2 = _("New PIN code:");
/* Translators: New PIN verification entry label */
label3 = _("Re-enter new PIN code:");
label2_min = label3_min = 4;
label2_max = label3_max = 8;
match23 = TRUE;
/* Translators: Show/obscure PIN/PUK checkbox label */
show_password_label = _("Show PIN/PUK codes");
puk = TRUE;
} else
g_assert_not_reached ();
gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ALWAYS);
gtk_window_set_title (GTK_WINDOW (dialog), title);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "header_label"));
str = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>", header);
gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
gtk_label_set_markup (GTK_LABEL (widget), str);
g_free (str);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "desc_label"));
gtk_label_set_text (GTK_LABEL (widget), desc);
g_free (desc);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "show_password_checkbutton"));
gtk_button_set_label (GTK_BUTTON (widget), show_password_label);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
g_signal_connect (widget, "toggled", G_CALLBACK (show_toggled_cb), dialog);
show_toggled_cb (widget, dialog);
g_signal_connect (dialog, "delete-event", G_CALLBACK (mpd_cancel_dialog), NULL);
gtk_widget_show_all (dialog);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "save_checkbutton"));
if (!puk)
g_object_set_data (G_OBJECT (widget), "active", GUINT_TO_POINTER (TRUE));
else
gtk_widget_hide (widget);
/* Set contents */
g_object_set_data (G_OBJECT (dialog), "match23", GUINT_TO_POINTER (match23));
/* code1_entry */
label = GTK_WIDGET (gtk_builder_get_object (builder, "code1_label"));
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code1_entry"));
gtk_label_set_text (GTK_LABEL (label), label1);
g_signal_connect (widget, "changed", G_CALLBACK (mpd_entry_changed), dialog);
g_signal_connect (widget, "insert-text", G_CALLBACK (mpd_entry_filter), NULL);
if (label1_max)
gtk_entry_set_max_length (GTK_ENTRY (widget), label1_max);
g_object_set_data (G_OBJECT (widget), "minlen", GUINT_TO_POINTER (label1_min));
g_object_set_data (G_OBJECT (widget), "active", GUINT_TO_POINTER (1));
/* code2_entry */
label = GTK_WIDGET (gtk_builder_get_object (builder, "code2_label"));
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code2_entry"));
if (label2) {
gtk_label_set_text (GTK_LABEL (label), label2);
g_signal_connect (widget, "changed", G_CALLBACK (mpd_entry_changed), dialog);
g_signal_connect (widget, "insert-text", G_CALLBACK (mpd_entry_filter), NULL);
if (label2_max)
gtk_entry_set_max_length (GTK_ENTRY (widget), label2_max);
g_object_set_data (G_OBJECT (widget), "minlen", GUINT_TO_POINTER (label2_min));
g_object_set_data (G_OBJECT (widget), "active", GUINT_TO_POINTER (1));
} else {
gtk_widget_hide (label);
gtk_widget_hide (widget);
}
/* code3_entry */
label = GTK_WIDGET (gtk_builder_get_object (builder, "code3_label"));
widget = GTK_WIDGET (gtk_builder_get_object (builder, "code3_entry"));
if (label3) {
gtk_label_set_text (GTK_LABEL (label), label3);
g_signal_connect (widget, "changed", G_CALLBACK (mpd_entry_changed), dialog);
g_signal_connect (widget, "insert-text", G_CALLBACK (mpd_entry_filter), NULL);
if (label3_max)
gtk_entry_set_max_length (GTK_ENTRY (widget), label3_max);
g_object_set_data (G_OBJECT (widget), "minlen", GUINT_TO_POINTER (label3_min));
g_object_set_data (G_OBJECT (widget), "active", GUINT_TO_POINTER (1));
} else {
gtk_widget_hide (label);
gtk_widget_hide (widget);
}
/* Make a single-entry dialog look better */
widget = GTK_WIDGET (gtk_builder_get_object (builder, "grid14"));
if (label2 || label3)
gtk_grid_set_row_spacing (GTK_GRID (widget), 6);
else
gtk_grid_set_row_spacing (GTK_GRID (widget), 0);
widget = GTK_WIDGET (gtk_builder_get_object (builder, "progress_hbox"));
gtk_widget_hide (widget);
mpd_entry_changed (NULL, dialog);
return dialog;
}