Line |
Branch |
Exec |
Source |
1 |
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
2 |
|
|
* |
3 |
|
|
* Copyright (C) 2012 Red Hat, Inc |
4 |
|
|
* |
5 |
|
|
* Licensed under the GNU General Public License Version 2 |
6 |
|
|
* |
7 |
|
|
* This program is free software; you can redistribute it and/or modify |
8 |
|
|
* it under the terms of the GNU General Public License as published by |
9 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
10 |
|
|
* (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 |
|
|
* |
17 |
|
|
* You should have received a copy of the GNU General Public License |
18 |
|
|
* along with this program; if not, write to the Free Software |
19 |
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20 |
|
|
*/ |
21 |
|
|
|
22 |
|
|
#include "config.h" |
23 |
|
|
|
24 |
|
|
#include <glib-object.h> |
25 |
|
|
#include <glib/gi18n.h> |
26 |
|
|
|
27 |
|
|
#include <NetworkManager.h> |
28 |
|
|
|
29 |
|
|
#include "net-connection-editor.h" |
30 |
|
|
#include "net-connection-editor-resources.h" |
31 |
|
|
#include "ce-page.h" |
32 |
|
|
#include "ce-page-details.h" |
33 |
|
|
#include "ce-page-wifi.h" |
34 |
|
|
#include "ce-page-ip4.h" |
35 |
|
|
#include "ce-page-ip6.h" |
36 |
|
|
#include "ce-page-security.h" |
37 |
|
|
#include "ce-page-ethernet.h" |
38 |
|
|
#include "ce-page-bluetooth.h" |
39 |
|
|
#include "ce-page-8021x-security.h" |
40 |
|
|
#include "ce-page-vpn.h" |
41 |
|
|
#include "ce-page-wireguard.h" |
42 |
|
|
#include "vpn-helpers.h" |
43 |
|
|
|
44 |
|
|
enum { |
45 |
|
|
DONE, |
46 |
|
|
LAST_SIGNAL |
47 |
|
|
}; |
48 |
|
|
|
49 |
|
|
static guint signals[LAST_SIGNAL] = { 0 }; |
50 |
|
|
|
51 |
|
|
struct _NetConnectionEditor |
52 |
|
|
{ |
53 |
|
|
AdwWindow parent; |
54 |
|
|
|
55 |
|
|
GtkBox *add_connection_box; |
56 |
|
|
AdwBin *add_connection_frame; |
57 |
|
|
GtkButton *apply_button; |
58 |
|
|
GtkButton *cancel_button; |
59 |
|
|
GtkNotebook *notebook; |
60 |
|
|
AdwToastOverlay *toast_overlay; |
61 |
|
|
GtkStack *toplevel_stack; |
62 |
|
|
|
63 |
|
|
NMClient *client; |
64 |
|
|
NMDevice *device; |
65 |
|
|
|
66 |
|
|
NMConnection *connection; |
67 |
|
|
NMConnection *orig_connection; |
68 |
|
|
gboolean is_new_connection; |
69 |
|
|
gboolean is_changed; |
70 |
|
|
NMAccessPoint *ap; |
71 |
|
|
GCancellable *cancellable; |
72 |
|
|
|
73 |
|
|
GSList *initializing_pages; |
74 |
|
|
|
75 |
|
|
NMClientPermissionResult can_modify; |
76 |
|
|
|
77 |
|
|
gboolean title_set; |
78 |
|
|
}; |
79 |
|
|
|
80 |
|
✗ |
G_DEFINE_TYPE (NetConnectionEditor, net_connection_editor, ADW_TYPE_WINDOW) |
81 |
|
|
|
82 |
|
|
/* Used as both GSettings keys and GObject data tags */ |
83 |
|
|
#define IGNORE_CA_CERT_TAG "ignore-ca-cert" |
84 |
|
|
#define IGNORE_PHASE2_CA_CERT_TAG "ignore-phase2-ca-cert" |
85 |
|
|
|
86 |
|
|
static GSettings * |
87 |
|
✗ |
_get_ca_ignore_settings (NMConnection *connection) |
88 |
|
|
{ |
89 |
|
|
GSettings *settings; |
90 |
|
✗ |
g_autofree gchar *path = NULL; |
91 |
|
|
const char *uuid; |
92 |
|
|
|
93 |
|
✗ |
g_return_val_if_fail (connection, NULL); |
94 |
|
|
|
95 |
|
✗ |
uuid = nm_connection_get_uuid (connection); |
96 |
|
✗ |
g_return_val_if_fail (uuid && *uuid, NULL); |
97 |
|
|
|
98 |
|
✗ |
path = g_strdup_printf ("/org/gnome/nm-applet/eap/%s/", uuid); |
99 |
|
✗ |
settings = g_settings_new_with_path ("org.gnome.nm-applet.eap", path); |
100 |
|
|
|
101 |
|
✗ |
return settings; |
102 |
|
|
} |
103 |
|
|
|
104 |
|
|
/** |
105 |
|
|
* eap_method_ca_cert_ignore_save: |
106 |
|
|
* @connection: the connection for which to save CA cert ignore values to GSettings |
107 |
|
|
* |
108 |
|
|
* Reads the CA cert ignore tags from the 802.1x setting GObject data and saves |
109 |
|
|
* then to GSettings if present, using the connection UUID as the index. |
110 |
|
|
*/ |
111 |
|
|
static void |
112 |
|
✗ |
eap_method_ca_cert_ignore_save (NMConnection *connection) |
113 |
|
|
{ |
114 |
|
|
NMSetting8021x *s_8021x; |
115 |
|
✗ |
g_autoptr(GSettings) settings = NULL; |
116 |
|
✗ |
gboolean ignore = FALSE, phase2_ignore = FALSE; |
117 |
|
|
|
118 |
|
✗ |
g_return_if_fail (connection); |
119 |
|
|
|
120 |
|
✗ |
s_8021x = nm_connection_get_setting_802_1x (connection); |
121 |
|
✗ |
if (s_8021x) { |
122 |
|
✗ |
ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_CA_CERT_TAG); |
123 |
|
✗ |
phase2_ignore = !!g_object_get_data (G_OBJECT (s_8021x), IGNORE_PHASE2_CA_CERT_TAG); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
✗ |
settings = _get_ca_ignore_settings (connection); |
127 |
|
✗ |
if (!settings) |
128 |
|
✗ |
return; |
129 |
|
|
|
130 |
|
✗ |
g_settings_set_boolean (settings, IGNORE_CA_CERT_TAG, ignore); |
131 |
|
✗ |
g_settings_set_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG, phase2_ignore); |
132 |
|
|
} |
133 |
|
|
|
134 |
|
|
/** |
135 |
|
|
* eap_method_ca_cert_ignore_load: |
136 |
|
|
* @connection: the connection for which to load CA cert ignore values to GSettings |
137 |
|
|
* |
138 |
|
|
* Reads the CA cert ignore tags from the 802.1x setting GObject data and saves |
139 |
|
|
* then to GSettings if present, using the connection UUID as the index. |
140 |
|
|
*/ |
141 |
|
|
static void |
142 |
|
✗ |
eap_method_ca_cert_ignore_load (NMConnection *connection) |
143 |
|
|
{ |
144 |
|
✗ |
g_autoptr(GSettings) settings = NULL; |
145 |
|
|
NMSetting8021x *s_8021x; |
146 |
|
|
gboolean ignore, phase2_ignore; |
147 |
|
|
|
148 |
|
✗ |
g_return_if_fail (connection); |
149 |
|
|
|
150 |
|
✗ |
s_8021x = nm_connection_get_setting_802_1x (connection); |
151 |
|
✗ |
if (!s_8021x) |
152 |
|
✗ |
return; |
153 |
|
|
|
154 |
|
✗ |
settings = _get_ca_ignore_settings (connection); |
155 |
|
✗ |
if (!settings) |
156 |
|
✗ |
return; |
157 |
|
|
|
158 |
|
✗ |
ignore = g_settings_get_boolean (settings, IGNORE_CA_CERT_TAG); |
159 |
|
✗ |
phase2_ignore = g_settings_get_boolean (settings, IGNORE_PHASE2_CA_CERT_TAG); |
160 |
|
|
|
161 |
|
✗ |
g_object_set_data (G_OBJECT (s_8021x), |
162 |
|
|
IGNORE_CA_CERT_TAG, |
163 |
|
✗ |
GUINT_TO_POINTER (ignore)); |
164 |
|
✗ |
g_object_set_data (G_OBJECT (s_8021x), |
165 |
|
|
IGNORE_PHASE2_CA_CERT_TAG, |
166 |
|
✗ |
GUINT_TO_POINTER (phase2_ignore)); |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
static void page_changed (NetConnectionEditor *self); |
170 |
|
|
|
171 |
|
|
static void |
172 |
|
✗ |
cancel_editing (NetConnectionEditor *self) |
173 |
|
|
{ |
174 |
|
✗ |
g_signal_emit (self, signals[DONE], 0, FALSE); |
175 |
|
✗ |
gtk_window_destroy (GTK_WINDOW (self)); |
176 |
|
✗ |
} |
177 |
|
|
|
178 |
|
|
static gboolean |
179 |
|
✗ |
net_connection_editor_close_request (GtkWindow *window) |
180 |
|
|
{ |
181 |
|
✗ |
cancel_editing (NET_CONNECTION_EDITOR (window)); |
182 |
|
|
|
183 |
|
✗ |
return GTK_WINDOW_CLASS (net_connection_editor_parent_class)->close_request (window); |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
static void |
187 |
|
✗ |
cancel_clicked_cb (NetConnectionEditor *self) |
188 |
|
|
{ |
189 |
|
✗ |
cancel_editing (self); |
190 |
|
✗ |
} |
191 |
|
|
|
192 |
|
|
static void |
193 |
|
✗ |
update_connection (NetConnectionEditor *self) |
194 |
|
|
{ |
195 |
|
✗ |
g_autoptr(GVariant) settings = NULL; |
196 |
|
|
|
197 |
|
✗ |
settings = nm_connection_to_dbus (self->connection, NM_CONNECTION_SERIALIZE_ALL); |
198 |
|
✗ |
nm_connection_replace_settings (self->orig_connection, settings, NULL); |
199 |
|
✗ |
} |
200 |
|
|
|
201 |
|
|
static void |
202 |
|
✗ |
update_complete (NetConnectionEditor *self, |
203 |
|
|
gboolean success) |
204 |
|
|
{ |
205 |
|
✗ |
g_signal_emit (self, signals[DONE], 0, success); |
206 |
|
✗ |
gtk_window_destroy (GTK_WINDOW (self)); |
207 |
|
✗ |
} |
208 |
|
|
|
209 |
|
|
static void |
210 |
|
✗ |
device_reapply_cb (GObject *source_object, |
211 |
|
|
GAsyncResult *res, |
212 |
|
|
gpointer user_data) |
213 |
|
|
{ |
214 |
|
✗ |
NetConnectionEditor *self = user_data; |
215 |
|
✗ |
g_autoptr(GError) error = NULL; |
216 |
|
✗ |
gboolean success = TRUE; |
217 |
|
|
|
218 |
|
✗ |
if (!nm_device_reapply_finish (NM_DEVICE (source_object), res, &error)) { |
219 |
|
✗ |
if (!g_error_matches (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE)) |
220 |
|
✗ |
g_warning ("Failed to reapply changes on device: %s", error->message); |
221 |
|
✗ |
success = FALSE; |
222 |
|
|
} |
223 |
|
|
|
224 |
|
✗ |
update_complete (self, success); |
225 |
|
✗ |
g_object_unref (self); |
226 |
|
✗ |
} |
227 |
|
|
|
228 |
|
|
static void |
229 |
|
✗ |
updated_connection_cb (GObject *source_object, |
230 |
|
|
GAsyncResult *res, |
231 |
|
|
gpointer user_data) |
232 |
|
|
{ |
233 |
|
✗ |
NetConnectionEditor *self = user_data; |
234 |
|
✗ |
g_autoptr(GError) error = NULL; |
235 |
|
|
|
236 |
|
✗ |
if (!nm_remote_connection_commit_changes_finish (NM_REMOTE_CONNECTION (source_object), |
237 |
|
|
res, &error)) { |
238 |
|
✗ |
g_warning ("Failed to commit changes: %s", error->message); |
239 |
|
✗ |
update_complete (self, FALSE); |
240 |
|
✗ |
g_object_unref (self); |
241 |
|
✗ |
return; |
242 |
|
|
} |
243 |
|
|
|
244 |
|
✗ |
nm_connection_clear_secrets (NM_CONNECTION (source_object)); |
245 |
|
|
|
246 |
|
✗ |
if (!self->device) { |
247 |
|
✗ |
update_complete (self, TRUE); |
248 |
|
✗ |
g_object_unref (self); |
249 |
|
✗ |
return; |
250 |
|
|
} |
251 |
|
|
|
252 |
|
✗ |
nm_device_reapply_async (self->device, NM_CONNECTION (self->orig_connection), |
253 |
|
|
0, 0, NULL, device_reapply_cb, self /* owned */); |
254 |
|
|
} |
255 |
|
|
|
256 |
|
|
static void |
257 |
|
✗ |
added_connection_cb (GObject *source_object, |
258 |
|
|
GAsyncResult *res, |
259 |
|
|
gpointer user_data) |
260 |
|
|
{ |
261 |
|
✗ |
NetConnectionEditor *self = user_data; |
262 |
|
✗ |
g_autoptr(GError) error = NULL; |
263 |
|
|
|
264 |
|
✗ |
if (!nm_client_add_connection_finish (NM_CLIENT (source_object), res, &error)) { |
265 |
|
✗ |
g_warning ("Failed to add connection: %s", error->message); |
266 |
|
✗ |
update_complete (self, FALSE); |
267 |
|
✗ |
g_object_unref (self); |
268 |
|
✗ |
return; |
269 |
|
|
} |
270 |
|
|
|
271 |
|
✗ |
if (!self->device) { |
272 |
|
✗ |
update_complete (self, TRUE); |
273 |
|
✗ |
g_object_unref (self); |
274 |
|
✗ |
return; |
275 |
|
|
} |
276 |
|
|
|
277 |
|
✗ |
nm_device_reapply_async (self->device, NM_CONNECTION (self->orig_connection), |
278 |
|
|
0, 0, NULL, device_reapply_cb, self /* owned */); |
279 |
|
|
} |
280 |
|
|
|
281 |
|
|
static void |
282 |
|
✗ |
apply_clicked_cb (NetConnectionEditor *self) |
283 |
|
|
{ |
284 |
|
✗ |
update_connection (self); |
285 |
|
|
|
286 |
|
✗ |
eap_method_ca_cert_ignore_save (self->connection); |
287 |
|
|
|
288 |
|
✗ |
if (self->is_new_connection) { |
289 |
|
✗ |
nm_client_add_connection_async (self->client, |
290 |
|
|
self->orig_connection, |
291 |
|
|
TRUE, |
292 |
|
|
NULL, |
293 |
|
|
added_connection_cb, |
294 |
|
|
g_object_ref (self)); |
295 |
|
|
} else { |
296 |
|
✗ |
nm_remote_connection_commit_changes_async (NM_REMOTE_CONNECTION (self->orig_connection), |
297 |
|
|
TRUE, |
298 |
|
|
NULL, |
299 |
|
|
updated_connection_cb, |
300 |
|
|
g_object_ref (self)); |
301 |
|
|
} |
302 |
|
|
|
303 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self), FALSE); |
304 |
|
✗ |
} |
305 |
|
|
|
306 |
|
|
static void |
307 |
|
✗ |
net_connection_editor_init (NetConnectionEditor *self) |
308 |
|
|
{ |
309 |
|
✗ |
gtk_widget_init_template (GTK_WIDGET (self)); |
310 |
|
✗ |
} |
311 |
|
|
|
312 |
|
|
static void |
313 |
|
✗ |
net_connection_editor_finalize (GObject *object) |
314 |
|
|
{ |
315 |
|
✗ |
NetConnectionEditor *self = NET_CONNECTION_EDITOR (object); |
316 |
|
|
|
317 |
|
✗ |
g_clear_object (&self->connection); |
318 |
|
✗ |
g_clear_object (&self->orig_connection); |
319 |
|
✗ |
g_clear_object (&self->device); |
320 |
|
✗ |
g_clear_object (&self->client); |
321 |
|
✗ |
g_clear_object (&self->ap); |
322 |
|
✗ |
g_cancellable_cancel (self->cancellable); |
323 |
|
✗ |
g_clear_object (&self->cancellable); |
324 |
|
|
|
325 |
|
✗ |
G_OBJECT_CLASS (net_connection_editor_parent_class)->finalize (object); |
326 |
|
✗ |
} |
327 |
|
|
|
328 |
|
|
static void |
329 |
|
✗ |
net_connection_editor_class_init (NetConnectionEditorClass *class) |
330 |
|
|
{ |
331 |
|
✗ |
GObjectClass *object_class = G_OBJECT_CLASS (class); |
332 |
|
✗ |
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); |
333 |
|
✗ |
GtkWindowClass *window_class = GTK_WINDOW_CLASS (class); |
334 |
|
|
|
335 |
|
✗ |
g_resources_register (net_connection_editor_get_resource ()); |
336 |
|
|
|
337 |
|
✗ |
object_class->finalize = net_connection_editor_finalize; |
338 |
|
|
|
339 |
|
✗ |
window_class->close_request = net_connection_editor_close_request; |
340 |
|
|
|
341 |
|
✗ |
signals[DONE] = g_signal_new ("done", |
342 |
|
|
G_OBJECT_CLASS_TYPE (object_class), |
343 |
|
|
G_SIGNAL_RUN_FIRST, |
344 |
|
|
0, |
345 |
|
|
NULL, NULL, |
346 |
|
|
NULL, |
347 |
|
|
G_TYPE_NONE, 1, G_TYPE_BOOLEAN); |
348 |
|
|
|
349 |
|
✗ |
gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "window.close", NULL); |
350 |
|
|
|
351 |
|
✗ |
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/connection-editor.ui"); |
352 |
|
|
|
353 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, add_connection_box); |
354 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, add_connection_frame); |
355 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, apply_button); |
356 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, cancel_button); |
357 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, notebook); |
358 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, toast_overlay); |
359 |
|
✗ |
gtk_widget_class_bind_template_child (widget_class, NetConnectionEditor, toplevel_stack); |
360 |
|
|
|
361 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, cancel_clicked_cb); |
362 |
|
✗ |
gtk_widget_class_bind_template_callback (widget_class, apply_clicked_cb); |
363 |
|
✗ |
} |
364 |
|
|
|
365 |
|
|
static void |
366 |
|
✗ |
nm_connection_editor_watch_cb (GPid pid, |
367 |
|
|
gint status, |
368 |
|
|
gpointer user_data) |
369 |
|
|
{ |
370 |
|
✗ |
g_debug ("Child %d" G_PID_FORMAT " exited %s", pid, |
371 |
|
|
g_spawn_check_wait_status (status, NULL) ? "normally" : "abnormally"); |
372 |
|
|
|
373 |
|
✗ |
g_spawn_close_pid (pid); |
374 |
|
|
/* Close the dialog when nm-connection-editor exits. */ |
375 |
|
✗ |
gtk_window_destroy (GTK_WINDOW (user_data)); |
376 |
|
✗ |
} |
377 |
|
|
|
378 |
|
|
static void |
379 |
|
✗ |
net_connection_editor_do_fallback (NetConnectionEditor *self, const gchar *type) |
380 |
|
|
{ |
381 |
|
✗ |
g_autoptr(GError) error = NULL; |
382 |
|
✗ |
g_autoptr(GStrvBuilder) builder = NULL; |
383 |
|
✗ |
g_auto(GStrv) argv = NULL; |
384 |
|
|
GPid child_pid; |
385 |
|
|
|
386 |
|
✗ |
builder = g_strv_builder_new (); |
387 |
|
✗ |
g_strv_builder_add (builder, "nm-connection-editor"); |
388 |
|
|
|
389 |
|
✗ |
if (self->is_new_connection) { |
390 |
|
✗ |
g_autofree gchar *type_str = NULL; |
391 |
|
|
|
392 |
|
✗ |
type_str = g_strdup_printf ("--type=%s", type); |
393 |
|
✗ |
g_strv_builder_add (builder, type_str); |
394 |
|
✗ |
g_strv_builder_add (builder, "--create"); |
395 |
|
|
} else { |
396 |
|
✗ |
g_autofree gchar *edit_str = NULL; |
397 |
|
|
|
398 |
|
✗ |
edit_str = g_strdup_printf ("--edit=%s", nm_connection_get_uuid (self->connection)); |
399 |
|
✗ |
g_strv_builder_add (builder, edit_str); |
400 |
|
|
} |
401 |
|
|
|
402 |
|
✗ |
g_strv_builder_add (builder, NULL); |
403 |
|
✗ |
argv = g_strv_builder_end (builder); |
404 |
|
|
|
405 |
|
✗ |
g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, |
406 |
|
|
NULL, NULL, &child_pid, NULL, NULL, NULL, &error); |
407 |
|
|
|
408 |
|
✗ |
if (error) { |
409 |
|
|
AdwToast *toast; |
410 |
|
✗ |
g_autofree gchar *message = NULL; |
411 |
|
|
|
412 |
|
✗ |
message = g_strdup_printf (_("Unable to open connection editor: %s"), error->message); |
413 |
|
✗ |
toast = adw_toast_new (message); |
414 |
|
|
|
415 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, toast); |
416 |
|
|
} else { |
417 |
|
✗ |
g_child_watch_add (child_pid, nm_connection_editor_watch_cb, self); |
418 |
|
|
} |
419 |
|
|
|
420 |
|
✗ |
g_signal_emit (self, signals[DONE], 0, FALSE); |
421 |
|
✗ |
} |
422 |
|
|
|
423 |
|
|
static void |
424 |
|
✗ |
net_connection_editor_update_title (NetConnectionEditor *self) |
425 |
|
|
{ |
426 |
|
✗ |
g_autofree gchar *id = NULL; |
427 |
|
|
|
428 |
|
✗ |
if (self->title_set) |
429 |
|
✗ |
return; |
430 |
|
|
|
431 |
|
✗ |
if (self->is_new_connection) { |
432 |
|
✗ |
if (self->device) { |
433 |
|
✗ |
id = g_strdup (_("New Profile")); |
434 |
|
|
} else { |
435 |
|
|
/* Leave it set to "Add New Connection" */ |
436 |
|
✗ |
return; |
437 |
|
|
} |
438 |
|
|
} else { |
439 |
|
|
NMSettingWireless *sw; |
440 |
|
✗ |
sw = nm_connection_get_setting_wireless (self->connection); |
441 |
|
✗ |
if (sw) { |
442 |
|
|
GBytes *ssid; |
443 |
|
✗ |
ssid = nm_setting_wireless_get_ssid (sw); |
444 |
|
✗ |
id = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); |
445 |
|
|
} else { |
446 |
|
✗ |
id = g_strdup (nm_connection_get_id (self->connection)); |
447 |
|
|
} |
448 |
|
|
} |
449 |
|
✗ |
gtk_window_set_title (GTK_WINDOW (self), id); |
450 |
|
|
} |
451 |
|
|
|
452 |
|
|
static gboolean |
453 |
|
✗ |
editor_is_initialized (NetConnectionEditor *self) |
454 |
|
|
{ |
455 |
|
✗ |
return self->initializing_pages == NULL; |
456 |
|
|
} |
457 |
|
|
|
458 |
|
|
static void |
459 |
|
✗ |
update_sensitivity (NetConnectionEditor *self) |
460 |
|
|
{ |
461 |
|
|
NMSettingConnection *sc; |
462 |
|
|
gboolean sensitive; |
463 |
|
|
gint i; |
464 |
|
|
|
465 |
|
✗ |
if (!editor_is_initialized (self)) |
466 |
|
✗ |
return; |
467 |
|
|
|
468 |
|
✗ |
sc = nm_connection_get_setting_connection (self->connection); |
469 |
|
|
|
470 |
|
✗ |
if (nm_setting_connection_get_read_only (sc)) { |
471 |
|
✗ |
sensitive = FALSE; |
472 |
|
|
} else { |
473 |
|
✗ |
sensitive = self->can_modify; |
474 |
|
|
} |
475 |
|
|
|
476 |
|
✗ |
for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) { |
477 |
|
✗ |
GtkWidget *page = gtk_notebook_get_nth_page (self->notebook, i); |
478 |
|
✗ |
gtk_widget_set_sensitive (page, sensitive); |
479 |
|
|
} |
480 |
|
|
} |
481 |
|
|
|
482 |
|
|
static void |
483 |
|
✗ |
validate (NetConnectionEditor *self) |
484 |
|
|
{ |
485 |
|
✗ |
gboolean valid = FALSE; |
486 |
|
✗ |
g_autofree gchar *apply_tooltip = NULL; |
487 |
|
|
gint i; |
488 |
|
|
|
489 |
|
✗ |
if (!editor_is_initialized (self)) |
490 |
|
✗ |
goto done; |
491 |
|
|
|
492 |
|
✗ |
valid = TRUE; |
493 |
|
✗ |
for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) { |
494 |
|
✗ |
CEPage *page = CE_PAGE (gtk_notebook_get_nth_page (self->notebook, i)); |
495 |
|
✗ |
g_autoptr(GError) error = NULL; |
496 |
|
|
|
497 |
|
✗ |
if (!ce_page_validate (page, self->connection, &error)) { |
498 |
|
✗ |
valid = FALSE; |
499 |
|
✗ |
if (error) { |
500 |
|
✗ |
apply_tooltip = g_strdup_printf (_("Invalid setting %s: %s"), ce_page_get_title (page), error->message); |
501 |
|
✗ |
g_debug ("%s", apply_tooltip); |
502 |
|
|
} else { |
503 |
|
✗ |
apply_tooltip = g_strdup_printf (_("Invalid setting %s"), ce_page_get_title (page)); |
504 |
|
✗ |
g_debug ("%s", apply_tooltip); |
505 |
|
|
} |
506 |
|
|
} |
507 |
|
|
} |
508 |
|
|
|
509 |
|
✗ |
update_sensitivity (self); |
510 |
|
✗ |
done: |
511 |
|
✗ |
if (apply_tooltip != NULL) |
512 |
|
✗ |
gtk_widget_set_tooltip_text(GTK_WIDGET (self->apply_button), apply_tooltip); |
513 |
|
|
|
514 |
|
✗ |
gtk_widget_set_sensitive (GTK_WIDGET (self->apply_button), valid && self->is_changed); |
515 |
|
✗ |
} |
516 |
|
|
|
517 |
|
|
static void |
518 |
|
✗ |
page_changed (NetConnectionEditor *self) |
519 |
|
|
{ |
520 |
|
✗ |
if (editor_is_initialized (self)) |
521 |
|
✗ |
self->is_changed = TRUE; |
522 |
|
✗ |
validate (self); |
523 |
|
✗ |
} |
524 |
|
|
|
525 |
|
|
static gboolean |
526 |
|
✗ |
idle_validate (gpointer user_data) |
527 |
|
|
{ |
528 |
|
✗ |
validate (NET_CONNECTION_EDITOR (user_data)); |
529 |
|
|
|
530 |
|
✗ |
return G_SOURCE_REMOVE; |
531 |
|
|
} |
532 |
|
|
|
533 |
|
|
static void |
534 |
|
✗ |
recheck_initialization (NetConnectionEditor *self) |
535 |
|
|
{ |
536 |
|
✗ |
if (!editor_is_initialized (self)) |
537 |
|
✗ |
return; |
538 |
|
|
|
539 |
|
✗ |
gtk_stack_set_visible_child (self->toplevel_stack, GTK_WIDGET (self->notebook)); |
540 |
|
✗ |
gtk_notebook_set_current_page (self->notebook, 0); |
541 |
|
|
|
542 |
|
✗ |
g_idle_add (idle_validate, self); |
543 |
|
|
|
544 |
|
✗ |
if (self->is_new_connection) |
545 |
|
✗ |
adw_bin_set_child (self->add_connection_frame, NULL); |
546 |
|
|
|
547 |
|
|
} |
548 |
|
|
|
549 |
|
|
static void |
550 |
|
✗ |
page_initialized (NetConnectionEditor *self, GError *error, CEPage *page) |
551 |
|
|
{ |
552 |
|
|
GtkWidget *label; |
553 |
|
|
gint position; |
554 |
|
|
gint i; |
555 |
|
|
|
556 |
|
✗ |
position = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position")); |
557 |
|
✗ |
g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position)); |
558 |
|
✗ |
for (i = 0; i < gtk_notebook_get_n_pages (self->notebook); i++) { |
559 |
|
✗ |
GtkWidget *page = gtk_notebook_get_nth_page (self->notebook, i); |
560 |
|
✗ |
gint pos = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page), "position")); |
561 |
|
✗ |
if (pos > position) |
562 |
|
✗ |
break; |
563 |
|
|
} |
564 |
|
|
|
565 |
|
✗ |
label = gtk_label_new (ce_page_get_title (page)); |
566 |
|
|
|
567 |
|
✗ |
gtk_notebook_insert_page (self->notebook, GTK_WIDGET (page), label, i); |
568 |
|
|
|
569 |
|
✗ |
self->initializing_pages = g_slist_remove (self->initializing_pages, page); |
570 |
|
|
|
571 |
|
✗ |
recheck_initialization (self); |
572 |
|
✗ |
} |
573 |
|
|
|
574 |
|
|
typedef struct { |
575 |
|
|
NetConnectionEditor *editor; |
576 |
|
|
CEPage *page; |
577 |
|
|
const gchar *setting_name; |
578 |
|
|
} GetSecretsInfo; |
579 |
|
|
|
580 |
|
|
static void |
581 |
|
✗ |
get_secrets_cb (GObject *source_object, |
582 |
|
|
GAsyncResult *res, |
583 |
|
|
gpointer user_data) |
584 |
|
|
{ |
585 |
|
|
NMRemoteConnection *connection; |
586 |
|
✗ |
g_autofree GetSecretsInfo *info = user_data; |
587 |
|
✗ |
g_autoptr(GError) error = NULL; |
588 |
|
✗ |
g_autoptr(GVariant) variant = NULL; |
589 |
|
|
|
590 |
|
✗ |
connection = NM_REMOTE_CONNECTION (source_object); |
591 |
|
✗ |
variant = nm_remote_connection_get_secrets_finish (connection, res, &error); |
592 |
|
|
|
593 |
|
✗ |
if (!variant) { |
594 |
|
✗ |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
595 |
|
✗ |
return; |
596 |
|
|
|
597 |
|
✗ |
g_warning ("Failed to get secrets: %s", error->message); |
598 |
|
|
} |
599 |
|
|
|
600 |
|
✗ |
ce_page_complete_init (info->page, info->editor->connection, info->setting_name, variant, g_steal_pointer (&error)); |
601 |
|
|
} |
602 |
|
|
|
603 |
|
|
static void |
604 |
|
✗ |
get_secrets_for_page (NetConnectionEditor *self, |
605 |
|
|
CEPage *page, |
606 |
|
|
const gchar *setting_name) |
607 |
|
|
{ |
608 |
|
|
GetSecretsInfo *info; |
609 |
|
|
|
610 |
|
✗ |
info = g_new0 (GetSecretsInfo, 1); |
611 |
|
✗ |
info->editor = self; |
612 |
|
✗ |
info->page = page; |
613 |
|
✗ |
info->setting_name = setting_name; |
614 |
|
|
|
615 |
|
✗ |
nm_remote_connection_get_secrets_async (NM_REMOTE_CONNECTION (self->orig_connection), |
616 |
|
|
setting_name, |
617 |
|
|
self->cancellable, |
618 |
|
|
get_secrets_cb, |
619 |
|
|
info); |
620 |
|
✗ |
} |
621 |
|
|
|
622 |
|
|
static void |
623 |
|
✗ |
add_page (NetConnectionEditor *self, CEPage *page) |
624 |
|
|
{ |
625 |
|
|
gint position; |
626 |
|
|
|
627 |
|
✗ |
position = g_slist_length (self->initializing_pages); |
628 |
|
✗ |
g_object_set_data (G_OBJECT (page), "position", GINT_TO_POINTER (position)); |
629 |
|
|
|
630 |
|
✗ |
self->initializing_pages = g_slist_append (self->initializing_pages, page); |
631 |
|
|
|
632 |
|
✗ |
g_signal_connect_object (page, "changed", G_CALLBACK (page_changed), self, G_CONNECT_SWAPPED); |
633 |
|
✗ |
g_signal_connect_object (page, "initialized", G_CALLBACK (page_initialized), self, G_CONNECT_SWAPPED); |
634 |
|
✗ |
} |
635 |
|
|
|
636 |
|
|
static void |
637 |
|
✗ |
net_connection_editor_set_connection (NetConnectionEditor *self, |
638 |
|
|
NMConnection *connection) |
639 |
|
|
{ |
640 |
|
|
GSList *pages, *l; |
641 |
|
|
NMSettingConnection *sc; |
642 |
|
|
const gchar *type; |
643 |
|
|
gboolean is_wired; |
644 |
|
|
gboolean is_wifi; |
645 |
|
|
gboolean is_vpn; |
646 |
|
|
gboolean is_wireguard; |
647 |
|
|
gboolean is_bluetooth; |
648 |
|
|
|
649 |
|
✗ |
self->is_new_connection = !nm_client_get_connection_by_uuid (self->client, |
650 |
|
|
nm_connection_get_uuid (connection)); |
651 |
|
|
|
652 |
|
✗ |
if (self->is_new_connection) { |
653 |
|
✗ |
gtk_button_set_label (self->apply_button, _("_Add")); |
654 |
|
✗ |
self->is_changed = TRUE; |
655 |
|
|
} |
656 |
|
|
|
657 |
|
✗ |
self->connection = nm_simple_connection_new_clone (connection); |
658 |
|
✗ |
self->orig_connection = g_object_ref (connection); |
659 |
|
|
|
660 |
|
✗ |
net_connection_editor_update_title (self); |
661 |
|
|
|
662 |
|
✗ |
eap_method_ca_cert_ignore_load (self->connection); |
663 |
|
|
|
664 |
|
✗ |
sc = nm_connection_get_setting_connection (connection); |
665 |
|
✗ |
type = nm_setting_connection_get_connection_type (sc); |
666 |
|
|
|
667 |
|
✗ |
is_wired = g_str_equal (type, NM_SETTING_WIRED_SETTING_NAME); |
668 |
|
✗ |
is_wifi = g_str_equal (type, NM_SETTING_WIRELESS_SETTING_NAME); |
669 |
|
✗ |
is_vpn = g_str_equal (type, NM_SETTING_VPN_SETTING_NAME); |
670 |
|
✗ |
is_wireguard = g_str_equal (type, NM_SETTING_WIREGUARD_SETTING_NAME); |
671 |
|
✗ |
is_bluetooth = g_str_equal (type, NM_SETTING_BLUETOOTH_SETTING_NAME); |
672 |
|
|
|
673 |
|
✗ |
add_page (self, CE_PAGE (ce_page_details_new (self->connection, self->device, self->ap, self, self->is_new_connection))); |
674 |
|
|
|
675 |
|
✗ |
if (is_wifi) |
676 |
|
✗ |
add_page (self, CE_PAGE (ce_page_wifi_new (self->connection, self->client))); |
677 |
|
✗ |
else if (is_wired) |
678 |
|
✗ |
add_page (self, CE_PAGE (ce_page_ethernet_new (self->connection, self->client))); |
679 |
|
✗ |
else if (is_vpn) |
680 |
|
✗ |
add_page (self, CE_PAGE (ce_page_vpn_new (self->connection))); |
681 |
|
✗ |
else if (is_wireguard) |
682 |
|
✗ |
add_page (self, CE_PAGE (ce_page_wireguard_new (self->connection))); |
683 |
|
✗ |
else if (is_bluetooth) |
684 |
|
✗ |
add_page (self, CE_PAGE (ce_page_bluetooth_new (self->connection))); |
685 |
|
|
else { |
686 |
|
|
/* Unsupported type */ |
687 |
|
✗ |
net_connection_editor_do_fallback (self, type); |
688 |
|
✗ |
return; |
689 |
|
|
} |
690 |
|
|
|
691 |
|
✗ |
add_page (self, CE_PAGE (ce_page_ip4_new (self->connection, self->client))); |
692 |
|
✗ |
add_page (self, CE_PAGE (ce_page_ip6_new (self->connection, self->client))); |
693 |
|
|
|
694 |
|
✗ |
if (is_wifi) |
695 |
|
✗ |
add_page (self, CE_PAGE (ce_page_security_new (self->connection))); |
696 |
|
✗ |
else if (is_wired) |
697 |
|
✗ |
add_page (self, CE_PAGE (ce_page_8021x_security_new (self->connection))); |
698 |
|
|
|
699 |
|
✗ |
pages = g_slist_copy (self->initializing_pages); |
700 |
|
✗ |
for (l = pages; l; l = l->next) { |
701 |
|
✗ |
CEPage *page = l->data; |
702 |
|
|
const gchar *security_setting; |
703 |
|
|
|
704 |
|
✗ |
security_setting = ce_page_get_security_setting (page); |
705 |
|
✗ |
if (!security_setting || self->is_new_connection) { |
706 |
|
✗ |
ce_page_complete_init (page, NULL, NULL, NULL, NULL); |
707 |
|
|
} else { |
708 |
|
✗ |
get_secrets_for_page (self, page, security_setting); |
709 |
|
|
} |
710 |
|
|
} |
711 |
|
✗ |
g_slist_free (pages); |
712 |
|
|
} |
713 |
|
|
|
714 |
|
|
static NMConnection * |
715 |
|
✗ |
complete_vpn_connection (NetConnectionEditor *self, |
716 |
|
|
NMConnection *connection, |
717 |
|
|
GType setting_type) |
718 |
|
|
{ |
719 |
|
|
NMSettingConnection *s_con; |
720 |
|
|
NMSetting *s_type; |
721 |
|
|
|
722 |
|
✗ |
if (!connection) |
723 |
|
✗ |
connection = nm_simple_connection_new (); |
724 |
|
|
|
725 |
|
✗ |
s_con = nm_connection_get_setting_connection (connection); |
726 |
|
✗ |
if (!s_con) { |
727 |
|
✗ |
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); |
728 |
|
✗ |
nm_connection_add_setting (connection, NM_SETTING (s_con)); |
729 |
|
|
} |
730 |
|
|
|
731 |
|
✗ |
if (!nm_setting_connection_get_uuid (s_con)) { |
732 |
|
✗ |
g_autofree gchar *uuid = nm_utils_uuid_generate (); |
733 |
|
✗ |
g_object_set (s_con, |
734 |
|
|
NM_SETTING_CONNECTION_UUID, uuid, |
735 |
|
|
NULL); |
736 |
|
|
} |
737 |
|
|
|
738 |
|
✗ |
if (!nm_setting_connection_get_id (s_con)) { |
739 |
|
|
const GPtrArray *connections; |
740 |
|
✗ |
g_autofree gchar *id = NULL; |
741 |
|
|
|
742 |
|
✗ |
connections = nm_client_get_connections (self->client); |
743 |
|
✗ |
id = ce_page_get_next_available_name (connections, NAME_FORMAT_TYPE, _("VPN")); |
744 |
|
✗ |
g_object_set (s_con, |
745 |
|
|
NM_SETTING_CONNECTION_ID, id, |
746 |
|
|
NULL); |
747 |
|
|
} |
748 |
|
|
|
749 |
|
✗ |
s_type = nm_connection_get_setting (connection, setting_type); |
750 |
|
✗ |
if (!s_type) { |
751 |
|
✗ |
s_type = g_object_new (setting_type, NULL); |
752 |
|
✗ |
nm_connection_add_setting (connection, s_type); |
753 |
|
|
} |
754 |
|
|
|
755 |
|
✗ |
if (!nm_setting_connection_get_connection_type (s_con)) { |
756 |
|
✗ |
g_object_set (s_con, |
757 |
|
|
NM_SETTING_CONNECTION_TYPE, nm_setting_get_name (s_type), |
758 |
|
|
NULL); |
759 |
|
|
} |
760 |
|
|
|
761 |
|
✗ |
return connection; |
762 |
|
|
} |
763 |
|
|
|
764 |
|
|
static void |
765 |
|
✗ |
finish_add_connection (NetConnectionEditor *self, NMConnection *connection) |
766 |
|
|
{ |
767 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->apply_button), TRUE); |
768 |
|
|
|
769 |
|
✗ |
if (connection) |
770 |
|
✗ |
net_connection_editor_set_connection (self, connection); |
771 |
|
✗ |
} |
772 |
|
|
|
773 |
|
|
static void |
774 |
|
✗ |
vpn_import_complete (NMConnection *connection, gpointer user_data) |
775 |
|
|
{ |
776 |
|
✗ |
NetConnectionEditor *self = user_data; |
777 |
|
✗ |
NMSetting *s_type = NULL; |
778 |
|
|
NMSettingConnection *s_con; |
779 |
|
|
|
780 |
|
✗ |
if (!connection) { |
781 |
|
|
AdwToast *toast; |
782 |
|
✗ |
g_autofree gchar *message = NULL; |
783 |
|
|
|
784 |
|
✗ |
message = g_strdup_printf (_("Invalid VPN configuration file")); |
785 |
|
✗ |
toast = adw_toast_new (message); |
786 |
|
✗ |
adw_toast_overlay_add_toast (self->toast_overlay, toast); |
787 |
|
|
|
788 |
|
✗ |
g_signal_emit (self, signals[DONE], 0, FALSE); |
789 |
|
✗ |
return; |
790 |
|
|
} |
791 |
|
|
|
792 |
|
✗ |
s_type = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIREGUARD); |
793 |
|
✗ |
if (s_type) |
794 |
|
✗ |
complete_vpn_connection (self, connection, NM_TYPE_SETTING_WIREGUARD); |
795 |
|
|
else |
796 |
|
✗ |
complete_vpn_connection (self, connection, NM_TYPE_SETTING_VPN); |
797 |
|
|
|
798 |
|
|
/* Mark the connection as private to this user, and non-autoconnect */ |
799 |
|
✗ |
s_con = nm_connection_get_setting_connection (connection); |
800 |
|
✗ |
g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); |
801 |
|
✗ |
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL); |
802 |
|
|
|
803 |
|
✗ |
finish_add_connection (self, connection); |
804 |
|
|
} |
805 |
|
|
|
806 |
|
|
static void |
807 |
|
✗ |
vpn_type_activated (NetConnectionEditor *self, GtkWidget *row) |
808 |
|
|
{ |
809 |
|
✗ |
const char *service_name = g_object_get_data (G_OBJECT (row), "service_name"); |
810 |
|
|
NMConnection *connection; |
811 |
|
✗ |
NMSettingVpn *s_vpn = NULL; |
812 |
|
|
NMSettingConnection *s_con; |
813 |
|
✗ |
GType s_type = NM_TYPE_SETTING_VPN; |
814 |
|
|
|
815 |
|
✗ |
if (!strcmp (service_name, "import")) { |
816 |
|
✗ |
vpn_import (GTK_WINDOW (self), vpn_import_complete, self); |
817 |
|
✗ |
return; |
818 |
|
✗ |
} else if (!strcmp (service_name, "wireguard")) { |
819 |
|
✗ |
s_type = NM_TYPE_SETTING_WIREGUARD; |
820 |
|
|
} |
821 |
|
|
|
822 |
|
✗ |
connection = complete_vpn_connection (self, NULL, s_type); |
823 |
|
✗ |
if (s_type == NM_TYPE_SETTING_VPN) { |
824 |
|
✗ |
s_vpn = nm_connection_get_setting_vpn (connection); |
825 |
|
✗ |
g_object_set (s_vpn, NM_SETTING_VPN_SERVICE_TYPE, service_name, NULL); |
826 |
|
|
} |
827 |
|
|
|
828 |
|
|
/* Mark the connection as private to this user, and non-autoconnect */ |
829 |
|
✗ |
s_con = nm_connection_get_setting_connection (connection); |
830 |
|
✗ |
g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); |
831 |
|
✗ |
nm_setting_connection_add_permission (s_con, "user", g_get_user_name (), NULL); |
832 |
|
|
|
833 |
|
✗ |
finish_add_connection (self, connection); |
834 |
|
|
} |
835 |
|
|
|
836 |
|
|
static void |
837 |
|
✗ |
select_vpn_type (NetConnectionEditor *self, GtkListBox *list) |
838 |
|
|
{ |
839 |
|
|
GSList *vpn_plugins, *iter; |
840 |
|
|
GtkWidget *row; |
841 |
|
|
GtkWidget *child; |
842 |
|
|
|
843 |
|
|
/* Get the available VPN types */ |
844 |
|
✗ |
vpn_plugins = vpn_get_plugins (); |
845 |
|
|
|
846 |
|
|
/* Remove the previous menu contents */ |
847 |
|
✗ |
while ((child = gtk_widget_get_first_child (GTK_WIDGET (list))) != NULL) |
848 |
|
✗ |
gtk_list_box_remove (list, child); |
849 |
|
|
|
850 |
|
|
/* Add the VPN types */ |
851 |
|
✗ |
for (iter = vpn_plugins; iter; iter = iter->next) { |
852 |
|
✗ |
NMVpnEditorPlugin *plugin = nm_vpn_plugin_info_get_editor_plugin (iter->data); |
853 |
|
✗ |
g_autofree gchar *name = NULL; |
854 |
|
✗ |
g_autofree gchar *desc = NULL; |
855 |
|
✗ |
g_autofree gchar *desc_markup = NULL; |
856 |
|
✗ |
g_autofree gchar *service_name = NULL; |
857 |
|
|
|
858 |
|
✗ |
g_object_get (plugin, |
859 |
|
|
NM_VPN_EDITOR_PLUGIN_NAME, &name, |
860 |
|
|
NM_VPN_EDITOR_PLUGIN_DESCRIPTION, &desc, |
861 |
|
|
NM_VPN_EDITOR_PLUGIN_SERVICE, &service_name, |
862 |
|
|
NULL); |
863 |
|
✗ |
desc_markup = g_markup_printf_escaped ("<span size='smaller'>%s</span>", desc); |
864 |
|
|
|
865 |
|
✗ |
row = adw_action_row_new (); |
866 |
|
✗ |
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); |
867 |
|
✗ |
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), name); |
868 |
|
✗ |
adw_action_row_set_subtitle (ADW_ACTION_ROW (row), desc_markup); |
869 |
|
|
|
870 |
|
✗ |
g_object_set_data_full (G_OBJECT (row), "service_name", g_steal_pointer (&service_name), g_free); |
871 |
|
✗ |
gtk_list_box_append (list, row); |
872 |
|
|
} |
873 |
|
|
|
874 |
|
|
/* Translators: VPN add dialog Wireguard description */ |
875 |
|
✗ |
gchar *desc = _("Free and open-source VPN solution designed for ease " |
876 |
|
|
"of use, high speed performance and low attack surface."); |
877 |
|
✗ |
gchar *desc_markup = g_markup_printf_escaped ("<span size='smaller'>%s</span>", desc); |
878 |
|
|
|
879 |
|
✗ |
row = adw_action_row_new (); |
880 |
|
✗ |
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); |
881 |
|
✗ |
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), _("WireGuard")); |
882 |
|
✗ |
adw_action_row_set_subtitle (ADW_ACTION_ROW (row), desc_markup); |
883 |
|
|
|
884 |
|
✗ |
g_object_set_data (G_OBJECT (row), "service_name", "wireguard"); |
885 |
|
✗ |
gtk_list_box_append (list, row); |
886 |
|
|
|
887 |
|
|
/* Import */ |
888 |
|
✗ |
row = adw_action_row_new (); |
889 |
|
✗ |
gtk_list_box_row_set_activatable (GTK_LIST_BOX_ROW (row), TRUE); |
890 |
|
✗ |
adw_preferences_row_set_title (ADW_PREFERENCES_ROW (row), _("Import from fileā¦")); |
891 |
|
|
|
892 |
|
✗ |
g_object_set_data (G_OBJECT (row), "service_name", "import"); |
893 |
|
✗ |
gtk_list_box_append (list, row); |
894 |
|
|
|
895 |
|
✗ |
g_signal_connect_object (list, "row-activated", |
896 |
|
|
G_CALLBACK (vpn_type_activated), self, G_CONNECT_SWAPPED); |
897 |
|
✗ |
} |
898 |
|
|
|
899 |
|
|
static void |
900 |
|
✗ |
net_connection_editor_add_connection (NetConnectionEditor *self) |
901 |
|
|
{ |
902 |
|
|
GtkListBox *list; |
903 |
|
|
|
904 |
|
✗ |
list = GTK_LIST_BOX (gtk_list_box_new ()); |
905 |
|
✗ |
gtk_list_box_set_selection_mode (list, GTK_SELECTION_NONE); |
906 |
|
✗ |
gtk_widget_add_css_class (GTK_WIDGET (list), "boxed-list"); |
907 |
|
|
|
908 |
|
✗ |
select_vpn_type (self, list); |
909 |
|
|
|
910 |
|
✗ |
adw_bin_set_child (self->add_connection_frame, GTK_WIDGET (list)); |
911 |
|
|
|
912 |
|
✗ |
gtk_stack_set_visible_child (self->toplevel_stack, GTK_WIDGET (self->add_connection_box)); |
913 |
|
✗ |
gtk_widget_set_visible (GTK_WIDGET (self->apply_button), FALSE); |
914 |
|
✗ |
gtk_window_set_title (GTK_WINDOW (self), _("Add VPN")); |
915 |
|
✗ |
} |
916 |
|
|
|
917 |
|
|
static void |
918 |
|
✗ |
permission_changed (NetConnectionEditor *self, |
919 |
|
|
NMClientPermission permission, |
920 |
|
|
NMClientPermissionResult result) |
921 |
|
|
{ |
922 |
|
✗ |
if (permission != NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM) |
923 |
|
✗ |
return; |
924 |
|
|
|
925 |
|
✗ |
if (result == NM_CLIENT_PERMISSION_RESULT_YES || result == NM_CLIENT_PERMISSION_RESULT_AUTH) |
926 |
|
✗ |
self->can_modify = TRUE; |
927 |
|
|
else |
928 |
|
✗ |
self->can_modify = FALSE; |
929 |
|
|
|
930 |
|
✗ |
validate (self); |
931 |
|
|
} |
932 |
|
|
|
933 |
|
|
NetConnectionEditor * |
934 |
|
✗ |
net_connection_editor_new (NMConnection *connection, |
935 |
|
|
NMDevice *device, |
936 |
|
|
NMAccessPoint *ap, |
937 |
|
|
NMClient *client) |
938 |
|
|
{ |
939 |
|
|
NetConnectionEditor *self; |
940 |
|
|
|
941 |
|
✗ |
self = g_object_new (net_connection_editor_get_type (), NULL); |
942 |
|
|
|
943 |
|
✗ |
self->cancellable = g_cancellable_new (); |
944 |
|
|
|
945 |
|
✗ |
if (ap) |
946 |
|
✗ |
self->ap = g_object_ref (ap); |
947 |
|
✗ |
if (device) |
948 |
|
✗ |
self->device = g_object_ref (device); |
949 |
|
✗ |
self->client = g_object_ref (client); |
950 |
|
|
|
951 |
|
✗ |
self->can_modify = nm_client_get_permission_result (client, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM); |
952 |
|
✗ |
g_signal_connect_object (self->client, "permission-changed", |
953 |
|
|
G_CALLBACK (permission_changed), self, G_CONNECT_SWAPPED); |
954 |
|
|
|
955 |
|
✗ |
if (connection) |
956 |
|
✗ |
net_connection_editor_set_connection (self, connection); |
957 |
|
|
else |
958 |
|
✗ |
net_connection_editor_add_connection (self); |
959 |
|
|
|
960 |
|
✗ |
return self; |
961 |
|
|
} |
962 |
|
|
|
963 |
|
|
static void |
964 |
|
✗ |
forgotten_cb (GObject *source_object, |
965 |
|
|
GAsyncResult *res, |
966 |
|
|
gpointer user_data) |
967 |
|
|
{ |
968 |
|
✗ |
NMRemoteConnection *connection = NM_REMOTE_CONNECTION (source_object); |
969 |
|
✗ |
NetConnectionEditor *self = user_data; |
970 |
|
✗ |
g_autoptr(GError) error = NULL; |
971 |
|
|
|
972 |
|
✗ |
if (!nm_remote_connection_delete_finish (connection, res, &error)) { |
973 |
|
✗ |
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
974 |
|
✗ |
g_warning ("Failed to delete connection %s: %s", |
975 |
|
|
nm_connection_get_id (NM_CONNECTION (connection)), |
976 |
|
|
error->message); |
977 |
|
✗ |
return; |
978 |
|
|
} |
979 |
|
|
|
980 |
|
✗ |
cancel_editing (self); |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
void |
984 |
|
✗ |
net_connection_editor_forget (NetConnectionEditor *self) |
985 |
|
|
{ |
986 |
|
✗ |
nm_remote_connection_delete_async (NM_REMOTE_CONNECTION (self->orig_connection), |
987 |
|
|
self->cancellable, forgotten_cb, self); |
988 |
|
✗ |
} |
989 |
|
|
|
990 |
|
|
void |
991 |
|
✗ |
net_connection_editor_set_title (NetConnectionEditor *self, |
992 |
|
|
const gchar *title) |
993 |
|
|
{ |
994 |
|
✗ |
gtk_window_set_title (GTK_WINDOW (self), title); |
995 |
|
✗ |
self->title_set = TRUE; |
996 |
|
✗ |
} |
997 |
|
|
|