applet.c 73.8 KB
Newer Older
1
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
 *
 * Dan Williams <dcbw@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
20
21
22
23
24
25
 * This applet used the GNOME Wireless Applet as a skeleton to build from.
 *
 * GNOME Wireless Applet Authors:
 *		Eskil Heyn Olsen <eskil@eskil.dk>
 *		Bastien Nocera <hadess@hadess.net> (Gnome2 port)
 *
26
 * (C) Copyright 2004-2005 Red Hat, Inc.
27
 * (C) Copyright 2001, 2002 Free Software Foundation
28
29
 */

30
31
32
33
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

34
35
#include <string.h>
#include <stdlib.h>
36
#include <unistd.h>
37
38
39
40
41
42
43
#include <sys/types.h>
#include <sys/wait.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <dirent.h>
44
#include <time.h>
45
46
47
48
49
50
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <net/if.h>
51

52
#include <gtk/gtk.h>
53
#include <glib/gi18n.h>
54
#include <libgnomeui/libgnomeui.h>
55
56

#if !GTK_CHECK_VERSION(2,6,0)
57
#include <gnome.h>
58
#endif
59

60
#include <glade/glade.h>
61
#include <gconf/gconf-client.h>
62

63
64
65
66
#include "applet.h"
#include "applet-dbus.h"
#include "applet-dbus-devices.h"
#include "applet-dbus-vpn.h"
67
#include "applet-dbus-info.h"
68
69
70
71
72
#include "other-network-dialog.h"
#include "passphrase-dialog.h"
#include "menu-items.h"
#include "vpn-password-dialog.h"
#include "vpn-connection.h"
73
#include "nm-utils.h"
74

75
76
77
78
79
80
81
/* Compat for GTK 2.4 and lower... */
#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
	#define GTK_STOCK_MEDIA_PAUSE		GTK_STOCK_STOP
	#define GTK_STOCK_MEDIA_PLAY		GTK_STOCK_REFRESH
	#define GTK_STOCK_ABOUT			GTK_STOCK_DIALOG_INFO
#endif

82
83
static GObject *	nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props);
static void		setup_stock (void);
84
static gboolean	nmwa_icons_init (NMWirelessApplet *applet);
85
static void		nmwa_icons_free (NMWirelessApplet *applet);
86
static void		nmwa_about_cb (NMWirelessApplet *applet);
87
static void		nmwa_context_menu_update (NMWirelessApplet *applet);
88
static GtkWidget *	nmwa_get_instance (NMWirelessApplet *applet);
89
90

G_DEFINE_TYPE(NMWirelessApplet, nmwa, EGG_TYPE_TRAY_ICON)
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * nm_null_safe_strcmp
 *
 * Doesn't freaking segfault if s1/s2 are NULL
 *
 */
int nm_null_safe_strcmp (const char *s1, const char *s2)
{
	if (!s1 && !s2)
		return 0;
	if (!s1 && s2)
		return -1;
	if (s1 && !s2)
		return 1;
		
	return (strcmp (s1, s2));
}


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * nmwa_get_first_active_device
 *
 * Return the first device marked as "active".
 *
 */
NetworkDevice * nmwa_get_first_active_device (GSList *dev_list)
{
	GSList *	elt;

	if (!dev_list)
		return NULL;

	for (elt = dev_list; elt; elt = g_slist_next (elt))
	{
		NetworkDevice *dev = (NetworkDevice *)(elt->data);

		if (network_device_get_active (dev))
			return dev;
	}

	return NULL;
}


136
static void nmwa_init (NMWirelessApplet *applet)
137
{
138
139
	applet->animation_id = 0;
	applet->animation_step = 0;
140
	glade_gnome_init ();
141

142
	setup_stock ();
143
144
	if (!nmwa_icons_init (applet))
		return;
145
146
147

/*	gtk_window_set_default_icon_from_file (ICONDIR"/NMWirelessApplet/wireless-applet.png", NULL); */
	gtk_widget_show (nmwa_get_instance (applet));
148
149
150
151
}

static void nmwa_class_init (NMWirelessAppletClass *klass)
{
152
	GObjectClass *gobject_class;
153

154
155
	gobject_class = G_OBJECT_CLASS (klass);
	gobject_class->constructor = nmwa_constructor;
156
157
}

158
static GObject *nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props)
159
{
160
161
162
	GObject *obj;
	NMWirelessApplet *applet;
	NMWirelessAppletClass *klass;
163

164
165
166
	klass = NM_WIRELESS_APPLET_CLASS (g_type_class_peek (type));
	obj = G_OBJECT_CLASS (nmwa_parent_class)->constructor (type, n_props, construct_props);
	applet =  NM_WIRELESS_APPLET (obj);
167

168
	return obj;
169
170
}

171
172
173
174
175
176
177
178
179
180
181
182
183
184
static GtkWidget * get_label (GtkWidget *info_dialog, GladeXML *xml, const char *name)
{
	GtkWidget *label;

	if (xml != NULL)
	{
		label = glade_xml_get_widget (xml, name);
		g_object_set_data (G_OBJECT (info_dialog), name, label);
	}
	else
		label = g_object_get_data (G_OBJECT (info_dialog), name);

	return label;
}
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
static void nmwa_show_socket_err (GtkWidget *info_dialog, const char *err)
{
	GtkWidget *error_dialog;
	char *msg;
	
	msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
					   _("Error displaying connection information: "), err);
	error_dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (info_dialog),
											 0, GTK_MESSAGE_ERROR,
											 GTK_BUTTONS_OK, msg);
	gtk_dialog_run (GTK_DIALOG (error_dialog));
	gtk_widget_destroy (error_dialog);
	g_free (msg);
}

static gboolean nmwa_update_info (NMWirelessApplet *applet)
{
	GtkWidget *info_dialog;
	char *addr = NULL, *mask = NULL, *broadcast = NULL;
	char *dest = NULL, *mac = NULL, *iface_and_type = NULL;
	GtkWidget *label;
	struct ifreq ifr;
	int fd, flags;
	gboolean ret_val = TRUE;
	const char *iface;
	NetworkDevice *dev;
	gboolean ret = TRUE;

	info_dialog = glade_xml_get_widget (applet->info_dialog_xml, "info_dialog");
	if (!info_dialog)
	{
		char *err = g_strdup (_("Could not find some required resources (the glade file)!"));
		nmwa_show_socket_err (info_dialog, err);
		g_free (err);
		return FALSE;
	}

	dev = nmwa_get_first_active_device (applet->gui_device_list);
	iface = network_device_get_iface (dev);
	if (!dev || !iface)
	{
		char *err = g_strdup (_("No active connections!"));
		nmwa_show_socket_err (info_dialog, err);
		g_free (err);
		return FALSE;
	}

	fd = socket (AF_INET, SOCK_DGRAM, 0);
	if (fd < 0)
	{
		char *err = g_strdup (_("Could not open socket!"));
		nmwa_show_socket_err (info_dialog, err);
		g_free (err);
		return FALSE;
	}

	ifr.ifr_addr.sa_family = AF_INET;

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (ioctl (fd, SIOCGIFADDR, &ifr) == 0)
		addr = g_strdup (inet_ntoa (((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr));

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (ioctl (fd, SIOCGIFFLAGS, &ifr) < 0)
	{
		char *err = g_strdup (_("Failed to get information about the interface!"));
		nmwa_show_socket_err (info_dialog, err);
		g_free (err);
		ret = FALSE;
		goto out;
	}
	flags = ifr.ifr_flags;

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (flags & IFF_BROADCAST && ioctl (fd, SIOCGIFBRDADDR, &ifr) == 0)
		broadcast = g_strdup (inet_ntoa (((struct sockaddr_in *) &ifr.ifr_broadaddr)->sin_addr));

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (ioctl (fd, SIOCGIFNETMASK, &ifr) == 0)
		mask = g_strdup (inet_ntoa (((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr));

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (flags & IFF_POINTOPOINT && ioctl (fd, SIOCGIFDSTADDR, &ifr) == 0)
		dest = g_strdup (inet_ntoa (((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr));

	g_strlcpy (ifr.ifr_name, iface, sizeof (ifr.ifr_name));
	if (ioctl (fd, SIOCGIFHWADDR, &ifr) == 0)
		mac = g_strdup_printf ("%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
		       (unsigned char) ifr.ifr_hwaddr.sa_data[0],
		       (unsigned char) ifr.ifr_hwaddr.sa_data[1],
		       (unsigned char) ifr.ifr_hwaddr.sa_data[2],
		       (unsigned char) ifr.ifr_hwaddr.sa_data[3],
		       (unsigned char) ifr.ifr_hwaddr.sa_data[4],
		       (unsigned char) ifr.ifr_hwaddr.sa_data[5]);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-interface");
	gtk_label_set_text (GTK_LABEL (label), iface);
	if (network_device_is_wired (dev))
		iface_and_type = g_strdup_printf (_("Wired Ethernet (%s)"), iface);
	else
		iface_and_type = g_strdup_printf (_("Wireless Ethernet (%s)"), iface);	
	gtk_label_set_text (GTK_LABEL (label), iface_and_type);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-ip-address");
	gtk_label_set_text (GTK_LABEL (label), addr);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-destination-address");
	if (flags & IFF_POINTOPOINT)
	{
		gtk_label_set_text (GTK_LABEL (label), dest);
		gtk_widget_show (label);
	}
	else
		gtk_widget_hide (label);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-destination-address-label");
	if (flags & IFF_POINTOPOINT)
	{
		gtk_label_set_text (GTK_LABEL (label), dest);
		gtk_widget_show (label);
	}
	else
		gtk_widget_hide (label);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-broadcast-address");
	gtk_label_set_text (GTK_LABEL (label), broadcast);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-subnet-mask");
	gtk_label_set_text (GTK_LABEL (label), mask);

	label = get_label (info_dialog, applet->info_dialog_xml, "label-hardware-address");
	gtk_label_set_text (GTK_LABEL (label), mac);

out:
	close (fd);
	g_free (addr);
	g_free (broadcast);
	g_free (mask);
	g_free (dest);
	g_free (iface_and_type);
	g_free (mac);

	return ret;
}

static void nmwa_show_info_cb (GtkMenuItem *mi, NMWirelessApplet *applet)
{
	GtkWidget *info_dialog;

	info_dialog = glade_xml_get_widget (applet->info_dialog_xml, "info_dialog");

	if (nmwa_update_info (applet))
	{
		gtk_window_present (GTK_WINDOW (info_dialog));
		gtk_dialog_run (GTK_DIALOG (info_dialog));
		gtk_widget_hide (GTK_WIDGET (info_dialog));
	}
}

static void nmwa_about_cb (NMWirelessApplet *applet)
346
{
347
348
349
350
	GdkPixbuf	*pixbuf;
	char		*file;
	GtkWidget	*about_dialog;

351
352
	static const gchar *authors[] =
	{
353
		"The Red Hat Desktop Team, including:\n",
354
355
		"Jonathan Blandford <jrb@redhat.com>",
		"John Palmieri <johnp@redhat.com>",
356
		"Ray Strode <rstrode@redhat.com>",
357
		"Colin Walters <walters@redhat.com>",
358
		"Dan Williams <dcbw@redhat.com>",
359
		"David Zeuthen <davidz@redhat.com>",
360
		"\nAnd others, including:\n",
Dan Williams's avatar
Dan Williams committed
361
		"Bill Moss <bmoss@clemson.edu>",
362
363
364
		"Tom Parker",
		"j@bootlab.org",
		"Peter Jones <pjones@redhat.com>",
365
		"Robert Love <rml@novell.com>",
366
367
368
369
370
371
372
373
		NULL
	};

	static const gchar *documenters[] =
	{
		NULL
	};

374
#if !GTK_CHECK_VERSION(2,6,0)
375
376
377
378
379
	/* GTK 2.4 and earlier, have to use libgnome for about dialog */
	file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, "gnome-networktool.png", FALSE, NULL);
	pixbuf = gdk_pixbuf_new_from_file (file, NULL);
	g_free (file);

380
381
	about_dialog = gnome_about_new (_("NetworkManager Applet"),
							  VERSION,
382
							  _("Copyright (C) 2004-2005 Red Hat, Inc."),
383
384
385
386
387
							  _("Notification area applet for managing your network devices and connections."),
							  authors,
							  documenters,
							  NULL,
							  pixbuf);
388
389
390
391
392
393
394
395
396
	g_object_unref (pixbuf);

	gtk_window_set_screen (GTK_WINDOW (about_dialog), gtk_widget_get_screen (GTK_WIDGET (applet)));
	g_signal_connect (about_dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &about_dialog);
	gtk_widget_show (about_dialog);

#else

	/* GTK 2.6 and later code */
397
	gtk_show_about_dialog (NULL,
398
399
					   "name", _("NetworkManager Applet"),
					   "version", VERSION,
400
					   "copyright", _("Copyright (C) 2004-2005 Red Hat, Inc."),
401
402
403
404
405
406
					   "comments",	_("Notification area applet for managing your network devices and connections."),
					   "authors", authors,
					   "documenters", documenters,
					   "translator-credits",	NULL,
					   "logo-icon-name", GTK_STOCK_NETWORK,
					   NULL);
407
#endif
408
409
}

410
typedef struct DialogCBData
411
{
412
413
414
	char *msg;
	char *title;
} DialogCBData;
415

416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
static void free_dialog_cb_data (DialogCBData *data)
{
	g_return_if_fail (data != NULL);

	g_free (data->msg);
	g_free (data->title);
	memset (data, 0, sizeof (DialogCBData));
	g_free (data);
}

static void vpn_failure_dialog_close_cb (GtkWidget *dialog, gpointer user_data)
{
	DialogCBData *data;

	if ((data = g_object_get_data (G_OBJECT (dialog), "data")))
431
	{
432
433
		g_object_set_data (G_OBJECT (dialog), "data", NULL);
		free_dialog_cb_data (data);
434
435
436
437
438
439
440
	}

	gtk_widget_destroy (dialog);
}


/*
441
 * nmwa_show_vpn_failure_dialog
442
 *
443
 * Present the VPN failure dialog.
444
445
 *
 */
446
static gboolean nmwa_show_vpn_failure_dialog (DialogCBData *cb_data)
447
448
{
	GtkWidget	*dialog;
449
	guint32	 timestamp;
450

451
452
453
454
455
456
457
458
459
	g_return_val_if_fail (cb_data != NULL, FALSE);
	g_return_val_if_fail (cb_data->msg != NULL, FALSE);
	g_return_val_if_fail (cb_data->title != NULL, FALSE);

	dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, cb_data->msg, NULL);
	gtk_window_set_title (GTK_WINDOW (dialog), cb_data->title);
	g_signal_connect (dialog, "response", G_CALLBACK (vpn_failure_dialog_close_cb), NULL);
	g_signal_connect (dialog, "close", G_CALLBACK (vpn_failure_dialog_close_cb), NULL);
	g_object_set_data (G_OBJECT (dialog), "data", cb_data);
460
461
	gtk_widget_show_all (dialog);

462
463
464
465
	/* Bash focus-stealing prevention in the face */
	timestamp = gdk_x11_get_server_time (dialog->window);
	gdk_x11_window_set_user_time (dialog->window, timestamp);

466
467
468
469
470
	return FALSE;
}


/*
471
 * nmwa_schedule_vpn_failure_dialog
472
 *
473
 * Schedule display of the VPN Failure dialog.
474
475
 *
 */
476
void nmwa_schedule_vpn_failure_dialog (NMWirelessApplet *applet, const char *member, const char *vpn_name, const char *error_msg)
477
{
478
	DialogCBData *cb_data = NULL;
479
480
481
	gchar *error_head = NULL;
	gchar *error_desc = NULL;
	gchar *error_data = NULL;
482
483

	g_return_if_fail (applet != NULL);
484
	g_return_if_fail (member != NULL);
485
486
487
	g_return_if_fail (vpn_name != NULL);
	g_return_if_fail (error_msg != NULL);

488
489
490
491
492
	cb_data = g_malloc0 (sizeof (DialogCBData));
	cb_data->title = g_strdup (_("VPN Error"));

	if (!strcmp (member, NM_DBUS_VPN_SIGNAL_LOGIN_FAILED))
	{
493
494
		error_head = g_strdup (_("VPN Login Failure"));
		error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a login failure."), vpn_name);
495
496
497
	}
	else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED))
	{
498
499
		error_head = g_strdup (_("VPN Start Failure"));
		error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a failure launching the VPN program."), vpn_name);
500
501
502
	}
	else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_CONNECT_FAILED))
	{
503
504
		error_head = g_strdup (_("VPN Connect Failure"));
		error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' due to a connection error."), vpn_name);
505
	}
506
507
	else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD))
	{
508
509
		error_head = g_strdup (_("VPN Configuration Error"));
		error_desc = g_strdup_printf (_("The VPN connection '%s' was not correctly configured."), vpn_name);
510
511
512
	}
	else if (!strcmp (member, NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD))
	{
513
514
		error_head = g_strdup (_("VPN Connect Failure"));
		error_desc = g_strdup_printf (_("Could not start the VPN connection '%s' because the VPN server did not return an adequate network configuration."), vpn_name);
515
	}
516
	else
517
	{
518
		free_dialog_cb_data (cb_data);
519
520
521
522
523
524
525
526
527
528
529
530
531
		return;
	}

	error_data = g_strdup_printf (_("The VPN service said: \"%s\""), error_msg);

	cb_data->msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n"
					"%s\n\n%s", error_head, error_desc, error_data);

	g_free (error_head);
	g_free (error_desc);
	g_free (error_data);

	g_idle_add ((GSourceFunc) nmwa_show_vpn_failure_dialog, cb_data);
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
}


static void vpn_login_banner_dialog_close_cb (GtkWidget *dialog, gpointer user_data)
{
	char *message;

	if ((message = g_object_get_data (G_OBJECT (dialog), "message")))
	{
		g_object_set_data (G_OBJECT (dialog), "message", NULL);
		g_free (message);
	}

	gtk_widget_destroy (dialog);
}


/*
 * nmwa_show_vpn_login_banner_dialog
 *
 * Present the VPN login banner dialog.
 *
 */
static gboolean nmwa_show_vpn_login_banner_dialog (char *message)
{
	GtkWidget	*dialog;
558
	guint32	 timestamp;
559
560
561
562

	g_return_val_if_fail (message != NULL, FALSE);

	dialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, message, NULL);
563
564
	g_signal_connect (dialog, "response", G_CALLBACK (vpn_login_banner_dialog_close_cb), NULL);
	g_signal_connect (dialog, "close", G_CALLBACK (vpn_login_banner_dialog_close_cb), NULL);
565
566
567
	g_object_set_data (G_OBJECT (dialog), "message", message);
	gtk_widget_show_all (dialog);

568
569
570
571
	/* Bash focus-stealing prevention in the face */
	timestamp = gdk_x11_get_server_time (dialog->window);
	gdk_x11_window_set_user_time (dialog->window, timestamp);

572
573
574
575
576
577
578
579
580
581
582
583
584
	return FALSE;
}


/*
 * nmwa_schedule_vpn_login_banner_dialog
 *
 * Schedule display of the VPN Login Banner dialog.
 *
 */
void nmwa_schedule_vpn_login_banner_dialog (NMWirelessApplet *applet, const char *vpn_name, const char *banner)
{
	char *msg;
585
	char *msg2;
586
587
588
589
590

	g_return_if_fail (applet != NULL);
	g_return_if_fail (vpn_name != NULL);
	g_return_if_fail (banner != NULL);

591
592
593
594
595
	msg2 = g_strdup_printf (_("VPN connection '%s' said:"), vpn_name);
	msg = g_strdup_printf (_("<span weight=\"bold\" size=\"larger\">%s</span>\n\n"
						"%s\n\n\"%s\""), , _("VPN Login Message"), msg2, banner);
	g_free (msg2);

596
	g_idle_add ((GSourceFunc) nmwa_show_vpn_login_banner_dialog, msg);
597
598
599
}


600
601
602
603
604
605
606
/*
 * nmwa_driver_notify_get_ignored_list
 *
 * Return list of devices for which we are supposed to ignore driver
 * notifications for from GConf.
 *
 */
607
static GSList *nmwa_driver_notify_get_ignored_list (NMWirelessApplet *applet)
608
609
610
611
612
613
614
615
616
{
	char			*key;
	GConfValue	*value;
	GSList		*mac_list = NULL;

	g_return_val_if_fail (applet != NULL, NULL);
	g_return_val_if_fail (applet->gconf_client != NULL, NULL);

	/* Get current list of access point MAC addresses for this AP from GConf */
617
	key = g_strdup_printf ("%s/non_notify_cards", GCONF_PATH_PREFS);
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
	value = gconf_client_get (applet->gconf_client, key, NULL);

	if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING))
		mac_list = gconf_client_get_list (applet->gconf_client, key, GCONF_VALUE_STRING, NULL);

	if (value)
		gconf_value_free (value);
	g_free (key);

	return (mac_list);
}


/*
 * nmwa_driver_notify_is_device_ignored
 *
 * Look in GConf and determine whether or not we are supposed to
 * ignore driver notifications for a particular device.
 *
 */
638
static gboolean nmwa_driver_notify_is_device_ignored (NMWirelessApplet *applet, NetworkDevice *dev)
639
{
640
641
642
643
	gboolean		found = FALSE;
	GSList *		mac_list = NULL;
	GSList *		elt;
	const char *	dev_addr;
644
645
646
647

	g_return_val_if_fail (applet != NULL, TRUE);
	g_return_val_if_fail (applet->gconf_client != NULL, TRUE);
	g_return_val_if_fail (dev != NULL, TRUE);
648
649
650
651

	dev_addr = network_device_get_address (dev);
	g_return_val_if_fail (dev_addr != NULL, TRUE);
	g_return_val_if_fail (strlen (dev_addr) > 0, TRUE);
652
653
654
655
656
657

	mac_list = nmwa_driver_notify_get_ignored_list (applet);

	/* Ensure that the MAC isn't already in the list */
	for (elt = mac_list; elt; elt = g_slist_next (elt))
	{
658
		if (elt->data && !strcmp (dev_addr, elt->data))
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
		{
			found = TRUE;
			break;
		}
	}

	/* Free the list, since gconf_client_set_list deep-copies it */
	g_slist_foreach (mac_list, (GFunc)g_free, NULL);
	g_slist_free (mac_list);

	return found;
}


/*
 * nmwa_driver_notify_ignore_device
 *
 * Add a device's MAC address to the list of ones that we ignore
 * in GConf.  Stores user's pref for "Don't remind me".
 *
 */
680
static void nmwa_driver_notify_ignore_device (NMWirelessApplet *applet, NetworkDevice *dev)
681
{
682
683
684
685
	gboolean		found = FALSE;
	GSList *		new_mac_list = NULL;
	GSList *		elt;
	const char *	dev_addr;
686
687
688
689

	g_return_if_fail (applet != NULL);
	g_return_if_fail (applet->gconf_client != NULL);
	g_return_if_fail (dev != NULL);
690
691
692
693

	dev_addr = network_device_get_address (dev);
	g_return_if_fail (dev_addr != NULL);
	g_return_if_fail (strlen (dev_addr) > 0);
694
695
696
697
698
699

	new_mac_list = nmwa_driver_notify_get_ignored_list (applet);

	/* Ensure that the MAC isn't already in the list */
	for (elt = new_mac_list; elt; elt = g_slist_next (elt))
	{
700
		if (elt->data && !strcmp (dev_addr, elt->data))
701
702
703
704
705
706
707
708
709
		{
			found = TRUE;
			break;
		}
	}

	/* Add the new MAC address to the end of the list */
	if (!found)
	{
710
		char *key = g_strdup_printf ("%s/non_notify_cards", GCONF_PATH_PREFS);
711

712
		new_mac_list = g_slist_append (new_mac_list, g_strdup (dev_addr));
713
714
715
716
717
718
719
720
721
		gconf_client_set_list (applet->gconf_client, key, GCONF_VALUE_STRING, new_mac_list, NULL);
		g_free (key);
	}

	/* Free the list, since gconf_client_set_list deep-copies it */
	g_slist_foreach (new_mac_list, (GFunc)g_free, NULL);
	g_slist_free (new_mac_list);
}

722
static gboolean nmwa_driver_notify_dialog_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
723
724
725
726
727
{
	gtk_widget_destroy (widget);
	return FALSE;
}

728
static gboolean nmwa_driver_notify_dialog_destroy_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
{
	DriverNotifyCBData	*cb_data = (DriverNotifyCBData *)(user_data);
	NetworkDevice		*dev;

	g_return_val_if_fail (cb_data != NULL, FALSE);
	g_return_val_if_fail (cb_data->xml != NULL, FALSE);

	dev = cb_data->dev;
	g_return_val_if_fail (dev != NULL, FALSE);

	network_device_unref (dev);

	g_object_unref (cb_data->xml);
	g_free (cb_data);

	return FALSE;
}


748
static gboolean nmwa_driver_notify_ok_cb (GtkButton *button, gpointer user_data)
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
{
	DriverNotifyCBData	*cb_data = (DriverNotifyCBData *)(user_data);
	NetworkDevice		*dev;
	NMWirelessApplet	*applet;
	GtkWidget			*dialog;
	GtkWidget			*checkbox;

	g_return_val_if_fail (cb_data != NULL, FALSE);
	g_return_val_if_fail (cb_data->xml != NULL, FALSE);

	dev = cb_data->dev;
	g_return_val_if_fail (dev != NULL, FALSE);

	applet = cb_data->applet;
	g_return_val_if_fail (applet != NULL, FALSE);

	checkbox = glade_xml_get_widget (cb_data->xml, "dont_remind_checkbox");
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)))
		nmwa_driver_notify_ignore_device (applet, dev);

	dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog");
	gtk_widget_destroy (dialog);

	return FALSE;
}


/*
 * nmwa_driver_notify
 *
 * Notify the user if there's some problem with the driver
 * of a specific network device.
 *
 */
gboolean nmwa_driver_notify (gpointer user_data)
{
785
786
787
	DriverNotifyCBData *	cb_data = (DriverNotifyCBData *)(user_data);
	NetworkDevice *		dev;
	NMWirelessApplet *		applet;
788
	GtkWidget *			dialog;
789
790
791
792
793
	GtkLabel *			label;
	char *				label_text = NULL;
	char *				temp = NULL;
	GtkButton *			button;
	NMDriverSupportLevel	support_level;
794
	guint32				timestamp;
795
796
797
798
799
800

	g_return_val_if_fail (cb_data != NULL, FALSE);

	dev = cb_data->dev;
	g_return_val_if_fail (dev != NULL, FALSE);

801
802
	if (!(applet = cb_data->applet) || !applet->glade_file)
		goto out;
803
804
805
806
807

	/* If the user has already requested that we ignore notifications for
	 * this device, don't do anything.
	 */
	if (nmwa_driver_notify_is_device_ignored (applet, dev))
808
		goto out;
809

810
	if (!(cb_data->xml = glade_xml_new (applet->glade_file, "driver_sucks_dialog", NULL)))
811
	{
812
813
		nmwa_schedule_warning_dialog (applet, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
		goto out;
814
815
	}

816
	dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog");
817
818
819
820
821
	g_signal_connect (G_OBJECT (dialog), "destroy-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_destroy_cb), cb_data);
	g_signal_connect (G_OBJECT (dialog), "delete-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_delete_cb), cb_data);

	label = GTK_LABEL (glade_xml_get_widget (cb_data->xml, "driver_sucks_label"));

822
	switch (network_device_get_driver_support_level (dev))
823
	{
824
825
826
827
828
829
830
831
832
833
834
835
836
		case NM_DRIVER_NO_WIRELESS_SCAN:
			temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."),
							network_device_get_desc (dev), network_device_get_iface (dev));
			label_text = g_strdup_printf (gtk_label_get_label (label), temp);
			g_free (temp);
		break;

		case NM_DRIVER_NO_CARRIER_DETECT:
			temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."),
							network_device_get_desc (dev), network_device_get_iface (dev));
			label_text = g_strdup_printf (gtk_label_get_label (label), temp);
			g_free (temp);
			break;
837

838
839
		default:
			break;
840
	}
841

842
843
844
845
846
847
848
849
	if (label_text)
		gtk_label_set_markup (label, label_text);

	button = GTK_BUTTON (glade_xml_get_widget (cb_data->xml, "ok_button"));
	g_signal_connect (G_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (nmwa_driver_notify_ok_cb), cb_data);

	gtk_widget_show_all (GTK_WIDGET (dialog));

850
851
852
853
	/* Bash focus-stealing prevention in the face */
	timestamp = gdk_x11_get_server_time (dialog->window);
	gdk_x11_window_set_user_time (dialog->window, timestamp);

854
out:
855
856
	network_device_unref (cb_data->dev);
	return (FALSE);
857
858
859
}


860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
static void nmwa_set_icon (NMWirelessApplet *applet, GdkPixbuf *new_icon)
{
	GdkPixbuf	*composite;

	g_return_if_fail (applet != NULL);
	g_return_if_fail (new_icon != NULL);

	composite = gdk_pixbuf_copy (new_icon);

	if (applet->gui_active_vpn)
	{
		int dest_x = gdk_pixbuf_get_width (new_icon) - gdk_pixbuf_get_width (applet->vpn_lock_icon);
		int dest_y = gdk_pixbuf_get_height (new_icon) - gdk_pixbuf_get_height (applet->vpn_lock_icon) - 2;

		gdk_pixbuf_composite (applet->vpn_lock_icon, composite, dest_x, dest_y, gdk_pixbuf_get_width (applet->vpn_lock_icon),
							gdk_pixbuf_get_height (applet->vpn_lock_icon), dest_x, dest_y, 1.0, 1.0, GDK_INTERP_NEAREST, 255);
	}

	gtk_image_set_from_pixbuf (GTK_IMAGE (applet->pixmap), composite);
	g_object_unref (composite);
}


883
884
885
886
887
888
889
890
891
892
893
static void nmwa_set_progress (NMWirelessApplet *applet, GdkPixbuf *progress_icon)
{
	g_return_if_fail (applet != NULL);

	gtk_image_set_from_pixbuf (GTK_IMAGE (applet->progress_bar), progress_icon);
	if (!progress_icon)
		gtk_widget_hide (applet->progress_bar);
	else
		gtk_widget_show (applet->progress_bar);
}

894
895
896
897
898
899
900
901
/*
 * animation_timeout
 *
 * Jump to the next frame of the applets icon if the icon
 * is supposed to be animated.
 *
 */
static gboolean animation_timeout (NMWirelessApplet *applet)
902
{
903
904
	NetworkDevice *act_dev = nmwa_get_first_active_device (applet->dbus_device_list);

905
	if (!applet->nm_running)
906
	{
907
908
909
		applet->animation_step = 0;
		return TRUE;
	}
910

911
912
	switch (applet->gui_nm_state)
	{
913
		case NM_STATE_CONNECTING:
914
			if (act_dev && network_device_is_wireless (act_dev))
915
916
917
918
919
			{
				if (applet->animation_step >= NUM_WIRELESS_CONNECTING_FRAMES)
					applet->animation_step = 0;
				nmwa_set_icon (applet, applet->wireless_connecting_icons[applet->animation_step]);
			}
920
			else if (act_dev)
921
922
923
924
925
			{
				if (applet->animation_step >= NUM_WIRED_CONNECTING_FRAMES)
					applet->animation_step = 0;
				nmwa_set_icon (applet, applet->wired_connecting_icons[applet->animation_step]);
			}
926
927
928
929
930
931
			applet->animation_step ++;
			break;

		default:
			break;
	}
932

933
	return TRUE;
934
935
936
}


937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
static GdkPixbuf * nmwa_act_stage_to_pixbuf (NMWirelessApplet *applet, NetworkDevice *dev, WirelessNetwork *net, char **tip)
{
	const char *essid;
	const char *iface;

	g_return_val_if_fail (applet != NULL, NULL);
	g_return_val_if_fail (dev != NULL, NULL);
	g_return_val_if_fail (tip != NULL, NULL);

	iface = network_device_get_iface (dev);
	essid = net ? wireless_network_get_essid (net) : NULL;
	switch (network_device_get_act_stage (dev))
	{
		case NM_ACT_STAGE_DEVICE_PREPARE:
		{
			if (network_device_is_wired (dev))
				*tip = g_strdup_printf (_("Preparing device %s for the wired network..."), iface);
			else if (network_device_is_wireless (dev))
				*tip = g_strdup_printf (_("Preparing device %s for the wireless network '%s'..."), iface, essid);
			return applet->progress_icons[1];
		}

		case NM_ACT_STAGE_DEVICE_CONFIG:
		{
			if (network_device_is_wired (dev))
				*tip = g_strdup_printf (_("Configuring device %s for the wired network..."), iface);
			else if (network_device_is_wireless (dev))
964
				*tip = g_strdup_printf (_("Attempting to join the wireless network '%s'..."), essid);
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
			return applet->progress_icons[3];
		}

		case NM_ACT_STAGE_NEED_USER_KEY:
		{
			if (network_device_is_wireless (dev))
				*tip = g_strdup_printf (_("Waiting for Network Key for the wireless network '%s'..."), essid);
			return applet->progress_icons[4];
		}

		case NM_ACT_STAGE_IP_CONFIG_START:
		{
			if (network_device_is_wired (dev))
				*tip = g_strdup_printf (_("Requesting a network address from the wired network..."));
			else if (network_device_is_wireless (dev))
				*tip = g_strdup_printf (_("Requesting a network address from the wireless network '%s'..."), essid);
			return applet->progress_icons[5];
		}

		case NM_ACT_STAGE_IP_CONFIG_GET:
		{
			if (network_device_is_wired (dev))
				*tip = g_strdup_printf (_("Requesting a network address from the wired network..."));
			else if (network_device_is_wireless (dev))
				*tip = g_strdup_printf (_("Requesting a network address from the wireless network '%s'..."), essid);
			return applet->progress_icons[8];
		}

		case NM_ACT_STAGE_IP_CONFIG_COMMIT:
		{
			if (network_device_is_wired (dev))
				*tip = g_strdup_printf (_("Finishing connection to the wired network..."));
			else if (network_device_is_wireless (dev))
				*tip = g_strdup_printf (_("Finishing connection to the wireless network '%s'..."), essid);
			return applet->progress_icons[10];
		}

		default:
		case NM_ACT_STAGE_ACTIVATED:
		case NM_ACT_STAGE_FAILED:
		case NM_ACT_STAGE_CANCELLED:
		case NM_ACT_STAGE_UNKNOWN:
			break;
	}
	return NULL;
}


1013
1014
1015
1016
1017
1018
1019
/*
 * nmwa_update_state
 *
 * Figure out what the currently active device is from NetworkManager, its type,
 * and what our icon on the panel should look like for each type.
 *
 */
1020
static void nmwa_update_state (NMWirelessApplet *applet)
1021
{
1022
1023
1024
1025
	gboolean			show_applet = TRUE;
	gboolean			need_animation = FALSE;
	gboolean			active_vpn = FALSE;
	GdkPixbuf *		pixbuf = NULL;
1026
	GdkPixbuf *		progress = NULL;
1027
1028
1029
	gint				strength = -1;
	char *			tip = NULL;
	WirelessNetwork *	active_network = NULL;
1030
	NetworkDevice *	act_dev = NULL;
1031
1032

	g_mutex_lock (applet->data_mutex);
1033

1034
	act_dev = nmwa_get_first_active_device (applet->gui_device_list);
1035
	if (act_dev && network_device_is_wireless (act_dev))
1036
	{
1037
1038
		active_network = network_device_get_active_wireless_network (act_dev);
		strength = CLAMP ((int)network_device_get_strength (act_dev), 0, 100);
1039
	}
1040

1041
	if (!applet->nm_running)
1042
	{
1043
1044
1045
		show_applet = FALSE;
		tip = g_strdup (_("NetworkManager is not running"));
		goto done;
1046
	}
1047

1048
	if (!act_dev)
1049
		applet->gui_nm_state = NM_STATE_DISCONNECTED;
1050

1051
	switch (applet->gui_nm_state)
1052
	{
1053
		case NM_STATE_DISCONNECTED:
1054
			pixbuf = applet->no_connection_icon;
1055
1056
1057
			tip = g_strdup (_("No network connection"));
			break;

1058
		case NM_STATE_CONNECTED:
1059
			if (network_device_is_wired (act_dev))
1060
1061
1062
1063
			{
				pixbuf = applet->wired_icon;
				tip = g_strdup (_("Wired network connection"));
			}
1064
			else if (network_device_is_wireless (act_dev))
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
			{
				if (applet->is_adhoc)
				{
					pixbuf = applet->adhoc_icon;
					tip = g_strdup (_("Connected to an Ad-Hoc wireless network"));
				}
				else
				{
					if (strength > 75)
						pixbuf = applet->wireless_100_icon;
					else if (strength > 50)
						pixbuf = applet->wireless_75_icon;
					else if (strength > 25)
						pixbuf = applet->wireless_50_icon;
					else if (strength > 0)
						pixbuf = applet->wireless_25_icon;
					else
						pixbuf = applet->wireless_00_icon;
1083
					tip = g_strdup_printf (_("Wireless network connection to '%s' (%d%%)"),
1084
							active_network ? wireless_network_get_essid (active_network) : "(unknown)", strength);
1085
1086
1087
1088
				}
			}
			break;

1089
		case NM_STATE_CONNECTING:
1090
			progress = nmwa_act_stage_to_pixbuf (applet, act_dev, active_network, &tip);
1091
1092
1093
1094
1095
			need_animation = TRUE;
			break;

		default:
			break;
1096
	}
1097
1098

done:
1099
1100
1101
1102
	g_mutex_unlock (applet->data_mutex);

	if (!applet->tooltips)
		applet->tooltips = gtk_tooltips_new ();
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114

	if (applet->gui_active_vpn != NULL) {
		char *newtip;
		char *vpntip;

		vpntip = g_strdup_printf (_("VPN connection to '%s'"), nmwa_vpn_connection_get_name (applet->gui_active_vpn));
		newtip = g_strconcat (tip, "\n", vpntip, NULL);
		g_free (vpntip);
		g_free (tip);
		tip = newtip;
	}

1115
1116
1117
	gtk_tooltips_set_tip (applet->tooltips, applet->event_box, tip, NULL);
	g_free (tip);

1118
1119
	nmwa_set_progress (applet, progress);	

1120
1121
1122
	if (applet->animation_id)
		g_source_remove (applet->animation_id);
	if (need_animation)
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
		applet->animation_id = g_timeout_add (100, (GSourceFunc) animation_timeout, applet);
	else
	{
		if (pixbuf)
			nmwa_set_icon (applet, pixbuf);
		else
			show_applet = FALSE;
	}

	/* determine if we should hide the notification icon */
	if (show_applet)
		gtk_widget_show (GTK_WIDGET (applet));
1135
	else
1136
		gtk_widget_hide (GTK_WIDGET (applet));
1137
1138
}

1139
1140

/*
1141
 * nmwa_redraw_timeout
1142
1143
1144
 *
 * Called regularly to update the applet's state and icon in the panel
 *
1145
 */
1146
static int nmwa_redraw_timeout (NMWirelessApplet *applet)
1147
1148
{
	nmwa_update_state (applet);
1149

1150
1151
1152
  	return (TRUE);
}

1153
static void nmwa_start_redraw_timeout (NMWirelessApplet *applet)
1154
{
1155
	applet->redraw_timeout_id = g_timeout_add (1000, (GtkFunction) nmwa_redraw_timeout, applet);
1156
1157
1158
}


1159
1160
1161
1162
1163
1164
/*
 * show_warning_dialog
 *
 * pop up a warning or error dialog with certain text
 *
 */
1165
static gboolean show_warning_dialog (char *mesg)
1166
{
1167
	GtkWidget	*	dialog;
1168
	guint32		timestamp;
1169

1170
	dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, mesg, NULL);
1171
	gtk_widget_realize (dialog);
1172
1173
1174
1175
1176

	/* Bash focus-stealing prevention in the face */
	timestamp = gdk_x11_get_server_time (dialog->window);
	gdk_x11_window_set_user_time (dialog->window, timestamp);

1177
1178
	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);
1179
	g_free (mesg);
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198

	return FALSE;
}


/*
 * nmwa_schedule_warning_dialog
 *
 * Run a warning dialog in the main event loop.
 *
 */
void nmwa_schedule_warning_dialog (NMWirelessApplet *applet, const char *msg)
{
	char *lcl_msg;

	g_return_if_fail (applet != NULL);
	g_return_if_fail (msg != NULL);

	lcl_msg = g_strdup (msg);
1199
	g_idle_add ((GSourceFunc) show_warning_dialog, lcl_msg);
1200
1201
1202
}


1203
1204
1205
1206
1207
1208
1209
/*
 * nmwa_get_device_for_nm_device
 *
 * Searches the device list for a device that matches the
 * NetworkManager ID given.
 *
 */
1210
NetworkDevice *nmwa_get_device_for_nm_path (GSList *dev_list, const char *nm_path)
1211
1212
{
	NetworkDevice	*found_dev = NULL;
1213
	GSList		*elt;
1214

1215
1216
	g_return_val_if_fail (nm_path != NULL, NULL);
	g_return_val_if_fail (strlen (nm_path), NULL);
1217

1218
	for (elt = dev_list; elt; elt = g_slist_next (elt))
1219
	{
1220
		NetworkDevice	*dev = (NetworkDevice *)(elt->data);
1221
		if (dev && (strcmp (network_device_get_nm_path (dev), nm_path) == 0))
1222
1223
1224
1225
1226
1227
1228
		{
			found_dev = dev;
			break;
		}
	}

	return (found_dev);
1229
1230
1231
1232
}


/*
1233
 * nmwa_menu_item_activate
1234
1235
1236
1237
 *
 * Signal function called when user clicks on a menu item
 *
 */
1238
static void nmwa_menu_item_activate (GtkMenuItem *item, gpointer user_data)
1239
1240
{
	NMWirelessApplet	*applet = (NMWirelessApplet *)user_data;
1241
1242
	NetworkDevice		*dev = NULL;
	WirelessNetwork	*net = NULL;
1243
	char				*tag;
1244
1245
1246
1247

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);

1248
1249
	if (!(tag = g_object_get_data (G_OBJECT (item), "device")))
		return;
1250

1251
1252
	g_mutex_lock (applet->data_mutex);
	if ((dev = nmwa_get_device_for_nm_path (applet->gui_device_list, tag)))
1253
		network_device_ref (dev);
1254
	g_mutex_unlock (applet->data_mutex);
1255

1256
1257
1258
1259
	if (!dev)
		return;

	if ((tag = g_object_get_data (G_OBJECT (item), "network")))
1260
		net = network_device_get_wireless_network_by_essid (dev, tag);
1261
1262
1263

	nmwa_dbus_set_device (applet->connection, dev, net ? wireless_network_get_essid (net) : NULL, -1, NULL);
	network_device_unref (dev);
1264
1265
1266
}


1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
/*
 * nmwa_menu_vpn_item_activate
 *
 * Signal function called when user clicks on a VPN menu item
 *
 */
static void nmwa_menu_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
{
	NMWirelessApplet	*applet = (NMWirelessApplet *)user_data;
	char				*tag;

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);

	if ((tag = g_object_get_data (G_OBJECT (item), "vpn")))
	{
		VPNConnection	*vpn = (VPNConnection *)tag;
		const char	*name = nmwa_vpn_connection_get_name (vpn);
1285
		GSList         *passwords;
1286
1287
1288

		if (vpn != applet->gui_active_vpn)
		{
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
			char *gconf_key;
			char *escaped_name;
			gboolean last_attempt_success;
			gboolean reprompt;

			escaped_name = gconf_escape_key (name, strlen (name));
			gconf_key = g_strdup_printf ("%s/%s/last_attempt_success", GCONF_PATH_VPN_CONNECTIONS, escaped_name);
			last_attempt_success = gconf_client_get_bool (applet->gconf_client, gconf_key, NULL);
			g_free (gconf_key);
			g_free (escaped_name);

			reprompt = ! last_attempt_success; /* it's obvious, but.. */

			if ((passwords = nmwa_vpn_request_password (applet, 
											    name, 
											    nmwa_vpn_connection_get_service (vpn), 
											    reprompt)) != NULL)
1306
			{
1307
1308
1309
1310
				nmwa_dbus_vpn_activate_connection (applet->connection, name, passwords);

				g_slist_foreach (passwords, (GFunc)g_free, NULL);
				g_slist_free (passwords);
1311
1312
1313
1314
1315
1316
			}
		}
	}
}


1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
/*
 * nmwa_menu_dialup_item_activate
 *
 * Signal function called when user clicks on a dialup menu item
 *
 */
static void nmwa_menu_dialup_item_activate (GtkMenuItem *item, gpointer user_data)
{
	NMWirelessApplet *applet = (NMWirelessApplet *) user_data;
	const char *dialup;

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);

	dialup = g_object_get_data (G_OBJECT (item), "dialup");
	if (!dialup)
		return;

	nmwa_dbus_dialup_activate_connection (applet, dialup);
}


1339
1340
1341
1342
1343
1344
1345
1346
1347
/*
 * nmwa_menu_configure_vpn_item_activate
 *
 * Signal function called when user clicks "Configure VPN..."
 *
 */
static void nmwa_menu_configure_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
{
	NMWirelessApplet	*applet = (NMWirelessApplet *)user_data;
1348
	const char *argv[] = { BINDIR "/nm-vpn-properties", NULL};
1349
1350
1351

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);
1352

1353
	g_spawn_async (NULL, (gchar **) argv, NULL, 0, NULL, NULL, NULL, NULL);
1354
1355
}

1356
1357
1358
/*
 * nmwa_menu_disconnect_vpn_item_activate
 *
1359
 * Signal function called when user clicks "Disconnect VPN..."
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
 *
 */
static void nmwa_menu_disconnect_vpn_item_activate (GtkMenuItem *item, gpointer user_data)
{
	NMWirelessApplet	*applet = (NMWirelessApplet *)user_data;

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);

	nmwa_dbus_vpn_deactivate_connection (applet->connection);
}


1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
static void scanning_menu_update (GtkWidget *menu_item, GtkCheckMenuItem *active_item)
{
	g_return_if_fail (active_item != NULL);

	g_object_set_data (G_OBJECT (menu_item), "block-activate", GINT_TO_POINTER(1));
	gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), (GTK_CHECK_MENU_ITEM (menu_item) == active_item) ? TRUE : FALSE);
	g_object_set_data (G_OBJECT (menu_item), "block-activate", GINT_TO_POINTER(0));
}


/*
 * nmwa_menu_scanning_item_activate
 *
 * Handle a request to change scanning behavior
 *
 */
static void nmwa_menu_scanning_item_activate (GtkMenuItem *item, gpointer user_data)
{
	NMWirelessApplet *	applet = (NMWirelessApplet *)user_data;
	char *			tag;

	g_return_if_fail (item != NULL);
	g_return_if_fail (applet != NULL);

	if ((tag = g_object_get_data (G_OBJECT (item), "block-activate")))
		if (GPOINTER_TO_INT(tag) == 1)
			return;

	if ((tag = g_object_get_data (G_OBJECT (item), "scan_method")))
	{
		NMWirelessScanMethod	method = GPOINTER_TO_UINT (tag);

1405
1406
		if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER)
			|| (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
			gconf_client_set_int (applet->gconf_client, GCONF_PATH_WIRELESS "/scan_method", method, NULL);
	}

	/* Check only this menu item */
	if (!applet->scanning_menu)
		return;

	gtk_container_foreach (GTK_CONTAINER (applet->scanning_menu), (GtkCallback) scanning_menu_update, (gpointer) item);
}


1418
/*
1419
1420
1421
 * nmwa_menu_add_separator_item
 *
 */
1422
static void nmwa_menu_add_separator_item (GtkWidget *menu)
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
{
	GtkWidget	*menu_item;
	menu_item = gtk_separator_menu_item_new ();