Signed-off-by: Jakub Filak jfilak@redhat.com --- libreport.spec.in | 1 + po/POTFILES.in | 1 + src/include/Makefile.am | 3 +- src/include/event_usability.h | 59 ++++++++++++ src/lib/Makefile.am | 4 +- src/lib/event_usability.c | 201 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 src/include/event_usability.h create mode 100644 src/lib/event_usability.c
diff --git a/libreport.spec.in b/libreport.spec.in index 6f6da01..3f730e3 100644 --- a/libreport.spec.in +++ b/libreport.spec.in @@ -296,6 +296,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_includedir}/libreport/problem_data.h %{_includedir}/libreport/report.h %{_includedir}/libreport/run_event.h +%{_includedir}/libreport/event_usability.h # Private api headers: %{_includedir}/libreport/internal_abrt_dbus.h %{_includedir}/libreport/internal_libreport.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 3203183..88c15f5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -14,6 +14,7 @@ src/lib/parse_options.c src/lib/curl.c src/lib/client.c src/lib/run_event.c +src/lib/event_usability.c src/lib/problem_data.c src/plugins/abrt_rh_support.c src/plugins/report.c diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 61b49a3..7aa5f78 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -9,4 +9,5 @@ libreport_include_HEADERS = \ libreport_curl.h \ \ internal_libreport.h \ - internal_abrt_dbus.h + internal_abrt_dbus.h \ + event_usability.h diff --git a/src/include/event_usability.h b/src/include/event_usability.h new file mode 100644 index 0000000..342c125 --- /dev/null +++ b/src/include/event_usability.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2009 Abrt team. + Copyright (C) 2009 RedHat inc. + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#ifndef LIBREPORT_EVENT_USABILITY_CHECK_H_ +#define LIBREPORT_EVENT_USABILITY_CHECK_H_ + +#include <glib.h> +#include "problem_data.h" +#include "event_config.h" + +/* + * Event usability levels + */ +enum event_usability_status +{ + EUS_GOOD, ///< event is usuable + EUS_LOW, ///< event is possibly unusable + EUS_UNUSABLE, ///< event is not usable +}; + +/* + * Selects the forst usability + * + * @param f an event usability level + * @param s an event usability level + * @return returns the worst usability from the two passed + */ +enum event_usability_status worst_usability(enum event_usability_status f, enum event_usability_status s); + +/* + * Cechcks event config agains problem items an returns event usability level. + * + * @param ec a checked event config + * @param pd a checked problem data + * @param not_loaded_items a items not in problem data, thier values are unknown + * @param issues a list of found issues + * @param min_level a minimal checked level, issues above this level are not reported + * @return returns the worst found usability + */ +enum event_usability_status check_event_usability(const event_config_t *ec, const problem_data_t *pd, + const GList *not_loaded_items, GList **issues, + enum event_usability_status min_level); + +#endif /* LIBREPORT_EVENT_USABILITY_CHECK_H_ */ diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index d2282db..cd1f164 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -47,7 +47,9 @@ libreport_la_SOURCES = \ report.c \ user_settings.c \ client.c \ - utf8.c + utf8.c \ + event_usability.c + libreport_la_CPPFLAGS = \ -Wall -Wwrite-strings -Werror \ -I$(srcdir)/../include \ diff --git a/src/lib/event_usability.c b/src/lib/event_usability.c new file mode 100644 index 0000000..f53168d --- /dev/null +++ b/src/lib/event_usability.c @@ -0,0 +1,201 @@ +/* + Copyright (C) 2012 ABRT Team + Copyright (C) 2012 RedHat inc. + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include <errno.h> +#include <stdlib.h> +#include "internal_libreport.h" +#include "event_usability.h" + +enum event_usability_status worst_usability(enum event_usability_status f, enum event_usability_status s) +{ + return f > s ? f : s; +} + +static enum event_usability_status check_btrating_usability(const event_config_t *cfg, const char *rating_str, char **message) +{ + enum event_usability_status ret = EUS_GOOD; + + if (rating_str) + { + char *endptr; + errno = 0; + long rating = strtol(rating_str, &endptr, 10); + char *issue = NULL; + if (errno != 0 || endptr == rating_str || *endptr != '\0') + { + issue = xasprintf("%s '%s'.", _("Reporting disabled because the rating does not contain a number"), rating_str); + ret = EUS_UNUSABLE; + } + else if (rating == cfg->ec_minimal_rating) /* bt is usable, but not complete, so show a warning */ + { + issue = xstrdup(_("The backtrace is incomplete, please make sure you provide the steps to reproduce.")); + ret = EUS_LOW; + } + else if (rating < cfg->ec_minimal_rating) + { + issue = xstrdup(_("Reporting disabled because the backtrace is unusable.")); + ret = EUS_UNUSABLE; + } + + if (message) + *message = issue; + else + free(issue); + } + + return ret; +} + +struct problem_item_source +{ + bool (* contain_item)(void *, const char *); + void *source; +}; + +static char *get_complement_as_comma_list(const struct problem_item_source *source, const char *input_item_list) +{ + if (!input_item_list) + return NULL; + + char *item_list = xstrdup(input_item_list); + char *result = item_list; + char *dst = item_list; + + while (item_list[0]) + { + char *end = strchr(item_list, ','); + if (end) *end = '\0'; + if (!source->contain_item(source->source, item_list)) + { + if (dst != result) + *dst++ = ','; + dst = stpcpy(dst, item_list); + } + if (!end) + break; + *end = ','; + item_list = end + 1; + } + if (result == dst) + { + free(result); + result = NULL; + } + return result; +} + +static bool contain_item_in_problem_data(void *source, const char *item_name) +{ + problem_data_t *pd = (problem_data_t *)source; + return !!get_problem_item_content_or_NULL(pd, item_name); +} + +static bool contain_item_in_glist(void *source, const char *item_name) +{ + GList *list = (GList *)source; + return !!g_list_find_custom(list, (gpointer)item_name, (GCompareFunc)strcmp); +} + +enum event_usability_status check_event_usability(const event_config_t *cfg, + const problem_data_t *pd, + const GList *not_loaded_items, + GList **issues, + enum event_usability_status min_level + ) +{ + enum event_usability_status ret = EUS_GOOD; + + if (!cfg) + return ret; + + GList* work_issues = NULL; + + struct problem_item_source pd_source; + pd_source.contain_item = contain_item_in_problem_data; + pd_source.source = (void *)pd; + + struct problem_item_source list_source; + list_source.contain_item = contain_item_in_glist; + list_source.source = (void *)not_loaded_items; + + /* find missing items */ + char *existing_missing = get_complement_as_comma_list(&pd_source, cfg->ec_requires_items); + char *created_missing = get_complement_as_comma_list(&list_source, existing_missing); + if (created_missing) + { + if (worst_usability(EUS_UNUSABLE, min_level) == EUS_UNUSABLE) + { + ret = EUS_UNUSABLE; + work_issues = g_list_prepend(work_issues, xasprintf("%s : %s.", _("Missing items "), created_missing)); + } + } + free(existing_missing); + free(created_missing); + +#if 0 + /* find already existing items */ + if (cfg->ec_creates_items) + { + existing_missing = get_complement_as_comma_list(&pd_source, cfg->ec_creates_items); + created_missing = get_complement_as_comma_list(&list_source, existing_missing); + if (!created_missing) + { + if (worst_usability(EUS_LOW, min_level) == EUS_LOW) + { + ret = worst_usability(EUS_LOW, ret); + work_issues = g_list_prepend(work_issues, xasprintf("%s : %s.", _("Items already exist "), cfg->ec_creates_items)); + } + } + free(existing_missing); + free(created_missing); + } +#endif + + /* if a rating is in not loaded items we cannot assure */ + /* that a rating is OK at a moment of event run */ + const char *rating_str = get_problem_item_content_or_NULL((problem_data_t *)pd, FILENAME_RATING); + if ((!rating_str || g_list_find_custom((GList *)not_loaded_items, FILENAME_RATING, (GCompareFunc)strcmp))) + { + if (worst_usability(EUS_LOW, min_level) == EUS_LOW) + { + ret = worst_usability(EUS_LOW, ret); + work_issues = g_list_prepend(work_issues, xstrdup(_("Backtrace rating can't be checked now and can be possibly low at a moment of event run"))); + } + } + else // btrating is in existing items + { + char *message = NULL; + enum event_usability_status bt = check_btrating_usability(cfg, rating_str, &message); + if (worst_usability(bt, min_level) == bt) + { + ret = worst_usability(bt, ret); + if (message) + work_issues = g_list_prepend(work_issues, message); + } + else + free(message); + } + + if (issues) + *issues = work_issues; + else + g_list_free(work_issues); + + return ret; +} +