void parse_osinfo_for_bz(map_string_t *osinfo, char** product, char** version) { const char *name = get_map_string_item_or_NULL(osinfo, "REDHAT_BUGZILLA_PRODUCT"); if (!name) name = get_map_string_item_or_NULL(osinfo, OSINFO_NAME); const char *version_id = get_map_string_item_or_NULL(osinfo, "REDHAT_BUGZILLA_PRODUCT_VERSION"); if (!version_id) version_id = get_map_string_item_or_NULL(osinfo, OSINFO_VERSION_ID); if (name && version_id) { *product = xstrdup(name); *version = xstrdup(version_id); return; } const char *pretty = get_map_string_item_or_NULL(osinfo, OSINFO_PRETTY_NAME); if (pretty) { parse_release_for_bz(pretty, product, version); return; } /* something bad happend */ *product = NULL; *version = NULL; }
static void set_settings(struct bugzilla_struct *b, map_string_t *settings) { const char *environ; environ = getenv("Bugzilla_Login"); b->b_login = xstrdup(environ ? environ : get_map_string_item_or_empty(settings, "Login")); environ = getenv("Bugzilla_Password"); b->b_password = xstrdup(environ ? environ : get_map_string_item_or_empty(settings, "Password")); environ = getenv("Bugzilla_BugzillaURL"); b->b_bugzilla_url = environ ? environ : get_map_string_item_or_empty(settings, "BugzillaURL"); if (!b->b_bugzilla_url[0]) b->b_bugzilla_url = "https://bugzilla.redhat.com"; else { /* We don't want trailing '/': "https://host/dir/" -> "https://host/dir" */ char *last_slash = strrchr(b->b_bugzilla_url, '/'); if (last_slash && last_slash[1] == '\0') *last_slash = '\0'; } b->b_bugzilla_xmlrpc = concat_path_file(b->b_bugzilla_url, "xmlrpc.cgi"); environ = getenv("Bugzilla_Product"); if (environ) { b->b_product = xstrdup(environ); environ = getenv("Bugzilla_ProductVersion"); if (environ) b->b_product_version = xstrdup(environ); } else { const char *option = get_map_string_item_or_NULL(settings, "Product"); if (option) b->b_product = xstrdup(option); option = get_map_string_item_or_NULL(settings, "ProductVersion"); if (option) b->b_product_version = xstrdup(option); } if (!b->b_product) { /* Compat, remove it later (2014?). */ environ = getenv("Bugzilla_OSRelease"); if (environ) parse_release_for_bz(environ, &b->b_product, &b->b_product_version); } environ = getenv("Bugzilla_SSLVerify"); b->b_ssl_verify = string_to_bool(environ ? environ : get_map_string_item_or_empty(settings, "SSLVerify")); environ = getenv("Bugzilla_DontMatchComponents"); b->b_DontMatchComponents = environ ? environ : get_map_string_item_or_empty(settings, "DontMatchComponents"); }
static void report_to_bugzilla(const char *dump_dir_name, map_string_h *settings) { struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) xfunc_die(); /* dd_opendir already emitted error msg */ problem_data_t *problem_data = create_problem_data_from_dump_dir(dd); dd_close(dd); const char *env; const char *login; const char *password; const char *bugzilla_xmlrpc; const char *bugzilla_url; bool ssl_verify; env = getenv("Bugzilla_Login"); login = env ? env : get_map_string_item_or_empty(settings, "Login"); env = getenv("Bugzilla_Password"); password = env ? env : get_map_string_item_or_empty(settings, "Password"); if (!login[0] || !password[0]) error_msg_and_die(_("Empty login or password, please check your configuration")); env = getenv("Bugzilla_BugzillaURL"); bugzilla_url = env ? env : get_map_string_item_or_empty(settings, "BugzillaURL"); if (!bugzilla_url[0]) bugzilla_url = "https://bugzilla.redhat.com"; bugzilla_xmlrpc = xasprintf("%s"XML_RPC_SUFFIX, bugzilla_url); env = getenv("Bugzilla_SSLVerify"); ssl_verify = string_to_bool(env ? env : get_map_string_item_or_empty(settings, "SSLVerify")); const char *component = get_problem_item_content_or_NULL(problem_data, FILENAME_COMPONENT); const char *duphash = get_problem_item_content_or_NULL(problem_data, FILENAME_DUPHASH); if (!duphash) error_msg_and_die(_("Essential file '%s' is missing, can't continue.."), FILENAME_DUPHASH); if (!*duphash) error_msg_and_die(_("Essential file '%s' is empty, can't continue.."), FILENAME_DUPHASH); const char *release = get_problem_item_content_or_NULL(problem_data, FILENAME_OS_RELEASE); if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */ release = get_problem_item_content_or_NULL(problem_data, "release"); struct abrt_xmlrpc *client = abrt_xmlrpc_new_client(bugzilla_xmlrpc, ssl_verify); log(_("Logging into Bugzilla at %s"), bugzilla_url); rhbz_login(client, login, password); log(_("Checking for duplicates")); char *product = NULL; char *version = NULL; parse_release_for_bz(release, &product, &version); free(version); xmlrpc_value *result; if (strcmp(product, "Fedora") == 0) result = rhbz_search_duphash(client, component, product, duphash); else result = rhbz_search_duphash(client, component, NULL, duphash); xmlrpc_value *all_bugs = rhbz_get_member("bugs", result); xmlrpc_DECREF(result); if (!all_bugs) error_msg_and_die(_("Missing mandatory member 'bugs'")); int all_bugs_size = rhbz_array_size(all_bugs); // When someone clones bug it has same duphash, so we can find more than 1. // Need to be checked if component is same. VERB3 log("Bugzilla has %i reports with same duphash '%s'", all_bugs_size, duphash); int bug_id = -1, dependent_bug = -1; struct bug_info *bz = NULL; if (all_bugs_size > 0) { bug_id = rhbz_bug_id(all_bugs); xmlrpc_DECREF(all_bugs); bz = rhbz_bug_info(client, bug_id); if (strcmp(bz->bi_product, product) != 0) { dependent_bug = bug_id; /* found something, but its a different product */ free_bug_info(bz); xmlrpc_value *result = rhbz_search_duphash(client, component, product, duphash); xmlrpc_value *all_bugs = rhbz_get_member("bugs", result); xmlrpc_DECREF(result); all_bugs_size = rhbz_array_size(all_bugs); if (all_bugs_size > 0) { bug_id = rhbz_bug_id(all_bugs); bz = rhbz_bug_info(client, bug_id); } xmlrpc_DECREF(all_bugs); } } free(product); if (all_bugs_size == 0) // Create new bug { log(_("Creating a new bug")); bug_id = rhbz_new_bug(client, problem_data, bug_id); log("Adding attachments to bug %i", bug_id); char bug_id_str[sizeof(int)*3 + 2]; sprintf(bug_id_str, "%i", bug_id); rhbz_attachments(client, bug_id_str, problem_data); log(_("Logging out")); rhbz_logout(client); log("Status: NEW %s/show_bug.cgi?id=%u", bugzilla_url, bug_id); abrt_xmlrpc_free_client(client); return; } // decision based on state log(_("Bug is already reported: %i"), bz->bi_id); if ((strcmp(bz->bi_status, "CLOSED") == 0) && (strcmp(bz->bi_resolution, "DUPLICATE") == 0)) { struct bug_info *origin; origin = rhbz_find_origin_bug_closed_duplicate(client, bz); if (origin) { free_bug_info(bz); bz = origin; } } if (strcmp(bz->bi_status, "CLOSED") != 0) { if ((strcmp(bz->bi_reporter, login) != 0) && (!g_list_find_custom(bz->bi_cc_list, login, (GCompareFunc)g_strcmp0))) { log(_("Add %s to CC list"), login); rhbz_mail_to_cc(client, bz->bi_id, login); } char *dsc = make_description_comment(problem_data); if (dsc) { const char *package = get_problem_item_content_or_NULL(problem_data, FILENAME_PACKAGE); const char *release = get_problem_item_content_or_NULL(problem_data, FILENAME_OS_RELEASE); if (!release) /* Old dump dir format compat. Remove in abrt-2.1 */ release = get_problem_item_content_or_NULL(problem_data, "release"); const char *arch = get_problem_item_content_or_NULL(problem_data, FILENAME_ARCHITECTURE); const char *is_private = get_problem_item_content_or_NULL(problem_data, "is_private"); char *full_dsc = xasprintf("Package: %s\n" "Architecture: %s\n" "OS Release: %s\n" "%s", package, arch, release, dsc); log(_("Adding new comment to bug %d"), bz->bi_id); free(dsc); int is_priv = is_private && string_to_bool(is_private); rhbz_add_comment(client, bz->bi_id, full_dsc, is_priv); free(full_dsc); } } log(_("Logging out")); rhbz_logout(client); log("Status: %s%s%s %s/show_bug.cgi?id=%u", bz->bi_status, bz->bi_resolution ? " " : "", bz->bi_resolution ? bz->bi_resolution : "", bugzilla_url, bz->bi_id); dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (dd) { char *msg = xasprintf("Bugzilla: URL=%s/show_bug.cgi?id=%u", bugzilla_url, bz->bi_id); add_reported_to(dd, msg); free(msg); dd_close(dd); } free_problem_data(problem_data); free_bug_info(bz); abrt_xmlrpc_free_client(client); }