--- /dev/null
+class ExitNodeDialog : Gtk.Dialog {
+ private const string GCONF_DIR_TOR = "/apps/maemo/tor";
+ private const string GCONF_KEY_EXITNODES = GCONF_DIR_TOR + "/exit_nodes";
+
+ GConf.Client gconf;
+ Gtk.ListStore list_store;
+
+ /**
+ * Show the exit node configuration dialog
+ */
+ private const int RESPONSE_NEW = 1;
+ public ExitNodeDialog (TorControl.Connection? tor_control = null) {
+ var content = (Gtk.VBox) get_content_area ();
+ content.set_size_request (-1, 5*70);
+
+ set_title (_("Exit nodes"));
+
+ gconf = GConf.Client.get_default ();
+ var exit_nodes = new SList<string> ();
+ try {
+ exit_nodes = gconf.get_list (GCONF_KEY_EXITNODES, GConf.ValueType.STRING);
+ } catch (Error e) {
+ Hildon.Banner.show_information (this, null, "Error loading exit nodes: %s".printf (e.message));
+ }
+
+ list_store = new Gtk.ListStore (1, typeof (string));
+ Gtk.TreeIter iter;
+ foreach (string exit_node in exit_nodes) {
+ list_store.append (out iter);
+ list_store.@set (iter, 0, exit_node);
+ }
+
+ var pannable_area = new Hildon.PannableArea ();
+ var tree_view = new Gtk.TreeView.with_model (list_store);
+ var renderer = new Gtk.CellRendererText ();
+ var column = new Gtk.TreeViewColumn.with_attributes ("IP", renderer, "text", 0);
+ tree_view.append_column (column);
+ pannable_area.add (tree_view);
+ content.pack_start (pannable_area, true, true, 0);
+
+ tree_view.row_activated.connect ((path, column) => {
+ exit_node_edit_dialog (list_store, path);
+ });
+
+ add_button (_("New"), RESPONSE_NEW);
+ response.connect ((response_id) => {
+ if (response_id == RESPONSE_NEW) {
+ exit_node_edit_dialog (list_store, null);
+ }
+ });
+
+ content.show_all ();
+ }
+
+ /**
+ * Show the exit node edit dialog
+ */
+ private const int RESPONSE_DELETE = 1;
+ private void exit_node_edit_dialog (Gtk.ListStore store, Gtk.TreePath? path) {
+ var dialog = new Gtk.Dialog ();
+ var content = (Gtk.VBox) dialog.get_content_area ();
+
+ if (path == null)
+ dialog.set_title (_("New exit node"));
+ else
+ dialog.set_title (_("Edit exit node"));
+
+ var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
+
+ var hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
+ var label = new Gtk.Label (_("Name"));
+ label.set_alignment (0, 0.5f);
+ size_group.add_widget (label);
+ hbox.pack_start (label, false, false, 0);
+ var name_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
+ hbox.pack_start (name_entry, true, true, 0);
+ content.pack_start (hbox, false, false, 0);
+
+ var iter = Gtk.TreeIter ();
+ if (path != null && store.get_iter (out iter, path)) {
+ string tmp;
+ store.@get (iter, 0, out tmp);
+ name_entry.set_text (tmp);
+
+ dialog.add_button (_("Delete"), RESPONSE_DELETE);
+ }
+ dialog.add_button (_("Save"), Gtk.ResponseType.OK);
+ dialog.response.connect ((response_id) => {
+ var exit_nodes = new SList<string> ();
+
+ if (response_id == RESPONSE_DELETE) {
+ if (path != null) {
+ Gtk.TreeIter iter2;
+ store.get_iter (out iter2, path);
+ store.remove (iter2);
+ string exit_node;
+ if (store.get_iter_first (out iter2)) do {
+ store.@get (iter2, 0, out exit_node);
+ exit_nodes.append (exit_node);
+ } while (store.iter_next (ref iter2));
+ try {
+ gconf.set_list (GCONF_KEY_EXITNODES,
+ GConf.ValueType.STRING,
+ exit_nodes);
+ } catch (Error e) {
+ Hildon.Banner.show_information (dialog, null,
+ "Failed to save exit node list: %s".printf (e.message));
+ }
+ }
+ dialog.destroy ();
+ }
+ if (response_id == Gtk.ResponseType.OK) {
+ Gtk.TreeIter iter2;
+ if (path == null) {
+ store.append (out iter2);
+ } else {
+ store.get_iter (out iter2, path);
+ }
+ store.@set (iter2, 0, name_entry.get_text ());
+ try {
+ exit_nodes = gconf.get_list (GCONF_KEY_EXITNODES,
+ GConf.ValueType.STRING);
+ } catch (Error e) {
+ Hildon.Banner.show_information (null, null,
+ "Error loading exit nodes: %s".printf (e.message));
+ }
+ if (path == null) {
+ exit_nodes.append (name_entry.get_text ());
+ } else {
+ exit_nodes = null;
+ string exit_node;
+ if (store.get_iter_first (out iter2)) do {
+ store.@get (iter2, 0, out exit_node);
+ exit_nodes.append (exit_node);
+ } while (store.iter_next (ref iter2));
+ }
+ try {
+ gconf.set_list (GCONF_KEY_EXITNODES,
+ GConf.ValueType.STRING,
+ exit_nodes);
+ } catch (Error e) {
+ Hildon.Banner.show_information (dialog, null,
+ "Failed to save exit node list: %s".printf (e.message));
+ }
+
+ dialog.destroy ();
+ }
+ });
+
+ dialog.show_all ();
+ }
+}
private const string GCONF_DIR_TOR = "/apps/maemo/tor";
private const string GCONF_KEY_TOR_ENABLED = GCONF_DIR_TOR + "/enabled";
private const string GCONF_KEY_BRIDGES = GCONF_DIR_TOR + "/bridges";
+ private const string GCONF_KEY_EXITNODES = GCONF_DIR_TOR + "/exit_nodes";
private const string GCONF_DIR_PROXY_HTTP = "/system/http_proxy";
private const string GCONF_KEY_PROXY_HTTP_ENABLED = GCONF_DIR_PROXY_HTTP + "/use_http_proxy";
"Failed to set up bridge relays");
}
}
+
+ var exits = gconf.get_list (GCONF_KEY_EXITNODES, GConf.ValueType.STRING);
+
+ if (exits.length () > 0) {
+ // Enable strict exit nodes
+ tor_control.set_conf_list ("ExitNodes", exits);
+ tor_control.set_conf_bool ("StrictExitNodes", true);
+
+ bool strict = yield tor_control.get_conf_bool_async ("StrictExitNodes");
+ if (!strict) {
+ Hildon.Banner.show_information (null, null,
+ "Failed to set up strict exit nodes");
+ }
+ }
}
/**
}
/**
+ * Show the exit node configuration dialog
+ */
+ private void exit_nodes_clicked_cb () {
+ var dialog = new ExitNodeDialog (tor_control);
+ dialog.show ();
+ }
+
+ /**
* Check whether the IP address consists of four numbers in the 0..255 range
*/
bool is_valid_ip_address (string address) {
private void button_clicked_cb () {
var dialog = new Gtk.Dialog ();
var content = (Gtk.VBox) dialog.get_content_area ();
- content.set_size_request (-1, 2*70);
+ content.set_size_request (-1, 3*70);
dialog.set_title (_("Tor: anonymity online"));
button.clicked.connect (bridges_clicked_cb);
content.pack_start (button, true, true, 0);
+ button = new Hildon.Button.with_text (Hildon.SizeType.FINGER_HEIGHT,
+ Hildon.ButtonArrangement.VERTICAL,
+ _("Restrict exit nodes"),
+ get_exit_node_list ());
+ button.set_style (Hildon.ButtonStyle.PICKER);
+ button.set_alignment (0, 0.5f, 0, 0.5f);
+ button.clicked.connect (exit_nodes_clicked_cb);
+ content.pack_start (button, true, true, 0);
+
dialog.add_button (_("Log"), RESPONSE_LOG);
dialog.add_button (_("Save"), Gtk.ResponseType.ACCEPT);
return list;
}
+ private string get_exit_node_list () {
+ string list = null;
+ var exits = new SList<string> ();
+ try {
+ exits = gconf.get_list (GCONF_KEY_EXITNODES, GConf.ValueType.STRING);
+ } catch (Error e) {
+ error ("Error loading exit nodes: %s", e.message);
+ }
+ foreach (string exit in exits) {
+ if (list == null)
+ list = exit;
+ else
+ list += ", " + exit;
+ }
+ if (list == null)
+ list = _("None");
+
+ return list;
+ }
+
/**
* Callback for the ConIc connection-event signal
*/