ec_gtk3_redirect.c (ettercap-0.8.3) | : | ec_gtk3_redirect.c (ettercap-0.8.3.1) | ||
---|---|---|---|---|
skipping to change at line 105 | skipping to change at line 105 | |||
treeview = gtk_tree_view_new(); | treeview = gtk_tree_view_new(); | |||
gtk_container_add(GTK_CONTAINER(scrolled), treeview); | gtk_container_add(GTK_CONTAINER(scrolled), treeview); | |||
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); | |||
gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); | gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); | |||
renderer = gtk_cell_renderer_text_new(); | renderer = gtk_cell_renderer_text_new(); | |||
column = gtk_tree_view_column_new_with_attributes("IP Version", renderer, | column = gtk_tree_view_column_new_with_attributes("IP Version", renderer, | |||
"text", 1, NULL); | "text", 1, NULL); | |||
gtk_tree_view_column_set_sort_column_id(column, 0); | ||||
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | ||||
renderer = gtk_cell_renderer_text_new(); | ||||
column = gtk_tree_view_column_new_with_attributes("Source", renderer, | ||||
"text", 2, NULL); | ||||
gtk_tree_view_column_set_sort_column_id(column, 1); | gtk_tree_view_column_set_sort_column_id(column, 1); | |||
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |||
renderer = gtk_cell_renderer_text_new(); | renderer = gtk_cell_renderer_text_new(); | |||
column = gtk_tree_view_column_new_with_attributes("Destination", renderer, | column = gtk_tree_view_column_new_with_attributes("Server IP", renderer, | |||
"text", 3, NULL); | "text", 2, NULL); | |||
gtk_tree_view_column_set_sort_column_id(column, 2); | gtk_tree_view_column_set_sort_column_id(column, 2); | |||
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |||
renderer = gtk_cell_renderer_text_new(); | renderer = gtk_cell_renderer_text_new(); | |||
column = gtk_tree_view_column_new_with_attributes("Service", renderer, | column = gtk_tree_view_column_new_with_attributes("Service", renderer, | |||
"text", 7, NULL); | "text", 6, NULL); | |||
gtk_tree_view_column_set_sort_column_id(column, 3); | gtk_tree_view_column_set_sort_column_id(column, 6); | |||
gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); | |||
gtkui_sslredir_create_lists(); | gtkui_sslredir_create_lists(); | |||
model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(redirrules)); | model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(redirrules)); | |||
gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), model); | gtk_tree_view_set_model(GTK_TREE_VIEW(treeview), model); | |||
hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); | hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5); | |||
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |||
skipping to change at line 179 | skipping to change at line 173 | |||
G_CALLBACK(gtkui_sslredir_key_pressed), model); | G_CALLBACK(gtkui_sslredir_key_pressed), model); | |||
gtk_widget_show_all(sslredir_window); | gtk_widget_show_all(sslredir_window); | |||
} | } | |||
/* Add a new line to the Rules list */ | /* Add a new line to the Rules list */ | |||
static void gtkui_sslredir_add(GtkWidget *widget, gpointer data) | static void gtkui_sslredir_add(GtkWidget *widget, gpointer data) | |||
{ | { | |||
GtkWidget *dialog, *content, *grid, *source, *destination, *label, *frame; | GtkWidget *dialog, *content, *grid, *destination, *label, *frame; | |||
GtkWidget *proto, *af; | GtkWidget *proto, *af; | |||
GtkTreeModel *model; | GtkTreeModel *model; | |||
GtkTreeIter iter; | GtkTreeIter iter; | |||
GtkCellRenderer *cell1, *cell2; | GtkCellRenderer *cell1, *cell2; | |||
GtkWidget *entry_widgets[2]; | ||||
GVariant *gv_from_port, *gv_to_port; | GVariant *gv_from_port, *gv_to_port; | |||
int ret = 0; | int ret = 0; | |||
guint16 from_port, to_port; | guint16 from_port, to_port; | |||
gchar *name; | gchar *name; | |||
const gchar *from, *to; | const gchar *server; | |||
ec_redir_proto_t ip_ver; | ec_redir_proto_t ip_ver; | |||
/* unused variabled */ | /* unused variabled */ | |||
(void) widget; | (void) widget; | |||
(void) data; | (void) data; | |||
DEBUG_MSG("gtkui_sslredir_add()"); | DEBUG_MSG("gtkui_sslredir_add()"); | |||
/* compile IP protocol family list if not already done */ | /* compile IP protocol family list if not already done */ | |||
if (af_list == NULL) { | if (af_list == NULL) { | |||
skipping to change at line 251 | skipping to change at line 244 | |||
af = gtk_combo_box_new(); | af = gtk_combo_box_new(); | |||
gtk_combo_box_set_model(GTK_COMBO_BOX(af), GTK_TREE_MODEL(af_list)); | gtk_combo_box_set_model(GTK_COMBO_BOX(af), GTK_TREE_MODEL(af_list)); | |||
gtk_combo_box_set_active(GTK_COMBO_BOX(af), 0); | gtk_combo_box_set_active(GTK_COMBO_BOX(af), 0); | |||
cell1 = gtk_cell_renderer_text_new(); | cell1 = gtk_cell_renderer_text_new(); | |||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(af), cell1, TRUE); | gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(af), cell1, TRUE); | |||
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(af), cell1, | gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(af), cell1, | |||
"text", 0, NULL); | "text", 0, NULL); | |||
gtk_grid_attach(GTK_GRID(grid), af, GTK_POS_LEFT+1, GTK_POS_TOP, 1, 1); | gtk_grid_attach(GTK_GRID(grid), af, GTK_POS_LEFT+1, GTK_POS_TOP, 1, 1); | |||
label = gtk_label_new("Source:"); | label = gtk_label_new("Server IP:"); | |||
gtk_widget_set_halign(label, GTK_ALIGN_START); | gtk_widget_set_halign(label, GTK_ALIGN_START); | |||
gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+1, 1, 1); | gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+1, 1, 1); | |||
source = gtk_entry_new(); | ||||
gtk_entry_set_text(GTK_ENTRY(source), "0.0.0.0/0"); | ||||
gtk_widget_grab_focus(source); | ||||
gtk_widget_activate(source); | ||||
gtk_grid_attach(GTK_GRID(grid), source, GTK_POS_LEFT+1, GTK_POS_TOP+1, 1, 1); | ||||
label = gtk_label_new("Destination:"); | ||||
gtk_widget_set_halign(label, GTK_ALIGN_START); | ||||
gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+2, 1, 1); | ||||
destination = gtk_entry_new(); | destination = gtk_entry_new(); | |||
gtk_entry_set_text(GTK_ENTRY(destination), "0.0.0.0/0"); | gtk_entry_set_text(GTK_ENTRY(destination), "0.0.0.0/0"); | |||
gtk_grid_attach(GTK_GRID(grid), destination, GTK_POS_LEFT+1, GTK_POS_TOP+2, 1 , 1); | gtk_grid_attach(GTK_GRID(grid), destination, GTK_POS_LEFT+1, GTK_POS_TOP+1, 1 , 1); | |||
label = gtk_label_new("Service:"); | label = gtk_label_new("Service:"); | |||
gtk_widget_set_halign(label, GTK_ALIGN_START); | gtk_widget_set_halign(label, GTK_ALIGN_START); | |||
gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+3, 1, 1); | gtk_grid_attach(GTK_GRID(grid), label, GTK_POS_LEFT, GTK_POS_TOP+2, 1, 1); | |||
proto = gtk_combo_box_new(); | proto = gtk_combo_box_new(); | |||
gtk_combo_box_set_model(GTK_COMBO_BOX(proto), GTK_TREE_MODEL(proto_list)); | gtk_combo_box_set_model(GTK_COMBO_BOX(proto), GTK_TREE_MODEL(proto_list)); | |||
gtk_combo_box_set_active(GTK_COMBO_BOX(proto), 0); | gtk_combo_box_set_active(GTK_COMBO_BOX(proto), 0); | |||
cell2 = gtk_cell_renderer_text_new(); | cell2 = gtk_cell_renderer_text_new(); | |||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(proto), cell2, TRUE); | gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(proto), cell2, TRUE); | |||
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(proto), cell2, | gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(proto), cell2, | |||
"text", 1, NULL); | "text", 1, NULL); | |||
gtk_grid_attach(GTK_GRID(grid), proto, GTK_POS_LEFT+1, GTK_POS_TOP+3, 1, 1); | gtk_grid_attach(GTK_GRID(grid), proto, GTK_POS_LEFT+1, GTK_POS_TOP+2, 1, 1); | |||
entry_widgets[0] = source; | ||||
entry_widgets[1] = destination; | ||||
g_signal_connect(G_OBJECT(af), "changed", | g_signal_connect(G_OBJECT(af), "changed", | |||
G_CALLBACK(gtkui_sslredir_af_changed), entry_widgets); | G_CALLBACK(gtkui_sslredir_af_changed), destination); | |||
gtk_widget_show_all(dialog); | gtk_widget_show_all(dialog); | |||
gtk_widget_grab_focus(destination); | ||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { | if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { | |||
gtk_widget_hide(dialog); | gtk_widget_hide(dialog); | |||
/* extract information from widgets */ | /* extract information from widgets */ | |||
model = gtk_combo_box_get_model(GTK_COMBO_BOX(af)); | model = gtk_combo_box_get_model(GTK_COMBO_BOX(af)); | |||
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(af), &iter); | gtk_combo_box_get_active_iter(GTK_COMBO_BOX(af), &iter); | |||
gtk_tree_model_get(model, &iter, 1, &ip_ver, -1); | gtk_tree_model_get(model, &iter, 1, &ip_ver, -1); | |||
model = gtk_combo_box_get_model(GTK_COMBO_BOX(proto)); | model = gtk_combo_box_get_model(GTK_COMBO_BOX(proto)); | |||
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(proto), &iter); | gtk_combo_box_get_active_iter(GTK_COMBO_BOX(proto), &iter); | |||
gtk_tree_model_get(model, &iter, 0, &name, | gtk_tree_model_get(model, &iter, 0, &name, | |||
2, &gv_from_port, 3, &gv_to_port, -1); | 2, &gv_from_port, 3, &gv_to_port, -1); | |||
/* convert back from GVariant to uint16 */ | /* convert back from GVariant to uint16 */ | |||
from_port = g_variant_get_uint16(gv_from_port); | from_port = g_variant_get_uint16(gv_from_port); | |||
to_port = g_variant_get_uint16(gv_to_port); | to_port = g_variant_get_uint16(gv_to_port); | |||
from = gtk_entry_get_text(GTK_ENTRY(source)); | server = gtk_entry_get_text(GTK_ENTRY(destination)); | |||
to = gtk_entry_get_text(GTK_ENTRY(destination)); | ||||
/* execute redirect action */ | /* execute redirect action */ | |||
ret = ec_redirect(EC_REDIR_ACTION_INSERT, name, ip_ver, | ret = ec_redirect(EC_REDIR_ACTION_INSERT, name, ip_ver, | |||
from, to, from_port, to_port); | server, from_port, to_port); | |||
/* inform user if redirect execution wasn't successful */ | /* inform user if redirect execution wasn't successful */ | |||
if (ret != E_SUCCESS) | if (ret != E_SUCCESS) | |||
gtkui_infobar_show(GTK_MESSAGE_ERROR, | gtkui_infobar_show(GTK_MESSAGE_ERROR, | |||
"Insertion of redirect rule failed."); | "Insertion of redirect rule failed."); | |||
else { /* otherwise add rule to rules list */ | else { /* otherwise add rule to rules list */ | |||
gtk_list_store_append(redirrules, &iter); | gtk_list_store_append(redirrules, &iter); | |||
gtk_list_store_set(redirrules, &iter, | gtk_list_store_set(redirrules, &iter, | |||
0, ip_ver, | 0, ip_ver, | |||
1, (ip_ver == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"), | 1, (ip_ver == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"), | |||
2, from, | 2, server, | |||
3, to, | 3, gv_from_port, | |||
4, gv_from_port, | 4, gv_to_port, | |||
5, gv_to_port, | 5, ec_strlc(name), | |||
6, ec_strlc(name), | 6, ec_struc(name), | |||
7, ec_struc(name), | ||||
-1); | -1); | |||
} | } | |||
} | } | |||
gtk_widget_destroy(dialog); | gtk_widget_destroy(dialog); | |||
} | } | |||
/* | /* | |||
* remove selected redirect rules | * remove selected redirect rules | |||
*/ | */ | |||
void gtkui_sslredir_del(GtkWidget *widget, gpointer data) | void gtkui_sslredir_del(GtkWidget *widget, gpointer data) | |||
{ | { | |||
GList *list; | GList *list; | |||
GtkTreeIter iter, iter_unsorted; | GtkTreeIter iter, iter_unsorted; | |||
GtkTreeModel *model; | GtkTreeModel *model; | |||
GVariant *gv_from_port, *gv_to_port; | GVariant *gv_from_port, *gv_to_port; | |||
int ret; | int ret; | |||
gchar *name; | gchar *name; | |||
const gchar *from, *to; | const gchar *server; | |||
guint16 from_port, to_port; | guint16 from_port, to_port; | |||
ec_redir_proto_t ip_ver; | ec_redir_proto_t ip_ver; | |||
/* variable not used */ | /* variable not used */ | |||
(void) widget; | (void) widget; | |||
DEBUG_MSG("gtkui_sslredir_del()"); | DEBUG_MSG("gtkui_sslredir_del()"); | |||
model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(data)); | model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(data)); | |||
/* get selected entries */ | /* get selected entries */ | |||
if (gtk_tree_selection_count_selected_rows(selection) > 0) { | if (gtk_tree_selection_count_selected_rows(selection) > 0) { | |||
list = gtk_tree_selection_get_selected_rows(selection, &model); | list = gtk_tree_selection_get_selected_rows(selection, &model); | |||
for (list = g_list_last(list); list; list = g_list_previous(list)) { | for (list = g_list_last(list); list; list = g_list_previous(list)) { | |||
/* extract parameters from GtkTreeView model */ | /* extract parameters from GtkTreeView model */ | |||
gtk_tree_model_get_iter(model, &iter, list->data); | gtk_tree_model_get_iter(model, &iter, list->data); | |||
gtk_tree_model_get(model, &iter, | gtk_tree_model_get(model, &iter, | |||
0, &ip_ver, | 0, &ip_ver, | |||
2, &from, | 2, &server, | |||
3, &to, | 3, &gv_from_port, | |||
4, &gv_from_port, | 4, &gv_to_port, | |||
5, &gv_to_port, | 5, &name, | |||
6, &name, | ||||
-1); | -1); | |||
/* convert back from GVariant to uint16 */ | /* convert back from GVariant to uint16 */ | |||
from_port = g_variant_get_uint16(gv_from_port); | from_port = g_variant_get_uint16(gv_from_port); | |||
to_port = g_variant_get_uint16(gv_to_port); | to_port = g_variant_get_uint16(gv_to_port); | |||
/* execute redirect action */ | /* execute redirect action */ | |||
ret = ec_redirect(EC_REDIR_ACTION_REMOVE, name, ip_ver, | ret = ec_redirect(EC_REDIR_ACTION_REMOVE, name, ip_ver, | |||
from, to, from_port, to_port); | server, from_port, to_port); | |||
/* inform user if redirect execution wasn't successful */ | /* inform user if redirect execution wasn't successful */ | |||
if (ret != E_SUCCESS) | if (ret != E_SUCCESS) | |||
gtkui_infobar_show(GTK_MESSAGE_ERROR, | gtkui_infobar_show(GTK_MESSAGE_ERROR, | |||
"Removal of redirect rule failed."); | "Removal of redirect rule failed."); | |||
else { /* otherwise remove from list */ | else { /* otherwise remove from list */ | |||
gtk_tree_model_sort_convert_iter_to_child_iter( | gtk_tree_model_sort_convert_iter_to_child_iter( | |||
GTK_TREE_MODEL_SORT(data), &iter_unsorted, &iter); | GTK_TREE_MODEL_SORT(data), &iter_unsorted, &iter); | |||
gtk_list_store_remove(GTK_LIST_STORE(redirrules), &iter_unsorted); | gtk_list_store_remove(GTK_LIST_STORE(redirrules), &iter_unsorted); | |||
} | } | |||
skipping to change at line 457 | skipping to change at line 436 | |||
* create the list for the list of interceptable protocols | * create the list for the list of interceptable protocols | |||
*/ | */ | |||
static void gtkui_sslredir_create_lists(void) | static void gtkui_sslredir_create_lists(void) | |||
{ | { | |||
int res; | int res; | |||
DEBUG_MSG("gtk_sslredir_create_lists()"); | DEBUG_MSG("gtk_sslredir_create_lists()"); | |||
/* populate redirect rules */ | /* populate redirect rules */ | |||
if (redirrules == NULL) { | if (redirrules == NULL) { | |||
redirrules = gtk_list_store_new(8, | redirrules = gtk_list_store_new(7, | |||
G_TYPE_UINT, /* IP address family */ | G_TYPE_UINT, /* IP address family */ | |||
G_TYPE_STRING, /* IP address family human readable */ | G_TYPE_STRING, /* IP address family human readable */ | |||
G_TYPE_STRING, /* source definition */ | ||||
G_TYPE_STRING, /* destination definition */ | G_TYPE_STRING, /* destination definition */ | |||
G_TYPE_VARIANT, /* protocol registered port */ | G_TYPE_VARIANT, /* protocol registered port */ | |||
G_TYPE_VARIANT, /* ettercap listener port */ | G_TYPE_VARIANT, /* ettercap listener port */ | |||
G_TYPE_STRING, /* protocol name lower case */ | G_TYPE_STRING, /* protocol name lower case */ | |||
G_TYPE_STRING); /* protocol name upper case */ | G_TYPE_STRING); /* protocol name upper case */ | |||
/* walk through list of registered redirects */ | /* walk through list of registered redirects */ | |||
res = ec_walk_redirects(>kui_sslredir_add_list); | res = ec_walk_redirects(>kui_sslredir_add_list); | |||
if (res == -E_NOTFOUND) { | if (res == -E_NOTFOUND) { | |||
DEBUG_MSG("gtk_sslredir_create_lists(): no redirects registered - " | DEBUG_MSG("gtk_sslredir_create_lists(): no redirects registered - " | |||
skipping to change at line 538 | skipping to change at line 516 | |||
/* make GVariant from uint16 */ | /* make GVariant from uint16 */ | |||
gv_from_port = g_variant_new_uint16(re->from_port); | gv_from_port = g_variant_new_uint16(re->from_port); | |||
gv_to_port = g_variant_new_uint16(re->to_port); | gv_to_port = g_variant_new_uint16(re->to_port); | |||
/* add rule to rules list */ | /* add rule to rules list */ | |||
gtk_list_store_append(redirrules, &iter); | gtk_list_store_append(redirrules, &iter); | |||
gtk_list_store_set(redirrules, &iter, | gtk_list_store_set(redirrules, &iter, | |||
0, re->proto, | 0, re->proto, | |||
1, (re->proto == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"), | 1, (re->proto == EC_REDIR_PROTO_IPV4 ? "IPv4" : "IPv6"), | |||
2, re->source, | 2, re->destination, | |||
3, re->destination, | 3, gv_from_port, | |||
4, gv_from_port, | 4, gv_to_port, | |||
5, gv_to_port, | 5, ec_strlc(re->name), | |||
6, ec_strlc(re->name), | 6, ec_struc(re->name), | |||
7, ec_struc(re->name), | ||||
-1); | -1); | |||
} | } | |||
/* | /* | |||
* callback when IP address family is changed | * callback when IP address family is changed | |||
* - update preset string of source / destination entry widgets | * - update preset string of source / destination entry widgets | |||
*/ | */ | |||
void gtkui_sslredir_af_changed(GtkWidget *widget, gpointer data) | void gtkui_sslredir_af_changed(GtkWidget *widget, gpointer data) | |||
{ | { | |||
GtkWidget **widgets; | ||||
GtkTreeModel *model; | GtkTreeModel *model; | |||
GtkTreeIter iter; | GtkTreeIter iter; | |||
ec_redir_proto_t proto; | ec_redir_proto_t proto; | |||
widgets = data; | ||||
model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); | model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); | |||
gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter); | gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter); | |||
gtk_tree_model_get(model, &iter, 1, &proto, -1); | gtk_tree_model_get(model, &iter, 1, &proto, -1); | |||
switch (proto) { | switch (proto) { | |||
case EC_REDIR_PROTO_IPV4: | case EC_REDIR_PROTO_IPV4: | |||
gtk_entry_set_text(GTK_ENTRY(widgets[0]), "0.0.0.0/0"); | gtk_entry_set_text(GTK_ENTRY(data), "0.0.0.0/0"); | |||
gtk_entry_set_text(GTK_ENTRY(widgets[1]), "0.0.0.0/0"); | gtk_widget_grab_focus(data); | |||
gtk_widget_grab_focus(widgets[0]); | ||||
break; | break; | |||
case EC_REDIR_PROTO_IPV6: | case EC_REDIR_PROTO_IPV6: | |||
gtk_entry_set_text(GTK_ENTRY(widgets[0]), "::/0"); | gtk_entry_set_text(GTK_ENTRY(data), "::/0"); | |||
gtk_entry_set_text(GTK_ENTRY(widgets[1]), "::/0"); | gtk_widget_grab_focus(data); | |||
gtk_widget_grab_focus(widgets[0]); | ||||
break; | break; | |||
default: | default: | |||
break; | break; | |||
} | } | |||
} | } | |||
/* | /* | |||
* callback function when delete key is pressed in redirect rule list | * callback function when delete key is pressed in redirect rule list | |||
*/ | */ | |||
End of changes. 27 change blocks. | ||||
63 lines changed or deleted | 35 lines changed or added |