1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 * Gui Policy Editor for TOMOYO Linux
6 * Copyright (C) Yoshihiro Kusuno 2010,2011 <yocto@users.sourceforge.jp>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Library General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
28 #include <glib/gi18n.h>
32 static void terminate(GtkAction *action, transition_t *transition);
33 static void copy_line(GtkAction *action, transition_t *transition);
34 static void optimize_acl(GtkAction *action, transition_t *transition);
35 static void delete_transition(GtkAction *action, transition_t *transition);
36 static void insert_history_buffer(GtkWidget *view, gchar *entry);
37 static void append_transition(GtkAction *action, transition_t *transition);
38 static void set_transition(GtkAction *action, transition_t *transition);
39 static void manager_transition(GtkAction *action, transition_t *transition);
40 static void memory_transition(GtkAction *action, transition_t *transition);
41 static void show_about_dialog(void);
42 static void Process_state(GtkAction *action, transition_t *transition);
43 static void Detach_acl(GtkAction *action, transition_t *transition);
45 static GtkActionEntry entries[] = {
46 {"FileMenu", NULL, N_("_File")},
47 {"EditMenu", NULL, N_("_Edit")},
48 {"ViewMenu", NULL, N_("_View")},
49 {"HelpMenu", NULL, N_("_Help")},
51 {"Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q",
52 N_("Quit a program"), G_CALLBACK(terminate)},
54 {"Edit", GTK_STOCK_EDIT, N_("S_et"), "<control>E",
55 N_("Set or Edit the selected line"), G_CALLBACK(set_transition)},
56 {"Add", GTK_STOCK_ADD, N_("_Add"), "<control>I",
57 N_("Append line"), G_CALLBACK(append_transition)},
58 {"Delete", GTK_STOCK_DELETE, N_("_Delete"), "<control>D",
59 N_("Delete the selected line"), G_CALLBACK(delete_transition)},
60 {"Copy", GTK_STOCK_COPY, N_("_Copy"), "<control>C",
61 N_("Copy an entry at the cursor position to history buffer"),
62 G_CALLBACK(copy_line)},
63 {"OptimizationSupport", GTK_STOCK_CONVERT,
64 N_("_OptimizationSupport"), "<control>O",
65 N_("Extraction of redundant ACL entries"), G_CALLBACK(optimize_acl)},
67 {"Search", GTK_STOCK_FIND, N_("_Search..."), "<control>F",
68 N_("Search for text"), G_CALLBACK(search_input)},
69 {"SearchBack", GTK_STOCK_GO_BACK, N_("Search_Backwards"), "<control><shift>G",
70 N_("Search backwards for the same text"), G_CALLBACK(search_back)},
71 {"SearchFoward", GTK_STOCK_GO_FORWARD, N_("SearchFor_wards"), "<control>G",
72 N_("Search forwards for the same text"), G_CALLBACK(search_forward)},
74 {"Refresh", GTK_STOCK_REFRESH, N_("_Refresh"), "<control>R",
75 N_("Refresh to the latest information"), G_CALLBACK(refresh_transition)},
76 {"Manager", GTK_STOCK_DND, N_("_Manager..."), "<control>M",
77 N_("Manager Profile Editor"), G_CALLBACK(manager_transition)},
78 {"Memory", GTK_STOCK_DND, N_("_Statistics..."), "<control>S",
79 N_("Statistics"), G_CALLBACK(memory_transition)},
81 {"About", GTK_STOCK_ABOUT, N_("_About"), "<alt>A",
82 N_("About a program"), show_about_dialog}
84 static guint n_entries = G_N_ELEMENTS(entries);
86 static GtkToggleActionEntry toggle_entries[] = {
87 { "Process", GTK_STOCK_MEDIA_RECORD, N_("Process"), "<control>at",
88 N_("Process State Viewer"), G_CALLBACK(Process_state), FALSE},
89 { "ACL", "", N_("Detach ACL"), "",
90 N_("Detach ACL window"), G_CALLBACK(Detach_acl), FALSE},
92 static guint n_toggle_entries = G_N_ELEMENTS(toggle_entries);
94 static const gchar *ui_info =
96 " <menubar name='MenuBar'>"
97 " <menu action='FileMenu'>"
98 " <menuitem action='Quit'/>"
101 " <menu action='EditMenu'>"
102 " <menuitem action='Edit'/>"
103 " <menuitem action='Add'/>"
104 " <menuitem action='Delete'/>"
106 " <menuitem action='Copy'/>"
107 " <menuitem action='OptimizationSupport'/>"
109 " <menuitem action='Search'/>"
110 " <menuitem action='SearchBack'/>"
111 " <menuitem action='SearchFoward'/>"
114 " <menu action='ViewMenu'>"
115 " <menuitem action='Refresh'/>"
117 " <menuitem action='Manager'/>"
118 " <menuitem action='Memory'/>"
120 " <menuitem action='Process'/>"
122 " <menuitem action='ACL'/>"
125 " <menu action='HelpMenu'>"
126 " <menuitem action='About'/>"
130 " <toolbar name='ToolBar'>"
131 " <toolitem action='Quit'/>"
133 " <toolitem action='Edit'/>"
134 " <toolitem action='Add'/>"
135 " <toolitem action='Delete'/>"
137 " <toolitem action='Copy'/>"
138 " <toolitem action='OptimizationSupport'/>"
140 " <toolitem action='Search'/>"
141 " <toolitem action='SearchBack'/>"
142 " <toolitem action='SearchFoward'/>"
144 " <toolitem action='Refresh'/>"
146 " <toolitem action='Process'/>"
148 " <toolitem action='About'/>"
151 " <popup name='PopUp'>"
152 " <menuitem action='Edit'/>"
153 " <menuitem action='Add'/>"
154 " <menuitem action='Delete'/>"
156 " <menuitem action='Copy'/>"
157 " <menuitem action='OptimizationSupport'/>"
161 GtkWidget *create_menu(GtkWidget *parent, transition_t *transition,
165 GtkActionGroup *actions;
166 GtkAccelGroup *accel_group;
167 GError *error = NULL;
170 actions = gtk_action_group_new("Actions");
171 gtk_action_group_set_translation_domain(actions, GETTEXT_PACKAGE);
172 gtk_action_group_add_actions(actions,
173 entries, n_entries, transition);
174 gtk_action_group_add_toggle_actions(actions,
175 toggle_entries, n_toggle_entries, transition);
177 ui = gtk_ui_manager_new();
178 gtk_ui_manager_insert_action_group(ui, actions, 0);
180 gtk_action_set_sensitive(
181 gtk_action_group_get_action(actions, "Search"), TRUE);
182 gtk_action_set_sensitive(
183 gtk_action_group_get_action(actions, "SearchBack"), FALSE);
184 gtk_action_set_sensitive(
185 gtk_action_group_get_action(actions, "SearchFoward"), FALSE);
186 gtk_action_set_sensitive(
187 gtk_action_group_get_action(actions, "Edit"), FALSE);
188 gtk_action_set_sensitive(gtk_action_group_get_action(
189 actions, "OptimizationSupport"), FALSE);
192 gtk_action_set_sensitive(
193 gtk_action_group_get_action(actions, "Process"), FALSE);
194 gtk_action_set_sensitive(
195 gtk_action_group_get_action(actions, "Memory"), FALSE);
198 transition->actions = actions;
200 // gtk_ui_manager_set_add_tearoffs(ui, TRUE);
201 accel_group = gtk_ui_manager_get_accel_group(ui);
202 gtk_window_add_accel_group(GTK_WINDOW(parent), accel_group);
203 if (!gtk_ui_manager_add_ui_from_string(ui, ui_info, -1, NULL)) {
204 g_message ("building menus failed: %s", error->message);
205 g_error_free (error);
208 *toolbar = gtk_ui_manager_get_widget(ui, "/ToolBar");
209 gtk_toolbar_set_style(GTK_TOOLBAR(*toolbar), GTK_TOOLBAR_ICONS);
211 /* to save gpet.c popup_menu() */
212 popup = gtk_ui_manager_get_widget(ui, "/PopUp");
213 g_object_set_data(G_OBJECT(transition->window), "popup", popup);
215 /* to save gpet.c gpet_main() */
216 g_object_set_data(G_OBJECT(transition->window),
217 "AccelGroup", accel_group);
219 return gtk_ui_manager_get_widget(ui, "/MenuBar");
221 /*-------+---------+---------+---------+---------+---------+---------+--------*/
222 void disp_statusbar(transition_t *transition, int scr)
224 gchar *status_str = NULL;
227 case CCS_SCREEN_EXCEPTION_LIST :
228 status_str = g_strdup_printf("Entry[%d]",
229 transition->exp.count);
231 case CCS_SCREEN_PROFILE_LIST :
232 status_str = g_strdup_printf("Entry[%d]",
233 transition->prf.count);
235 case CCS_SCREEN_NS_LIST :
236 status_str = g_strdup_printf("Entry[%d]",
237 transition->ns.count);
239 case CCS_SCREEN_DOMAIN_LIST :
240 case CCS_SCREEN_ACL_LIST :
241 if (transition->task_flag)
242 status_str = g_strdup_printf("Process[%d] Policy[%d]",
243 transition->tsk.count, transition->acl.count);
245 status_str = g_strdup_printf("Domain[%d] Policy[%d]",
246 transition->domain_count, transition->acl.count);
249 status_str = g_strdup_printf("Domain[%d]",
250 transition->domain_count);
253 g_warning("BUG: screen [%d] file(%s) line(%d)",
254 scr, __FILE__, __LINE__);
257 gtk_statusbar_pop(GTK_STATUSBAR(transition->statusbar),
258 transition->contextid);
259 gtk_statusbar_push(GTK_STATUSBAR(transition->statusbar),
260 transition->contextid, status_str);
263 /*---------------------------------------------------------------------------*/
264 /* from realpath.c (ccs-patch-1.8.1-20110505) */
265 gchar *encode_to_octal_str(const char *str)
277 str_len = strlen(str);
278 for (i = 0; i < str_len; i++) {
279 const unsigned char c = p[i];
283 else if (c > ' ' && c < 127)
290 /* Reserve space for appending "/". */
291 cp = g_malloc0(len + 10);
297 for (i = 0; i < str_len; i++) {
298 const unsigned char c = p[i];
302 } else if (c > ' ' && c < 127) {
306 *cp++ = (c >> 6) + '0';
307 *cp++ = ((c >> 3) & 7) + '0';
308 *cp++ = (c & 7) + '0';
314 static gint encode_copy(gchar *cp, gchar *buff)
322 str = encode_to_octal_str(cp);
324 len = strlen(str) - 1;
330 static gchar *escape_str_encode(const char *input)
332 gchar *str, *cp0, *cp1;
333 gchar *tmp, buff[strlen(input)*3+1];
334 gboolean match = FALSE;
339 cp0 = str = g_strdup(input);
341 for( ; *cp0; cp0++, tmp++) {
342 if (*cp0 == '\\' && *(cp0 + 1) == '\'') {
344 } else if (*cp0 == '\'') { // start "
346 for ( ; *cp0; cp0++) {
347 if (*cp0 == '\\' && *(cp0 + 1) == '\'') {
350 tmp += encode_copy(cp1, tmp);
356 } else if (*cp0 == '\'') { // end "
364 tmp += encode_copy(cp1, tmp);
367 g_warning(" [\']pair not match!");
378 return g_strdup(buff);
380 /*-------+---------+---------+---------+---------+---------+---------+--------*/
381 static void terminate(GtkAction *action, transition_t *transition)
383 write_config(transition);
384 g_object_unref(transition->actions);
387 /*-------+---------+---------+---------+---------+---------+---------+--------*/
388 static gulong handler_id = 0UL;
390 static gboolean cb_destroy_acl(GtkWidget *widget, GdkEvent *event,
391 transition_t *transition)
393 GtkWidget *acl_container;
396 if (handler_id == 0UL)
399 /* get gpet.c main()*/
400 acl_container = g_object_get_data(G_OBJECT(transition->window), "acl_container");
401 paned = g_object_get_data(G_OBJECT(transition->window), "pane");
403 g_signal_handler_disconnect(
404 G_OBJECT(transition->acl_window), handler_id);
407 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(
408 gtk_action_group_get_action(transition->actions, "ACL")), FALSE);
409 transition->acl_detached = FALSE;
411 gtk_widget_reparent(GTK_WIDGET(transition->container),
414 gtk_widget_reparent(GTK_WIDGET(acl_container),
417 transition->current_page = CCS_SCREEN_DOMAIN_LIST;
418 set_sensitive(transition->actions, transition->task_flag,
419 transition->current_page);
420 refresh_transition(NULL, transition);
422 return gtk_widget_hide_on_delete(transition->acl_window);
425 static void Detach_acl(GtkAction *action, transition_t *transition)
427 GtkWidget *acl_container;
429 /* get gpet.c main()*/
430 acl_container = g_object_get_data(G_OBJECT(transition->window), "acl_container");
431 paned = g_object_get_data(G_OBJECT(transition->window), "pane");
433 if (transition->acl_detached) {
434 cb_destroy_acl(NULL, NULL, transition);
436 gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(
437 gtk_action_group_get_action(transition->actions, "ACL")), TRUE);
438 transition->acl_detached = TRUE;
439 handler_id = g_signal_connect(
440 G_OBJECT(transition->acl_window), "delete_event",
441 G_CALLBACK(cb_destroy_acl), transition);
442 gtk_widget_reparent(GTK_WIDGET(acl_container),
443 transition->acl_window);
444 gtk_widget_show_all(transition->acl_window);
446 gtk_widget_reparent(GTK_WIDGET(transition->container),
448 transition->current_page = CCS_SCREEN_ACL_LIST;
449 set_sensitive(transition->actions, transition->task_flag,
450 transition->current_page);
451 refresh_transition(NULL, transition);
454 /*-------+---------+---------+---------+---------+---------+---------+--------*/
455 static void Process_state(GtkAction *action, transition_t *transition)
462 view = transition->task_flag ?
463 transition->tsk.treeview : transition->treeview;
464 gtk_container_remove(transition->container, view);
467 transition->task_flag = ~transition->task_flag & 1;
469 if (transition->task_flag) {
470 label_str = _("Process State");
471 view = transition->tsk.treeview;
473 label_str = _("Domain Transition");
474 view = transition->treeview;
477 /* from gpet.c:gpet_main()*/
478 notebook = g_object_get_data(
479 G_OBJECT(transition->window), "notebook");
480 tab1 = g_object_get_data(
481 G_OBJECT(transition->window), "tab1");
482 gtk_notebook_set_tab_label_text(
483 GTK_NOTEBOOK(notebook), tab1, label_str);
484 gtk_notebook_set_menu_label_text(
485 GTK_NOTEBOOK(notebook), tab1, label_str);
487 gtk_container_add(transition->container, view);
489 transition->current_page = CCS_SCREEN_DOMAIN_LIST;
490 set_sensitive(transition->actions, transition->task_flag,
491 transition->current_page);
492 if (transition->acl_detached)
493 g_object_set(G_OBJECT(notebook), "can-focus", FALSE, NULL);
495 g_object_set(G_OBJECT(notebook), "can-focus", TRUE, NULL);
496 refresh_transition(action, transition);
498 /*-------+---------+---------+---------+---------+---------+---------+--------*/
499 void view_cursor_set(GtkWidget *view,
500 GtkTreePath *path, GtkTreeViewColumn *column)
503 path = gtk_tree_path_new_from_indices(0, -1);
507 gchar *path_str = gtk_tree_path_to_string(path);
508 DEBUG_PRINT("<%s> TreePath[%s]\n",
509 g_type_name(G_OBJECT_TYPE(view)), path_str);
513 gtk_tree_view_set_cursor(GTK_TREE_VIEW(view), path, column, FALSE);
514 gtk_tree_path_free(path);
515 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view), &path, &column);
517 path = gtk_tree_path_new_from_indices(0, -1);
518 gtk_tree_view_set_cursor(
519 GTK_TREE_VIEW(view), path, column, FALSE);
521 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view), path, NULL,
522 TRUE, 0.5, 0.0); // ksn
523 gtk_tree_path_free(path);
526 static void clear_acl_view(transition_t *transition)
528 gtk_entry_set_text(GTK_ENTRY(transition->domainbar), get_ns_name());
529 transition->acl.count = 0;
530 add_list_data(&(transition->acl), CCS_SCREEN_ACL_LIST);
533 void refresh_transition(GtkAction *action, transition_t *transition)
535 GtkTreePath *path = NULL;
536 GtkTreeViewColumn *column = NULL;
537 GtkWidget *view = NULL;
539 DEBUG_PRINT("In Refresh Page[%d]\n", (int)transition->current_page);
540 switch((int)transition->current_page) {
541 case CCS_SCREEN_EXCEPTION_LIST :
542 view = transition->exp.listview;
543 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
545 if (get_exception_policy(
546 &(transition->exp.list), &(transition->exp.count)))
548 add_list_data(&(transition->exp), CCS_SCREEN_EXCEPTION_LIST);
549 set_position_addentry(transition, &path);
550 disp_statusbar(transition, CCS_SCREEN_EXCEPTION_LIST);
551 view_cursor_set(view, path, column);
552 gtk_widget_grab_focus(view);
554 case CCS_SCREEN_PROFILE_LIST :
555 view = transition->prf.listview;
556 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
559 &(transition->prf.list), &(transition->prf.count)))
561 add_list_data(&(transition->prf), CCS_SCREEN_PROFILE_LIST);
562 set_position_addentry(transition, &path);
563 disp_statusbar(transition, CCS_SCREEN_PROFILE_LIST);
564 view_cursor_set(view, path, column);
565 gtk_widget_grab_focus(view);
567 case CCS_SCREEN_NS_LIST :
568 view = transition->ns.listview;
569 gtk_tree_view_get_cursor(GTK_TREE_VIEW(view),
572 &(transition->ns.list), &(transition->ns.count)))
574 add_list_data(&(transition->ns), CCS_SCREEN_NS_LIST);
575 set_position_addentry(transition, &path);
576 disp_statusbar(transition, CCS_SCREEN_NS_LIST);
577 view_cursor_set(view, path, column);
578 gtk_widget_grab_focus(view);
580 case CCS_SCREEN_DOMAIN_LIST :
582 view = transition->task_flag ?
583 transition->tsk.treeview : transition->treeview;
584 gtk_tree_view_get_cursor(
585 GTK_TREE_VIEW(view), &path, &column);
587 gtk_widget_hide(view);
588 if (transition->task_flag) {
589 if (get_task_list(&(transition->tsk.task),
590 &(transition->tsk.count)))
592 add_task_tree_data(GTK_TREE_VIEW(view), &(transition->tsk));
593 gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
594 view_cursor_set(view, path, column);
596 if (get_domain_policy(
597 transition->dp, &(transition->domain_count)))
599 add_tree_data(GTK_TREE_VIEW(view), transition->dp);
600 gtk_tree_view_expand_all(GTK_TREE_VIEW(view));
601 set_position_addentry(transition, &path);
602 if (transition->domain_count)
603 view_cursor_set(view, path, column);
605 clear_acl_view(transition);
607 gtk_widget_show(view);
608 gtk_widget_grab_focus(view);
610 case CCS_SCREEN_ACL_LIST :
611 view = transition->task_flag ?
612 transition->tsk.treeview : transition->treeview;
613 gtk_tree_view_get_cursor(
614 GTK_TREE_VIEW(view), &path, &column);
615 view_cursor_set(view, path, column);
616 gtk_widget_grab_focus(transition->acl.listview);
620 if (transition->acl_detached) {
621 DEBUG_PRINT("★Transition[%d] Acl[%d]\n",
622 gtk_window_has_toplevel_focus(GTK_WINDOW(transition->window)),
623 gtk_window_has_toplevel_focus(GTK_WINDOW(transition->acl_window)));
625 DEBUG_PRINT("Out Refresh Page[%d]\n", (int)transition->current_page);
627 /*-------+---------+---------+---------+---------+---------+---------+--------*/
628 static void copy_line(GtkAction *action, transition_t *transition)
633 switch((int)transition->current_page) {
634 case CCS_SCREEN_DOMAIN_LIST :
635 index = get_current_domain_index(transition);
636 view = transition->treeview;
638 insert_history_buffer(view, decode_from_octal_str(
639 get_domain_name(transition->dp, index)));
641 case CCS_SCREEN_ACL_LIST :
642 view = transition->acl.listview;
643 insert_history_buffer(view, get_alias_and_operand(view, TRUE));
645 case CCS_SCREEN_EXCEPTION_LIST :
646 view = transition->exp.listview;
647 insert_history_buffer(view, get_alias_and_operand(view, TRUE));
649 case CCS_SCREEN_PROFILE_LIST :
650 view = transition->prf.listview;
651 insert_history_buffer(view, get_alias_and_operand(view, FALSE));
653 case CCS_SCREEN_NS_LIST :
654 view = transition->ns.listview;
655 insert_history_buffer(view, get_alias_and_operand(view, FALSE));
661 /*-------+---------+---------+---------+---------+---------+---------+--------*/
662 static void optimize_acl(GtkAction *action, transition_t *transition)
664 GtkTreeSelection *selection;
668 if ((int)transition->current_page != CCS_SCREEN_ACL_LIST)
671 selection = gtk_tree_view_get_selection(
672 GTK_TREE_VIEW(transition->acl.listview));
673 if (!selection || !(count =
674 gtk_tree_selection_count_selected_rows(selection)))
676 DEBUG_PRINT("count[%d]\n", count);
679 current = select_list_line(&(transition->acl));
683 get_optimize_acl_list(current,
684 &(transition->acl.list), transition->acl.count);
686 model = gtk_tree_view_get_model(GTK_TREE_VIEW(transition->acl.listview));
687 gtk_tree_model_foreach(model,
688 (GtkTreeModelForeachFunc)disp_acl_line, &(transition->acl));
692 GtkTreePath *start_path, *end_path;
693 gint start_index, end_index;
695 start_path = end_path = gtk_tree_path_new_from_indices(current, -1);
696 gtk_tree_selection_unselect_range(selection, start_path, end_path);
698 for (index = 0; index < transition->acl.count; index++) {
699 if (transition->acl.list[index].selected)
703 start_path = gtk_tree_path_new_from_indices(index, -1);
704 start_index = end_index = index;
706 for ( ; index < transition->acl.count; index++) {
708 // 対象データ:ccs_gacl_list[index].selected == 1;
709 if (!transition->acl.list[index].selected)
713 if (index == (start_index + count)) {
714 end_path = gtk_tree_path_new_from_indices(index, -1);
718 end_path = start_path;
721 g_print("start[%d] end[%d]\n", start_index, end_index);
722 gtk_tree_selection_select_range(
723 selection, start_path, end_path);
725 start_path = gtk_tree_path_new_from_indices(index, -1);
733 g_print("start[%d] end[%d]\n", start_index, end_index);
734 gtk_tree_selection_select_range(selection, start_path, end_path);
738 /*-------+---------+---------+---------+---------+---------+---------+--------*/
739 static gint message_dialog(GtkWidget *parent, gchar *message)
744 dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(parent) ,
745 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
746 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
748 gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), message);
750 result = gtk_dialog_run(GTK_DIALOG(dialog));
751 gtk_widget_destroy(dialog);
756 static void delete_transition(GtkAction *action, transition_t *transition)
758 GtkTreeSelection *selection;
761 gchar *message = NULL;
764 DEBUG_PRINT("delete : current page[%d]\n", transition->current_page);
766 switch((int)transition->current_page) {
767 case CCS_SCREEN_EXCEPTION_LIST :
768 selection = gtk_tree_view_get_selection(
769 GTK_TREE_VIEW(transition->exp.listview));
770 if (!selection || !(count =
771 gtk_tree_selection_count_selected_rows(selection)))
773 DEBUG_PRINT("count[%d]\n", count);
774 message = count > 1 ?
776 "<span foreground='red' size='x-large'>"
777 "<b>Delete</b> the %d selected exception policies?</span>"), count) :
779 "<span foreground='red' size='x-large'>"
780 "<b>Delete</b> the selected exception policy?</span>"));
781 if (GTK_RESPONSE_YES ==
782 message_dialog(transition->window, message)) {
783 ret = delete_exp(transition, selection, count);
786 case CCS_SCREEN_DOMAIN_LIST :
788 selection = gtk_tree_view_get_selection(
789 GTK_TREE_VIEW(transition->treeview));
790 if (!selection || !(count =
791 gtk_tree_selection_count_selected_rows(selection)))
793 DEBUG_PRINT("count[%d]\n", count);
794 message = count > 1 ?
796 "<span foreground='red' size='x-large'>"
797 "<b>Delete</b> the %d selected domains?</span>"), count) :
799 "<span foreground='red' size='x-large'>"
800 "<b>Delete</b> the selected domain?</span>"));
801 if (GTK_RESPONSE_YES ==
802 message_dialog(transition->window, message)) {
803 ret = delete_domain(transition, selection, count);
806 case CCS_SCREEN_ACL_LIST :
807 DEBUG_PRINT("Delete ACL\n");
808 selection = gtk_tree_view_get_selection(
809 GTK_TREE_VIEW(transition->acl.listview));
810 if (!selection || !(count =
811 gtk_tree_selection_count_selected_rows(selection)))
813 DEBUG_PRINT("count[%d]\n", count);
814 parent = transition->acl_detached ?
815 transition->acl_window : transition->window;
816 message = count > 1 ?
818 "<span foreground='blue' size='x-large'>"
819 "<b>Delete</b> the %d selected policies?</span>"), count) :
821 "<span foreground='blue' size='x-large'>"
822 "<b>Delete</b> the selected policy?</span>"));
823 if (GTK_RESPONSE_YES ==
824 message_dialog(parent, message)) {
825 ret = delete_acl(transition, selection, count);
828 case CCS_SCREEN_MANAGER_LIST :
829 DEBUG_PRINT("Delete manager\n");
836 refresh_transition(NULL, transition);
838 /*-------+---------+---------+---------+---------+---------+---------+--------*/
839 #define COMBO_LIST_LIMIT 20
840 static GList *combolist = NULL;
841 static gchar *Last_entry_string = NULL;
843 gchar *get_combo_entry_last(void)
848 buff = g_malloc0(strlen(Last_entry_string) + 1);
853 for (cp = Last_entry_string; *cp; cp++) {
854 if (*cp == '\\' && *(cp + 1) == '\'') {
856 } else if (*cp != '\'') {
862 //g_print("[%s]\n", buff);
866 static void insert_history_buffer(GtkWidget *view, gchar *entry)
868 GtkClipboard *clipboard;
875 /* to system clipboard */
876 clipboard = gtk_widget_get_clipboard(view, GDK_SELECTION_CLIPBOARD);
877 gtk_clipboard_set_text(clipboard, entry, -1);
879 for (list = combolist; list; list = g_list_next(list)) {
880 if (strcmp(entry, (gchar *)list->data) == 0) {
886 combolist = g_list_insert(combolist, entry, 0);
887 len = g_list_length(combolist);
888 if (len > COMBO_LIST_LIMIT) {
889 g_free(g_list_nth_data(combolist, len - 1));
890 combolist = g_list_delete_link(combolist,
891 g_list_nth(combolist, len - 1));
895 static gchar *normalize_strdup(gchar *input)
898 gint len = strlen(input);
900 gboolean match = FALSE;
905 cp = input + len - 1;
906 if (g_ascii_isspace(*cp)) {
907 while (len && g_ascii_isspace(*cp)) {
914 while (len && g_ascii_isspace(*cp)) {
919 buff = g_malloc0(len + 1);
925 if (*cp == '\\' && *(cp + 1) == '\'') {
928 } else if (*cp == '\'') {
929 match = match ? FALSE : TRUE;
931 if (!match && g_ascii_isspace(*cp)) {
932 while (g_ascii_isspace(*(cp+1))) {
943 //g_print("%2d[%s]\n", len, buff);
947 static gint combo_entry_apply(GtkWidget *combo, gchar **new_text)
949 GtkComboBox *combobox;
951 gboolean exist_flag = FALSE;
953 combobox = GTK_COMBO_BOX(combo);
954 (*new_text) = gtk_combo_box_get_active_text(combobox);
955 if(!(*new_text) || strcmp(*new_text, "") == 0)
958 g_free(Last_entry_string);
959 Last_entry_string = normalize_strdup(*new_text);
961 *new_text = g_strdup(Last_entry_string);
963 for (list = combolist; list; list = g_list_next(list)) {
964 if (strcmp(*new_text, (gchar *)list->data) == 0) {
972 combolist = insert_item(combobox, combolist, *new_text, 0);
973 len = g_list_length(combolist);
974 if (len > COMBO_LIST_LIMIT) {
975 combolist = remove_item(combobox, combolist, len - 1);
977 DEBUG_PRINT("Append '%s'.\n", *new_text);
980 return exist_flag ? 1 : 0;
983 static void cb_combo_entry_activate(GtkEntry *entry, GtkWidget *dialog)
985 const gchar *input = gtk_entry_get_text(entry);
987 if (!input || strcmp(input, "") == 0)
990 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
993 /*---------------------------------------------------------------------------*/
994 static gint append_dialog(transition_t *transition,
995 gchar *title, gchar **input)
997 GtkWidget *dialog, *parent;
1000 gint response, result = 1;
1002 parent = (transition->acl_detached &&
1003 (int)transition->current_page == CCS_SCREEN_ACL_LIST) ?
1004 transition->acl_window : transition->window;
1006 dialog = gtk_dialog_new_with_buttons(title,
1008 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1009 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1010 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1013 combo = gtk_combo_box_entry_new_text();
1014 g_signal_connect(G_OBJECT(GTK_BIN(combo)->child) , "activate" ,
1015 G_CALLBACK(cb_combo_entry_activate), dialog);
1017 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
1019 for (list = combolist; list; list = g_list_next(list)) {
1020 gtk_combo_box_append_text(
1021 GTK_COMBO_BOX(combo), (gchar *)list->data);
1025 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), combo);
1026 gtk_widget_set_size_request(dialog, 600, -1);
1027 gtk_widget_show_all(dialog);
1029 response = gtk_dialog_run(GTK_DIALOG(dialog));
1030 if (response == GTK_RESPONSE_APPLY) {
1032 combo_entry_apply(combo, input);
1033 tmp = escape_str_encode(*input);
1034 // g_print("[%s]:[%s]\n", *input, tmp);
1039 gtk_widget_destroy(dialog);
1044 static void append_transition(GtkAction *action, transition_t *transition)
1046 gchar *input = NULL;
1047 gint index, result = 1;
1048 enum addentry_type type = ADDENTRY_NON;
1049 char *err_buff = NULL;
1051 switch((int)transition->current_page) {
1052 case CCS_SCREEN_DOMAIN_LIST :
1053 DEBUG_PRINT("append domain\n");
1054 result = append_dialog(transition,
1055 _("Add Domain"), &input);
1057 result = add_domain(input, &err_buff);
1058 type = ADDENTRY_DOMAIN_LIST;
1060 case CCS_SCREEN_ACL_LIST :
1061 DEBUG_PRINT("append acl\n");
1062 result = append_dialog(transition, _("Add Acl"), &input);
1064 index = get_current_domain_index(transition);
1066 result = add_acl_list(transition->dp,
1067 index, input, &err_buff);
1069 type = ADDENTRY_ACL_LIST;
1071 case CCS_SCREEN_EXCEPTION_LIST :
1072 DEBUG_PRINT("append exception\n");
1073 result = append_dialog(transition,
1074 _("Add Exception"), &input);
1076 result = add_exception_policy(input, &err_buff);
1077 type = ADDENTRY_EXCEPTION_LIST;
1079 case CCS_SCREEN_PROFILE_LIST :
1080 DEBUG_PRINT("append profile\n");
1081 result = append_dialog(transition,
1082 _("Add Profile (0 - 255)"), &input);
1084 result = add_profile(input, &err_buff);
1085 type = ADDENTRY_PROFILE_LIST;
1087 case CCS_SCREEN_NS_LIST :
1088 DEBUG_PRINT("append namespace\n");
1089 result = append_dialog(transition,
1090 _("Add Namespace"), &input);
1092 result = add_namespace(input, &err_buff);
1093 type = ADDENTRY_NAMESPACE_LIST;
1096 DEBUG_PRINT("append ???\n");
1102 g_warning("%s", err_buff);
1105 transition->addentry = ADDENTRY_NON;
1107 transition->addentry = type;
1108 refresh_transition(NULL, transition);
1111 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1112 enum list_column_pos {
1113 LIST_PROFILE, // display
1114 PROFILE_NO, // hidden
1117 static GtkWidget *create_list_profile(void)
1119 GtkWidget *treeview;
1120 GtkListStore *liststore;
1121 GtkCellRenderer *renderer;
1122 GtkTreeViewColumn *column;
1124 liststore = gtk_list_store_new(N_COLUMNS_LIST,
1125 G_TYPE_STRING, G_TYPE_UINT);
1126 treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore));
1127 g_object_unref(liststore);
1129 renderer = gtk_cell_renderer_text_new();
1130 column = gtk_tree_view_column_new();
1131 gtk_tree_view_column_pack_start(column, renderer, FALSE);
1132 column = gtk_tree_view_column_new_with_attributes("operand",
1133 renderer, "text", LIST_PROFILE, NULL);
1134 gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column);
1137 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
1142 static void add_list_profile(GtkWidget *listview,
1143 generic_list_t *generic)
1145 GtkListStore *store;
1150 store = GTK_LIST_STORE(gtk_tree_view_get_model(
1151 GTK_TREE_VIEW(listview)));
1152 gtk_list_store_clear(store);
1154 DEBUG_PRINT("Count[%d]\n", generic->count);
1155 for(i = 0; i < generic->count; i++){
1156 if (generic->list[i].directive > 255 ||
1157 !strstr(generic->list[i].operand, "COMMENT="))
1160 DEBUG_PRINT("[%3d]:%3u-%s\n", i,
1161 generic->list[i].directive, generic->list[i].operand);
1163 gtk_list_store_append(store, &iter);
1164 profile = g_strdup_printf("%3u-%s",
1165 generic->list[i].directive,
1166 generic->list[i].operand);
1167 gtk_list_store_set(store, &iter,
1168 LIST_PROFILE, profile,
1169 PROFILE_NO, generic->list[i].directive,
1175 static gboolean apply_profile(transition_t *transition,
1176 GtkTreeSelection *domain_selection,
1177 GtkWidget *listview)
1179 GtkTreeSelection *selection;
1181 GtkTreeModel *model;
1186 selection = gtk_tree_view_get_selection(
1187 GTK_TREE_VIEW(listview));
1189 gtk_tree_selection_count_selected_rows(selection) == 1) {
1190 list = gtk_tree_selection_get_selected_rows(
1192 model = gtk_tree_view_get_model(GTK_TREE_VIEW(listview));
1193 gtk_tree_model_get_iter(model, &iter,
1194 g_list_first(list)->data);
1195 gtk_tree_model_get(model, &iter,
1196 PROFILE_NO, &profile_no, -1);
1197 DEBUG_PRINT("Selct Profile [%u]\n", profile_no);
1198 result = set_domain_profile(transition,
1199 domain_selection, profile_no);
1201 refresh_transition(NULL, transition);
1208 static void cb_profile_activate(GtkTreeView *treeview, GtkTreePath *treepath,
1209 GtkTreeViewColumn *treeviewcolumn, GtkWidget *dialog)
1211 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
1214 static void set_domain(transition_t *transition)
1216 GtkTreeSelection *domain_selection;
1218 GtkWidget *listview;
1219 gint count, response;
1221 if (transition->task_flag)
1222 domain_selection = gtk_tree_view_get_selection(
1223 GTK_TREE_VIEW(transition->tsk.treeview));
1225 domain_selection = gtk_tree_view_get_selection(
1226 GTK_TREE_VIEW(transition->treeview));
1228 if (!domain_selection || !(count =
1229 gtk_tree_selection_count_selected_rows(domain_selection)))
1232 dialog = gtk_dialog_new_with_buttons(_("Profile list"),
1233 GTK_WINDOW(transition->window),
1234 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1235 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1236 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1239 listview = create_list_profile();
1240 g_signal_connect(G_OBJECT(listview), "row-activated",
1241 G_CALLBACK(cb_profile_activate), dialog);
1242 add_list_profile(listview, &(transition->prf));
1243 view_cursor_set(listview, NULL, NULL);
1245 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), listview);
1246 gtk_widget_set_size_request(dialog, 400, 300);
1247 gtk_widget_set_name(dialog, "GpetProfileSelectDialog"); // .gpetrc
1248 gtk_widget_show_all(dialog);
1251 response = gtk_dialog_run(GTK_DIALOG(dialog));
1252 if (response == GTK_RESPONSE_APPLY) {
1253 DEBUG_PRINT("Apply button was pressed.\n");
1254 if (!apply_profile(transition,
1255 domain_selection, listview))
1257 } else if (response == GTK_RESPONSE_CANCEL) {
1258 DEBUG_PRINT("Cancel button was pressed.\n");
1260 DEBUG_PRINT("Another response was recieved.\n");
1262 gtk_widget_destroy(dialog);
1265 static void cb_profile_entry_activate(GtkEntry *entry, GtkWidget *dialog)
1267 const gchar *input = gtk_entry_get_text(entry);
1269 if (!input || strcmp(input, "") == 0)
1272 gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
1275 static void edit_profile(transition_t *transition)
1281 gchar *profile, *label_str, *ptr;
1282 gint index, response;
1284 if ((index = select_list_line(&(transition->prf))) < 0)
1287 entry = gtk_entry_new();
1289 profile = g_strdup(transition->prf.list[index].operand);
1290 ptr = strchr(profile, '=');
1294 gtk_entry_set_text(GTK_ENTRY(entry), ptr);
1298 if (transition->prf.list[index].directive < 256)
1299 label_str = g_strdup_printf("%3u-%s",
1300 transition->prf.list[index].directive, profile);
1302 label_str = g_strdup_printf("%s", profile);
1303 label = gtk_label_new(label_str);
1307 dialog = gtk_dialog_new_with_buttons(_("Profile Edit"),
1308 GTK_WINDOW(transition->window),
1309 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1310 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1311 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
1314 g_signal_connect(G_OBJECT(entry) , "activate" ,
1315 G_CALLBACK(cb_profile_entry_activate), dialog);
1317 hbox = gtk_hbox_new(FALSE, 5);
1319 GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), hbox);
1321 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1322 gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
1324 gtk_widget_set_size_request(dialog, 600, -1);
1325 gtk_widget_show_all(dialog);
1327 response = gtk_dialog_run(GTK_DIALOG(dialog));
1328 if (response == GTK_RESPONSE_APPLY) {
1330 char *err_buff = NULL;
1331 // transition->prf.list[index].selected = 1;
1332 input = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
1333 DEBUG_PRINT("Edit profile [%s] index[%d]\n", input, index);
1334 if (set_profile_level(index, input, &err_buff)) {
1335 g_warning("%s", err_buff);
1338 refresh_transition(NULL, transition);
1341 gtk_widget_destroy(dialog);
1344 static void set_transition(GtkAction *action, transition_t *transition)
1346 switch((int)transition->current_page) {
1347 case CCS_SCREEN_DOMAIN_LIST :
1348 DEBUG_PRINT("set profile\n");
1349 set_domain(transition);
1351 case CCS_SCREEN_PROFILE_LIST :
1352 DEBUG_PRINT("edit profile\n");
1353 edit_profile(transition);
1356 DEBUG_PRINT("edit ???\n");
1360 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1361 static void manager_transition(GtkAction *action, transition_t *transition)
1363 manager_main(transition);
1366 static void memory_transition(GtkAction *action, transition_t *transition)
1368 memory_main(transition);
1370 /*-------+---------+---------+---------+---------+---------+---------+--------*/
1371 GdkPixbuf *get_png_file(void)
1376 pixbuf = gdk_pixbuf_new_from_file(PACKAGE_ICON_DIR "/tomoyo.png", &err);
1378 g_warning("%s", err->message);
1384 static void show_about_dialog(void)
1387 GtkAboutDialog *about;
1390 const gchar *authors[] = {
1391 _("Yoshihiro Kusuno <yocto@users.sourceforge.jp>"),
1392 _("ccstools --- kumaneko san"),
1394 const gchar *documenters[] = {_("Yoshihiro Kusuno"), NULL};
1395 // const gchar *translators = "none";
1397 dialog = gtk_about_dialog_new();
1398 about = GTK_ABOUT_DIALOG(dialog);
1399 gtk_about_dialog_set_name(about, "gpet");
1400 gtk_about_dialog_set_authors(about, authors);
1401 gtk_about_dialog_set_documenters(about, documenters);
1402 // gtk_about_dialog_set_translator_credits(about, translators);
1403 gtk_about_dialog_set_version(about, VERSION);
1404 gtk_about_dialog_set_copyright(about,
1405 "Copyright(C) 2010,2011 TOMOYO Linux Project");
1406 gtk_about_dialog_set_comments(about,
1407 "Gui Policy Editor for TOMOYO Linux 2.4 , 1.8.2"
1409 "\n(based on ccs-editpolicy:ccstools)");
1410 gtk_about_dialog_set_website(about, "http://sourceforge.jp/projects/gpet/");
1411 // gtk_about_dialog_set_website_label(about, "http://tomoyo.sourceforge.jp/");
1413 pixbuf = get_png_file();
1415 gtk_about_dialog_set_logo(about, pixbuf);
1416 g_object_unref(pixbuf);
1418 gtk_container_set_border_width(GTK_CONTAINER(dialog), 5);
1420 gtk_dialog_run(GTK_DIALOG(about));
1421 gtk_widget_destroy(GTK_WIDGET(about));