Blame src/plugins/bodhi.c

Packit Service 8a8a03
/*
Packit Service 8a8a03
    Copyright (C) 2011  ABRT Team
Packit Service 8a8a03
    Copyright (C) 2011  RedHat inc.
Packit Service 8a8a03
Packit Service 8a8a03
    This program is free software; you can redistribute it and/or modify
Packit Service 8a8a03
    it under the terms of the GNU General Public License as published by
Packit Service 8a8a03
    the Free Software Foundation; either version 2 of the License, or
Packit Service 8a8a03
    (at your option) any later version.
Packit Service 8a8a03
Packit Service 8a8a03
    This program is distributed in the hope that it will be useful,
Packit Service 8a8a03
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8a8a03
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 8a8a03
    GNU General Public License for more details.
Packit Service 8a8a03
Packit Service 8a8a03
    You should have received a copy of the GNU General Public License along
Packit Service 8a8a03
    with this program; if not, write to the Free Software Foundation, Inc.,
Packit Service 8a8a03
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit Service 8a8a03
*/
Packit Service 8a8a03
Packit Service 8a8a03
#include <json.h>
Packit Service 8a8a03
#include <rpm/rpmts.h>
Packit Service 8a8a03
#include <rpm/rpmcli.h>
Packit Service 8a8a03
#include <rpm/rpmdb.h>
Packit Service 8a8a03
#include <rpm/rpmpgp.h>
Packit Service 8a8a03
Packit Service 8a8a03
#include <libreport/internal_libreport.h>
Packit Service 8a8a03
#include <libreport/libreport_curl.h>
Packit Service 8a8a03
#include <libreport/client.h>
Packit Service 8a8a03
Packit Service 8a8a03
#include "libabrt.h"
Packit Service 8a8a03
Packit Service 8a8a03
//699198,705037,705036
Packit Service 8a8a03
Packit Service 8a8a03
/* bodhi returns json structure
Packit Service 8a8a03
Packit Service 8a8a03
{
Packit Service 8a8a03
 "rows_per_page": 20,
Packit Service 8a8a03
    "total": 1,
Packit Service 8a8a03
    "chrome": true,
Packit Service 8a8a03
    "display_user": true,
Packit Service 8a8a03
    "pages": 1,
Packit Service 8a8a03
    "updates": [
Packit Service 8a8a03
       {
Packit Service 8a8a03
        "close_bugs": true,
Packit Service 8a8a03
        "old_updateid": "FEDORA-2015-13720",
Packit Service 8a8a03
        "pushed": true,
Packit Service 8a8a03
        "require_testcases": false,
Packit Service 8a8a03
        "critpath": false,
Packit Service 8a8a03
        "date_approved": null,
Packit Service 8a8a03
        "stable_karma": null,
Packit Service 8a8a03
        "date_pushed": "2015-08-19 04:49:00",
Packit Service 8a8a03
        "requirements": null,
Packit Service 8a8a03
        "severity": "unspecified",
Packit Service 8a8a03
        "title": "hwloc-1.11.0-3.fc22",
Packit Service 8a8a03
        "suggest": "unspecified",
Packit Service 8a8a03
        "require_bugs": false,
Packit Service 8a8a03
        "comments": [
Packit Service 8a8a03
           {
Packit Service 8a8a03
            "bug_feedback": [],
Packit Service 8a8a03
            "user_id": 91,
Packit Service 8a8a03
            "text": "This update has been submitted for testing by jhladky. ",
Packit Service 8a8a03
            "testcase_feedback": [],
Packit Service 8a8a03
            "karma_critpath": 0,
Packit Service 8a8a03
            "update": 21885,
Packit Service 8a8a03
            "update_id": 21885,
Packit Service 8a8a03
            "karma": 0,
Packit Service 8a8a03
            "anonymous": false,
Packit Service 8a8a03
            "timestamp": "2015-08-18 13:38:35",
Packit Service 8a8a03
            "id": 166016,
Packit Service 8a8a03
            "user": {"stacks": [],
Packit Service 8a8a03
                "name": "bodhi",
Packit Service 8a8a03
                "avatar": "https://apps.fedoraproject.org/img/icons/bodhi-24.png"}
Packit Service 8a8a03
           },
Packit Service 8a8a03
           {
Packit Service 8a8a03
           ...
Packit Service 8a8a03
           }
Packit Service 8a8a03
        ],
Packit Service 8a8a03
        "updateid": "FEDORA-2015-13720",
Packit Service 8a8a03
        "cves": [],
Packit Service 8a8a03
        "type": "bugfix",
Packit Service 8a8a03
        "status": "testing",
Packit Service 8a8a03
        "date_submitted": "2015-08-18 13:37:26",
Packit Service 8a8a03
        "unstable_karma": null,
Packit Service 8a8a03
        "submitter": "jhladky",
Packit Service 8a8a03
        "user":
Packit Service 8a8a03
           {
Packit Service 8a8a03
            "stacks": [],
Packit Service 8a8a03
            "buildroot_overrides": [],
Packit Service 8a8a03
            "name": "jhladky",
Packit Service 8a8a03
            "avatar": "https://seccdn.libravatar.org/avatar/b838b78fcf707a13cdaeb1c846d514e614d617cbf2c106718e71cb397607f59b?s=24&d=retro"
Packit Service 8a8a03
           },
Packit Service 8a8a03
        "locked": false,
Packit Service 8a8a03
        "builds": [{"override": null,
Packit Service 8a8a03
            "nvr": "hwloc-1.11.0-3.fc22"}],
Packit Service 8a8a03
        "date_modified": null,
Packit Service 8a8a03
        "test_cases": [],
Packit Service 8a8a03
        "notes": "Fix for BZ1253977",
Packit Service 8a8a03
        "request": null,
Packit Service 8a8a03
        "bugs": [
Packit Service 8a8a03
           {
Packit Service 8a8a03
            "bug_id": 1253977,
Packit Service 8a8a03
            "security": false,
Packit Service 8a8a03
            "feedback": [],
Packit Service 8a8a03
            "parent": false,
Packit Service 8a8a03
            "title": "conflict between hwloc-libs-1.11.0-1.fc22.i686 and hwloc-libs-1.11.0-1.fc22.x86_64"
Packit Service 8a8a03
           }
Packit Service 8a8a03
        ],
Packit Service 8a8a03
        "alias": "FEDORA-2015-13720",
Packit Service 8a8a03
        "karma": 0,
Packit Service 8a8a03
        "release":
Packit Service 8a8a03
           {
Packit Service 8a8a03
            "dist_tag": "f22",
Packit Service 8a8a03
            "name": "F22",
Packit Service 8a8a03
            "testing_tag": "f22-updates-testing",
Packit Service 8a8a03
            "pending_stable_tag": "f22-updates-pending",
Packit Service 8a8a03
            "long_name": "Fedora 22",
Packit Service 8a8a03
            "state": "current",
Packit Service 8a8a03
            "version": "22",
Packit Service 8a8a03
            "override_tag": "f22-override",
Packit Service 8a8a03
            "branch": "f22",
Packit Service 8a8a03
            "id_prefix": "FEDORA",
Packit Service 8a8a03
            "pending_testing_tag": "f22-updates-testing-pending",
Packit Service 8a8a03
            "stable_tag": "f22-updates",
Packit Service 8a8a03
            "candidate_tag": "f22-updates-candidate"
Packit Service 8a8a03
           }
Packit Service 8a8a03
       }
Packit Service 8a8a03
    ],
Packit Service 8a8a03
    "display_request": true,
Packit Service 8a8a03
    "page": 1
Packit Service 8a8a03
}
Packit Service 8a8a03
*/
Packit Service 8a8a03
Packit Service 8a8a03
static const char *bodhi_url = "https://bodhi.fedoraproject.org/updates";
Packit Service 8a8a03
Packit Service 8a8a03
struct bodhi {
Packit Service 8a8a03
    char *nvr;
Packit Service 8a8a03
#if 0
Packit Service 8a8a03
    char *date_pushed;
Packit Service 8a8a03
    char *status;
Packit Service 8a8a03
    char *dist_tag;
Packit Service 8a8a03
Packit Service 8a8a03
    GList *bz_ids;
Packit Service 8a8a03
#endif
Packit Service 8a8a03
};
Packit Service 8a8a03
Packit Service 8a8a03
enum {
Packit Service 8a8a03
    BODHI_READ_STR,
Packit Service 8a8a03
    BODHI_READ_INT,
Packit Service 8a8a03
    BODHI_READ_JSON_OBJ,
Packit Service 8a8a03
};
Packit Service 8a8a03
Packit Service 8a8a03
static void free_bodhi_item(struct bodhi *b)
Packit Service 8a8a03
{
Packit Service 8a8a03
    if (!b)
Packit Service 8a8a03
        return;
Packit Service 8a8a03
Packit Service 8a8a03
    free(b->nvr);
Packit Service 8a8a03
Packit Service 8a8a03
#if 0
Packit Service 8a8a03
    list_free_with_free(b->bz_ids);
Packit Service 8a8a03
    free(b->date_pushed);
Packit Service 8a8a03
    free(b->status);
Packit Service 8a8a03
    free(b->dist_tag);
Packit Service 8a8a03
#endif
Packit Service 8a8a03
Packit Service 8a8a03
    free(b);
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
static void bodhi_read_value(json_object *json, const char *item_name,
Packit Service 8a8a03
                             void *value, int flags)
Packit Service 8a8a03
{
Packit Service 8a8a03
    json_object *j = NULL;
Packit Service 8a8a03
    if (!json_object_object_get_ex(json, item_name, &j))
Packit Service 8a8a03
    {
Packit Service 8a8a03
        error_msg("'%s' section is not available", item_name);
Packit Service 8a8a03
        return;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    switch (flags) {
Packit Service 8a8a03
    case BODHI_READ_INT:
Packit Service 8a8a03
        *(int *) value = json_object_get_int(j);
Packit Service 8a8a03
        break;
Packit Service 8a8a03
    case BODHI_READ_STR:
Packit Service 8a8a03
        *(char **) value = (char *) strtrimch(xstrdup(json_object_to_json_string(j)), '"');
Packit Service 8a8a03
        break;
Packit Service 8a8a03
    case BODHI_READ_JSON_OBJ:
Packit Service 8a8a03
        *(json_object **) value = (json_object *) j;
Packit Service 8a8a03
        break;
Packit Service 8a8a03
    };
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
#if 0
Packit Service 8a8a03
static void print_bodhi(struct bodhi *b)
Packit Service 8a8a03
{
Packit Service 8a8a03
    for (GList *l = b->nvr; l; l = l->next)
Packit Service 8a8a03
        printf("'%s' ", (char *)l->data);
Packit Service 8a8a03
Packit Service 8a8a03
    for (GList *l = b->name; l; l = l->next)
Packit Service 8a8a03
        printf("'%s' ", (char *)l->data);
Packit Service 8a8a03
Packit Service 8a8a03
    if (b->date_pushed)
Packit Service 8a8a03
        printf(" '%s'", b->date_pushed);
Packit Service 8a8a03
Packit Service 8a8a03
    if (b->status)
Packit Service 8a8a03
        printf(" '%s'", b->status);
Packit Service 8a8a03
Packit Service 8a8a03
    if (b->dist_tag)
Packit Service 8a8a03
        printf(" '%s'", b->dist_tag);
Packit Service 8a8a03
Packit Service 8a8a03
    printf(" %i", b->karma);
Packit Service 8a8a03
Packit Service 8a8a03
Packit Service 8a8a03
/*
Packit Service 8a8a03
    for (GList *li = b->bz_ids; li; li = li->next)
Packit Service 8a8a03
        printf(" %i", *(int*) li->data);
Packit Service 8a8a03
*/
Packit Service 8a8a03
    puts("");
Packit Service 8a8a03
}
Packit Service 8a8a03
#endif
Packit Service 8a8a03
Packit Service 8a8a03
/* bodhi returns following json structure in case of error
Packit Service 8a8a03
{
Packit Service 8a8a03
   "status": "error",
Packit Service 8a8a03
   "errors":
Packit Service 8a8a03
              [
Packit Service 8a8a03
                {
Packit Service 8a8a03
                   "location": "querystring",
Packit Service 8a8a03
                   "name": "releases",
Packit Service 8a8a03
                   "description": "Invalid releases specified: Rawhide"
Packit Service 8a8a03
                }
Packit Service 8a8a03
              ]
Packit Service 8a8a03
}
Packit Service 8a8a03
*/
Packit Service 8a8a03
static void bodhi_print_errors_from_json(json_object *json)
Packit Service 8a8a03
{
Packit Service 8a8a03
Packit Service 8a8a03
    json_object *errors_array = NULL;
Packit Service 8a8a03
    bodhi_read_value(json, "errors", &errors_array, BODHI_READ_JSON_OBJ);
Packit Service 8a8a03
    if (!errors_array)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        error_msg("Error: unable to read 'errors' array from json");
Packit Service 8a8a03
        return;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    int errors_len = json_object_array_length(errors_array);
Packit Service 8a8a03
    for (int i = 0; i < errors_len; ++i)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        json_object *error = json_object_array_get_idx(errors_array, i);
Packit Service 8a8a03
        if (!error)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            error_msg("Error: unable to get 'error[%d]'", i);
Packit Service 8a8a03
            json_object_put(errors_array);
Packit Service 8a8a03
            return;
Packit Service 8a8a03
        }
Packit Service 8a8a03
Packit Service 8a8a03
        char *desc_item = NULL;
Packit Service 8a8a03
        bodhi_read_value(error, "description", &desc_item, BODHI_READ_STR);
Packit Service 8a8a03
        if (!desc_item)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            error_msg("Error: unable to get 'description' from 'error[%d]'", i);
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
        }
Packit Service 8a8a03
Packit Service 8a8a03
        error_msg("Error: %s", desc_item);
Packit Service 8a8a03
        json_object_put(error);
Packit Service 8a8a03
        free(desc_item);
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    json_object_put(errors_array);
Packit Service 8a8a03
    return;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
/**
Packit Service 8a8a03
 * Parses only name from nvr
Packit Service 8a8a03
 * nvr is RPM packages naming convention format: name-version-release
Packit Service 8a8a03
 *
Packit Service 8a8a03
 * for example: meanwhile3.34.3-3.34-3.fc666
Packit Service 8a8a03
 *              ^name           ^ver.^release
Packit Service 8a8a03
 */
Packit Service 8a8a03
static int parse_nvr_name(const char *nvr, char **name)
Packit Service 8a8a03
{
Packit Service 8a8a03
    const int len = strlen(nvr);
Packit Service 8a8a03
    if (len <= 0)
Packit Service 8a8a03
        return EINVAL;
Packit Service 8a8a03
    const char *c = nvr + len - 1;
Packit Service 8a8a03
    /* skip release */
Packit Service 8a8a03
    for (; *c != '-'; --c)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        if (c <= nvr)
Packit Service 8a8a03
            return EINVAL;
Packit Service 8a8a03
    }
Packit Service 8a8a03
    --c;
Packit Service 8a8a03
    /* skip version */
Packit Service 8a8a03
    for (; *c != '-'; --c)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        if (c <= nvr)
Packit Service 8a8a03
            return EINVAL;
Packit Service 8a8a03
    }
Packit Service 8a8a03
    if (c <= nvr)
Packit Service 8a8a03
        return EINVAL;
Packit Service 8a8a03
Packit Service 8a8a03
    *name = xstrndup(nvr, (c - nvr));
Packit Service 8a8a03
Packit Service 8a8a03
    return 0;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
static GHashTable *bodhi_parse_json(json_object *json, const char *release)
Packit Service 8a8a03
{
Packit Service 8a8a03
Packit Service 8a8a03
    int num_items = 0;
Packit Service 8a8a03
    bodhi_read_value(json, "total", &num_items, BODHI_READ_INT);
Packit Service 8a8a03
    if (num_items <= 0)
Packit Service 8a8a03
        return NULL;
Packit Service 8a8a03
Packit Service 8a8a03
    json_object *updates = NULL;
Packit Service 8a8a03
    bodhi_read_value(json, "updates", &updates, BODHI_READ_JSON_OBJ);
Packit Service 8a8a03
    if (!updates)
Packit Service 8a8a03
        return NULL;
Packit Service 8a8a03
Packit Service 8a8a03
    int updates_len = json_object_array_length(updates);
Packit Service 8a8a03
Packit Service 8a8a03
    GHashTable *bodhi_table = g_hash_table_new_full(g_str_hash, g_str_equal, free,
Packit Service 8a8a03
                                                    (GDestroyNotify) free_bodhi_item);
Packit Service 8a8a03
    for (int i = 0; i < updates_len; ++i)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        json_object *updates_item = json_object_array_get_idx(updates, i);
Packit Service 8a8a03
Packit Service 8a8a03
        /* some of item are null */
Packit Service 8a8a03
        if (!updates_item)
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
Packit Service 8a8a03
        json_object *builds_item = NULL;
Packit Service 8a8a03
        bodhi_read_value(updates_item, "builds", &builds_item, BODHI_READ_JSON_OBJ);
Packit Service 8a8a03
        if (!builds_item) /* broken json */
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
Packit Service 8a8a03
        int karma, unstable_karma;
Packit Service 8a8a03
        bodhi_read_value(updates_item, "karma", &karma, BODHI_READ_INT);
Packit Service 8a8a03
        bodhi_read_value(updates_item, "unstable_karma", &unstable_karma, BODHI_READ_INT);
Packit Service 8a8a03
        if (karma <= unstable_karma)
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
Packit Service 8a8a03
        struct bodhi *b = NULL;
Packit Service 8a8a03
        int builds_len = json_object_array_length(builds_item);
Packit Service 8a8a03
        for (int k = 0; k < builds_len; ++k)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            b = xzalloc(sizeof(struct bodhi));
Packit Service 8a8a03
Packit Service 8a8a03
            char *name = NULL;
Packit Service 8a8a03
            json_object *build = json_object_array_get_idx(builds_item, k);
Packit Service 8a8a03
Packit Service 8a8a03
            bodhi_read_value(build, "nvr", &b->nvr, BODHI_READ_STR);
Packit Service 8a8a03
Packit Service 8a8a03
            if (parse_nvr_name(b->nvr, &name))
Packit Service 8a8a03
                error_msg_and_die("failed to parse package name from nvr: '%s'", b->nvr);
Packit Service 8a8a03
Packit Service 8a8a03
            log_info("Found package: %s\n", name);
Packit Service 8a8a03
Packit Service 8a8a03
            struct bodhi *bodhi_tbl_item = g_hash_table_lookup(bodhi_table, name);
Packit Service 8a8a03
            if (bodhi_tbl_item && rpmvercmp(bodhi_tbl_item->nvr, b->nvr) > 0)
Packit Service 8a8a03
            {
Packit Service 8a8a03
                free_bodhi_item(b);
Packit Service 8a8a03
                continue;
Packit Service 8a8a03
            }
Packit Service 8a8a03
            g_hash_table_replace(bodhi_table, name, b);
Packit Service 8a8a03
        }
Packit Service 8a8a03
Packit Service 8a8a03
#if 0
Packit Service 8a8a03
        bodhi_read_value(updates_item, "date_pushed", &b->date_pushed, BODHI_READ_STR);
Packit Service 8a8a03
        bodhi_read_value(updates_item, "status", &b->status, BODHI_READ_STR);
Packit Service 8a8a03
Packit Service 8a8a03
        json_object *release_item = NULL;
Packit Service 8a8a03
        bodhi_read_value(updates_item, "release", &release_item, BODHI_READ_JSON_OBJ);
Packit Service 8a8a03
        if (release_item)
Packit Service 8a8a03
            bodhi_read_value(release_item, "dist_tag", &b->dist_tag, BODHI_READ_STR);
Packit Service 8a8a03
Packit Service 8a8a03
        json_object *bugs = NULL;
Packit Service 8a8a03
        bodhi_read_value(updates_item, "bugs", &release_item, BODHI_READ_JSON_OBJ);
Packit Service 8a8a03
        if (bugs)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            for (int j = 0; j < json_object_array_length(bugs); ++j)
Packit Service 8a8a03
            {
Packit Service 8a8a03
                int *bz_id = xmalloc(sizeof(int));
Packit Service 8a8a03
                json_object *bug_item = json_object_array_get_idx(bugs, j);
Packit Service 8a8a03
                bodhi_read_value(bug_item, "bz_id", bz_id, BODHI_READ_INT);
Packit Service 8a8a03
                b->bz_ids = g_list_append(b->bz_ids, bz_id);
Packit Service 8a8a03
            }
Packit Service 8a8a03
        }
Packit Service 8a8a03
#endif
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    return bodhi_table;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
static GHashTable *bodhi_query_list(const char *query, const char *release)
Packit Service 8a8a03
{
Packit Service 8a8a03
    char *bodhi_url_bugs = xasprintf("%s/?%s", bodhi_url, query);
Packit Service 8a8a03
Packit Service 8a8a03
    post_state_t *post_state = new_post_state(POST_WANT_BODY
Packit Service 8a8a03
                                              | POST_WANT_SSL_VERIFY
Packit Service 8a8a03
                                              | POST_WANT_ERROR_MSG);
Packit Service 8a8a03
Packit Service 8a8a03
    const char *headers[] = {
Packit Service 8a8a03
        "Accept: application/json",
Packit Service 8a8a03
        NULL
Packit Service 8a8a03
    };
Packit Service 8a8a03
Packit Service 8a8a03
    get(post_state, bodhi_url_bugs, "application/x-www-form-urlencoded",
Packit Service 8a8a03
                     headers);
Packit Service 8a8a03
Packit Service 8a8a03
    if (post_state->http_resp_code != 200 && post_state->http_resp_code != 400)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        char *errmsg = post_state->curl_error_msg;
Packit Service 8a8a03
        if (errmsg && errmsg[0])
Packit Service 8a8a03
            error_msg_and_die("%s '%s'", errmsg, bodhi_url_bugs);
Packit Service 8a8a03
    }
Packit Service 8a8a03
    free(bodhi_url_bugs);
Packit Service 8a8a03
Packit Service 8a8a03
//    log_warning("%s", post_state->body);
Packit Service 8a8a03
Packit Service 8a8a03
    json_object *json = json_tokener_parse(post_state->body);
Packit Service 8a8a03
    if (json == NULL)
Packit Service 8a8a03
        error_msg_and_die("fatal: unable parse response from bodhi server");
Packit Service 8a8a03
Packit Service 8a8a03
    /* we must check the http_resp_code because only error responses contain
Packit Service 8a8a03
     * 'status' item. 'bodhi_read_value' function prints an error message in
Packit Service 8a8a03
     * the case it did not found the item */
Packit Service 8a8a03
    if (post_state->http_resp_code != 200)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        char *status_item = NULL;
Packit Service 8a8a03
        bodhi_read_value(json, "status", &status_item, BODHI_READ_STR);
Packit Service 8a8a03
        if (status_item != NULL && strcmp(status_item, "error") == 0)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            free(status_item);
Packit Service 8a8a03
            bodhi_print_errors_from_json(json);
Packit Service 8a8a03
            json_object_put(json);
Packit Service 8a8a03
            xfunc_die(); // error_msg are printed in bodhi_print_errors_from_json
Packit Service 8a8a03
        }
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    GHashTable *bodhi_table = bodhi_parse_json(json, release);
Packit Service 8a8a03
    json_object_put(json);
Packit Service 8a8a03
    free_post_state(post_state);
Packit Service 8a8a03
Packit Service 8a8a03
    return bodhi_table;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
static char *rpm_get_nvr_by_pkg_name(const char *pkg_name)
Packit Service 8a8a03
{
Packit Service 8a8a03
    int status = rpmReadConfigFiles((const char *) NULL, (const char *) NULL);
Packit Service 8a8a03
    if (status)
Packit Service 8a8a03
        error_msg_and_die("error reading RPM rc files");
Packit Service 8a8a03
Packit Service 8a8a03
    char *nvr = NULL;
Packit Service 8a8a03
Packit Service 8a8a03
    rpmts ts = rpmtsCreate();
Packit Service 8a8a03
    rpmdbMatchIterator iter = rpmtsInitIterator(ts, RPMTAG_NAME, pkg_name, 0);
Packit Service 8a8a03
    Header header = rpmdbNextIterator(iter);
Packit Service 8a8a03
Packit Service 8a8a03
    if (!header)
Packit Service 8a8a03
        goto error;
Packit Service 8a8a03
Packit Service 8a8a03
    const char *errmsg = NULL;
Packit Service 8a8a03
    nvr = headerFormat(header, "%{name}-%{version}-%{release}", &errmsg);
Packit Service 8a8a03
Packit Service 8a8a03
    if (!nvr && errmsg)
Packit Service 8a8a03
        error_msg("cannot get nvr. reason: %s", errmsg);
Packit Service 8a8a03
Packit Service 8a8a03
error:
Packit Service 8a8a03
    rpmdbFreeIterator(iter);
Packit Service 8a8a03
    rpmtsFree(ts);
Packit Service 8a8a03
Packit Service 8a8a03
    rpmFreeRpmrc();
Packit Service 8a8a03
    rpmFreeCrypto();
Packit Service 8a8a03
    rpmFreeMacros(NULL);
Packit Service 8a8a03
Packit Service 8a8a03
    return nvr;
Packit Service 8a8a03
}
Packit Service 8a8a03
Packit Service 8a8a03
int main(int argc, char **argv)
Packit Service 8a8a03
{
Packit Service 8a8a03
    abrt_init(argv);
Packit Service 8a8a03
    enum {
Packit Service 8a8a03
        OPT_v = 1 << 0,
Packit Service 8a8a03
        OPT_d = 1 << 1,
Packit Service 8a8a03
        OPT_g = 1 << 2,
Packit Service 8a8a03
        OPT_b = 1 << 3,
Packit Service 8a8a03
        OPT_u = 1 << 4,
Packit Service 8a8a03
        OPT_r = 1 << 5,
Packit Service 8a8a03
    };
Packit Service 8a8a03
Packit Service 8a8a03
    const char *bugs = NULL, *release = NULL, *dump_dir_path = ".";
Packit Service 8a8a03
    /* Keep enum above and order of options below in sync! */
Packit Service 8a8a03
    struct options program_options[] = {
Packit Service 8a8a03
        OPT__VERBOSE(&g_verbose),
Packit Service 8a8a03
        OPT__DUMP_DIR(&dump_dir_path),
Packit Service 8a8a03
        OPT_GROUP(""),
Packit Service 8a8a03
        OPT_STRING('b', "bugs", &bugs, "ID1[,ID2,...]" , _("List of bug ids")),
Packit Service 8a8a03
        OPT_STRING('u', "url", &bodhi_url, "URL", _("Specify a bodhi server url")),
Packit Service 8a8a03
        OPT_OPTSTRING('r', "release", &release, "RELEASE", _("Specify a release")),
Packit Service 8a8a03
        OPT_END()
Packit Service 8a8a03
    };
Packit Service 8a8a03
Packit Service 8a8a03
    const char *program_usage_string = _(
Packit Service 8a8a03
        "& [-v] [-r[RELEASE]] (-b ID1[,ID2,...] | PKG-NAME) [PKG-NAME]... \n"
Packit Service 8a8a03
        "\n"
Packit Service 8a8a03
        "Search for updates on bodhi server"
Packit Service 8a8a03
    );
Packit Service 8a8a03
Packit Service 8a8a03
    unsigned opts =  parse_opts(argc, argv, program_options, program_usage_string);
Packit Service 8a8a03
Packit Service 8a8a03
    if (!bugs && !argv[optind])
Packit Service 8a8a03
        show_usage_and_die(program_usage_string, program_options);
Packit Service 8a8a03
Packit Service 8a8a03
    struct strbuf *query = strbuf_new();
Packit Service 8a8a03
    if (bugs)
Packit Service 8a8a03
        query = strbuf_append_strf(query, "bugs=%s&", bugs);
Packit Service 8a8a03
Packit Service 8a8a03
    if (opts & OPT_r)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        if (release)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            /* There are no bodhi updates for Rawhide */
Packit Service 8a8a03
            if (strcasecmp(release, "rawhide") == 0)
Packit Service 8a8a03
                error_msg_and_die("Release \"%s\" is not supported",release);
Packit Service 8a8a03
Packit Service 8a8a03
            query = strbuf_append_strf(query, "releases=%s&", release);
Packit Service 8a8a03
        }
Packit Service 8a8a03
        else
Packit Service 8a8a03
        {
Packit Service 8a8a03
            struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
Packit Service 8a8a03
            if (!dd)
Packit Service 8a8a03
                xfunc_die();
Packit Service 8a8a03
Packit Service 8a8a03
            problem_data_t *problem_data = create_problem_data_from_dump_dir(dd);
Packit Service 8a8a03
            dd_close(dd);
Packit Service 8a8a03
            if (!problem_data)
Packit Service 8a8a03
                xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */
Packit Service 8a8a03
Packit Service 8a8a03
            char *product, *version;
Packit Service 8a8a03
            map_string_t *osinfo = new_map_string();
Packit Service 8a8a03
            problem_data_get_osinfo(problem_data, osinfo);
Packit Service 8a8a03
            parse_osinfo_for_rhts(osinfo, &product, &version);
Packit Service 8a8a03
Packit Service 8a8a03
            /* There are no bodhi updates for Rawhide */
Packit Service 8a8a03
            bool rawhide = strcasecmp(version, "rawhide") == 0;
Packit Service 8a8a03
            if (!rawhide)
Packit Service 8a8a03
                query = strbuf_append_strf(query, "releases=f%s&", version);
Packit Service 8a8a03
Packit Service 8a8a03
            free(product);
Packit Service 8a8a03
            free(version);
Packit Service 8a8a03
            free_map_string(osinfo);
Packit Service 8a8a03
Packit Service 8a8a03
            if (rawhide)
Packit Service 8a8a03
            {
Packit Service 8a8a03
                strbuf_free(query);
Packit Service 8a8a03
                error_msg_and_die("Release \"Rawhide\" is not supported");
Packit Service 8a8a03
            }
Packit Service 8a8a03
        }
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    if (argv[optind])
Packit Service 8a8a03
    {
Packit Service 8a8a03
        char *escaped = g_uri_escape_string(argv[optind], NULL, 0);
Packit Service 8a8a03
        query = strbuf_append_strf(query, "packages=%s&", escaped);
Packit Service 8a8a03
        free(escaped);
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    if (query->buf[query->len - 1] == '&')
Packit Service 8a8a03
        query->buf[query->len - 1] = '\0';
Packit Service 8a8a03
Packit Service 8a8a03
    log_warning(_("Searching for updates"));
Packit Service 8a8a03
    GHashTable *update_hash_tbl = bodhi_query_list(query->buf, release);
Packit Service 8a8a03
    strbuf_free(query);
Packit Service 8a8a03
Packit Service 8a8a03
    if (!update_hash_tbl || !g_hash_table_size(update_hash_tbl))
Packit Service 8a8a03
    {
Packit Service 8a8a03
        log_warning(_("No updates for this package found"));
Packit Service 8a8a03
        /*if (update_hash_tbl) g_hash_table_unref(update_hash_tbl);*/
Packit Service 8a8a03
        return 0;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    GHashTableIter iter;
Packit Service 8a8a03
    char *name;
Packit Service 8a8a03
    struct bodhi *b;
Packit Service 8a8a03
    struct strbuf *q = strbuf_new();
Packit Service 8a8a03
    g_hash_table_iter_init(&iter, update_hash_tbl);
Packit Service 8a8a03
    while (g_hash_table_iter_next(&iter, (void **) &name, (void **) &b))
Packit Service 8a8a03
    {
Packit Service 8a8a03
        char *installed_pkg_nvr = rpm_get_nvr_by_pkg_name(name);
Packit Service 8a8a03
        if (installed_pkg_nvr && rpmvercmp(installed_pkg_nvr, b->nvr) >= 0)
Packit Service 8a8a03
        {
Packit Service 8a8a03
            log_info("Update %s is older or same as local version %s, skipping", b->nvr, installed_pkg_nvr);
Packit Service 8a8a03
            free(installed_pkg_nvr);
Packit Service 8a8a03
            continue;
Packit Service 8a8a03
        }
Packit Service 8a8a03
        free(installed_pkg_nvr);
Packit Service 8a8a03
Packit Service 8a8a03
        strbuf_append_strf(q, " %s", b->nvr);
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    /*g_hash_table_unref(update_hash_tbl);*/
Packit Service 8a8a03
Packit Service 8a8a03
    if (!q->len)
Packit Service 8a8a03
    {
Packit Service 8a8a03
        /*strbuf_free(q);*/
Packit Service 8a8a03
        log_warning(_("Local version of the package is newer than available updates"));
Packit Service 8a8a03
        return 0;
Packit Service 8a8a03
    }
Packit Service 8a8a03
Packit Service 8a8a03
    /* Message is split into text and command in order to make
Packit Service 8a8a03
     * translator's job easier
Packit Service 8a8a03
     */
Packit Service 8a8a03
Packit Service 8a8a03
    /* We suggest the command which is most likely to exist on user's system,
Packit Service 8a8a03
     * and which is familiar to the largest population of users.
Packit Service 8a8a03
     * There are other tools (pkcon et al) which might be somewhat more
Packit Service 8a8a03
     * convenient (for example, they might be usable from non-root), but they
Packit Service 8a8a03
     * might be not present on the system, may evolve or be superseded,
Packit Service 8a8a03
     * as it did happen to yum.
Packit Service 8a8a03
     */
Packit Service 8a8a03
Packit Service 8a8a03
    map_string_t *settings = new_map_string();
Packit Service 8a8a03
    load_abrt_plugin_conf_file("CCpp.conf", settings);
Packit Service 8a8a03
Packit Service 8a8a03
    const char *value;
Packit Service 8a8a03
    strbuf_prepend_str(q, " update --enablerepo=fedora --enablerepo=updates --enablerepo=updates-testing");
Packit Service 8a8a03
    value = get_map_string_item_or_NULL(settings, "PackageManager");
Packit Service 8a8a03
    if (value)
Packit Service 8a8a03
        strbuf_prepend_str(q, value);
Packit Service 8a8a03
    else
Packit Service 8a8a03
        strbuf_prepend_str(q, DEFAULT_PACKAGE_MANAGER);
Packit Service 8a8a03
    free_map_string(settings);
Packit Service 8a8a03
Packit Service 8a8a03
    char *msg = xasprintf(_("An update exists which might fix your problem. "
Packit Service 8a8a03
                "You can install it by running: %s. "
Packit Service 8a8a03
                "Do you want to continue with reporting the bug?"),
Packit Service 8a8a03
                q->buf
Packit Service 8a8a03
    );
Packit Service 8a8a03
    /*strbuf_free(q);*/
Packit Service 8a8a03
Packit Service 8a8a03
    return ask_yes_no(msg) ? 0 : EXIT_STOP_EVENT_RUN;
Packit Service 8a8a03
}