Signed-off-by: Jakub Filak <[email protected]>
---
 src/plugins/ureport.c | 245 ++++++++++++++++++++++++++------------------------
 1 file changed, 127 insertions(+), 118 deletions(-)

diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index b48cabb..f4f2d32 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -45,22 +45,25 @@ static void load_ureport_server_config(struct 
ureport_server_config *config)
     config->ur_ssl_verify = environ ? string_to_bool(environ) : 
config->ur_ssl_verify;
 }
 
-
-enum response_type
-{
-    UREPORT_SERVER_RESP_UNKNOWN_TYPE,
-    UREPORT_SERVER_RESP_KNOWN,
-    UREPORT_SERVER_RESP_ERROR,
-};
-
 struct ureport_server_response {
-    enum response_type type;
+    /* need it because we don't want to make a copy of each response field */
+    json_object *source;
+    bool is_error;
     const char *value;
     const char *message;
     const char *bthash;
     GList *reported_to_list;
 };
 
+void free_ureport_server_response(struct ureport_server_response *resp)
+{
+    if (!resp)
+        return;
+
+    json_object_put(resp->source);
+    free(resp);
+}
+
 /* reported_to json element should be a list of structures
 { "reporter": "Bugzilla",
   "type": "url",
@@ -127,22 +130,23 @@ static GList *parse_reported_to_from_json_list(struct 
json_object *list)
  * {"response":"true"}
  * {"response":"false"}
  */
-static bool ureport_server_parse_json(json_object *json, struct 
ureport_server_response *out_response)
+static struct ureport_server_response *ureport_server_parse_json(json_object 
*json)
 {
     json_object *obj = json_object_object_get(json, "error");
 
     if (obj)
     {
-        out_response->type = UREPORT_SERVER_RESP_ERROR;
+        struct ureport_server_response *out_response = 
xzalloc(sizeof(*out_response));
+        out_response->is_error = true;
         out_response->value = json_object_to_json_string(obj);
-        return true;
+        return out_response;
     }
 
     obj = json_object_object_get(json, "result");
 
     if (obj)
     {
-        out_response->type = UREPORT_SERVER_RESP_KNOWN;
+        struct ureport_server_response *out_response = 
xzalloc(sizeof(*out_response));
         out_response->value = json_object_get_string(obj);
 
         json_object *message = json_object_object_get(json, "message");
@@ -157,29 +161,83 @@ static bool ureport_server_parse_json(json_object *json, 
struct ureport_server_r
         if (reported_to_list)
             out_response->reported_to_list = 
parse_reported_to_from_json_list(reported_to_list);
 
-        return true;
+        return out_response;
+    }
+
+    return NULL;
+}
+
+static struct ureport_server_response *get_server_response(post_state_t 
*post_state)
+{
+    if (post_state->http_resp_code == 404)
+    {
+        error_msg(_("Can't get server response because of invalid url"));
+        return NULL;
+    }
+
+    json_object *const json = json_tokener_parse(post_state->body);
+
+    if (is_error(json))
+    {
+        error_msg(_("Unable to parse response from ureport server"));
+        json_object_put(json);
+        return NULL;
+    }
+
+    struct ureport_server_response *response = ureport_server_parse_json(json);
+
+    if (response)
+        response->source = json;
+    else
+        json_object_put(json);
+
+    if (post_state->http_resp_code == 202)
+    {
+        if (!response)
+            error_msg(_("Server response data has invalid format"));
+        else if (response->is_error)
+        {
+            /* HTTP CODE 202 means that call was successful but the response */
+            /* has an error message */
+            error_msg(_("Server response type mismatch"));
+            free_ureport_server_response(response);
+            response = NULL;
+        }
+    }
+    else if (!response || !response->is_error)
+    {
+        /* can't print better error message */
+        error_msg(_("Unexpected HTTP status code: %d"), 
post_state->http_resp_code);
+        free_ureport_server_response(response);
+        response = NULL;
     }
 
-    out_response->type = UREPORT_SERVER_RESP_UNKNOWN_TYPE;
-    return false;
+end_server_response:
+    return response;
 }
 
-static bool check_response_statuscode(post_state_t *post_state, 
-                                      const char *url)
+static bool perform_attach(struct ureport_server_config *config, const char 
*ureport_hash, int rhbz_bug)
 {
-    if (post_state->http_resp_code != 202)
+    char *dest_url = xasprintf("%s%s", config->ur_url, ATTACH_URL_SFX);
+    const char *old_url = config->ur_url;
+    config->ur_url = dest_url;
+    post_state_t *post_state = ureport_attach_rhbz(ureport_hash, rhbz_bug, 
config);
+    config->ur_url = old_url;
+    free(dest_url);
+
+    struct ureport_server_response *resp = get_server_response(post_state);
+    free_post_state(post_state);
+    /* don't use str_bo_bool() because we require "true" string */
+    const int result = !resp || resp->is_error || strcmp(resp->value,"true") 
!= 0;
+
+    if (resp && resp->is_error)
     {
-        char *errmsg = post_state->curl_error_msg;
-        if (errmsg && *errmsg)
-            error_msg("%s '%s'", errmsg, url);
-        else
-            error_msg("Unexpected HTTP status code: %d",
-                      post_state->http_resp_code);
-
-        return false;
+        VERB1 error_msg(_("Server side error: '%s'"), resp->value);
     }
 
-    return true;
+    free_ureport_server_response(resp);
+
+    return result;
 }
 
 int main(int argc, char **argv)
@@ -226,15 +284,7 @@ int main(int argc, char **argv)
     /* we either need both -b & -a or none of them */
     if (ureport_hash && rhbz_bug > 0)
     {
-        char *dest_url = xasprintf("%s%s", config.ur_url, ATTACH_URL_SFX);
-        config.ur_url = dest_url;
-        post_state = ureport_attach_rhbz(ureport_hash, rhbz_bug, &config);
-        const int result = !check_response_statuscode(post_state, dest_url);
-
-        free_post_state(post_state);
-        free(dest_url);
-
-        return result;
+        return perform_attach(&config, ureport_hash, rhbz_bug);
     }
     else if (ureport_hash && rhbz_bug <= 0)
         error_msg_and_die(_("You need to specify bug ID to attach."));
@@ -274,16 +324,7 @@ int main(int argc, char **argv)
 
         free_report_result(bz_result);
 
-        char *dest_url = xasprintf("%s%s", config.ur_url, ATTACH_URL_SFX);
-        config.ur_url = dest_url;
-        post_state = ureport_attach_rhbz(bthash, bugid, &config);
-        free(bthash);
-
-        int ret = !check_response_statuscode(post_state, dest_url);
-        free_post_state(post_state);
-        free(dest_url);
-
-        return ret;
+        return perform_attach(&config, bthash, bugid);
     }
 
     /* -b, -a nor -r were specified - upload uReport from dump_dir */
@@ -295,96 +336,64 @@ int main(int argc, char **argv)
     char *dest_url = xasprintf("%s%s", config.ur_url, REPORT_URL_SFX);
     config.ur_url = dest_url;
     post_state = post_ureport(pd, &config);
+    free(dest_url);
     problem_data_free(pd);
 
     int ret = 1; /* return 1 by default */
 
-    if (!check_response_statuscode(post_state, dest_url))
-        /* check_response_statuscode() already logged an error message */
-        goto err;
-
-    json_object *const json = json_tokener_parse(post_state->body);
-
-    if (is_error(json))
-    {
-        error_msg("fatal: unable to parse response from ureport server");
-        goto err;
-    }
-
-    struct ureport_server_response response = {
-        .type=UREPORT_SERVER_RESP_UNKNOWN_TYPE,
-        .value=NULL,
-        .message=NULL,
-        .bthash=NULL,
-    };
-
-    const bool is_valid_response = ureport_server_parse_json(json, &response);
+    struct ureport_server_response *response = get_server_response(post_state);
 
-    if (!is_valid_response)
-    {
-        error_msg("fatal: wrong format of response from ureport server");
+    if (!response)
         goto format_err;
-    }
 
-    switch (response.type)
+    if (!response->is_error)
     {
-        case UREPORT_SERVER_RESP_KNOWN:
-            VERB1 log("is known: %s", response.value);
-            ret = 0;
+        VERB1 log("is known: %s", response->value);
+        ret = 0;
 
-            if (response.bthash)
-            {
-                dd = dd_opendir(dump_dir_path, /* flags */ 0);
-                if (!dd)
-                    xfunc_die();
+        if (response->bthash)
+        {
+            dd = dd_opendir(dump_dir_path, /* flags */ 0);
+            if (!dd)
+                xfunc_die();
 
-                char *msg = xasprintf("uReport: BTHASH=%s", response.bthash);
-                add_reported_to(dd, msg);
-                free(msg);
+            char *msg = xasprintf("uReport: BTHASH=%s", response->bthash);
+            add_reported_to(dd, msg);
+            free(msg);
 
-                if (response.reported_to_list)
+            if (response->reported_to_list)
+            {
+                GList *elem = response->reported_to_list;
+                while (elem)
                 {
-                    GList *elem = response.reported_to_list;
-                    while (elem)
-                    {
-                        add_reported_to(dd, elem->data);
-                        free(elem->data);
-                        elem = g_list_next(elem);
-                    }
-
-                    g_list_free(response.reported_to_list);
+                    add_reported_to(dd, elem->data);
+                    free(elem->data);
+                    elem = g_list_next(elem);
                 }
 
-                dd_close(dd);
+                g_list_free(response->reported_to_list);
             }
 
-            /* If a reported problem is not known then emit NEEDMORE */
-            if (strcmp("true", response.value) == 0)
-            {
-                log("This problem has already been reported.");
-                if (response.message)
-                    log(response.message);
-                log("THANKYOU");
-            }
-            break;
-        case UREPORT_SERVER_RESP_ERROR:
-            VERB1 log("server side error: %s", response.value);
-            ret = 1; /* just to be sure */
-            break;
-        case UREPORT_SERVER_RESP_UNKNOWN_TYPE:
-            error_msg("invalid server response: %s", response.value);
-            ret = 1; /* just to be sure */
-            break;
-        default:
-            error_msg("reporter internal error: missing handler for response 
type");
-            ret = 1; /* just to be sure */
-            break;
+            dd_close(dd);
+        }
+
+        /* If a reported problem is not known then emit NEEDMORE */
+        if (strcmp("true", response->value) == 0)
+        {
+            log("This problem has already been reported.");
+            if (response->message)
+                log(response->message);
+            log("THANKYOU");
+        }
+    }
+    else
+    {
+        VERB1 log("server side error: %s", response->value);
     }
 
+    free_ureport_server_response(response);
+
 format_err:
-    json_object_put(json);
-err:
-    free(dest_url);
     free_post_state(post_state);
 
     return ret;
-- 
1.7.11.4

Reply via email to