1 /*
2 * vinagre-reverse-vnc-listener-dialog.c
3 * This file is part of vinagre
4 *
5 * Copyright (C) 2009 Jonh Wendell <wendell@bani.com.br>
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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <config.h>
22
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <net/if.h>
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
28
29 #ifdef HAVE_IFADDRS_H
30 #include <ifaddrs.h>
31 #else
32 #include "if/ifaddrs.h"
33 #endif
34
35 #ifdef RFC2553
36 #define ADDR_FAMILY_MEMBER ss_family
37 #else
38 #define ADDR_FAMILY_MEMBER sa_family
39 #endif
40
41 #include <string.h>
42 #include <glib/gi18n.h>
43
44 #include "vinagre-prefs.h"
45 #include "vinagre-reverse-vnc-listener-dialog.h"
46 #include "vinagre-reverse-vnc-listener.h"
47 #include "vinagre-vala.h"
48
49 typedef struct
50 {
51 GtkBuilder *xml;
52 GtkWidget *dialog;
53 GtkWidget *enable_reverse_check;
54 GtkWidget *always_enabled_check;
55 GtkWidget *port_label;
56 GtkWidget *connectivity_exp;
57 GtkTextBuffer *ip_buffer;
58 VinagreReverseVncListener *listener;
59 } VncListenDialog;
60
61 static void
setup_ip_buffer(VncListenDialog * dialog)62 setup_ip_buffer (VncListenDialog *dialog)
63 {
64 char buf[INET6_ADDRSTRLEN], *dup;
65 struct ifaddrs *myaddrs, *ifa;
66 void *sin;
67 GArray *ipv4, *ipv6;
68 GString *str;
69 int i;
70
71 ipv4 = g_array_new (FALSE, TRUE, sizeof (char *));
72 ipv6 = g_array_new (FALSE, TRUE, sizeof (char *));
73 str = g_string_new (NULL);
74
75 getifaddrs (&myaddrs);
76 for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
77 {
78 if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0 || strncmp (ifa->ifa_name, "lo", 2) == 0)
79 continue;
80
81 switch (ifa->ifa_addr->ADDR_FAMILY_MEMBER)
82 {
83 case AF_INET:
84 sin = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
85 inet_ntop (AF_INET, sin, buf, INET6_ADDRSTRLEN);
86 dup = g_strdup (buf);
87 g_array_append_val (ipv4, dup);
88 break;
89
90 case AF_INET6:
91 sin = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
92 inet_ntop (AF_INET6, sin, buf, INET6_ADDRSTRLEN);
93 dup = g_strdup (buf);
94 g_array_append_val (ipv6, dup);
95 break;
96 default: continue;
97 }
98 }
99
100 if (ipv4->len > 0)
101 {
102 if (ipv6->len > 0)
103 g_string_append (str, _("IPv4:"));
104
105 for (i = 0; i < ipv4->len; i++)
106 {
107 dup = g_array_index (ipv4, char *, i);
108 g_string_append_printf (str, "\n%s", dup);
109 g_free (dup);
110 }
111 }
112 if (ipv6->len > 0)
113 {
114 if (ipv4->len > 0)
115 g_string_append (str, _("\n\nIPv6:"));
116
117 for (i = 0; i < ipv6->len; i++)
118 {
119 dup = g_array_index (ipv6, char *, i);
120 g_string_append_printf (str, "\n%s", g_array_index (ipv6, char *, i));
121 g_free (dup);
122 }
123 }
124
125 gtk_text_buffer_set_text (dialog->ip_buffer, str->str, -1);
126
127 freeifaddrs (myaddrs);
128 g_array_free (ipv4, TRUE);
129 g_array_free (ipv6, TRUE);
130 g_string_free (str, TRUE);
131 }
132
133 static void
dialog_destroy(GtkWidget * widget,VncListenDialog * dialog)134 dialog_destroy (GtkWidget *widget,
135 VncListenDialog *dialog)
136 {
137 g_object_unref (dialog->xml);
138 g_object_unref (dialog->listener);
139 g_slice_free (VncListenDialog, dialog);
140 }
141
142 static void
dialog_response_handler(GtkDialog * widget,gint res_id,VncListenDialog * dialog)143 dialog_response_handler (GtkDialog *widget,
144 gint res_id,
145 VncListenDialog *dialog)
146 {
147 switch (res_id)
148 {
149 case GTK_RESPONSE_HELP:
150 vinagre_utils_show_help (GTK_WINDOW (dialog->dialog),
151 "connect-reverse");
152 break;
153
154 default:
155 gtk_widget_destroy (dialog->dialog);
156 break;
157 }
158 }
159
160 static void
update_ui_sensitivity(VncListenDialog * dialog)161 update_ui_sensitivity (VncListenDialog *dialog)
162 {
163 gboolean listening;
164 gchar *str;
165
166 listening = vinagre_reverse_vnc_listener_is_listening (dialog->listener);
167
168 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->enable_reverse_check),
169 listening);
170 gtk_widget_set_sensitive (dialog->always_enabled_check, listening);
171 gtk_widget_set_sensitive (dialog->connectivity_exp, listening);
172
173 if (listening)
174 {
175 str = g_strdup_printf (_("On the port %d"), vinagre_reverse_vnc_listener_get_port (dialog->listener));
176 gtk_label_set_label (GTK_LABEL (dialog->port_label), str);
177 g_free (str);
178 }
179 else
180 {
181 gtk_expander_set_expanded (GTK_EXPANDER (dialog->connectivity_exp), FALSE);
182 }
183 }
184
185 static void
enable_reverse_toggled_cb(GtkToggleButton * button,VncListenDialog * dialog)186 enable_reverse_toggled_cb (GtkToggleButton *button, VncListenDialog *dialog)
187 {
188 if (gtk_toggle_button_get_active (button))
189 vinagre_reverse_vnc_listener_start (dialog->listener);
190 else
191 {
192 vinagre_reverse_vnc_listener_stop (dialog->listener);
193 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->always_enabled_check),
194 FALSE);
195 }
196
197 update_ui_sensitivity (dialog);
198 }
199
200 static void
always_enabled_toggled_cb(GtkToggleButton * button,VncListenDialog * dialog)201 always_enabled_toggled_cb (GtkToggleButton *button, VncListenDialog *dialog)
202 {
203 g_object_set (vinagre_prefs_get_default (),
204 "always-enable-listening", gtk_toggle_button_get_active (button),
205 NULL);
206 }
207
208 void
vinagre_reverse_vnc_listener_dialog_show(GtkWindow * parent)209 vinagre_reverse_vnc_listener_dialog_show (GtkWindow *parent)
210 {
211 VncListenDialog *dialog;
212 GtkBuilder *xml;
213 gboolean always;
214
215 xml = vinagre_utils_get_builder ();
216
217 if (!xml)
218 return;
219
220 dialog = g_slice_new (VncListenDialog);
221 dialog->xml = xml;
222
223 dialog->listener = vinagre_reverse_vnc_listener_get_default ();
224
225 dialog->dialog = GTK_WIDGET (gtk_builder_get_object (xml, "listener_dialog"));
226 g_assert (dialog->dialog != NULL);
227
228 dialog->ip_buffer = GTK_TEXT_BUFFER (gtk_builder_get_object (xml, "ip_textbuffer"));
229 g_assert (dialog->ip_buffer != NULL);
230 setup_ip_buffer (dialog);
231
232 dialog->enable_reverse_check = GTK_WIDGET (gtk_builder_get_object (xml, "enable_reverse_check"));
233 g_assert (dialog->enable_reverse_check != NULL);
234 g_signal_connect (dialog->enable_reverse_check,
235 "toggled",
236 G_CALLBACK (enable_reverse_toggled_cb),
237 dialog);
238
239 dialog->always_enabled_check = GTK_WIDGET (gtk_builder_get_object (xml, "always_enabled_check"));
240 g_assert (dialog->always_enabled_check != NULL);
241 g_object_get (vinagre_prefs_get_default (),
242 "always-enable-listening", &always,
243 NULL);
244 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->always_enabled_check),
245 always);
246 g_signal_connect (dialog->always_enabled_check,
247 "toggled",
248 G_CALLBACK (always_enabled_toggled_cb),
249 dialog);
250
251 dialog->connectivity_exp = GTK_WIDGET (gtk_builder_get_object (xml, "connectivity_exp"));
252 g_assert (dialog->connectivity_exp != NULL);
253
254 dialog->port_label = GTK_WIDGET (gtk_builder_get_object (xml, "port_label"));
255 g_assert (dialog->port_label != NULL);
256
257 update_ui_sensitivity (dialog);
258
259 g_signal_connect (dialog->dialog,
260 "destroy",
261 G_CALLBACK (dialog_destroy),
262 dialog);
263
264 g_signal_connect (dialog->dialog,
265 "response",
266 G_CALLBACK (dialog_response_handler),
267 dialog);
268
269 if (parent)
270 gtk_window_set_transient_for (GTK_WINDOW (dialog->dialog), parent);
271
272 gtk_widget_show_all (dialog->dialog);
273 }
274