/* This file is part of status-area-applet-tor.
*
* Copyright (C) 2010-2011 Philipp Zabel
*
* status-area-applet-tor is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* status-area-applet-tor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with status-area-applet-tor. If not, see .
*/
class BridgeDialog : Gtk.Dialog {
private const string GCONF_DIR_TOR = "/apps/maemo/tor";
private const string GCONF_KEY_BRIDGES = GCONF_DIR_TOR + "/bridges";
GConf.Client gconf;
Gtk.ListStore list_store;
/**
* Show the bridge relay configuration dialog
*/
private const int RESPONSE_NEW = 1;
public BridgeDialog () {
var content = (Gtk.VBox) get_content_area ();
content.set_size_request (-1, 5*70);
set_title (_("Bridge relays"));
gconf = GConf.Client.get_default ();
var bridges = new SList ();
try {
bridges = gconf.get_list (GCONF_KEY_BRIDGES, GConf.ValueType.STRING);
} catch (Error e) {
Hildon.Banner.show_information (null, null, "Error loading bridges: %s".printf (e.message));
}
list_store = new Gtk.ListStore (1, typeof (string));
Gtk.TreeIter iter;
foreach (string bridge in bridges) {
list_store.append (out iter);
list_store.@set (iter, 0, bridge);
}
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) => {
bridge_edit_dialog (list_store, path);
});
add_button (_("New"), RESPONSE_NEW);
response.connect ((response_id) => {
if (response_id == RESPONSE_NEW) {
bridge_edit_dialog (list_store, null);
}
});
content.show_all ();
}
/**
* Show the bridge relay edit dialog
*/
private const int RESPONSE_DELETE = 1;
private void bridge_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 bridge relay"));
else
dialog.set_title (_("Edit bridge relay"));
var size_group = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL);
var hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
var label = new Gtk.Label (_("IP address"));
label.set_alignment (0, 0.5f);
size_group.add_widget (label);
hbox.pack_start (label, false, false, 0);
var ip_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
ip_entry.set ("hildon-input-mode", Hildon.GtkInputMode.NUMERIC |
Hildon.GtkInputMode.SPECIAL);
hbox.pack_start (ip_entry, true, true, 0);
content.pack_start (hbox, false, false, 0);
hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
label = new Gtk.Label (_("Port"));
label.set_alignment (0, 0.5f);
size_group.add_widget (label);
hbox.pack_start (label, false, false, 0);
var port_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
port_entry.set ("hildon-input-mode", Hildon.GtkInputMode.NUMERIC);
hbox.pack_start (port_entry, true, true, 0);
content.pack_start (hbox, true, true, 0);
hbox = new Gtk.HBox (false, Hildon.MARGIN_DOUBLE);
label = new Gtk.Label (_("Fingerprint"));
label.set_alignment (0, 0.5f);
size_group.add_widget (label);
hbox.pack_start (label, false, false, 0);
var fingerprint_entry = new Hildon.Entry (Hildon.SizeType.FINGER_HEIGHT);
fingerprint_entry.set ("hildon-input-mode", Hildon.GtkInputMode.HEXA);
hbox.pack_start (fingerprint_entry, true, true, 0);
content.pack_start (hbox, true, true, 0);
var iter = Gtk.TreeIter ();
if (path == null) {
port_entry.set_text ("443");
} else if (store.get_iter (out iter, path)) {
string tmp;
store.@get (iter, 0, out tmp);
string[] ip_port = tmp.split (":");
if (ip_port.length == 2) {
ip_entry.set_text (ip_port[0]);
port_entry.set_text (ip_port[1]);
}
dialog.add_button (_("Delete"), RESPONSE_DELETE);
}
dialog.add_button (_("Save"), Gtk.ResponseType.OK);
dialog.response.connect ((response_id) => {
var bridges = new SList ();
if (response_id == RESPONSE_DELETE) {
if (path != null) {
Gtk.TreeIter iter2;
store.get_iter (out iter2, path);
store.remove (iter2);
string bridge;
if (store.get_iter_first (out iter2)) do {
store.@get (iter2, 0, out bridge);
bridges.append (bridge);
} while (store.iter_next (ref iter2));
try {
gconf.set_list (GCONF_KEY_BRIDGES,
GConf.ValueType.STRING,
bridges);
} catch (Error e) {
Hildon.Banner.show_information (dialog, null,
"Failed to save bridge relay list: %s".printf (e.message));
}
}
dialog.destroy ();
}
if (response_id == Gtk.ResponseType.OK) {
if (!is_valid_ip_address (ip_entry.get_text ())) {
Hildon.Banner.show_information (dialog, null,
_("Invalid IP address"));
return;
}
int port = port_entry.get_text ().to_int ();
if (port < 0 || port > 65565) {
Hildon.Banner.show_information (dialog, null,
_("Invalid port number"));
return;
}
Gtk.TreeIter iter2;
if (path == null) {
store.append (out iter2);
} else {
store.get_iter (out iter2, path);
}
store.@set (iter2, 0, "%s:%d".printf (ip_entry.get_text (), port));
try {
bridges = gconf.get_list (GCONF_KEY_BRIDGES,
GConf.ValueType.STRING);
} catch (Error e) {
Hildon.Banner.show_information (null, null,
"Error loading bridges: %s".printf (e.message));
}
if (path == null) {
bridges.append ("%s:%d".printf (ip_entry.get_text (), port));
} else {
bridges = null;
string bridge;
if (store.get_iter_first (out iter2)) do {
store.@get (iter2, 0, out bridge);
bridges.append (bridge);
} while (store.iter_next (ref iter2));
}
try {
gconf.set_list (GCONF_KEY_BRIDGES,
GConf.ValueType.STRING,
bridges);
} catch (Error e) {
Hildon.Banner.show_information (dialog, null,
"Failed to save bridge relay list: %s".printf (e.message));
}
dialog.destroy ();
}
});
dialog.show_all ();
}
/**
* Check whether the IP address consists of four numbers in the 0..255 range
*/
bool is_valid_ip_address (string address) {
string[] ip = address.split (".");
if (ip.length != 4)
return false;
for (int i = 0; i < ip.length; i++) {
int n = ip[i].to_int ();
if (n < 0 || n > 255)
return false;
}
return true;
}
}