Move bridge relay configuration dialog into separate file
[tor-status] / src / bridge-dialog.vala
1 class BridgeDialog : Gtk.Dialog {
2         private const string GCONF_DIR_TOR     = "/apps/maemo/tor";
3         private const string GCONF_KEY_BRIDGES = GCONF_DIR_TOR + "/bridges";
4
5         GConf.Client gconf;
6         Gtk.ListStore list_store;
7
8         /**
9          * Show the bridge relay configuration dialog
10          */
11         private const int RESPONSE_NEW = 1;
12         public BridgeDialog () {
13                 var content = (Gtk.VBox) get_content_area ();
14                 content.set_size_request (-1, 5*70);
15
16                 set_title (_("Bridge relays"));
17
18                 gconf = GConf.Client.get_default ();
19                 var bridges = new SList<string> ();
20                 try {
21                         bridges = gconf.get_list (GCONF_KEY_BRIDGES, GConf.ValueType.STRING);
22                 } catch (Error e) {
23                         Hildon.Banner.show_information (null, null, "Error loading bridges: %s".printf (e.message));
24                 }
25
26                 list_store = new Gtk.ListStore (1, typeof (string));
27                 Gtk.TreeIter iter;
28                 foreach (string bridge in bridges) {
29                         list_store.append (out iter);
30                         list_store.@set (iter, 0, bridge);
31                 }
32
33                 var pannable_area = new Hildon.PannableArea ();
34                 var tree_view = new Gtk.TreeView.with_model (list_store);
35                 var renderer = new Gtk.CellRendererText ();
36                 var column = new Gtk.TreeViewColumn.with_attributes ("IP", renderer, "text", 0);
37                 tree_view.append_column (column);
38                 pannable_area.add (tree_view);
39                 content.pack_start (pannable_area, true, true, 0);
40
41                 tree_view.row_activated.connect ((path, column) => {
42                         bridge_edit_dialog (list_store, path);
43                 });
44
45                 add_button (_("New"), RESPONSE_NEW);
46                 response.connect ((response_id) => {
47                         if (response_id == RESPONSE_NEW) {
48                                 bridge_edit_dialog (list_store, null);
49                         }
50                 });
51
52                 content.show_all ();
53         }
54
55         /**
56          * Show the bridge relay edit dialog
57          */
58         private const int RESPONSE_DELETE = 1;
59         private void bridge_edit_dialog (Gtk.ListStore store, Gtk.TreePath? path) {
60                 var dialog = new Gtk.Dialog ();
61                 var content = (Gtk.VBox) dialog.get_content_area ();
62
63                 if (path == null)
64                         dialog.set_title (_("New bridge relay"));
65                 else
66                         dialog.set_title (_("Edit bridge relay"));
67
68                 var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
69
70                 var hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
71                 var label = new Gtk.Label (_("IP address"));
72                 label.set_alignment (0, 0.5f);
73                 size_group.add_widget (label);
74                 hbox.pack_start (label, false, false, 0);
75                 var ip_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
76                 ip_entry.set ("hildon-input-mode", Hildon.GtkInputMode.NUMERIC |
77                                                    Hildon.GtkInputMode.SPECIAL);
78                 hbox.pack_start (ip_entry, true, true, 0);
79                 content.pack_start (hbox, false, false, 0);
80
81                 hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
82                 label = new Gtk.Label (_("Port"));
83                 label.set_alignment (0, 0.5f);
84                 size_group.add_widget (label);
85                 hbox.pack_start (label, false, false, 0);
86                 var port_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
87                 port_entry.set ("hildon-input-mode", Hildon.GtkInputMode.NUMERIC);
88                 hbox.pack_start (port_entry, true, true, 0);
89                 content.pack_start (hbox, true, true, 0);
90
91                 hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
92                 label = new Gtk.Label (_("Fingerprint"));
93                 label.set_alignment (0, 0.5f);
94                 size_group.add_widget (label);
95                 hbox.pack_start (label, false, false, 0);
96                 var fingerprint_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
97                 fingerprint_entry.set ("hildon-input-mode", Hildon.GtkInputMode.HEXA);
98                 hbox.pack_start (fingerprint_entry, true, true, 0);
99                 content.pack_start (hbox, true, true, 0);
100
101                 var iter = Gtk.TreeIter ();
102                 if (path == null) {
103                         port_entry.set_text ("443");
104                 } else if (store.get_iter (out iter, path)) {
105                         string tmp;
106                         store.@get (iter, 0, out tmp);
107                         string[] ip_port = tmp.split (":");
108                         if (ip_port.length == 2) {
109                                 ip_entry.set_text (ip_port[0]);
110                                 port_entry.set_text (ip_port[1]);
111                         }
112
113                         dialog.add_button (_("Delete"), RESPONSE_DELETE);
114                 }
115                 dialog.add_button (_("Save"), Gtk.ResponseType.OK);
116                 dialog.response.connect ((response_id) => {
117                         var bridges = new SList<string> ();
118
119                         if (response_id == RESPONSE_DELETE) {
120                                 if (path != null) {
121                                         Gtk.TreeIter iter2;
122                                         store.get_iter (out iter2, path);
123                                         store.remove (iter2);
124                                         string bridge;
125                                         if (store.get_iter_first (out iter2)) do {
126                                                 store.@get (iter2, 0, out bridge);
127                                                 bridges.append (bridge);
128                                         } while (store.iter_next (ref iter2));
129                                         try {
130                                                 gconf.set_list (GCONF_KEY_BRIDGES,
131                                                                 GConf.ValueType.STRING,
132                                                                 bridges);
133                                         } catch (Error e) {
134                                                 Hildon.Banner.show_information (dialog, null,
135                                                                                 "Failed to save bridge relay list: %s".printf (e.message));
136                                         }
137                                 }
138                                 dialog.destroy ();
139                         }
140                         if (response_id == Gtk.ResponseType.OK) {
141                                 if (!is_valid_ip_address (ip_entry.get_text ())) {
142                                         Hildon.Banner.show_information (dialog, null,
143                                                                         _("Invalid IP address"));
144                                         return;
145                                 }
146                                 int port = port_entry.get_text ().to_int ();
147                                 if (port < 0 || port > 65565) {
148                                         Hildon.Banner.show_information (dialog, null,
149                                                                         _("Invalid port number"));
150                                         return;
151                                 }
152                                 Gtk.TreeIter iter2;
153                                 if (path == null) {
154                                         store.append (out iter2);
155                                 } else {
156                                         store.get_iter (out iter2, path);
157                                 }
158                                 store.@set (iter2, 0, "%s:%d".printf (ip_entry.get_text (), port));
159                                 try {
160                                         bridges = gconf.get_list (GCONF_KEY_BRIDGES,
161                                                                   GConf.ValueType.STRING);
162                                 } catch (Error e) {
163                                         Hildon.Banner.show_information (null, null,
164                                                                         "Error loading bridges: %s".printf (e.message));
165                                 }
166                                 if (path == null) {
167                                         bridges.append ("%s:%d".printf (ip_entry.get_text (), port));
168                                 } else {
169                                         bridges = null;
170                                         string bridge;
171                                         if (store.get_iter_first (out iter2)) do {
172                                                 store.@get (iter2, 0, out bridge);
173                                                 bridges.append (bridge);
174                                         } while (store.iter_next (ref iter2));
175                                 }
176                                 try {
177                                         gconf.set_list (GCONF_KEY_BRIDGES,
178                                                         GConf.ValueType.STRING,
179                                                         bridges);
180                                 } catch (Error e) {
181                                                 Hildon.Banner.show_information (dialog, null,
182                                                                                 "Failed to save bridge relay list: %s".printf (e.message));
183                                 }
184
185                                 dialog.destroy ();
186                         }
187                 });
188
189                 dialog.show_all ();
190         }
191
192         /**
193          * Check whether the IP address consists of four numbers in the 0..255 range
194          */
195         bool is_valid_ip_address (string address) {
196                 string[] ip = address.split (".");
197
198                 if (ip.length != 4)
199                         return false;
200
201                 for (int i = 0; i < ip.length; i++) {
202                         int n = ip[i].to_int ();
203                         if (n < 0 || n > 255)
204                                 return false;
205                 }
206
207                 return true;
208         }
209 }