[Automatic Bug Reporting Tool - ABRT] #879: problem API generates duplicate problem identifiers
by fedora-badges
#879: problem API generates duplicate problem identifiers
-----------------------+------------------------------
Reporter: jfilak | Owner: crash-catcher@…
Type: defect | Status: new
Priority: major | Milestone:
Component: libreport | Version:
Keywords: | Blocked By:
Blocking: |
-----------------------+------------------------------
abrt/libreport uses current time in range of seconds to generate unique
problem identifiers. This approach worked fine untill NewProblem() DBus
method was introduced.
libreport:src/lib/create_dump_dir.c:33
struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *,
const char *);
--
Ticket URL: <https://fedorahosted.org/abrt/ticket/879>
Automatic Bug Reporting Tool - ABRT <http://fedorahoted.org/abrt/>
Automatic bug reporting tool
11 years, 5 months
[LIBREPORT PATCH 1/2] - implemented saving/loading configuratio for workflows - related to trac#822
by Jiri Moskovcak
- configuration is shared with the events, so changes in events
are reflected in workflow and vice versa
---
src/gtk-helpers/config_dialog.c | 252 +++++++++++++++++++++++--------
src/gtk-helpers/event_config_dialog.c | 158 ++++++++-----------
src/gtk-helpers/internal_libreport_gtk.h | 39 +++--
src/gtk-helpers/workflow_config_dialog.c | 83 +++++-----
src/gui-wizard-gtk/main.c | 2 +-
src/gui-wizard-gtk/wizard.c | 8 +-
src/include/event_config.h | 4 +-
src/include/internal_libreport.h | 2 +-
src/lib/event_config.c | 13 +-
src/lib/workflow.c | 17 ++-
10 files changed, 357 insertions(+), 221 deletions(-)
diff --git a/src/gtk-helpers/config_dialog.c b/src/gtk-helpers/config_dialog.c
index 88d01ae..7d60301 100644
--- a/src/gtk-helpers/config_dialog.c
+++ b/src/gtk-helpers/config_dialog.c
@@ -34,19 +34,55 @@ enum
TYPE_POINTER
};
+struct config_dialog
+{
+ GtkWidget *dialog;
+ gpointer *data;
+ ConfigSaveFun save_data;
+};
+
GtkListStore *new_conf_liststore(void)
{
/* Create data store for the list and attach it
- * COLUMN_EVENT_UINAME -> name+description
- * COLUMN_EVENT_NAME -> event name so we can retrieve it from the row
+ * COLUMN_UINAME -> name+description
+ * COLUMN_NAME -> config name so we can retrieve it from the row
*/
return gtk_list_store_new(NUM_COLUMNS,
G_TYPE_STRING, /* Event name + description */
G_TYPE_STRING, /* event name */
- G_TYPE_POINTER
+ G_TYPE_POINTER, /* dialog */
+ G_TYPE_POINTER /* option_list */
);
}
+
+config_dialog_t *new_config_dialog(GtkWidget *dialog,
+ gpointer config_data,
+ ConfigSaveFun save_fun)
+{
+ config_dialog_t *cdialog = (config_dialog_t *)xmalloc(sizeof(*cdialog));
+ cdialog->dialog = dialog;
+ cdialog->data = config_data;
+ cdialog->save_data = save_fun;
+ return cdialog;
+}
+
+void cdialog_set_widget(config_dialog_t *cdialog, GtkWidget *widget)
+{
+ //TODO destroy(cdialog-dialog) ??
+ cdialog->dialog = widget;
+}
+
+GtkWidget *cdialog_get_widget(config_dialog_t *cdialog)
+{
+ return cdialog->dialog;
+}
+
+gpointer cdialog_get_data(config_dialog_t *cdialog)
+{
+ return cdialog->data;
+}
+
static const void *get_column_value_from_row(GtkTreeView *treeview, int column, int type)
{
GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
@@ -71,40 +107,39 @@ static const void *get_column_value_from_row(GtkTreeView *treeview, int column,
return retval;
}
-static void on_row_changed_cb(GtkTreeView *treeview, gpointer user_data)
-{
- VERB1 log("activated row: '%s'", (const char*)get_column_value_from_row(treeview, COLUMN_NAME, TYPE_STR));
-
- const void *dialog = get_column_value_from_row(treeview, CONFIG_DIALOG, TYPE_POINTER);
- gtk_widget_set_sensitive(GTK_WIDGET(user_data), dialog != NULL);
-}
-
-static void on_configure_button_cb(GtkWidget *button, gpointer user_data)
+static void save_value_from_widget(gpointer data, gpointer user_data)
{
- GtkTreeView *tv = (GtkTreeView *)user_data;
- const void * dialog = get_column_value_from_row(tv, CONFIG_DIALOG, TYPE_POINTER);
+ option_widget_t *ow = (option_widget_t *)data;
- if (dialog != NULL)
+ const char *val = NULL;
+ switch (ow->option->eo_type)
{
- int result = gtk_dialog_run(GTK_DIALOG(dialog));
- if (result == GTK_RESPONSE_APPLY)
- {
- //TODO: saving!!!
- g_print("apply\n");
- }
- //else if (result == GTK_RESPONSE_CANCEL)
- // log("log");
- gtk_widget_hide(GTK_WIDGET(dialog));
+ case OPTION_TYPE_TEXT:
+ case OPTION_TYPE_NUMBER:
+ case OPTION_TYPE_PASSWORD:
+ val = (char *)gtk_entry_get_text(GTK_ENTRY(ow->widget));
+ break;
+ case OPTION_TYPE_BOOL:
+ val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ow->widget)) ? "yes" : "no";
+ break;
+ default:
+ log("unsupported option type");
+ }
+ if (val)
+ {
+ free(ow->option->eo_value);
+ ow->option->eo_value = xstrdup(val);
+ VERB1 log("saved: %s:%s", ow->option->eo_name, ow->option->eo_value);
}
}
-static void on_close_list_cb(GtkWidget *button, gpointer user_data)
+void dehydrate_config_dialog(GList *option_widgets)
{
- GtkWidget *window = (GtkWidget *)user_data;
- gtk_widget_destroy(window);
+ if (option_widgets != NULL)
+ g_list_foreach(option_widgets, &save_value_from_widget, NULL);
}
-void add_item_to_config_liststore(gpointer dialog, gpointer inf, gpointer user_data)
+void add_item_to_config_liststore(gpointer cdialog, gpointer inf, gpointer user_data)
{
GtkListStore *list_store = (GtkListStore *)user_data;
config_item_info_t *info = (config_item_info_t *)inf;
@@ -115,24 +150,20 @@ void add_item_to_config_liststore(gpointer dialog, gpointer inf, gpointer user_d
label = xasprintf("<b>%s</b>\n%s",ci_get_screen_name(info), ci_get_description(info));
else
//if event has no xml description
- label = xasprintf("<b>%s</b>\nNo description available", ci_get_name(info));
+ label = xasprintf("<b>%s</b>\n%s", _("No description available"), ci_get_name(info));
GtkTreeIter iter;
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter,
COLUMN_UINAME, label,
COLUMN_NAME, ci_get_name(info),
- CONFIG_DIALOG, dialog,
+ CONFIG_DIALOG, cdialog,
-1);
free(label);
}
-GtkWidget *create_config_list_dialog(const char *column_label,
- GHashTable *items,
- GtkWindow *dialog,
- GHFunc item_to_config_info,
- GCallback on_config_cb,
- GCallback on_row_change)
+GtkWidget *create_config_tab_content(const char *column_label,
+ GtkListStore *store)
{
GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
@@ -161,37 +192,138 @@ GtkWidget *create_config_list_dialog(const char *column_label,
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tv), TRUE);
// TODO: gtk_tree_view_set_headers_visible(FALSE)? We have only one column anyway...
- /* Create data store for the list and attach it
- * COLUMN_UINAME -> name+description
- * COLUMN_NAME -> workflow name so we can retrieve it from the row
- */
- GtkListStore *list_store = new_conf_liststore();
- gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(list_store));
+ gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(store));
+ gtk_container_add(GTK_CONTAINER(scroll), tv);
- g_hash_table_foreach(items,
- item_to_config_info,
- list_store);
-//TODO: can unref workflows_list_store? treeview holds one ref.
+ gtk_box_pack_start(GTK_BOX(main_vbox), scroll, true, true, 10);
+ return main_vbox;
+}
- /* Double click/Enter handler */
- //g_signal_connect(workflows_tv, "row-activated", G_CALLBACK(on_workflow_row_activated_cb), NULL);
+static void add_config_tabs(const char *name, GtkListStore *store, gpointer nb)
+{
+ GtkNotebook *ntb = (GtkNotebook *)nb;
- gtk_container_add(GTK_CONTAINER(scroll), tv);
+ GtkWidget *config_list_vbox = create_config_tab_content(
+ name,
+ store);
- GtkWidget *configure_btn = gtk_button_new_with_mnemonic(_("C_onfigure"));
- gtk_widget_set_sensitive(configure_btn, false);
- g_signal_connect(configure_btn, "clicked", G_CALLBACK(on_configure_button_cb), tv);
- g_signal_connect(tv, "cursor-changed", G_CALLBACK(on_row_changed_cb), configure_btn);
+ gtk_notebook_append_page(ntb, config_list_vbox, gtk_label_new(name));
+}
+
+static void on_configure_cb(GtkWidget *btn, gpointer user_data)
+{
+ GtkNotebook *nb = (GtkNotebook *)user_data;
+ guint current_page_n = gtk_notebook_get_current_page(nb);
+ GtkWidget *vbox = gtk_notebook_get_nth_page(nb, current_page_n);
+ GList *children = gtk_container_get_children(GTK_CONTAINER(vbox));
+ GtkScrolledWindow *sw = (GtkScrolledWindow *)children->data;
+ GtkTreeView *tv = (GtkTreeView *)gtk_bin_get_child(GTK_BIN(sw));
+ config_dialog_t *cdialog = (config_dialog_t *)get_column_value_from_row(tv, CONFIG_DIALOG, TYPE_POINTER);
+ const char *name = (const char *)get_column_value_from_row(tv, COLUMN_NAME, TYPE_STR);
+
+
+ if (cdialog == NULL || cdialog->dialog == NULL)
+ {
+ log("There is no configurable option for: '%s'", name);
+ return;
+ }
+
+ int result = gtk_dialog_run(GTK_DIALOG(cdialog->dialog));
+ if (result == GTK_RESPONSE_APPLY)
+ {
+ if (cdialog->save_data)
+ cdialog->save_data(cdialog->data, name);
+ }
+ else if (result == GTK_RESPONSE_CANCEL)
+ VERB1 log("Cancelling on user request");
+
+ gtk_widget_hide(GTK_WIDGET(cdialog->dialog));
+}
+
+static void on_close_cb(GtkWidget *btn, gpointer config_list_w)
+{
+ GtkWidget *w = (GtkWidget *)config_list_w;
+ gtk_widget_hide(w);
+}
+
+GtkWindow *create_config_list_window(GHashTable *configs, GtkWindow *parent)
+{
+
+ // config window
+ GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_container_set_border_width(GTK_CONTAINER(window), 5);
+ gtk_window_set_title(GTK_WINDOW(window), _("Configuration"));
+ gtk_window_set_default_size(GTK_WINDOW(window), 450, 400);
+ gtk_window_set_position(GTK_WINDOW(window), parent
+ ? GTK_WIN_POS_CENTER_ON_PARENT
+ : GTK_WIN_POS_CENTER);
+
+ if (parent != NULL)
+ {
+ gtk_window_set_modal(GTK_WINDOW(window), true);
+ gtk_window_set_transient_for(GTK_WINDOW(window), parent);
+ }
+
+ //g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ GtkWidget *main_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
+ GtkWidget *config_nb = gtk_notebook_new();
+ gtk_box_pack_start(GTK_BOX(main_vbox), config_nb, 1, 1, 0);
+
+ g_hash_table_foreach(configs, (GHFunc)add_config_tabs, config_nb);
+
+ //buttons
+ GtkWidget *btn_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,5);
+ GtkWidget *configure_btn = gtk_button_new_with_mnemonic(_("C_onfigure"));
+ GtkWidget *align = gtk_alignment_new(0, 0, 0, 0);
GtkWidget *close_btn = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
- g_signal_connect(close_btn, "clicked", G_CALLBACK(on_close_list_cb), dialog);
+ GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
+ //force apply and close to have the same size
+ gtk_size_group_add_widget(sg, close_btn);
+ gtk_size_group_add_widget(sg, configure_btn);
- GtkWidget *btnbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
- gtk_box_pack_end(GTK_BOX(btnbox), close_btn, false, false, 0);
- gtk_box_pack_end(GTK_BOX(btnbox), configure_btn, false, false, 0);
+ g_signal_connect(configure_btn, "clicked", (GCallback)on_configure_cb, config_nb);
+ g_signal_connect(close_btn, "clicked", (GCallback)on_close_cb, window);
- gtk_box_pack_start(GTK_BOX(main_vbox), scroll, true, true, 10);
- gtk_box_pack_start(GTK_BOX(main_vbox), btnbox, false, false, 0);
+ gtk_box_pack_start(GTK_BOX(btn_box), close_btn, 0, 0, 5);
+ gtk_box_pack_start(GTK_BOX(btn_box), align, true, true, 5);
+ gtk_box_pack_start(GTK_BOX(btn_box), configure_btn, 0, 0, 5);
- return main_vbox;
+
+ gtk_box_pack_start(GTK_BOX(main_vbox), btn_box, 0, 0, 0);
+ gtk_container_add(GTK_CONTAINER(window), main_vbox);
+
+ //gtk_widget_show_all(window);
+ return GTK_WINDOW(window);
+}
+
+/* Name | vbox with the gtk_Tree
+ * <String name, GtkWidget *vbox>
+*/
+
+void show_config_list_dialog(GtkWindow *parent)
+{
+ GHashTable *confs = g_hash_table_new_full(
+ /*hash_func*/ g_str_hash,
+ /*key_equal_func:*/ g_str_equal,
+ /*key_destroy_func:*/ g_free,
+ /*value_destroy_func:*/ NULL);
+
+
+ //TODO: free the hashtables somewhere!!
+ GHashTable *events = load_event_config_data();
+ load_event_config_data_from_user_storage(events);
+
+ GtkListStore *events_store = add_events_to_liststore(events);
+ g_hash_table_insert(confs, _("Events"), events_store);
+
+
+ GHashTable *workflows = load_workflow_config_data(WORKFLOWS_DIR);
+ load_workflow_config_data_from_user_storage(workflows);
+ GtkListStore *workflows_store = add_workflows_to_liststore(workflows);
+ g_hash_table_insert(confs, _("Workflows"), workflows_store);
+
+ GtkWindow *window = create_config_list_window(confs, parent);
+ gtk_widget_show_all(GTK_WIDGET(window));
}
diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c
index 01527ec..6bc85cd 100644
--- a/src/gtk-helpers/event_config_dialog.c
+++ b/src/gtk-helpers/event_config_dialog.c
@@ -20,7 +20,8 @@
#include "internal_libreport_gtk.h"
static GtkWindow *g_event_list_window;
-static GList *option_widget_list;
+static GList *g_option_list = NULL;
+
static bool has_password_option;
enum
@@ -30,14 +31,6 @@ enum
NUM_COLUMNS
};
-typedef struct
-{
- event_option_t *option;
- GtkWidget *widget;
-} option_widget_t;
-
-int show_event_config_dialog(const char *event_name, GtkWindow *parent);
-
static GtkWidget *gtk_label_new_justify_left(const gchar *label_str)
{
GtkWidget *label = gtk_label_new(label_str);
@@ -48,12 +41,14 @@ static GtkWidget *gtk_label_new_justify_left(const gchar *label_str)
return label;
}
-static void add_option_widget(GtkWidget *widget, event_option_t *option)
+GList *add_option_widget(GList *options, GtkWidget *widget, event_option_t *option)
{
- option_widget_t *ow = (option_widget_t *)xmalloc(sizeof(option_widget_t));
+ option_widget_t *ow = (option_widget_t *)xmalloc(sizeof(*ow));
ow->widget = widget;
ow->option = option;
- option_widget_list = g_list_prepend(option_widget_list, ow);
+ options = g_list_prepend(options, ow);
+
+ return options;
}
static void on_show_pass_cb(GtkToggleButton *tb, gpointer user_data)
@@ -75,6 +70,23 @@ static unsigned add_one_row_to_grid(GtkGrid *table)
return rows;
}
+void save_data_from_event_config_dialog(GList *widgets, event_config_t *ec)
+{
+ dehydrate_config_dialog(widgets);
+ const char *const store_passwords_s = get_user_setting("store_passwords");
+ save_event_config_data_to_user_storage(ec_get_name(ec),
+ ec,
+ !(store_passwords_s && !strcmp(store_passwords_s, "no")));
+}
+
+static void save_data_from_event_dialog_name(GList *widgets, const char *name)
+{
+ event_config_t *ec = get_event_config(name);
+
+ save_data_from_event_config_dialog(widgets, ec);
+}
+
+
static void add_option_to_table(gpointer data, gpointer user_data)
{
event_option_t *option = data;
@@ -116,7 +128,7 @@ static void add_option_to_table(gpointer data, gpointer user_data)
gtk_grid_attach(option_table, option_input,
/*left,top:*/ 1, last_row,
/*width,height:*/ 1, 1);
- add_option_widget(option_input, option);
+ g_option_list = add_option_widget(g_option_list, option_input, option);
if (option->eo_type == OPTION_TYPE_PASSWORD)
{
gtk_entry_set_visibility(GTK_ENTRY(option_input), 0);
@@ -151,7 +163,7 @@ static void add_option_to_table(gpointer data, gpointer user_data)
if (option->eo_value != NULL)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(option_input),
string_to_bool(option->eo_value));
- add_option_widget(option_input, option);
+ g_option_list = add_option_widget(g_option_list, option_input, option);
break;
default:
@@ -177,39 +189,7 @@ static void add_option_to_table(gpointer data, gpointer user_data)
free(option_label);
}
-static void save_value_from_widget(gpointer data, gpointer user_data)
-{
- option_widget_t *ow = (option_widget_t *)data;
-
- const char *val = NULL;
- switch (ow->option->eo_type)
- {
- case OPTION_TYPE_TEXT:
- case OPTION_TYPE_NUMBER:
- case OPTION_TYPE_PASSWORD:
- val = (char *)gtk_entry_get_text(GTK_ENTRY(ow->widget));
- break;
- case OPTION_TYPE_BOOL:
- val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ow->widget)) ? "yes" : "no";
- break;
- default:
- log("unsupported option type");
- }
- if (val)
- {
- free(ow->option->eo_value);
- ow->option->eo_value = xstrdup(val);
- VERB1 log("saved: %s:%s", ow->option->eo_name, ow->option->eo_value);
- }
-}
-
-static void dehydrate_config_dialog()
-{
- if (option_widget_list != NULL)
- g_list_foreach(option_widget_list, &save_value_from_widget, NULL);
-}
-
-GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *content)
+config_dialog_t *create_event_config_dialog_content(event_config_t *event, GtkWidget *content)
{
if (content == NULL)
content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
@@ -238,6 +218,13 @@ GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *
g_object_set_data(G_OBJECT(option_table), "advanced-options", adv_option_table);
has_password_option = false;
+ /* it's already stored in config_dialog_t from the previous call
+ * we need to set it to null so we create a new list for the actual
+ * event_config
+ * note: say *NO* to the global variables!
+ */
+ g_option_list = NULL;
+ /* this fills the g_option_list, so we can use it for new_config_dialog */
g_list_foreach(event->options, &add_option_to_table, option_table);
/* if there is at least one password option, add checkbox to disable storing passwords */
@@ -275,17 +262,17 @@ GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *
gtk_widget_show_all(content); //make it all visible
- return content;
+ //g_option_list is filled on
+ config_dialog_t *cdialog = new_config_dialog(NULL,
+ g_option_list,
+ (ConfigSaveFun)save_data_from_event_dialog_name
+ );
+
+ return cdialog;
}
-GtkWidget *create_config_dialog(const char *event_name, GtkWindow *parent)
+config_dialog_t *create_event_config_dialog(const char *event_name, GtkWindow *parent)
{
- if (option_widget_list != NULL)
- {
- g_list_free(option_widget_list);
- option_widget_list = NULL;
- }
-
event_config_t *event = get_event_config(event_name);
if(!ec_is_configurable(event))
@@ -320,26 +307,30 @@ GtkWidget *create_config_dialog(const char *event_name, GtkWindow *parent)
}
GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
- content = create_event_config_dialog_content(event, content);
+ config_dialog_t *cdialog = create_event_config_dialog_content(event, content);
+ cdialog_set_widget(cdialog, dialog);
- return dialog;
+ return cdialog;
}
-static void add_event_to_liststore(gpointer key, gpointer value, gpointer user_data)
+static void add_event_to_liststore(gpointer key, gpointer value, gpointer list_store)
{
config_item_info_t *info = ec_get_config_info((event_config_t *)value);
- GtkWidget *dialog = create_config_dialog(key, NULL);
- add_item_to_config_liststore(dialog, info, user_data);
+ config_dialog_t *cdialog = create_event_config_dialog(key, NULL);
+
+ add_item_to_config_liststore(cdialog, info, list_store);
}
-int show_event_config_dialog(const char *event_name, GtkWindow *parent)
+GtkListStore *add_events_to_liststore(GHashTable *events)
{
- if (option_widget_list != NULL)
- {
- g_list_free(option_widget_list);
- option_widget_list = NULL;
- }
+ GtkListStore *list_store = new_conf_liststore();
+ g_hash_table_foreach(events, (GHFunc)add_event_to_liststore, list_store);
+
+ return list_store;
+}
+int show_event_config_dialog(const char *event_name, GtkWindow *parent)
+{
event_config_t *event = get_event_config(event_name);
GtkWindow *parent_window = parent ? parent : g_event_list_window;
@@ -371,14 +362,14 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
}
GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
- content = create_event_config_dialog_content(event, content);
+ content = cdialog_get_widget(create_event_config_dialog_content(event, content));
gtk_widget_show_all(content);
int result = gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_APPLY)
{
- dehydrate_config_dialog();
+ dehydrate_config_dialog(g_option_list);
const char *const store_passwords_s = get_user_setting("store_passwords");
save_event_config_data_to_user_storage(event_name,
get_event_config(event_name),
@@ -390,34 +381,3 @@ int show_event_config_dialog(const char *event_name, GtkWindow *parent)
return result;
}
-void show_events_list_dialog(GtkWindow *parent)
-{
- /*remove this line if we want to reload the config
- *everytime we show the config dialog
- */
- if (g_event_config_list == NULL)
- {
- load_event_config_data();
- load_event_config_data_from_user_storage(g_event_config_list);
- }
-
- GtkWidget *event_list_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_event_list_window = (GtkWindow*)event_list_window;
- gtk_window_set_title(g_event_list_window, _("Event Configuration"));
- gtk_window_set_default_size(g_event_list_window, 450, 400);
- gtk_window_set_position(g_event_list_window, parent ? GTK_WIN_POS_CENTER_ON_PARENT : GTK_WIN_POS_CENTER);
- if (parent != NULL)
- {
- gtk_window_set_transient_for(g_event_list_window, parent);
- // modal = parent window can't steal focus
- gtk_window_set_modal(g_event_list_window, true);
- gtk_window_set_icon_name(g_event_list_window,
- gtk_window_get_icon_name(parent));
- }
-
- GtkWidget *main_vbox = create_config_list_dialog(_("Event"), g_event_config_list, GTK_WINDOW(event_list_window), &add_event_to_liststore, NULL, NULL);
-
- gtk_container_add(GTK_CONTAINER(event_list_window), main_vbox);
-
- gtk_widget_show_all(event_list_window);
-}
diff --git a/src/gtk-helpers/internal_libreport_gtk.h b/src/gtk-helpers/internal_libreport_gtk.h
index 5e631cb..516f98e 100644
--- a/src/gtk-helpers/internal_libreport_gtk.h
+++ b/src/gtk-helpers/internal_libreport_gtk.h
@@ -27,6 +27,15 @@
extern "C" {
#endif
+typedef struct config_dialog config_dialog_t;
+typedef void (* ConfigSaveFun)(gpointer data, const char *event_name);
+
+typedef struct
+{
+ event_option_t *option;
+ GtkWidget *widget;
+} option_widget_t;
+
#define make_label_autowrap_on_resize libreport_make_label_autowrap_on_resize
void make_label_autowrap_on_resize(GtkLabel *label);
@@ -51,22 +60,28 @@ void save_event_config_data_to_user_storage(const char *event_name,
int show_event_config_dialog(const char *event_name, GtkWindow *parent);
#define create_event_config_dialog_content libreport_create_event_config_dialog_content
-GtkWidget *create_event_config_dialog_content(event_config_t *event, GtkWidget *content);
+config_dialog_t *create_event_config_dialog_content(event_config_t *event, GtkWidget *content);
+
+//#define show_workflow_list_dialog libreport_show_workflow_list_dialog
+//void show_workflow_list_dialog(GtkWindow *parent);
-#define show_workflow_list_dialog libreport_show_workflow_list_dialog
-void show_workflow_list_dialog(GtkWindow *parent);
+void save_data_from_event_config_dialog(GList *widgets, event_config_t *ec);
#define add_item_to_config_liststore libreport_add_item_to_config_liststore
-void add_item_to_config_liststore(gpointer key, gpointer value, gpointer user_data);
-
-#define create_config_list_dialog libreport_create_config_list_dialog
-GtkWidget *create_config_list_dialog(const char *column_label,
- GHashTable *items,
- GtkWindow *dialog,
- GHFunc item_to_config_info,
- GCallback on_config_cb,
- GCallback on_row_change);
+void add_item_to_config_liststore(gpointer cdialog, gpointer inf, gpointer user_data);
+
GtkListStore *new_conf_liststore(void);
+void show_config_list_dialog(GtkWindow *parent);
+GtkListStore *add_events_to_liststore(GHashTable *events);
+GtkListStore *add_workflows_to_liststore(GHashTable *workflows);
+config_dialog_t *new_config_dialog(GtkWidget *dialog, gpointer config_data, ConfigSaveFun save_fun);
+void load_workflow_config_data_from_user_storage(GHashTable *workflows);
+
+void cdialog_set_widget(config_dialog_t *cdialog, GtkWidget *widget);
+GtkWidget *cdialog_get_widget(config_dialog_t *cdialog);
+gpointer cdialog_get_data(config_dialog_t *cdialog);
+
+void dehydrate_config_dialog(GList *option_widgets);
char * tag_url(const char* line, const char* prefix);
diff --git a/src/gtk-helpers/workflow_config_dialog.c b/src/gtk-helpers/workflow_config_dialog.c
index de10134..90f2d49 100644
--- a/src/gtk-helpers/workflow_config_dialog.c
+++ b/src/gtk-helpers/workflow_config_dialog.c
@@ -27,13 +27,42 @@ enum
};
static GtkWindow *g_parent_window;
+static GHashTable *g_events_options = NULL;
static void create_event_config_dialog_content_cb(event_config_t *ec, gpointer content)
{
- create_event_config_dialog_content(ec, (GtkWidget *)content);
+ if (ec->options)
+ {
+ GtkWidget *ev_lbl = gtk_label_new(ec_get_screen_name(ec));
+ gtk_box_pack_start(GTK_BOX(content), ev_lbl, false, false, 0);
+ }
+
+ config_dialog_t *cdialog = create_event_config_dialog_content(ec, (GtkWidget *)content);
+ if (g_events_options == NULL)
+ {
+ g_events_options = g_hash_table_new_full(
+ /*hash_func*/ g_str_hash,
+ /*key_equal_func:*/ g_str_equal,
+ /*key_destroy_func:*/ g_free,
+ /*value_destroy_func:*/ NULL);
+ }
+ g_hash_table_insert(g_events_options, ec, cdialog);
+
}
-GtkWidget *create_workflow_config_dialog(const char *workflow_name, GtkWindow *parent)
+static void save_event_config_data_foreach(event_config_t *ec,
+ config_dialog_t *cdialog,
+ gpointer user_data)
+{
+ save_data_from_event_config_dialog(cdialog_get_data(cdialog), ec);
+}
+
+void save_data_from_worfklow_dialog(gpointer data, /* not needed */ const char *name)
+{
+ g_hash_table_foreach((GHashTable *)data, (GHFunc)save_event_config_data_foreach, NULL);
+}
+
+config_dialog_t *create_workflow_config_dialog(const char *workflow_name, GtkWindow *parent)
{
workflow_t *workflow = get_workflow(workflow_name);
GList *events = wf_get_event_list(workflow);
@@ -61,16 +90,28 @@ GtkWidget *create_workflow_config_dialog(const char *workflow_name, GtkWindow *p
GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ g_events_options = NULL;
g_list_foreach(events, (GFunc)create_event_config_dialog_content_cb, content);
- return dialog;
+ config_dialog_t *cdialog = new_config_dialog(dialog,
+ g_events_options,
+ (ConfigSaveFun)save_data_from_worfklow_dialog);
+ return cdialog;
}
static void add_workflow_to_liststore(gpointer key, gpointer value, gpointer user_data)
{
config_item_info_t *info = workflow_get_config_info((workflow_t *)value);
- GtkWidget *dialog = create_workflow_config_dialog(key, g_parent_window);
- add_item_to_config_liststore(dialog, info, user_data);
+ config_dialog_t *cdialog = create_workflow_config_dialog(key, g_parent_window);
+ add_item_to_config_liststore(cdialog, info, user_data);
+}
+
+GtkListStore *add_workflows_to_liststore(GHashTable *workflows)
+{
+ GtkListStore *list_store = new_conf_liststore();
+ g_hash_table_foreach(workflows, (GHFunc)add_workflow_to_liststore, list_store);
+
+ return list_store;
}
static void load_single_event_config_foreach(event_config_t *ec, gpointer user_data)
@@ -83,35 +124,7 @@ static void load_events_foreach_workflow(const char *name, workflow_t *workflow,
g_list_foreach(wf_get_event_list(workflow), (GFunc)load_single_event_config_foreach, NULL);
}
-void show_workflow_list_dialog(GtkWindow *parent)
+void load_workflow_config_data_from_user_storage(GHashTable *workflows)
{
- g_parent_window = parent;
- //g_verbose = 3;
- if (g_workflow_list == NULL)
- {
- VERB1 log("workflow list is empty - reloading");
- load_workflow_config_data(WORKFLOWS_DIR);
- }
-
- g_hash_table_foreach(g_workflow_list, (GHFunc)load_events_foreach_workflow, NULL);
-
- GtkWindow *workflow_list_window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
- gtk_window_set_title(workflow_list_window, _("Workflow Configuration"));
- gtk_window_set_default_size(workflow_list_window, 450, 400);
- gtk_window_set_position(workflow_list_window, parent ? GTK_WIN_POS_CENTER_ON_PARENT : GTK_WIN_POS_CENTER);
- if (parent != NULL)
- {
- gtk_window_set_transient_for(workflow_list_window, parent);
- // modal = parent window can't steal focus
- gtk_window_set_modal(workflow_list_window, true);
- gtk_window_set_icon_name(workflow_list_window,
- gtk_window_get_icon_name(parent));
- }
-
- GtkWidget *main_vbox = create_config_list_dialog(_("Workflow"), g_workflow_list, workflow_list_window, add_workflow_to_liststore, NULL, NULL);
-
- gtk_container_add(GTK_CONTAINER(workflow_list_window), main_vbox);
-
- gtk_widget_show_all(GTK_WIDGET(workflow_list_window));
-
+ g_hash_table_foreach(workflows, (GHFunc)load_events_foreach_workflow, NULL);
}
diff --git a/src/gui-wizard-gtk/main.c b/src/gui-wizard-gtk/main.c
index 03f8fd2..b47687b 100644
--- a/src/gui-wizard-gtk/main.c
+++ b/src/gui-wizard-gtk/main.c
@@ -140,7 +140,7 @@ int main(int argc, char **argv)
/* load /etc/abrt/events/foo.{conf,xml} stuff
and $XDG_CACHE_HOME/abrt/events/foo.conf */
- load_event_config_data();
+ g_event_config_list = load_event_config_data();
load_event_config_data_from_user_storage(g_event_config_list);
load_user_settings("report-gtk");
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index dae4e80..0abcbba 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -1522,9 +1522,6 @@ static bool is_processing_finished()
static void hide_next_step_button()
{
- if(gtk_widget_get_visible(GTK_WIDGET(g_btn_next)) == false)
- return
-
/* replace 'Forward' with 'Close' button */
/* 1. hide next button */
gtk_widget_hide(g_btn_next);
@@ -1534,9 +1531,6 @@ static void hide_next_step_button()
static void show_next_step_button()
{
- if(gtk_widget_get_visible(GTK_WIDGET(g_btn_next)) == true)
- return
-
gtk_box_reorder_child(g_box_buttons, g_btn_close, 0);
gtk_widget_show(g_btn_next);
}
@@ -2044,7 +2038,7 @@ static void on_no_comment_toggled(GtkToggleButton *togglebutton, gpointer user_d
static void on_show_event_list_cb(GtkWidget *button, gpointer user_data)
{
- show_events_list_dialog(GTK_WINDOW(g_wnd_assistant));
+ show_config_list_dialog(GTK_WINDOW(g_wnd_assistant));
}
#if 0
diff --git a/src/include/event_config.h b/src/include/event_config.h
index 68463d3..24e1eac 100644
--- a/src/include/event_config.h
+++ b/src/include/event_config.h
@@ -103,12 +103,14 @@ void free_event_config(event_config_t *p);
void load_event_description_from_file(event_config_t *event_config, const char* filename);
// (Re)loads data from /etc/abrt/events/*.{conf,xml}
-void load_event_config_data(void);
+GHashTable *load_event_config_data(void);
/* Frees all loaded data */
void free_event_config_data(void);
event_config_t *get_event_config(const char *event_name);
event_option_t *get_event_option_from_list(const char *option_name, GList *event_options);
+/* for debugging */
+void ec_print(event_config_t *ec);
extern GHashTable *g_event_config_list; // for iterating through entire list of all loaded configs
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index 4f85b2a..88a1f25 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -644,7 +644,7 @@ file_obj_t *new_file_obj(const char* fullpath, const char* filename);
#define free_file_obj libreport_free_file_obj
void free_file_obj(file_obj_t *f);
#define load_workflow_config_data libreport_load_workflow_config_data
-void load_workflow_config_data(const char* path);
+GHashTable *load_workflow_config_data(const char* path);
/* Connect to abrtd over unix domain socket, issue DELETE command */
int delete_dump_dir_possibly_using_abrtd(const char *dump_dir_name);
diff --git a/src/lib/event_config.c b/src/lib/event_config.c
index e6ae269..88041ff 100644
--- a/src/lib/event_config.c
+++ b/src/lib/event_config.c
@@ -79,6 +79,15 @@ bool ec_is_configurable(event_config_t* ec)
return g_list_length(ec->options) > 0;
}
+void ec_print(event_config_t *ec)
+{
+ printf("%s\n\t%s\n\t%s\n",
+ ec_get_name(ec),
+ ec_get_screen_name(ec),
+ ec_get_description(ec)
+ );
+}
+
void free_event_option(event_option_t *p)
{
if (!p)
@@ -183,7 +192,7 @@ static void load_config_files(const char *dir_path)
}
/* (Re)loads data from /etc/abrt/events/foo.{xml,conf} and $XDG_CACHE_HOME/abrt/events/foo.conf */
-void load_event_config_data(void)
+GHashTable *load_event_config_data(void)
{
free_event_config_data();
@@ -227,6 +236,8 @@ void load_event_config_data(void)
cachedir = concat_path_file(g_get_user_cache_dir(), "abrt/events");
load_config_files(cachedir);
free(cachedir);
+
+ return g_event_config_list;
}
/* Frees all loaded data */
diff --git a/src/lib/workflow.c b/src/lib/workflow.c
index 1b92283..6fa2634 100644
--- a/src/lib/workflow.c
+++ b/src/lib/workflow.c
@@ -53,10 +53,14 @@ static void free_workflow_cb(const char *name, workflow_t *w, gpointer user_data
free_workflow(w);
}
-void free_workflow_list(GHashTable *wl)
+void free_workflow_list(GHashTable **wl)
{
- g_hash_table_foreach(wl, (GHFunc)free_workflow_cb, NULL);
- g_hash_table_destroy(wl);
+ if(*wl != NULL)
+ {
+ g_hash_table_foreach(*wl, (GHFunc)free_workflow_cb, NULL);
+ g_hash_table_destroy(*wl);
+ *wl = NULL;
+ }
}
workflow_t *get_workflow(const char *name)
@@ -74,8 +78,11 @@ workflow_t *get_workflow(const char *name)
return g_hash_table_lookup(g_workflow_list, name);
}
-void load_workflow_config_data(const char* path)
+GHashTable *load_workflow_config_data(const char* path)
{
+ if (g_workflow_list)
+ return g_workflow_list;
+
if (g_workflow_list == NULL)
{
g_workflow_list = g_hash_table_new_full(
@@ -104,6 +111,8 @@ void load_workflow_config_data(const char* path)
workflow_files = g_list_next(workflow_files);
}
free_file_list(workflow_files);
+
+ return g_workflow_list;
}
config_item_info_t *workflow_get_config_info(workflow_t *w)
--
1.8.0
11 years, 5 months
[LIBREPORT PATCH 1/2] teach reporter-bugzilla to add reporter to CC
by Jakub Filak
- a part of trac#833
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/reporter-bugzilla.c | 56 ++++++++++++++++++++++++-----------------
1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
index 2623122..e20a7e6 100644
--- a/src/plugins/reporter-bugzilla.c
+++ b/src/plugins/reporter-bugzilla.c
@@ -762,6 +762,8 @@ int main(int argc, char **argv)
"\nor:"
"\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] FILE..."
"\nor:"
+ "\n& [-v] [-c CONFFILE]... [-d DIR] -t[ID] -w"
+ "\nor:"
"\n& [-v] [-c CONFFILE]... -h DUPHASH"
"\n"
"\nReports problem to Bugzilla."
@@ -787,6 +789,8 @@ int main(int argc, char **argv)
"\nOption -tID uploads FILEs to the bug with specified ID on Bugzilla site."
"\n-d DIR is ignored."
"\n"
+ "\nOption -w adds bugzilla user to bug's CC list."
+ "\n"
"\nIf not specified, CONFFILE defaults to "CONF_DIR"/plugins/bugzilla.conf"
"\nIts lines should have 'PARAM = VALUE' format."
"\nRecognized string parameters: BugzillaURL, Login, Password, OSRelease."
@@ -803,9 +807,10 @@ int main(int argc, char **argv)
OPT_t = 1 << 4,
OPT_b = 1 << 5,
OPT_f = 1 << 6,
- OPT_h = 1 << 7,
- OPT_g = 1 << 8,
- OPT_D = 1 << 9,
+ OPT_w = 1 << 7,
+ OPT_h = 1 << 8,
+ OPT_g = 1 << 9,
+ OPT_D = 1 << 10,
};
const char *dump_dir_name = ".";
GList *conf_file = NULL;
@@ -823,6 +828,7 @@ int main(int argc, char **argv)
OPT_OPTSTRING('t', "ticket", &ticket_no , "ID" , _("Attach FILEs [to bug with this ID]")),
OPT_BOOL( 'b', NULL, NULL, _("When creating bug, attach binary files too")),
OPT_BOOL( 'f', NULL, NULL, _("Force reporting even if this problem is already reported")),
+ OPT_BOOL( 'w', NULL, NULL, _("Add bugzilla user to CC list [of bug with this ID]")),
OPT_STRING( 'h', "duphash", &abrt_hash, "DUPHASH", _("Print BUG_ID which has given DUPHASH")),
OPT_LIST( 'g', "group", &group , "GROUP" , _("Restrict access to this group only")),
OPT_OPTSTRING('D', "debug", &debug_str , "STR" , _("Debug")),
@@ -910,35 +916,39 @@ int main(int argc, char **argv)
// ...
}
- /* Attach files to existing BZ */
- if (!argv[0])
+ if ((!argv[0] && !(opts & OPT_w)) || (argv[0] && (opts & OPT_w)))
show_usage_and_die(program_usage_string, program_options);
log(_("Logging into Bugzilla at %s"), rhbz.b_bugzilla_url);
rhbz_login(client, rhbz.b_login, rhbz.b_password);
- while (*argv)
- {
- const char *filename = *argv++;
- VERB1 log("Attaching file '%s' to bug %s", filename, ticket_no);
-
- int fd = open(filename, O_RDONLY);
- if (fd < 0)
+ if (opts & OPT_w)
+ rhbz_mail_to_cc(client, xatoi_positive(ticket_no), rhbz.b_login, /* require mail notify */ 0);
+ else
+ { /* Attach files to existing BZ */
+ while (*argv)
{
- perror_msg("Can't open '%s'", filename);
- continue;
- }
+ const char *filename = *argv++;
+ VERB1 log("Attaching file '%s' to bug %s", filename, ticket_no);
- struct stat st;
- if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
- {
- error_msg("'%s': not a regular file", filename);
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ {
+ perror_msg("Can't open '%s'", filename);
+ continue;
+ }
+
+ struct stat st;
+ if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode))
+ {
+ error_msg("'%s': not a regular file", filename);
+ close(fd);
+ continue;
+ }
+
+ rhbz_attach_fd(client, ticket_no, filename, fd, /*flags*/ 0);
close(fd);
- continue;
}
-
- rhbz_attach_fd(client, ticket_no, filename, fd, /*flags*/ 0);
- close(fd);
}
log(_("Logging out"));
--
1.7.11.7
11 years, 5 months
[Automatic Bug Reporting Tool - ABRT] #889: handle decorator frames in python stacktraces
by fedora-badges
#889: handle decorator frames in python stacktraces
----------------------+----------------------
Reporter: jfilak | Owner: kklic@…
Type: defect | Status: new
Priority: major | Milestone:
Component: btparser | Version:
Keywords: | Blocked By:
Blocking: |
----------------------+----------------------
{{{
Traceback (most recent call last):
File "/usr/bin/system-config-services", line 1092, in
on_serviceDisable_activate
self._systemd_change_unit_file(service, "disable")
File "/usr/bin/system-config-services", line 1071, in
_systemd_change_unit_file
self.systemd_manager.DisableUnitFiles([unit.unit_id])
File "<string>", line 2, in DisableUnitFiles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python2.7/site-packages/slip/dbus/polkit.py", line 141,
in _enable_proxy
return func(*p, **k)
File "/usr/lib/python2.7/site-
packages/scservices/core/systemd/manager.py", line 149, in
DisableUnitFiles
runtime)
File "/usr/lib/python2.7/site-packages/slip/dbus/proxies.py", line 50,
in __call__
return dbus.proxies._ProxyMethod.__call__(self, *args, **kwargs)
File "/usr/lib/python2.7/site-packages/dbus/proxies.py", line 145, in
__call__
**keywords)
File "/usr/lib/python2.7/site-packages/dbus/connection.py", line 651, in
call_blocking
message, timeout)
DBusException: org.freedesktop.DBus.Error.FileNotFound: No such file or
directory
}}}
{{{
def enable_proxy(func=None, authfail_result=AUTHFAIL_DONTCATCH,
authfail_exception=None, authfail_callback=None):
"""Decorator for DBus proxy methods.
}}}
{{{
@polkit.enable_proxy
def RestartUnit(self, name, mode='replace'):
return self.privileged_manager_interface.RestartUnit(name, mode)
}}}
--
Ticket URL: <https://fedorahosted.org/abrt/ticket/889>
Automatic Bug Reporting Tool - ABRT <http://fedorahoted.org/abrt/>
Automatic bug reporting tool
11 years, 5 months
Re: [Automatic Bug Reporting Tool - ABRT] #754: alllow users to delete, change and add problem element over DBus
by fedora-badges
#754: alllow users to delete, change and add problem element over DBus
-----------------------+---------------------------------------
Reporter: jfilak | Owner: jfilak
Type: task | Status: closed
Priority: major | Milestone: Remove_Directory_Stealing
Component: dbus-api | Version: 2.0
Resolution: fixed | Keywords: ABRTF18
Blocked By: | Blocking:
-----------------------+---------------------------------------
Changes (by jfilak):
* status: new => closed
* resolution: => fixed
Comment:
abrt git
{{{
commit a1857bc75b745f867afa27c7e5066068a958f5b6
Author: Jakub Filak <jfilak(a)redhat.com>
Date: Thu Nov 29 11:08:07 2012 +0100
testsuite: Set/Delete element D-Bus methods
- related to trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
commit 01f74814a15be459652a2442a427721de9238810
Author: Jakub Filak <jfilak(a)redhat.com>
Date: Thu Nov 29 11:04:04 2012 +0100
introduce DeleteElement D-Bus method
- closes trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
commit 97add0e479476d10c44f7cf93192fafd7a734feb
Author: Jakub Filak <jfilak(a)redhat.com>
Date: Thu Nov 29 10:55:09 2012 +0100
introduce SetElement D-Bus method
- a part of trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
}}}
libreport git
{{{
commit 23e513dabb93eb468218cbe3500009a190e7a29d
Author: Jakub Filak <jfilak(a)redhat.com>
Date: Thu Nov 29 09:36:41 2012 +0100
introduce a function deleting dd's element
- required for implementation of abrt's DeleteElement D-Bus method.
- trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
commit 159de8cab58d281d093a7ca23f54afb5d1ab43fc
Author: Jakub Filak <jfilak(a)redhat.com>
Date: Mon Oct 1 13:35:24 2012 +0200
introduce a function getting no. of Bytes of dd's element
- required for implementation of abrt's SetElement D-Bus method.
- trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
}}}
--
Ticket URL: <https://fedorahosted.org/abrt/ticket/754#comment:5>
Automatic Bug Reporting Tool - ABRT <http://fedorahoted.org/abrt/>
Automatic bug reporting tool
11 years, 5 months
[LIBREPORT PATCH] introduce a function getting no. of Bytes of dd's element
by Jakub Filak
- required for implementation of abrt's SetElement D-Bus method.
- trac#754
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/include/dump_dir.h | 5 +++++
src/lib/dump_dir.c | 21 +++++++++++++++++++++
2 files changed, 26 insertions(+)
diff --git a/src/include/dump_dir.h b/src/include/dump_dir.h
index 21e8a2b..2b9fc7d 100644
--- a/src/include/dump_dir.h
+++ b/src/include/dump_dir.h
@@ -68,6 +68,11 @@ char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned fla
char* dd_load_text(const struct dump_dir *dd, const char *name);
void dd_save_text(struct dump_dir *dd, const char *name, const char *data);
void dd_save_binary(struct dump_dir *dd, const char *name, const char *data, unsigned size);
+/* Returns value less than 0 if any error occured; otherwise returns size of an
+ * item in Bytes. If an item does not exist returns 0 instead of an error
+ * value.
+ */
+long dd_get_item_size(struct dump_dir *dd, const char *name);
/* Returns 0 if directory is deleted or not found */
int dd_delete(struct dump_dir *dd);
int dd_rename(struct dump_dir *dd, const char *new_path);
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
index 0fc7da7..a287ebb 100644
--- a/src/lib/dump_dir.c
+++ b/src/lib/dump_dir.c
@@ -827,6 +827,27 @@ void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, uns
free(full_path);
}
+long dd_get_item_size(struct dump_dir *dd, const char *name)
+{
+ long size = -1;
+ char *iname = concat_path_file(dd->dd_dirname, name);
+ struct stat statbuf;
+
+ if (lstat(iname, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
+ size = statbuf.st_size;
+ else
+ {
+ if (errno == ENOENT)
+ size = 0;
+ else
+ perror_msg("Can't get size of file '%s'", iname);
+ }
+
+ free(iname);
+
+ return size;
+}
+
DIR *dd_init_next_file(struct dump_dir *dd)
{
// if (!dd->locked)
--
1.7.11.4
11 years, 5 months
[ABRT PATCH] trac#754: introduce SetElement/DeleteElement D-Bus methods
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 152 ++++++++++++-
tests/runtests/aux/test_order | 1 +
tests/runtests/dbus-elements-handling/PURPOSE | 7 +
tests/runtests/dbus-elements-handling/runtest.sh | 278 +++++++++++++++++++++++
4 files changed, 437 insertions(+), 1 deletion(-)
create mode 100644 tests/runtests/dbus-elements-handling/PURPOSE
create mode 100755 tests/runtests/dbus-elements-handling/runtest.sh
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index 425409f..d952e83 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -36,6 +36,15 @@ static const gchar introspection_xml[] =
" <arg type='as' name='element_names' direction='in'/>"
" <arg type='a{ss}' name='response' direction='out'/>"
" </method>"
+ " <method name='SetElement'>"
+ " <arg type='s' name='problem_dir' direction='in'/>"
+ " <arg type='s' name='name' direction='in'/>"
+ " <arg type='s' name='value' direction='in'/>"
+ " </method>"
+ " <method name='DeleteElement'>"
+ " <arg type='s' name='problem_dir' direction='in'/>"
+ " <arg type='s' name='name' direction='in'/>"
+ " </method>"
" <method name='ChownProblemDir'>"
" <arg type='s' name='problem_dir' direction='in'/>"
" </method>"
@@ -154,7 +163,9 @@ static bool uid_in_group(uid_t uid, gid_t gid)
static int dir_accessible_by_uid(const char *dir_path, uid_t uid)
{
struct stat statbuf;
- if (stat(dir_path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
+ if (stat(dir_path, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode))
+ errno = ENOTDIR;
+ else
{
if (uid == 0 || (statbuf.st_mode & S_IROTH) || uid_in_group(uid, statbuf.st_gid))
{
@@ -403,6 +414,65 @@ static void return_InvalidProblemDir_error(GDBusMethodInvocation *invocation, co
free(msg);
}
+/*
+ * Checks element's rights and does not open directory if element is protected.
+ * Checks problem's rights and does not open directory if user hasn't got
+ * access to a problem.
+ *
+ * Returns a dump directory opened for writing or NULL.
+ *
+ * If any operation from the above listed fails, immediately returns D-Bus
+ * error to a D-Bus caller.
+ */
+static struct dump_dir *open_directory_for_modification_of_element(
+ GDBusMethodInvocation *invocation,
+ uid_t caller_uid,
+ const char *problem_id,
+ const char *element)
+{
+ static const char *const protected_elements[] = {
+ FILENAME_TIME,
+ FILENAME_UID,
+ NULL,
+ };
+
+ for (const char *const *protected = protected_elements; *protected; ++protected)
+ {
+ if (strcmp(*protected, element) == 0)
+ {
+ char *error = xasprintf(_("'%s' element can't be modified"), element);
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.ProtectedElement",
+ error);
+ free(error);
+ return NULL;
+ }
+ }
+
+ if (!dir_accessible_by_uid(problem_id, caller_uid))
+ {
+ if (errno == ENOTDIR)
+ return_InvalidProblemDir_error(invocation, problem_id);
+ else
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.AuthFailure",
+ _("Not Authorized"));
+
+ return NULL;
+ }
+
+ struct dump_dir *dd = dd_opendir(problem_id, /* flags : */ 0);
+ if (!dd)
+ { /* This should not happen because of the access check above */
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.Failure",
+ _("Can't access the problem for modification"));
+ return NULL;
+ }
+
+ return dd;
+}
+
static void handle_method_call(GDBusConnection *connection,
const gchar *caller,
const gchar *object_path,
@@ -620,6 +690,86 @@ static void handle_method_call(GDBusConnection *connection,
return;
}
+ if (g_strcmp0(method_name, "SetElement") == 0)
+ {
+ const char *problem_id;
+ const char *element;
+ const char *value;
+
+ g_variant_get(parameters, "(&s&s&s)", &problem_id, &element, &value);
+
+ if (element == NULL || element[0] == '\0' || strlen(element) > 64)
+ {
+ char *error = xasprintf(_("'%s' is not a valid element name"), element);
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.InvalidElement",
+ error);
+
+ free(error);
+ return;
+ }
+
+ struct dump_dir *dd = open_directory_for_modification_of_element(
+ invocation, caller_uid, problem_id, element);
+ if (!dd)
+ return;
+
+ /* Is it good idea to make it static? Is it possible to change the max size while a single run? */
+ const double max_size = g_settings_nMaxCrashReportsSize * (1024 * 1024);
+
+ const double requested_size = strlen(value) - dd_get_item_size(dd, element);
+ /* Don't want to check the size limit in case of reducing of size */
+ if (requested_size > 0
+ && requested_size > (max_size - get_dirsize(g_settings_dump_location)))
+ {
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.Failure",
+ _("No problem space left"));
+ }
+ else
+ {
+ dd_save_text(dd, element, value);
+ g_dbus_method_invocation_return_value(invocation, NULL);
+ }
+
+ dd_close(dd);
+
+ return;
+ }
+
+ if (g_strcmp0(method_name, "DeleteElement") == 0)
+ {
+ const char *problem_id;
+ const char *element;
+
+ g_variant_get(parameters, "(&s&s)", &problem_id, &element);
+
+ struct dump_dir *dd = open_directory_for_modification_of_element(
+ invocation, caller_uid, problem_id, element);
+ if (!dd)
+ return;
+
+ // TODO : move it to libreport/src/lib/dump_dir.c
+ char *path = concat_path_file(problem_id, element);
+ const int res = unlink(path);
+ if (res == 0 || errno == ENOENT)
+ g_dbus_method_invocation_return_value(invocation, NULL);
+ else
+ {
+ perror_msg("Can't delete an element '%s'", path);
+ char *error = xasprintf(_("Can't delete an element '%s' from a problem directory '%s'"), element, problem_id);
+ g_dbus_method_invocation_return_dbus_error(invocation,
+ "org.freedesktop.problems.Failure",
+ error);
+ free(error);
+ }
+
+ free(path);
+ dd_close(dd);
+
+ return;
+ }
+
if (g_strcmp0(method_name, "DeleteProblem") == 0)
{
/* Dbus parameters are always tuples.
diff --git a/tests/runtests/aux/test_order b/tests/runtests/aux/test_order
index e43c139..0020aad 100644
--- a/tests/runtests/aux/test_order
+++ b/tests/runtests/aux/test_order
@@ -24,6 +24,7 @@ dumpoops
dumpxorg
dbus-api
dbus-NewProblem
+dbus-elements-handling
bodhi
oops_processing
diff --git a/tests/runtests/dbus-elements-handling/PURPOSE b/tests/runtests/dbus-elements-handling/PURPOSE
new file mode 100644
index 0000000..5c185a6
--- /dev/null
+++ b/tests/runtests/dbus-elements-handling/PURPOSE
@@ -0,0 +1,7 @@
+PURPOSE of dbus-elements-handling
+Description: Check D-Bus add/remove elements and change element values methods
+Author: Jakub Filak <jfilak(a)redhat.com>
+
+This is a test of ABRT D-Bus methods. This test is focused on adding, changing
+and removing elements. The test requires two different user because the test is
+focused on correct handling of priviliges for required functions.
diff --git a/tests/runtests/dbus-elements-handling/runtest.sh b/tests/runtests/dbus-elements-handling/runtest.sh
new file mode 100755
index 0000000..9427b89
--- /dev/null
+++ b/tests/runtests/dbus-elements-handling/runtest.sh
@@ -0,0 +1,278 @@
+#!/bin/bash
+# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# runtest.sh of dbus-elements-handling
+# Description: Check D-Bus add/remove elements and change element values methods
+# Author: Jakub Filak <jfilak(a)redhat.com>
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#
+# Copyright (c) 2012 Red Hat, Inc. All rights reserved.
+#
+# This program 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.
+#
+# This program 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 this program. If not, see http://www.gnu.org/licenses/.
+#
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+. /usr/share/beakerlib/beakerlib.sh
+
+TEST="dbus-elements-handling"
+PACKAGE="abrt"
+STAT="stat --format=%A,%U,%G"
+
+function abrtDBusNewProblem() {
+ args=analyzer,libreport,executable,$(which true)
+
+ if [ -n "$2" ]; then
+ args = $args,$2
+ fi
+
+ dbus-send --system --type=method_call --print-reply \
+ --dest=org.freedesktop.problems /org/freedesktop/problems org.freedesktop.problems.NewProblem \
+ dict:string:string:$args 2>&1 | tail -1 | sed 's/ *string *"\(.*\)"/\1/'
+}
+
+function abrtDBusSetElement() {
+ dbus-send --system --type=method_call --print-reply \
+ --dest=org.freedesktop.problems /org/freedesktop/problems org.freedesktop.problems.SetElement \
+ string:$1 string:$2 string:$3 2>&1 | awk -v first=1 '{ if (first) { first=0 } else { print } } /Error/ { print }'
+}
+
+function abrtDBusDelElement() {
+ dbus-send --system --type=method_call --print-reply \
+ --dest=org.freedesktop.problems /org/freedesktop/problems org.freedesktop.problems.DeleteElement \
+ string:$1 string:$2 2>&1 | awk -v first=1 '{ if (first) { first=0 } else { print} } /Error/ { print }'
+}
+
+function abrtDBusGetElement() {
+ dbus-send --system --type=method_call --print-reply \
+ --dest=org.freedesktop.problems /org/freedesktop/problems org.freedesktop.problems.GetInfo \
+ string:$1 array:string:$2 2>&1 | awk -v elem=$2 -F\" '/string/ { if (beg) { print $2; exit } } $0 ~ "string \""elem { beg=1 }'
+}
+
+# $1 problem directory
+# $2 user name
+# $3 expected response for new
+# $4 expected response for change
+# $5 expected response for delete
+# $6 expected response for delete nonexisting
+function abrtElementsHandlingTest() {
+ # the time element is required, it must be there
+ problem_stat=`$STAT $1/time`
+
+ rlAssertEquals "A new element is not created yet" "_$(abrtDBusGetElement $1 the_element)" "_"
+ res=$(su $2 -c "abrtDBusSetElement $1 the_element an_elements_value")
+ rlAssertEquals "SetElement method for nonexisting element" "_$res" "_$3"
+ if [ -n "$3" ]; then
+ rlAssertEquals "Failed to create the new element" "_$(abrtDBusGetElement $1 the_element)" "_"
+ rlAssertEquals "SetElement method for nonexisting element as root" "_$(abrtDBusSetElement $1 the_element an_elements_value)" "_"
+ else
+ rlAssertExists $1/the_element
+ fi
+ rlAssertEquals "The element has been created with a passed value" "_$(abrtDBusGetElement $1 the_element)" "_an_elements_value"
+ rlAssertEquals "The new element has correct rights" "_$($STAT $1/the_element)" "_$problem_stat"
+
+ if [ ! -e $1/the_element ]; then
+ rlLog "Create missing element manually"
+ rlRun "echo -n 'the_element' > $1/the_element" 0 "Add element"
+ rlRun "chmod `stat --format=%a $1/time` $1/the_element" 0 "Set correct perms"
+ rlRun "chown `stat --format=%U:%G $1/time` $1/the_element" 0 "Set correct user and group"
+ fi
+
+ res=$(su $2 -c "abrtDBusSetElement $1 the_element the_fifth_element")
+ rlAssertEquals "SetElement method for existing element" "_$res" "_$4"
+ if [ -n "$4" ]; then
+ rlAssertEquals "Failed to update the element" "_$(abrtDBusGetElement $1 the_element)" "_an_elements_value"
+ rlAssertEquals "SetElement method for existing element as root" "_$(abrtDBusSetElement $1 the_element the_fifth_element)" "_"
+ fi
+ rlAssertEquals "A value of the updated element has the_element" "_$(abrtDBusGetElement $1 the_element)" "_the_fifth_element"
+ rlAssertEquals "The updated element has correct rights" "_$($STAT $1/the_element)" "_$problem_stat"
+
+ res=$(su $2 -c "abrtDBusDelElement $1 the_element")
+ rlAssertEquals "DelElement method for existing element" "_$res" "_$5"
+ if [ -n "$5" ]; then
+ rlAssertEquals "Failed to delete the element" "_$(abrtDBusGetElement $1 the_element)" "_the_fifth_element"
+ rlAssertEquals "DelElement method for existing element as root" "_$(abrtDBusDelElement $1 the_element)" "_"
+ else
+ rlAssertNotExists $1/the_element
+ fi
+ res=$(su $2 -c "abrtDBusDelElement $1 the_element")
+ rlAssertEquals "DelElement method for nonexisting element" "_$res" "_$6"
+
+ old_uid=$(abrtDBusGetElement $1 uid)
+ res=$(su $2 -c "abrtDBusDelElement $1 uid")
+ rlAssertEquals "DelElement method for UID" "_$res" "_Error org.freedesktop.problems.ProtectedElement: 'uid' element can't be modified"
+ rlAssertEquals "The UID element is unchanged after delete attempt" "_$(abrtDBusGetElement $1 uid)" "_$old_uid"
+
+ new_uid=$(id -u abrtdbustestanother)
+ res=$(su $2 -c "abrtDBusSetElement $1 uid $new_uid")
+ rlAssertEquals "SetElement method for UID element" "_$res" "_Error org.freedesktop.problems.ProtectedElement: 'uid' element can't be modified"
+ rlAssertEquals "The UID element is unchanged after set attempt" "_$(abrtDBusGetElement $1 uid)" "_$old_uid"
+
+ old_time=$(abrtDBusGetElement $1 time)
+ res=$(su $2 -c "abrtDBusDelElement $1 time")
+ rlAssertEquals "DelElement method for TIME" "_$res" "_Error org.freedesktop.problems.ProtectedElement: 'time' element can't be modified"
+ rlAssertEquals "The TIME element is unchanged after delete attempt" "_$(abrtDBusGetElement $1 time)" "_$old_time"
+
+ new_time=$((old_time + 10))
+ res=$(su $2 -c "abrtDBusSetElement $1 time $new_time")
+ rlAssertEquals "SetElement method for TIME element" "_$res" "_Error org.freedesktop.problems.ProtectedElement: 'time' element can't be modified"
+ rlAssertEquals "The TIME element is unchanged after set attempt" "_$(abrtDBusGetElement $1 time)" "_$old_time"
+}
+
+function abrtMaxCrashReportsSizeTest() {
+ resp=`su $2 -c "python <<EOF
+import dbus
+import sys
+proxy=dbus.SystemBus().get_object('org.freedesktop.problems', '/org/freedesktop/problems')
+iface=dbus.Interface(proxy, 'org.freedesktop.problems')
+try:
+ iface.SetElement(\"$1\", \"onemibofx\", 1024*1024*\"x\")
+except dbus.exceptions.DBusException as e:
+ print \"%s: %s\" % (e.get_dbus_name(), e.get_dbus_message())
+EOF"`
+ rlAssertEquals "No free space detected" "_$resp" "_org.freedesktop.problems.Failure: No problem space left"
+
+ resp=`su $2 -c "python <<EOF
+import dbus
+import sys
+proxy=dbus.SystemBus().get_object('org.freedesktop.problems', '/org/freedesktop/problems')
+iface=dbus.Interface(proxy, 'org.freedesktop.problems')
+try:
+ iface.SetElement(\"$1\", \"onemibofx\", 512*1024*\"x\")
+ iface.SetElement(\"$1\", \"onemibofx\", 512*1024*\"x\")
+except dbus.exceptions.DBusException as e:
+ print \"%s: %s\" % (e.get_dbus_name(), e.get_dbus_message())
+EOF"`
+ rlAssertEquals "Size limit correctly checks the size limit according to a new size of an element" "_$resp" "_"
+}
+
+rlJournalStart
+ rlPhaseStartSetup
+ rlRun "useradd -c \"dbus-elements-handling test an unprivileged user\" -M abrtdbustest" 0 "Create a test user"
+ rlRun "useradd -c \"dbus-elements-handling test an another user\" -M abrtdbustestanother" 0 "Create an another test user"
+ export -f abrtDBusNewProblem
+ export -f abrtDBusSetElement
+ export -f abrtDBusDelElement
+ export -f abrtDBusGetElement
+ DUMP_LOCATION=`mktemp -d`
+ # Set limit to 1Midk
+ rlRun "cp /etc/abrt/abrt.conf /etc/abrt/abrt.conf.bak" 0 "Create a backup of abrt configuration"
+ rlRun "sed 's,^.*MaxCrashReportsSize.*=.*$,MaxCrashReportsSize=1,' -i /etc/abrt/abrt.conf" 0 "Set limit for crash reports to 1MiB"
+ rlRun "sed 's,^.*DumpLocation.*=.*$,DumpLocation=$DUMP_LOCATION,' -i /etc/abrt/abrt.conf" 0 "Change the dump location"
+ rlRun "systemctl restart abrtd.service" 0 "Restart abrt service"
+
+ rlLog "Create a problem data as the root user"
+ roots_problem=`abrtDBusNewProblem deleted,to_be_deleted,changed,to_be_changed`
+ sleep 5
+ roots_problem_path="$(abrt-cli list -f $DUMP_LOCATION | awk -v id=$roots_problem '$0 ~ "Directory:.*"id { print $2 }')"
+ if [ -z "$roots_problem_path" ]; then
+ rlDie "Not found path"
+ fi
+
+ rlLog "Create a problem data as the unprivileged user"
+ unprivilegeds_problem=`su abrtdbustest -c 'abrtDBusNewProblem deleted,to_be_deleted,changed,to_be_changed'`
+ sleep 5
+ unprivilegeds_problem_path="$(abrt-cli list -f $DUMP_LOCATION | awk -v id=$unprivilegeds_problem '$0 ~ "Directory:.*"id { print $2 }')"
+ if [ -z "$unprivilegeds_problem_path" ]; then
+ rlDie "Not found path"
+ fi
+ rlPhaseEnd
+
+ rlPhaseStartTest "Sanity tests"
+ rlAssertEquals "SetElement method for an invalid problem id" "_$(abrtDBusSetElement foo the_element a_value)" "_Error org.freedesktop.problems.InvalidProblemDir: 'foo' is not a valid problem directory"
+ rlAssertEquals "DelElement method for an invalid problem id" "_$(abrtDBusDelElement foo the_element)" "_Error org.freedesktop.problems.InvalidProblemDir: 'foo' is not a valid problem directory"
+
+ rlAssertEquals "Can't create an element with empty name" "_$(abrtDBusSetElement $roots_problem_path '' some_value)" "_Error org.freedesktop.problems.InvalidElement: '' is not a valid element name"
+ rlAssertEquals "Can't create an element with too long name" "_$(abrtDBusSetElement $roots_problem_path 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' some_value)" "_Error org.freedesktop.problems.InvalidElement: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' is not a valid element name"
+ rlPhaseEnd
+
+ rlPhaseStartTest "Handle elements as root"
+ # Test functionality as the root user
+ rlLog "root changes root's problem"
+ abrtElementsHandlingTest "$roots_problem_path" "root"
+
+ rlLog "root changes user's problem"
+ abrtElementsHandlingTest "$unprivilegeds_problem_path" "root"
+
+ rlLog "Chech max crash reports size"
+ abrtMaxCrashReportsSizeTest "$roots_problem_path" "root"
+ rlPhaseEnd
+
+ rlPhaseStartCleanup
+ rlRun "abrt-cli rm $roots_problem_path" 0 "Remove roots crash directory"
+ rlRun "abrt-cli rm $unprivilegeds_problem_path" 0 "Remove users crash directory"
+ rlPhaseEnd
+
+ rlPhaseStartSetup
+ rlRun "systemctl stop abrtd.service" 0 "Stop abrtd before cleaning of the dump location"
+ rlRun "rm -rf $DUMP_LOCATION/*" 0 "Clean the dump location"
+ rlRun "systemctl start abrtd.service" 0 "Start abrtd after cleaning of the dump location"
+
+ rlLog "Create a problem data as the root user"
+ roots_problem=`abrtDBusNewProblem`
+ sleep 5
+ roots_problem_path="$(abrt-cli list -f $DUMP_LOCATION | awk -v id=$roots_problem '$0 ~ "Directory:.*"id { print $2 }')"
+ if [ -z "$roots_problem_path" ]; then
+ rlDie "Not found path problem path"
+ fi
+
+ rlLog "Create a problem data as the unprivileged user"
+ unprivilegeds_problem=`su abrtdbustest -c 'abrtDBusNewProblem'`
+ sleep 5
+ unprivilegeds_problem_path="$(abrt-cli list -f $DUMP_LOCATION | awk -v id=$unprivilegeds_problem '$0 ~ "Directory:.*"id { print $2 }')"
+ if [ -z "$unprivilegeds_problem_path" ]; then
+ rlDie "Not found path problem path"
+ fi
+
+ rlLog "Create a problem data as the unprivileged user"
+ second_unprivilegeds_problem=`su abrtdbustest -c 'abrtDBusNewProblem'`
+ sleep 5
+ second_unprivilegeds_problem_path="$(abrt-cli list -f $DUMP_LOCATION | awk -v id=$second_unprivilegeds_problem '$0 ~ "Directory:.*"id { print $2 }')"
+ if [ -z "$second_unprivilegeds_problem_path" ]; then
+ rlDie "Not found path problem path"
+ fi
+ rlPhaseEnd
+
+ rlPhaseStartTest "Handle elements as a user"
+ rlLog "User changes root's problem"
+ abrtElementsHandlingTest "$roots_problem_path" "abrtdbustest" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized"
+
+ rlLog "User changes user's problem"
+ abrtElementsHandlingTest "$unprivilegeds_problem_path" "abrtdbustest"
+
+ rlLog "Another user changes user's problem"
+ abrtElementsHandlingTest "$second_unprivilegeds_problem_path" "abrtdbustestanother" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized" \
+ "Error org.freedesktop.problems.AuthFailure: Not Authorized"
+
+ rlLog "Chech max crash reports size"
+ abrtMaxCrashReportsSizeTest "$unprivilegeds_problem_path" "abrtdbustest"
+ rlPhaseEnd
+
+ rlPhaseStartCleanup
+ rlRun "userdel -r abrtdbustest" 0 "Remove the test user"
+ rlRun "userdel -r abrtdbustestanother" 0 "Remove the another test user"
+ rlRun "mv /etc/abrt/abrt.conf.bak /etc/abrt/abrt.conf" 0 "Restore abrt configuration"
+ rlRun "systemctl restart abrtd.service" 0 "Restart abrtd after configuration changes"
+ rlRun "rm -rf $DUMP_LOCATION"
+ rlPhaseEnd
+ rlJournalPrintText
+rlJournalEnd
--
1.7.11.4
11 years, 5 months