Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
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