static xmlrpc_value *rhbz_search_duphash(struct abrt_xmlrpc *ax, const char *product, const char *version, const char *component, const char *duphash) { struct strbuf *query = strbuf_new(); strbuf_append_strf(query, "ALL whiteboard:\"%s\"", duphash); if (product) strbuf_append_strf(query, " product:\"%s\"", product); if (version) strbuf_append_strf(query, " version:\"%s\"", version); if (component) strbuf_append_strf(query, " component:\"%s\"", component); char *s = strbuf_free_nobuf(query); VERB3 log("search for '%s'", s); xmlrpc_value *search = abrt_xmlrpc_call(ax, "Bug.search", "({s:s})", "quicksearch", s); free(s); xmlrpc_value *bugs = rhbz_get_member("bugs", search); xmlrpc_DECREF(search); if (!bugs) error_msg_and_die(_("Bug.search(quicksearch) return value did not contain member 'bugs'")); return bugs; }
unsigned rhbz_version(struct abrt_xmlrpc *ax) { func_entry(); xmlrpc_value *result; result = abrt_xmlrpc_call(ax, "Bugzilla.version", "()"); char *version = NULL; if (result) version = rhbz_bug_read_item("version", result, RHBZ_READ_STR); if (!result || !version) error_msg_and_die("Can't determine %s", "Bugzilla.version"); xmlrpc_DECREF(result); strchrnul(version, '-')[0] = '\0'; /* format must be x.y.z */ char *vp; int i = 0, v[3] = {0, 0, 0}; for (vp = version; i < 3; vp = NULL, ++i) { char *tok = strtok(vp, "."); if (!tok) break; v[i] = strtoul(tok, NULL, 10); } free(version); return BUGZILLA_VERSION(v[0], v[1], v[2]); }
static GList *rhbz_comments(struct abrt_xmlrpc *ax, int bug_id) { func_entry(); /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html#comments */ /* * <methodResponse> * <params><param> * <value><struct> * <member><name>bugs</name> * <value><struct> * <member><name>BUG_ID</name> * <value><struct> * <member><name>comments</name> * <value><array> * ... */ xmlrpc_value *xml_response = abrt_xmlrpc_call(ax, "Bug.comments", "({s:(i)})", "ids", bug_id); /* bugs * This is used for bugs specified in ids. This is a hash, where the * keys are the numeric ids of the bugs, and the value is a hash with a * single key, comments, which is an array of comments. */ xmlrpc_value *bugs_memb = rhbz_get_member("bugs", xml_response); /* Get hash value assigned to bug_id key */ char *item = xasprintf("%d", bug_id); xmlrpc_value *item_memb = rhbz_get_member(item, bugs_memb); free(item); /* Get array of comments */ xmlrpc_value *comments_memb = rhbz_get_member("comments", item_memb); xmlrpc_env env; xmlrpc_env_init(&env); int comments_memb_size = rhbz_array_size(comments_memb); GList *comments = NULL; for (int i = 0; i < comments_memb_size; ++i) { xmlrpc_value* item = NULL; xmlrpc_array_read_item(&env, comments_memb, i, &item); if (env.fault_occurred) abrt_xmlrpc_die(&env); char *comment_body = rhbz_bug_read_item("text", item, RHBZ_READ_STR); /* attachments are sometimes without comments -- skip them */ if (comment_body) comments = g_list_prepend(comments, comment_body); xmlrpc_DECREF(item); } xmlrpc_env_clean(&env); xmlrpc_DECREF(comments_memb); xmlrpc_DECREF(item_memb); xmlrpc_DECREF(bugs_memb); xmlrpc_DECREF(xml_response); return g_list_reverse(comments); }
struct bug_info *rhbz_bug_info(struct abrt_xmlrpc *ax, int bug_id) { func_entry(); struct bug_info *bz = new_bug_info(); /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html#get * * <methodResponse> * <params> * <param><value><struct> * <member><name>faults</name><value><array><data/></array></value></member> * <member><name>bugs</name> * <value><array><data> * ... */ xmlrpc_value *xml_bug_response = abrt_xmlrpc_call(ax, "Bug.get", "({s:(i)})", "ids", bug_id); xmlrpc_value *bugs_memb = rhbz_get_member("bugs", xml_bug_response); xmlrpc_value *bug_item = rhbz_array_item_at(bugs_memb, 0); int *ret = (int*)rhbz_bug_read_item("id", bug_item, RHBZ_MANDATORY_MEMB | RHBZ_READ_INT); bz->bi_id = *ret; free(ret); bz->bi_product = rhbz_bug_read_item("product", bug_item, RHBZ_MANDATORY_MEMB | RHBZ_READ_STR); bz->bi_reporter = rhbz_bug_read_item("creator", bug_item, RHBZ_MANDATORY_MEMB | RHBZ_READ_STR); bz->bi_status = rhbz_bug_read_item("status", bug_item, RHBZ_MANDATORY_MEMB | RHBZ_READ_STR); bz->bi_resolution = rhbz_bug_read_item("resolution", bug_item, RHBZ_READ_STR); bz->bi_platform = rhbz_bug_read_item("platform", bug_item, RHBZ_READ_STR); if (strcmp(bz->bi_status, "CLOSED") == 0 && !bz->bi_resolution) error_msg_and_die(_("Bug %i is CLOSED, but it has no RESOLUTION"), bz->bi_id); ret = (int*)rhbz_bug_read_item("dupe_of", bug_item, RHBZ_READ_INT); if (strcmp(bz->bi_status, "CLOSED") == 0 && strcmp(bz->bi_resolution, "DUPLICATE") == 0 && !ret) { error_msg_and_die(_("Bug %i is CLOSED as DUPLICATE, but it has no DUP_ID"), bz->bi_id); } bz->bi_dup_id = (ret) ? *ret: -1; free(ret); bz->bi_cc_list = rhbz_bug_cc(bug_item); bz->bi_comments = rhbz_comments(ax, bug_id); bz->bi_best_bt_rating = find_best_bt_rating_in_comments(bz->bi_comments); xmlrpc_DECREF(bugs_memb); xmlrpc_DECREF(bug_item); xmlrpc_DECREF(xml_bug_response); return bz; }