1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #define _BSD_SOURCE
21
22 #include <unistd.h>
23 #include <string.h>
24
25 #include "applet-struct.h"
26 #include "applet-connections.h"
27 #include "applet-menu.h"
28
cd_NetworkMonitor_get_connections_for_access_point(const gchar * cAccessPoint,const gchar * cDevice,const gchar * cSsid,const gchar * cHwAddress,int iMode,int iWirelessCapabilities,GPtrArray * paConnections,GPtrArray * paSettings)29 static GList *cd_NetworkMonitor_get_connections_for_access_point (const gchar *cAccessPoint, const gchar *cDevice, const gchar *cSsid, const gchar *cHwAddress, int iMode, int iWirelessCapabilities, GPtrArray *paConnections, GPtrArray *paSettings)
30 {
31 g_return_val_if_fail (paConnections != NULL, NULL);
32 GList *pConnList = NULL;
33 gchar *cConnection;
34 GHashTable *pSettings, *pSubSettings;
35 GValue *v;
36 uint i;
37 for (i = 0; i < paConnections->len; i++)
38 {
39 cConnection = (gchar *)g_ptr_array_index(paConnections, i);
40 cd_debug (" Connection path : %s", cConnection);
41
42 pSettings = g_ptr_array_index (paSettings, i);
43
44 pSubSettings = g_hash_table_lookup (pSettings, "connection");
45 if (pSubSettings == NULL)
46 continue;
47
48 const gchar *cType = NULL;
49 v = g_hash_table_lookup (pSubSettings, "type");
50 if (v && G_VALUE_HOLDS_STRING (v))
51 {
52 cType = g_value_get_string (v);
53 cd_debug (" type : %s", cType);
54 }
55 if (cType == NULL || strcmp (cType, "802-11-wireless") != 0) // on veut du wifi.
56 continue;
57
58 const gchar *cID = NULL;
59 v = g_hash_table_lookup (pSubSettings, "id");
60 if (v && G_VALUE_HOLDS_STRING (v))
61 {
62 cID = g_value_get_string (v);
63 cd_debug (" id : %s", cID);
64 }
65
66 pSubSettings = g_hash_table_lookup (pSettings, "802-11-wireless");
67 if (pSubSettings == NULL)
68 continue;
69 const gchar *cMode = NULL;
70 v = g_hash_table_lookup (pSubSettings, "mode");
71 if (v && G_VALUE_HOLDS_STRING (v))
72 {
73 cMode = g_value_get_string (v);
74 cd_debug (" mode : %s", cMode);
75 }
76 if (iMode && cMode)
77 {
78 if (iMode == 1 && strcmp (cMode, "ad-hoc") != 0)
79 continue;
80 if (iMode == 2 && strcmp (cMode, "infrastructure") != 0)
81 continue;
82 }
83
84 gchar *cAPSsid = NULL;
85 v = g_hash_table_lookup (pSubSettings, "ssid");
86 if (v && G_VALUE_HOLDS_BOXED (v))
87 {
88 GByteArray *a = g_value_get_boxed (v);
89 cAPSsid = g_strndup ((gchar *) a->data, a->len);
90 cd_debug (" ssid : %s", cSsid);
91 }
92 if (cSsid == NULL || (cAPSsid != NULL && strcmp (cAPSsid, cSsid) != 0)) // le SSID est necessaire.
93 continue;
94
95 const gchar *cMacAddress = NULL;
96 v = g_hash_table_lookup (pSubSettings, "mac-address");
97 if (v && G_VALUE_HOLDS_STRING (v))
98 {
99 cMacAddress = g_value_get_string (v);
100 cd_debug (" mac address : %s", cMacAddress);
101 }
102 if (cHwAddress != NULL && cMacAddress != NULL && strcmp (cMacAddress, cHwAddress) != 0)
103 continue;
104
105 pSubSettings = g_hash_table_lookup (pSettings, "802-11-wireless-security");
106 if (pSubSettings)
107 {
108 /// on verra plus tard ...
109
110 }
111
112 pConnList = g_list_prepend (pConnList, GINT_TO_POINTER (i));
113 }
114
115 return pConnList;
116 }
117
118 /* Not used
119 static GList *cd_NetworkMonitor_get_connections_for_wired_device (const gchar *cDevice, const gchar *cHwAddress, GPtrArray *paConnections)
120 {
121 GList *pConnList = NULL;
122 //\_____________ On cherche une connection qui ait le meme type (wifi ou filaire), et soit le meme SSID, soit la meme interface.
123 gchar *cConnection;
124 uint i;
125 for (i = 0; i < paConnections->len; i++)
126 {
127 cConnection = (gchar *)g_ptr_array_index(paConnections, i);
128 cd_debug (" Connection path : %s", cConnection);
129
130 }
131
132 return pConnList;
133 }
134 */
135
_on_select_access_point(GtkMenuItem * menu_item,CDMenuItemData * pItemData)136 static void _on_select_access_point (GtkMenuItem *menu_item, CDMenuItemData *pItemData)
137 {
138 if (pItemData == NULL || pItemData->cConnection == NULL)
139 {
140 /// il faut creer une connection ...
141 cd_debug ("aucune des connexions existantes ne convient pour ce point d'acces\n");
142
143 GHashTable *pSettings = g_hash_table_new_full (g_str_hash,
144 g_str_equal,
145 g_free,
146 (GDestroyNotify) g_hash_table_destroy); // a table of tables.
147 GHashTable *pSubSettings;
148
149 // connection: type, id, uuid
150 pSubSettings = g_hash_table_new_full (g_str_hash,
151 g_str_equal,
152 g_free,
153 g_free);
154 g_hash_table_insert (pSettings, g_strdup ("connection"), pSubSettings);
155 g_hash_table_insert (pSubSettings, g_strdup ("type"), g_strdup ("802-11-wireless"));
156 g_hash_table_insert (pSubSettings, g_strdup ("id"), g_strdup_printf ("CD - %s", pItemData->cSsid));
157
158 // 802-11-wireless: ssid, mode, seen-bssids
159 pSubSettings = g_hash_table_new_full (g_str_hash,
160 g_str_equal,
161 g_free,
162 g_free);
163 g_hash_table_insert (pSettings, g_strdup ("802-11-wireless"), pSubSettings);
164 g_hash_table_insert (pSubSettings, g_strdup ("ssid"), g_strdup (pItemData->cSsid));
165 g_hash_table_insert (pSubSettings, g_strdup ("mode"), g_strdup ("infrastructure"));
166
167 // AddConnection
168 DBusGProxy *dbus_proxy_Settings = cairo_dock_create_new_system_proxy (
169 myData.cServiceName,
170 "/org/freedesktop/NetworkManagerSettings",
171 "org.freedesktop.NetworkManagerSettings");
172
173 GError *erreur = NULL;
174 dbus_g_proxy_call (dbus_proxy_Settings, "AddConnection", &erreur,
175 CD_DBUS_TYPE_HASH_TABLE_OF_HASH_TABLE, pSettings,
176 G_TYPE_INVALID,
177 G_TYPE_INVALID);
178 if (erreur != NULL)
179 {
180 cd_warning (erreur->message);
181 g_error_free (erreur);
182 return ;
183 }
184
185 /// on attend le signal NewConnection ...
186
187
188
189 /// on active la connexion...
190
191
192
193 }
194 else
195 {
196 cd_debug ("on a choisit (%s; %s; %s)", pItemData->cAccessPoint, pItemData->cDevice, pItemData->cConnection);
197
198 //ActivateConnection ( s: service_name, o: connection, o: device, o: specific_object )o
199 GError *erreur = NULL;
200 GValue active_connection_path = G_VALUE_INIT;
201 g_value_init (&active_connection_path, DBUS_TYPE_G_OBJECT_PATH);
202
203 gchar *cNewActiveConnectionPath = NULL;
204 dbus_g_proxy_call (myData.dbus_proxy_NM, "ActivateConnection", &erreur,
205 G_TYPE_STRING, myData.cServiceName,
206 DBUS_TYPE_G_OBJECT_PATH, pItemData->cConnection,
207 DBUS_TYPE_G_OBJECT_PATH, pItemData->cDevice,
208 DBUS_TYPE_G_OBJECT_PATH, pItemData->cAccessPoint,
209 G_TYPE_INVALID,
210 DBUS_TYPE_G_OBJECT_PATH, &cNewActiveConnectionPath,
211 G_TYPE_INVALID);
212 if (erreur != NULL)
213 {
214 cd_warning (erreur->message);
215 g_error_free (erreur);
216 return ;
217 }
218 cd_debug (" => new active connection path : %s", cNewActiveConnectionPath);
219 }
220 }
221
cd_NetworkMonitor_build_menu_with_access_points(void)222 GtkWidget * cd_NetworkMonitor_build_menu_with_access_points (void)
223 {
224 //\_____________ On recupere les connections existantes, ainsi que leur settings.
225 DBusGProxy *dbus_proxy_Settings = cairo_dock_create_new_system_proxy (
226 myData.cServiceName,
227 "/org/freedesktop/NetworkManagerSettings",
228 "org.freedesktop.NetworkManagerSettings");
229 GPtrArray *paConnections = cairo_dock_dbus_get_array (dbus_proxy_Settings, "ListConnections");
230 cd_debug ("%d connection(s)", paConnections ? paConnections->len : 0);
231 g_object_unref (dbus_proxy_Settings);
232
233 GPtrArray *paSettings = NULL;
234 gchar *cConnection;
235 if (paConnections != NULL && paConnections->len > 0)
236 {
237 paSettings = g_ptr_array_sized_new (paConnections->len);
238 g_ptr_array_set_size (paSettings, paConnections->len);
239 DBusGProxy *dbus_proxy_ConnectionSettings;
240 GError *erreur = NULL;
241 GHashTable *pSettingsTable;
242 uint i;
243 for (i = 0; i < paConnections->len; i++)
244 {
245 cConnection = (gchar *)g_ptr_array_index(paConnections, i);
246 cd_debug (" Connection path : %s", cConnection);
247
248 dbus_proxy_ConnectionSettings = cairo_dock_create_new_system_proxy (
249 "org.freedesktop.NetworkManagerUserSettings",
250 cConnection,
251 "org.freedesktop.NetworkManagerSettings.Connection");
252 erreur = NULL;
253 pSettingsTable = NULL;
254 dbus_g_proxy_call (dbus_proxy_ConnectionSettings, "GetSettings", &erreur,
255 G_TYPE_INVALID,
256 CD_DBUS_TYPE_HASH_TABLE_OF_HASH_TABLE, &pSettingsTable,
257 G_TYPE_INVALID);
258 if (erreur != NULL)
259 {
260 cd_warning (erreur->message);
261 g_error_free (erreur);
262 erreur = NULL;
263 }
264 paSettings->pdata[i] = pSettingsTable;
265
266 g_object_unref (dbus_proxy_ConnectionSettings);
267 }
268 }
269
270 //\_____________ On recupere la liste des devices.
271 GPtrArray *paDevices = cairo_dock_dbus_get_array (myData.dbus_proxy_NM, "GetDevices");
272 g_return_val_if_fail (paDevices != NULL, FALSE);
273 cd_debug ("%d device(s)", paDevices->len);
274
275 GtkWidget *pMenu = gldi_menu_new (myIcon);
276
277 //\_____________ On parcourt tous les devices.
278 GHashTable *pSsidTable = g_hash_table_new_full (g_str_hash,
279 g_str_equal,
280 g_free,
281 NULL);
282 gchar *cDevice;
283 DBusGProxy *dbus_proxy_Device_prop;
284 guint iDeviceType;
285 DBusGProxy *dbus_proxy_WirelessDevice;
286 DBusGProxy *dbus_proxy_AccessPoint_prop;
287 gchar *cAccessPointPath;
288 GHashTable *hProperties;
289 GValue *v;
290 gint iPercent;
291 gchar *cSsid = NULL;
292 const gchar *cHwAddress;
293 CDMenuItemData *pItemData;
294 uint i, j;
295 for (i = 0; i < paDevices->len; i++)
296 {
297 // on recupere le device.
298 cDevice = (gchar *)g_ptr_array_index(paDevices, i);
299 dbus_proxy_Device_prop = cairo_dock_create_new_system_proxy (
300 "org.freedesktop.NetworkManager",
301 cDevice,
302 "org.freedesktop.DBus.Properties");
303 if (!DBUS_IS_G_PROXY (dbus_proxy_Device_prop))
304 continue;
305 cd_debug (" device %s", cDevice);
306
307 // on regarde son type.
308 iDeviceType = cairo_dock_dbus_get_property_as_uint (dbus_proxy_Device_prop, "org.freedesktop.NetworkManager.Device", "DeviceType"); // 1 : ethernet, 2 : wifi
309 cd_debug (" device type : %d", iDeviceType);
310 if (iDeviceType != 1 && iDeviceType != 2) // ne nous insteresse pas.
311 {
312 cd_debug (" useless device type\n");
313 g_object_unref (dbus_proxy_Device_prop);
314 continue;
315 }
316
317 if (iDeviceType == 2)
318 {
319 // On recupere ses proprietes.
320 hProperties = cairo_dock_dbus_get_all_properties (dbus_proxy_Device_prop, "org.freedesktop.NetworkManager.Device.Wireless");
321
322 /*v = (GValue *)g_hash_table_lookup (hProperties, "HwAddress");
323 if (v && G_VALUE_HOLDS_STRING (v))
324 {
325 cAccessPointHwAdress = g_value_get_string (v);
326 }*/
327
328 int iMode = 0;
329 v = (GValue *)g_hash_table_lookup (hProperties, "Mode");
330 if (v && G_VALUE_HOLDS_UINT (v))
331 {
332 iMode = g_value_get_uint (v);
333 }
334
335 int iWirelessCapabilities = 0;
336 v = (GValue *)g_hash_table_lookup (hProperties, "WirelessCapabilities");
337 if (v && G_VALUE_HOLDS_UINT (v))
338 {
339 iWirelessCapabilities = g_value_get_uint (v);
340 }
341
342 // On recupere la liste des points d'acces.
343 dbus_proxy_WirelessDevice = cairo_dock_create_new_system_proxy (
344 "org.freedesktop.NetworkManager",
345 cDevice,
346 "org.freedesktop.NetworkManager.Device.Wireless");
347 GError *erreur = NULL;
348 GPtrArray *pAccessPoints = NULL;
349 dbus_g_proxy_call (dbus_proxy_WirelessDevice, "GetAccessPoints", &erreur,
350 G_TYPE_INVALID,
351 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &pAccessPoints,
352 G_TYPE_INVALID);
353 g_object_unref (dbus_proxy_WirelessDevice);
354 if (erreur != NULL)
355 {
356 cd_warning (erreur->message);
357 g_error_free (erreur);
358 erreur = NULL;
359 g_object_unref (dbus_proxy_Device_prop);
360 continue;
361 }
362 if (!pAccessPoints || pAccessPoints->len == 0)
363 {
364 cd_debug (" aucun point d'acces\n");
365 g_object_unref (dbus_proxy_Device_prop);
366 /// ajouter une entree pour dire si le wifi est desactive ...
367
368 continue;
369 }
370
371 // on insere chaque point d'acces dans le menu.
372 for (j = 0; j < pAccessPoints->len; j ++)
373 {
374 // on recupere le point d'acces.
375 cAccessPointPath = (gchar *)g_ptr_array_index (pAccessPoints, j);
376 dbus_proxy_AccessPoint_prop = cairo_dock_create_new_system_proxy (
377 "org.freedesktop.NetworkManager",
378 cAccessPointPath,
379 "org.freedesktop.DBus.Properties");
380
381 // on recupere ses proprietes.
382 hProperties = cairo_dock_dbus_get_all_properties (dbus_proxy_AccessPoint_prop, "org.freedesktop.NetworkManager.AccessPoint");
383 if (hProperties == NULL)
384 {
385 g_object_unref (dbus_proxy_AccessPoint_prop);
386 continue;
387 }
388
389 iPercent = 0;
390 v = (GValue *)g_hash_table_lookup (hProperties, "Strength");
391 if (v != NULL && G_VALUE_HOLDS_UCHAR (v))
392 {
393 iPercent = g_value_get_uchar (v);
394 }
395
396 v = (GValue *)g_hash_table_lookup (hProperties, "Ssid");
397 if (v != NULL && G_VALUE_HOLDS_BOXED (v))
398 {
399 GByteArray *a = g_value_get_boxed (v);
400 cSsid = g_strndup ((gchar *) a->data, a->len);
401 }
402
403 // on empeche les doublons.
404 pItemData = (cSsid ? g_hash_table_lookup (pSsidTable, cSsid) : NULL);
405 if (pItemData != NULL)
406 {
407 if (pItemData->iPercent > iPercent)
408 {
409 g_free (cSsid);
410 g_object_unref (dbus_proxy_AccessPoint_prop);
411 }
412 else
413 {
414 g_free (pItemData->cAccessPoint);
415 pItemData->cAccessPoint = g_strdup (cAccessPointPath);
416 }
417 continue;
418 }
419
420 cHwAddress = NULL;
421 v = (GValue *)g_hash_table_lookup (hProperties, "HwAddress");
422 if (v != NULL && G_VALUE_HOLDS_STRING (v))
423 {
424 cHwAddress = g_value_get_string (v);
425 }
426
427 iMode = 0;
428 v = (GValue *)g_hash_table_lookup (hProperties, "Mode");
429 if (v != NULL && G_VALUE_HOLDS_UINT (v))
430 {
431 iMode = g_value_get_uint (v);
432 }
433
434 iWirelessCapabilities = 0;
435 v = (GValue *)g_hash_table_lookup (hProperties, "WpaFlags");
436 if (v != NULL && G_VALUE_HOLDS_UINT (v))
437 {
438 iWirelessCapabilities = g_value_get_uint (v);
439 }
440
441 cd_debug ("%d) %s : %s (%s, %d%%)", j, cSsid, cAccessPointPath, cHwAddress, iPercent);
442
443 const gchar *cImage = NULL;
444 if (iPercent > 80)
445 cImage = MY_APPLET_SHARE_DATA_DIR"/link-5.svg";
446 else if (iPercent > 60)
447 cImage = MY_APPLET_SHARE_DATA_DIR"/link-4.svg";
448 else if (iPercent > 40)
449 cImage = MY_APPLET_SHARE_DATA_DIR"/link-3.svg";
450 else if (iPercent > 20)
451 cImage = MY_APPLET_SHARE_DATA_DIR"/link-2.svg";
452 else if (iPercent > 0)
453 cImage = MY_APPLET_SHARE_DATA_DIR"/link-1.svg";
454 else
455 cImage = MY_APPLET_SHARE_DATA_DIR"/link-0.svg";
456
457 /// recuperer les flags, wpa flags, et rsn flags -> encrypted.
458 /// et le mode -> ad_hoc
459 /// et mettre une icone asociee dans une hbox...
460
461 // on cherche une connection qui convienne.
462 GList *pConnList = cd_NetworkMonitor_get_connections_for_access_point (cAccessPointPath, cDevice, cSsid, cHwAddress, iMode, iWirelessCapabilities, paConnections, paSettings);
463
464 cd_debug ("%d connexion(s) satisfont a ce point d'acces", g_list_length (pConnList));
465
466 if (pConnList == NULL || pConnList->next == NULL)
467 {
468 if (pItemData == NULL)
469 {
470 pItemData = g_new0 (CDMenuItemData, 1);
471 g_hash_table_insert (pSsidTable, g_strdup (cSsid), pItemData);
472 }
473 else
474 {
475 g_free (pItemData->cAccessPoint);
476 }
477 pItemData->cDevice = g_strdup (cDevice);
478 pItemData->iPercent = iPercent;
479 pItemData->cAccessPoint = g_strdup (cAccessPointPath);
480 pItemData->cSsid = g_strdup (cSsid);
481 if (pConnList)
482 {
483 int n = GPOINTER_TO_INT (pConnList->data);
484 pItemData->cConnection = g_strdup (g_ptr_array_index (paConnections, n));
485 }
486 cairo_dock_add_in_menu_with_stock_and_data (cSsid, cImage, G_CALLBACK (_on_select_access_point), pMenu, pItemData);
487 }
488 else
489 {
490 GtkWidget *pSubMenu = cairo_dock_create_sub_menu (cSsid, pMenu, cImage);
491 GList *c;
492 for (c = pConnList; c != NULL; c = c->next)
493 {
494 int n = GPOINTER_TO_INT (c->data);
495 GHashTable *h = g_ptr_array_index (paSettings, n);
496 if (!h)
497 continue;
498 GHashTable *hh = g_hash_table_lookup (h, "connection");
499 if (!hh)
500 continue;
501 v = g_hash_table_lookup (hh, "id");
502 if (v && G_VALUE_HOLDS_STRING (v))
503 {
504 const gchar *cID = g_value_get_string (v);
505
506 pItemData = g_new0 (CDMenuItemData, 1);
507 pItemData->cConnection = g_strdup (g_ptr_array_index (paConnections, n));
508 pItemData->cDevice = g_strdup (cDevice);
509 pItemData->cAccessPoint = g_strdup (cAccessPointPath);
510
511 cairo_dock_add_in_menu_with_stock_and_data (cID, NULL, G_CALLBACK (_on_select_access_point), pSubMenu, GINT_TO_POINTER (n));
512 }
513 }
514 }
515 g_list_free (pConnList);
516
517 g_object_unref (dbus_proxy_AccessPoint_prop);
518 }
519 g_ptr_array_free (pAccessPoints, TRUE);
520 }
521 else
522 {
523 /// si non connecte : ajouter une entree grisee.
524
525 /// sinon ajouter une entree pour (des)activer ce device.
526
527 }
528 }
529 g_ptr_array_free (paDevices, TRUE);
530 g_ptr_array_free (paConnections, TRUE);
531 g_hash_table_destroy (pSsidTable);
532
533 return pMenu;
534 }
535