Signed-off-by: Michal Toman <[email protected]>
---
 src/lib/json.c        |   42 ++++++++++++++++++++++++++
 src/lib/ureport.h     |    4 ++
src/plugins/ureport.c | 78 +++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 109 insertions(+), 15 deletions(-)

diff --git a/src/lib/json.c b/src/lib/json.c
index 2cda77d..a413751 100644
--- a/src/lib/json.c
+++ b/src/lib/json.c
@@ -251,6 +251,22 @@ char *new_json_ureport(problem_data_t *pd)
     return j;
 }

+char *new_json_attachment(const char *bthash, const char *type, const char *data)
+{
+    struct json_object *attachment = json_object_new_object();
+    if (!attachment)
+        die_out_of_memory();
+
+    ureport_add_str(attachment, "bthash", bthash);
+    ureport_add_str(attachment, "type", type);
+    ureport_add_str(attachment, "data", data);
+
+    char *result = xstrdup(json_object_to_json_string(attachment));
+    json_object_put(attachment);
+
+    return result;
+}
+
struct post_state *post_ureport(problem_data_t *pd, struct ureport_server_config *config)
 {
     int flags = POST_WANT_BODY | POST_WANT_ERROR_MSG;
@@ -275,3 +291,29 @@ struct post_state *post_ureport(problem_data_t *pd, struct ureport_server_config

     return post_state;
 }
+
+struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
+ struct ureport_server_config *config)
+{
+    int flags = POST_WANT_BODY | POST_WANT_ERROR_MSG;
+
+    if (config->ur_ssl_verify)
+        flags |= POST_WANT_SSL_VERIFY;
+
+    struct post_state *post_state = new_post_state(flags);
+
+    static const char *headers[] = {
+        "Accept: application/json",
+        "Connection: close",
+        NULL,
+    };
+
+    char *str_bug_id = xasprintf("%d", rhbz_bug_id);
+ char *json_attachment = new_json_attachment(bthash, "RHBZ", str_bug_id); + post_string_as_form_data(post_state, config->ur_url, "application/json",
+                             headers, json_attachment);
+    free(str_bug_id);
+    free(json_attachment);
+
+    return post_state;
+}
diff --git a/src/lib/ureport.h b/src/lib/ureport.h
index 4e1bfcc..f851806 100644
--- a/src/lib/ureport.h
+++ b/src/lib/ureport.h
@@ -39,6 +39,10 @@ struct abrt_post_state;
 #define post_ureport libreport_post_ureport
struct post_state *post_ureport(problem_data_t *pd, struct ureport_server_config *config);

+#define ureport_attach_rhbz libreport_ureport_attach_rhbz
+struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
+ struct ureport_server_config *config);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index bd7a3bb..99ce60a 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -22,6 +22,9 @@
 #include "ureport.h"
 #include "libreport_curl.h"

+#define REPORT_URL "https://retrace.fedoraproject.org/faf/reports/new/";
+#define ATTACH_URL "https://retrace.fedoraproject.org/faf/reports/attach/";
+
 /*
  * Loads uReport configuration from various sources.
  *
@@ -95,58 +98,103 @@ static bool ureport_server_parse_json(json_object *json, struct ureport_server_r
     return false;
 }

+static bool check_response_statuscode(post_state_t *post_state,
+                                      const char *url)
+{
+    if (post_state->http_resp_code != 202)
+    {
+        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;
+    }
+
+    return true;
+}
+
 int main(int argc, char **argv)
 {
     abrt_init(argv);

     struct ureport_server_config config = {
-        .ur_url = "https://retrace.fedoraproject.org/faf/reports/new/";,
+        .ur_url = NULL,
         .ur_ssl_verify = true,
     };

     bool insecure = !config.ur_ssl_verify;
     const char *dump_dir_path = ".";
+    const char *ureport_hash = NULL;
+    int rhbz_bug = -1;
     struct options program_options[] = {
         OPT__VERBOSE(&g_verbose),
         OPT__DUMP_DIR(&dump_dir_path),
         OPT_STRING('u', "url", &config.ur_url, "URL", _("Specify url")),
         OPT_BOOL('k', "insecure", &insecure,
_("Allow insecure connection to ureport server")),
+        OPT_STRING('a', "attach", &ureport_hash, "BTHASH",
+                          _("bthash of uReport to attach")),
+        OPT_INTEGER('b', "bug-id", &rhbz_bug,
+                          _("Attach RHBZ bug (requires -a)")),
         OPT_END(),
     };

     const char *program_usage_string = _(
-        "& [-v] [-u URL] [-k] -d DIR\n"
+        "& [-v] [-u URL] [-k] [-a bthash -b bug-id] [-d DIR]\n"
         "\n"
-        "Upload micro report"
+        "Upload micro report or add an attachment to a micro report"
     );

     parse_opts(argc, argv, program_options, program_usage_string);
-    struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
-    if (!dd)
-        xfunc_die();

     config.ur_ssl_verify = !insecure;
     load_ureport_server_config(&config);
+    post_state_t *post_state = NULL;
+
+    /* we either need both -b & -a or none of them */
+    if (ureport_hash && rhbz_bug > 0)
+    {
+        if (!config.ur_url)
+            config.ur_url = ATTACH_URL;
+
+        post_state = ureport_attach_rhbz(ureport_hash, rhbz_bug, &config);
+        if (!check_response_statuscode(post_state, config.ur_url))
+        {
+            free_post_state(post_state);
+            return 1;
+        }
+
+        free_post_state(post_state);
+        return 0;
+    }
+    else if (ureport_hash && rhbz_bug <= 0)
+        error_msg_and_die(_("You need to specify bug ID to attach."));
+    else if (!ureport_hash && rhbz_bug > 0)
+ error_msg_and_die(_("You need to specify bthash of the uReport to attach."));
+
+    /* -b nor -a were specified - upload uReport from dump_dir */
+    if (!config.ur_url)
+        config.ur_url = REPORT_URL;
+
+    struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
+    if (!dd)
+        xfunc_die();

     problem_data_t *pd = create_problem_data_from_dump_dir(dd);
     dd_close(dd);
     if (!pd)
xfunc_die(); /* create_problem_data_for_reporting already emitted error msg */

-    post_state_t *post_state = NULL;
     post_state = post_ureport(pd, &config);
     problem_data_free(pd);

-    if (post_state->http_resp_code != 200)
+    if (!check_response_statuscode(post_state, config.ur_url))
     {
-        char *errmsg = post_state->curl_error_msg;
-        if (errmsg && *errmsg)
-        {
-            error_msg("%s '%s'", errmsg, config.ur_url);
-            free_post_state(post_state);
-            return 1;
-        }
+        free_post_state(post_state);
+        return 1;
     }

     int ret = 1; /* return 1 by default */
--
1.7.1

Reply via email to