Blame SOURCES/0079-ureport-publish-ureport.h-and-refactore-uReport-sour.patch

0c9110
From e67393a38e1739ff1b0453fdb3b68ff7e4fb36e9 Mon Sep 17 00:00:00 2001
0c9110
From: Jakub Filak <jfilak@redhat.com>
0c9110
Date: Fri, 12 Sep 2014 17:20:01 +0200
0c9110
Subject: [LIBREPORT PATCH 79/93] ureport: publish ureport.h and refactore
0c9110
 uReport source
0c9110
0c9110
Allow other plugins to submit uReport and allow external applications to
0c9110
use libreport to submit uReport.
0c9110
0c9110
Related to rhbz1139987
0c9110
0c9110
Signed-off-by: Jakub Filak <jfilak@redhat.com>
0c9110
---
0c9110
 src/include/Makefile.am        |   4 +
0c9110
 src/include/ureport.h          |  76 ++++
0c9110
 src/lib/Makefile.am            |   4 +-
0c9110
 src/lib/json.c                 | 180 ----------
0c9110
 src/lib/ureport.c              | 180 ++++++++++
0c9110
 src/lib/ureport.h              |  76 ----
0c9110
 src/plugins/Makefile.am        |   4 +-
0c9110
 src/plugins/reporter-ureport.c | 777 +++++++++++++++++++++++++++++++++++++++++
0c9110
 src/plugins/ureport.c          | 777 -----------------------------------------
0c9110
 9 files changed, 1043 insertions(+), 1035 deletions(-)
0c9110
 create mode 100644 src/include/ureport.h
0c9110
 delete mode 100644 src/lib/json.c
0c9110
 create mode 100644 src/lib/ureport.c
0c9110
 delete mode 100644 src/lib/ureport.h
0c9110
 create mode 100644 src/plugins/reporter-ureport.c
0c9110
 delete mode 100644 src/plugins/ureport.c
0c9110
0c9110
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
0c9110
index 806b93e..de44cda 100644
0c9110
--- a/src/include/Makefile.am
0c9110
+++ b/src/include/Makefile.am
0c9110
@@ -15,3 +15,7 @@ libreport_include_HEADERS = \
0c9110
     internal_libreport.h \
0c9110
     internal_abrt_dbus.h \
0c9110
     xml_parser.h
0c9110
+
0c9110
+if BUILD_UREPORT
0c9110
+libreport_include_HEADERS += ureport.h
0c9110
+endif
0c9110
diff --git a/src/include/ureport.h b/src/include/ureport.h
0c9110
new file mode 100644
0c9110
index 0000000..d341f6e
0c9110
--- /dev/null
0c9110
+++ b/src/include/ureport.h
0c9110
@@ -0,0 +1,76 @@
0c9110
+/*
0c9110
+    Copyright (C) 2012  ABRT team
0c9110
+    Copyright (C) 2012  RedHat Inc
0c9110
+
0c9110
+    This program is free software; you can redistribute it and/or modify
0c9110
+    it under the terms of the GNU General Public License as published by
0c9110
+    the Free Software Foundation; either version 2 of the License, or
0c9110
+    (at your option) any later version.
0c9110
+
0c9110
+    This program is distributed in the hope that it will be useful,
0c9110
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
+    GNU General Public License for more details.
0c9110
+
0c9110
+    You should have received a copy of the GNU General Public License along
0c9110
+    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
+*/
0c9110
+#ifndef UREPORT_H_
0c9110
+#define UREPORT_H_
0c9110
+
0c9110
+#include "problem_data.h"
0c9110
+
0c9110
+#ifdef __cplusplus
0c9110
+extern "C" {
0c9110
+#endif
0c9110
+
0c9110
+/*
0c9110
+ * uReport generation configuration
0c9110
+ */
0c9110
+struct ureport_preferences
0c9110
+{
0c9110
+    GList *urp_auth_items;  ///< list of file names included in 'auth' key
0c9110
+};
0c9110
+
0c9110
+/*
0c9110
+ * uReport server configuration
0c9110
+ */
0c9110
+struct ureport_server_config
0c9110
+{
0c9110
+    const char *ur_url;   ///< Web service URL
0c9110
+    bool ur_ssl_verify;   ///< Verify HOST and PEER certificates
0c9110
+    char *ur_client_cert; ///< Path to certificate used for client
0c9110
+                          ///< authentication (or NULL)
0c9110
+    char *ur_client_key;  ///< Private key for the certificate
0c9110
+    map_string_t *ur_http_headers; ///< Additional HTTP headers
0c9110
+
0c9110
+    struct ureport_preferences ur_prefs; ///< configuration for uReport generation
0c9110
+};
0c9110
+
0c9110
+struct abrt_post_state;
0c9110
+
0c9110
+#define ureport_post libreport_ureport_post
0c9110
+struct post_state *ureport_post(const char *json_ureport,
0c9110
+                                struct ureport_server_config *config);
0c9110
+
0c9110
+#define ureport_attach_rhbz libreport_ureport_attach_rhbz
0c9110
+struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
0c9110
+                                       struct ureport_server_config *config);
0c9110
+
0c9110
+#define ureport_attach_email libreport_ureport_attach_email
0c9110
+struct post_state *ureport_attach_email(const char *bthash, const char *email,
0c9110
+                                        struct ureport_server_config *config);
0c9110
+
0c9110
+#define ureport_from_dump_dir libreport_ureport_from_dump_dir
0c9110
+char *ureport_from_dump_dir(const char *dump_dir_path);
0c9110
+
0c9110
+#define ureport_from_dump_dir_ext libreport_ureport_from_dump_dir_ext
0c9110
+char *ureport_from_dump_dir_ext(const char *dump_dir_path,
0c9110
+                                const struct ureport_preferences *preferences);
0c9110
+
0c9110
+#ifdef __cplusplus
0c9110
+}
0c9110
+#endif
0c9110
+
0c9110
+#endif
0c9110
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
0c9110
index d2ff675..7d9722a 100644
0c9110
--- a/src/lib/Makefile.am
0c9110
+++ b/src/lib/Makefile.am
0c9110
@@ -72,6 +72,7 @@ libreport_la_CPPFLAGS = \
0c9110
     -DDEFAULT_DUMP_DIR_MODE=$(DEFAULT_DUMP_DIR_MODE) \
0c9110
     -DDUMP_DIR_OWNED_BY_USER=$(DUMP_DIR_OWNED_BY_USER) \
0c9110
     -DLARGE_DATA_TMP_DIR=\"$(LARGE_DATA_TMP_DIR)\" \
0c9110
+    $(JSON_C_CFLAGS) \
0c9110
     $(GLIB_CFLAGS) \
0c9110
     $(GOBJECT_CFLAGS) \
0c9110
     $(AUGEAS_CFLAGS) \
0c9110
@@ -79,6 +80,7 @@ libreport_la_CPPFLAGS = \
0c9110
 libreport_la_LDFLAGS = \
0c9110
     -version-info 0:1:0
0c9110
 libreport_la_LIBADD = \
0c9110
+    $(JSON_C_LIBS) \
0c9110
     $(GLIB_LIBS) \
0c9110
     $(JOURNAL_LIBS) \
0c9110
     $(GOBJECT_LIBS) \
0c9110
@@ -113,7 +115,7 @@ libreport_web_o += abrt_xmlrpc.h abrt_xmlrpc.c
0c9110
 endif
0c9110
 
0c9110
 if BUILD_UREPORT
0c9110
-libreport_web_o += ureport.h json.c
0c9110
+libreport_web_o += ureport.c
0c9110
 endif
0c9110
 
0c9110
 libreport_web_la_SOURCES = $(libreport_web_o) \
0c9110
diff --git a/src/lib/json.c b/src/lib/json.c
0c9110
deleted file mode 100644
0c9110
index 6fbbf39..0000000
0c9110
--- a/src/lib/json.c
0c9110
+++ /dev/null
0c9110
@@ -1,180 +0,0 @@
0c9110
-/*
0c9110
-    Copyright (C) 2012  ABRT team
0c9110
-    Copyright (C) 2012  RedHat Inc
0c9110
-
0c9110
-    This program is free software; you can redistribute it and/or modify
0c9110
-    it under the terms of the GNU General Public License as published by
0c9110
-    the Free Software Foundation; either version 2 of the License, or
0c9110
-    (at your option) any later version.
0c9110
-
0c9110
-    This program is distributed in the hope that it will be useful,
0c9110
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
-    GNU General Public License for more details.
0c9110
-
0c9110
-    You should have received a copy of the GNU General Public License along
0c9110
-    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
-*/
0c9110
-
0c9110
-#include <json/json.h>
0c9110
-
0c9110
-#include <satyr/abrt.h>
0c9110
-#include <satyr/report.h>
0c9110
-
0c9110
-#include "internal_libreport.h"
0c9110
-#include "ureport.h"
0c9110
-#include "libreport_curl.h"
0c9110
-
0c9110
-
0c9110
-static void ureport_add_str(struct json_object *ur, const char *key,
0c9110
-                            const char *s)
0c9110
-{
0c9110
-    struct json_object *jstring = json_object_new_string(s);
0c9110
-    if (!jstring)
0c9110
-        die_out_of_memory();
0c9110
-
0c9110
-    json_object_object_add(ur, key, jstring);
0c9110
-}
0c9110
-
0c9110
-char *ureport_from_dump_dir_ext(const char *dump_dir_path, const struct ureport_preferences *preferences)
0c9110
-{
0c9110
-    char *error_message;
0c9110
-    struct sr_report *report = sr_abrt_report_from_dir(dump_dir_path,
0c9110
-                                                       &error_message);
0c9110
-
0c9110
-    if (!report)
0c9110
-        error_msg_and_die("%s", error_message);
0c9110
-
0c9110
-    if (preferences != NULL && preferences->urp_auth_items != NULL)
0c9110
-    {
0c9110
-        struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
0c9110
-        if (!dd)
0c9110
-            xfunc_die(); /* dd_opendir() already printed an error message */
0c9110
-
0c9110
-        GList *iter = preferences->urp_auth_items;
0c9110
-        for ( ; iter != NULL; iter = g_list_next(iter))
0c9110
-        {
0c9110
-            const char *key = (const char *)iter->data;
0c9110
-            char *value = dd_load_text_ext(dd, key,
0c9110
-                    DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE | DD_FAIL_QUIETLY_ENOENT);
0c9110
-
0c9110
-            if (value == NULL)
0c9110
-            {
0c9110
-                perror_msg("Cannot include '%s' in 'auth'", key);
0c9110
-                continue;
0c9110
-            }
0c9110
-
0c9110
-            sr_report_add_auth(report, key, value);
0c9110
-        }
0c9110
-
0c9110
-        dd_close(dd);
0c9110
-    }
0c9110
-
0c9110
-    char *json_ureport = sr_report_to_json(report);
0c9110
-    sr_report_free(report);
0c9110
-
0c9110
-    return json_ureport;
0c9110
-}
0c9110
-
0c9110
-char *ureport_from_dump_dir(const char *dump_dir_path)
0c9110
-{
0c9110
-    return ureport_from_dump_dir_ext(dump_dir_path, /*no preferences*/NULL);
0c9110
-}
0c9110
-
0c9110
-char *new_json_attachment(const char *bthash, const char *type, const char *data)
0c9110
-{
0c9110
-    struct json_object *attachment = json_object_new_object();
0c9110
-    if (!attachment)
0c9110
-        die_out_of_memory();
0c9110
-
0c9110
-    ureport_add_str(attachment, "bthash", bthash);
0c9110
-    ureport_add_str(attachment, "type", type);
0c9110
-    ureport_add_str(attachment, "data", data);
0c9110
-
0c9110
-    char *result = xstrdup(json_object_to_json_string(attachment));
0c9110
-    json_object_put(attachment);
0c9110
-
0c9110
-    return result;
0c9110
-}
0c9110
-
0c9110
-struct post_state *post_ureport(const char *json, struct ureport_server_config *config)
0c9110
-{
0c9110
-    int flags = POST_WANT_BODY | POST_WANT_ERROR_MSG;
0c9110
-
0c9110
-    if (config->ur_ssl_verify)
0c9110
-        flags |= POST_WANT_SSL_VERIFY;
0c9110
-
0c9110
-    struct post_state *post_state = new_post_state(flags);
0c9110
-
0c9110
-    if (config->ur_client_cert && config->ur_client_key)
0c9110
-    {
0c9110
-        post_state->client_cert_path = config->ur_client_cert;
0c9110
-        post_state->client_key_path = config->ur_client_key;
0c9110
-    }
0c9110
-
0c9110
-    char **headers = xmalloc(sizeof(char *) * (3 + size_map_string(config->ur_http_headers)));
0c9110
-    headers[0] = (char *)"Accept: application/json";
0c9110
-    headers[1] = (char *)"Connection: close";
0c9110
-    headers[2] = NULL;
0c9110
-
0c9110
-    if (config->ur_http_headers != NULL)
0c9110
-    {
0c9110
-        unsigned i = 2;
0c9110
-        const char *header;
0c9110
-        const char *value;
0c9110
-        map_string_iter_t iter;
0c9110
-        init_map_string_iter(&iter, config->ur_http_headers);
0c9110
-        while (next_map_string_iter(&iter, &header, &value))
0c9110
-            headers[i++] = xasprintf("%s: %s", header, value);
0c9110
-        headers[i] = NULL;
0c9110
-    }
0c9110
-
0c9110
-    post_string_as_form_data(post_state, config->ur_url, "application/json",
0c9110
-                    (const char **)headers, json);
0c9110
-
0c9110
-    /* Client authentication failed. Try again without client auth.
0c9110
-     * CURLE_SSL_CONNECT_ERROR - cert not found/server doesnt trust the CA
0c9110
-     * CURLE_SSL_CERTPROBLEM - malformed certificate/no permission
0c9110
-     */
0c9110
-    if ((post_state->curl_result == CURLE_SSL_CONNECT_ERROR
0c9110
-         || post_state->curl_result == CURLE_SSL_CERTPROBLEM)
0c9110
-            && config->ur_client_cert && config->ur_client_key)
0c9110
-    {
0c9110
-        warn_msg("Authentication failed. Retrying unauthenticated.");
0c9110
-        free_post_state(post_state);
0c9110
-        post_state = new_post_state(flags);
0c9110
-
0c9110
-        post_string_as_form_data(post_state, config->ur_url, "application/json",
0c9110
-                         (const char **)headers, json);
0c9110
-
0c9110
-    }
0c9110
-
0c9110
-    for (unsigned i = size_map_string(config->ur_http_headers); i != 0; --i)
0c9110
-        free(headers[i + 1]);
0c9110
-    free(headers);
0c9110
-
0c9110
-    return post_state;
0c9110
-}
0c9110
-
0c9110
-struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
0c9110
-                                       struct ureport_server_config *config)
0c9110
-{
0c9110
-    char *str_bug_id = xasprintf("%d", rhbz_bug_id);
0c9110
-    char *json_attachment = new_json_attachment(bthash, "RHBZ", str_bug_id);
0c9110
-    struct post_state *post_state = post_ureport(json_attachment, config);
0c9110
-    free(str_bug_id);
0c9110
-    free(json_attachment);
0c9110
-
0c9110
-    return post_state;
0c9110
-}
0c9110
-
0c9110
-struct post_state *ureport_attach_email(const char *bthash, const char *email,
0c9110
-                                       struct ureport_server_config *config)
0c9110
-{
0c9110
-    char *json_attachment = new_json_attachment(bthash, "email", email);
0c9110
-    struct post_state *post_state = post_ureport(json_attachment, config);
0c9110
-    free(json_attachment);
0c9110
-
0c9110
-    return post_state;
0c9110
-}
0c9110
diff --git a/src/lib/ureport.c b/src/lib/ureport.c
0c9110
new file mode 100644
0c9110
index 0000000..761fe62
0c9110
--- /dev/null
0c9110
+++ b/src/lib/ureport.c
0c9110
@@ -0,0 +1,180 @@
0c9110
+/*
0c9110
+    Copyright (C) 2012,2014  ABRT team
0c9110
+    Copyright (C) 2012,2014  RedHat Inc
0c9110
+
0c9110
+    This program is free software; you can redistribute it and/or modify
0c9110
+    it under the terms of the GNU General Public License as published by
0c9110
+    the Free Software Foundation; either version 2 of the License, or
0c9110
+    (at your option) any later version.
0c9110
+
0c9110
+    This program is distributed in the hope that it will be useful,
0c9110
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
+    GNU General Public License for more details.
0c9110
+
0c9110
+    You should have received a copy of the GNU General Public License along
0c9110
+    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
+*/
0c9110
+
0c9110
+#include <json.h>
0c9110
+
0c9110
+#include <satyr/abrt.h>
0c9110
+#include <satyr/report.h>
0c9110
+
0c9110
+#include "internal_libreport.h"
0c9110
+#include "ureport.h"
0c9110
+#include "libreport_curl.h"
0c9110
+
0c9110
+
0c9110
+static void ureport_add_str(struct json_object *ur, const char *key,
0c9110
+                            const char *s)
0c9110
+{
0c9110
+    struct json_object *jstring = json_object_new_string(s);
0c9110
+    if (!jstring)
0c9110
+        die_out_of_memory();
0c9110
+
0c9110
+    json_object_object_add(ur, key, jstring);
0c9110
+}
0c9110
+
0c9110
+char *ureport_from_dump_dir_ext(const char *dump_dir_path, const struct ureport_preferences *preferences)
0c9110
+{
0c9110
+    char *error_message;
0c9110
+    struct sr_report *report = sr_abrt_report_from_dir(dump_dir_path,
0c9110
+                                                       &error_message);
0c9110
+
0c9110
+    if (!report)
0c9110
+        error_msg_and_die("%s", error_message);
0c9110
+
0c9110
+    if (preferences != NULL && preferences->urp_auth_items != NULL)
0c9110
+    {
0c9110
+        struct dump_dir *dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
0c9110
+        if (!dd)
0c9110
+            xfunc_die(); /* dd_opendir() already printed an error message */
0c9110
+
0c9110
+        GList *iter = preferences->urp_auth_items;
0c9110
+        for ( ; iter != NULL; iter = g_list_next(iter))
0c9110
+        {
0c9110
+            const char *key = (const char *)iter->data;
0c9110
+            char *value = dd_load_text_ext(dd, key,
0c9110
+                    DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE | DD_FAIL_QUIETLY_ENOENT);
0c9110
+
0c9110
+            if (value == NULL)
0c9110
+            {
0c9110
+                perror_msg("Cannot include '%s' in 'auth'", key);
0c9110
+                continue;
0c9110
+            }
0c9110
+
0c9110
+            sr_report_add_auth(report, key, value);
0c9110
+        }
0c9110
+
0c9110
+        dd_close(dd);
0c9110
+    }
0c9110
+
0c9110
+    char *json_ureport = sr_report_to_json(report);
0c9110
+    sr_report_free(report);
0c9110
+
0c9110
+    return json_ureport;
0c9110
+}
0c9110
+
0c9110
+char *ureport_from_dump_dir(const char *dump_dir_path)
0c9110
+{
0c9110
+    return ureport_from_dump_dir_ext(dump_dir_path, /*no preferences*/NULL);
0c9110
+}
0c9110
+
0c9110
+static char *new_json_attachment(const char *bthash, const char *type, const char *data)
0c9110
+{
0c9110
+    struct json_object *attachment = json_object_new_object();
0c9110
+    if (!attachment)
0c9110
+        die_out_of_memory();
0c9110
+
0c9110
+    ureport_add_str(attachment, "bthash", bthash);
0c9110
+    ureport_add_str(attachment, "type", type);
0c9110
+    ureport_add_str(attachment, "data", data);
0c9110
+
0c9110
+    char *result = xstrdup(json_object_to_json_string(attachment));
0c9110
+    json_object_put(attachment);
0c9110
+
0c9110
+    return result;
0c9110
+}
0c9110
+
0c9110
+struct post_state *ureport_post(const char *json, struct ureport_server_config *config)
0c9110
+{
0c9110
+    int flags = POST_WANT_BODY | POST_WANT_ERROR_MSG;
0c9110
+
0c9110
+    if (config->ur_ssl_verify)
0c9110
+        flags |= POST_WANT_SSL_VERIFY;
0c9110
+
0c9110
+    struct post_state *post_state = new_post_state(flags);
0c9110
+
0c9110
+    if (config->ur_client_cert && config->ur_client_key)
0c9110
+    {
0c9110
+        post_state->client_cert_path = config->ur_client_cert;
0c9110
+        post_state->client_key_path = config->ur_client_key;
0c9110
+    }
0c9110
+
0c9110
+    char **headers = xmalloc(sizeof(char *) * (3 + size_map_string(config->ur_http_headers)));
0c9110
+    headers[0] = (char *)"Accept: application/json";
0c9110
+    headers[1] = (char *)"Connection: close";
0c9110
+    headers[2] = NULL;
0c9110
+
0c9110
+    if (config->ur_http_headers != NULL)
0c9110
+    {
0c9110
+        unsigned i = 2;
0c9110
+        const char *header;
0c9110
+        const char *value;
0c9110
+        map_string_iter_t iter;
0c9110
+        init_map_string_iter(&iter, config->ur_http_headers);
0c9110
+        while (next_map_string_iter(&iter, &header, &value))
0c9110
+            headers[i++] = xasprintf("%s: %s", header, value);
0c9110
+        headers[i] = NULL;
0c9110
+    }
0c9110
+
0c9110
+    post_string_as_form_data(post_state, config->ur_url, "application/json",
0c9110
+                    (const char **)headers, json);
0c9110
+
0c9110
+    /* Client authentication failed. Try again without client auth.
0c9110
+     * CURLE_SSL_CONNECT_ERROR - cert not found/server doesnt trust the CA
0c9110
+     * CURLE_SSL_CERTPROBLEM - malformed certificate/no permission
0c9110
+     */
0c9110
+    if ((post_state->curl_result == CURLE_SSL_CONNECT_ERROR
0c9110
+         || post_state->curl_result == CURLE_SSL_CERTPROBLEM)
0c9110
+            && config->ur_client_cert && config->ur_client_key)
0c9110
+    {
0c9110
+        warn_msg("Authentication failed. Retrying unauthenticated.");
0c9110
+        free_post_state(post_state);
0c9110
+        post_state = new_post_state(flags);
0c9110
+
0c9110
+        post_string_as_form_data(post_state, config->ur_url, "application/json",
0c9110
+                         (const char **)headers, json);
0c9110
+
0c9110
+    }
0c9110
+
0c9110
+    for (unsigned i = size_map_string(config->ur_http_headers); i != 0; --i)
0c9110
+        free(headers[i + 1]);
0c9110
+    free(headers);
0c9110
+
0c9110
+    return post_state;
0c9110
+}
0c9110
+
0c9110
+struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
0c9110
+                                       struct ureport_server_config *config)
0c9110
+{
0c9110
+    char *str_bug_id = xasprintf("%d", rhbz_bug_id);
0c9110
+    char *json_attachment = new_json_attachment(bthash, "RHBZ", str_bug_id);
0c9110
+    struct post_state *post_state = ureport_post(json_attachment, config);
0c9110
+    free(str_bug_id);
0c9110
+    free(json_attachment);
0c9110
+
0c9110
+    return post_state;
0c9110
+}
0c9110
+
0c9110
+struct post_state *ureport_attach_email(const char *bthash, const char *email,
0c9110
+                                       struct ureport_server_config *config)
0c9110
+{
0c9110
+    char *json_attachment = new_json_attachment(bthash, "email", email);
0c9110
+    struct post_state *post_state = ureport_post(json_attachment, config);
0c9110
+    free(json_attachment);
0c9110
+
0c9110
+    return post_state;
0c9110
+}
0c9110
diff --git a/src/lib/ureport.h b/src/lib/ureport.h
0c9110
deleted file mode 100644
0c9110
index 319aca9..0000000
0c9110
--- a/src/lib/ureport.h
0c9110
+++ /dev/null
0c9110
@@ -1,76 +0,0 @@
0c9110
-/*
0c9110
-    Copyright (C) 2012  ABRT team
0c9110
-    Copyright (C) 2012  RedHat Inc
0c9110
-
0c9110
-    This program is free software; you can redistribute it and/or modify
0c9110
-    it under the terms of the GNU General Public License as published by
0c9110
-    the Free Software Foundation; either version 2 of the License, or
0c9110
-    (at your option) any later version.
0c9110
-
0c9110
-    This program is distributed in the hope that it will be useful,
0c9110
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
-    GNU General Public License for more details.
0c9110
-
0c9110
-    You should have received a copy of the GNU General Public License along
0c9110
-    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
-*/
0c9110
-#ifndef UREPORT_H_
0c9110
-#define UREPORT_H_
0c9110
-
0c9110
-#include "problem_data.h"
0c9110
-
0c9110
-#ifdef __cplusplus
0c9110
-extern "C" {
0c9110
-#endif
0c9110
-
0c9110
-/*
0c9110
- * uReport generation configuration
0c9110
- */
0c9110
-struct ureport_preferences
0c9110
-{
0c9110
-    GList *urp_auth_items;  ///< list of file names included in 'auth' key
0c9110
-};
0c9110
-
0c9110
-/*
0c9110
- * uReport server configuration
0c9110
- */
0c9110
-struct ureport_server_config
0c9110
-{
0c9110
-    const char *ur_url;   ///< Web service URL
0c9110
-    bool ur_ssl_verify;   ///< Verify HOST and PEER certificates
0c9110
-    char *ur_client_cert; ///< Path to certificate used for client
0c9110
-                          ///< authentication (or NULL)
0c9110
-    char *ur_client_key;  ///< Private key for the certificate
0c9110
-    map_string_t *ur_http_headers; ///< Additional HTTP headers
0c9110
-
0c9110
-    struct ureport_preferences ur_prefs; ///< configuration for uReport generation
0c9110
-};
0c9110
-
0c9110
-struct abrt_post_state;
0c9110
-
0c9110
-#define post_ureport libreport_post_ureport
0c9110
-struct post_state *post_ureport(const char *json_ureport,
0c9110
-                                struct ureport_server_config *config);
0c9110
-
0c9110
-#define ureport_attach_rhbz libreport_ureport_attach_rhbz
0c9110
-struct post_state *ureport_attach_rhbz(const char *bthash, int rhbz_bug_id,
0c9110
-                                       struct ureport_server_config *config);
0c9110
-
0c9110
-#define ureport_attach_email libreport_ureport_attach_email
0c9110
-struct post_state *ureport_attach_email(const char *bthash, const char *email,
0c9110
-                                        struct ureport_server_config *config);
0c9110
-
0c9110
-#define ureport_from_dump_dir libreport_ureport_from_dump_dir
0c9110
-char *ureport_from_dump_dir(const char *dump_dir_path);
0c9110
-
0c9110
-#define ureport_from_dump_dir_ext libreport_ureport_from_dump_dir_ext
0c9110
-char *ureport_from_dump_dir_ext(const char *dump_dir_path,
0c9110
-                                const struct ureport_preferences *preferences);
0c9110
-
0c9110
-#ifdef __cplusplus
0c9110
-}
0c9110
-#endif
0c9110
-
0c9110
-#endif
0c9110
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
0c9110
index 7ec5219..7ec08d7 100644
0c9110
--- a/src/plugins/Makefile.am
0c9110
+++ b/src/plugins/Makefile.am
0c9110
@@ -250,15 +250,17 @@ endif
0c9110
 
0c9110
 if BUILD_UREPORT
0c9110
 reporter_ureport_SOURCES = \
0c9110
-    ureport.c
0c9110
+    reporter-ureport.c
0c9110
 reporter_ureport_CPPFLAGS = \
0c9110
     -I$(srcdir)/../include \
0c9110
     -I$(srcdir)/../lib \
0c9110
+    $(JSON_C_CFLAGS) \
0c9110
     $(GLIB_CFLAGS) \
0c9110
     $(LIBREPORT_CFLAGS) \
0c9110
     -DPLUGINS_CONF_DIR=\"$(REPORT_PLUGINS_CONF_DIR)\" \
0c9110
     -D_GNU_SOURCE
0c9110
 reporter_ureport_LDADD = \
0c9110
+    $(JSON_C_LIBS) \
0c9110
     ../lib/libreport.la \
0c9110
     ../lib/libreport-web.la
0c9110
 endif
0c9110
diff --git a/src/plugins/reporter-ureport.c b/src/plugins/reporter-ureport.c
0c9110
new file mode 100644
0c9110
index 0000000..d827c7d
0c9110
--- /dev/null
0c9110
+++ b/src/plugins/reporter-ureport.c
0c9110
@@ -0,0 +1,777 @@
0c9110
+/*
0c9110
+    Copyright (C) 2012  ABRT Team
0c9110
+    Copyright (C) 2012  RedHat inc.
0c9110
+
0c9110
+    This program is free software; you can redistribute it and/or modify
0c9110
+    it under the terms of the GNU General Public License as published by
0c9110
+    the Free Software Foundation; either version 2 of the License, or
0c9110
+    (at your option) any later version.
0c9110
+
0c9110
+    This program is distributed in the hope that it will be useful,
0c9110
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
+    GNU General Public License for more details.
0c9110
+
0c9110
+    You should have received a copy of the GNU General Public License along
0c9110
+    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
+*/
0c9110
+
0c9110
+#include <json.h>
0c9110
+#include "internal_libreport.h"
0c9110
+#include "ureport.h"
0c9110
+#include "libreport_curl.h"
0c9110
+
0c9110
+#define CONF_FILE_PATH PLUGINS_CONF_DIR"/ureport.conf"
0c9110
+
0c9110
+#define REPORT_URL_SFX "reports/new/"
0c9110
+#define ATTACH_URL_SFX "reports/attach/"
0c9110
+#define BTHASH_URL_SFX "reports/bthash/"
0c9110
+
0c9110
+#define RHSM_CERT_PATH "/etc/pki/consumer/cert.pem"
0c9110
+#define RHSM_KEY_PATH "/etc/pki/consumer/key.pem"
0c9110
+
0c9110
+#define RHAP_PEM_DIR_PATH "/etc/pki/entitlement"
0c9110
+#define RHAP_ENT_DATA_BEGIN_TAG "-----BEGIN ENTITLEMENT DATA-----"
0c9110
+#define RHAP_ENT_DATA_END_TAG "-----END ENTITLEMENT DATA-----"
0c9110
+#define RHAP_SIG_DATA_BEGIN_TAG "-----BEGIN RSA SIGNATURE-----"
0c9110
+#define RHAP_SIG_DATA_END_TAG "-----END RSA SIGNATURE-----"
0c9110
+
0c9110
+#define VALUE_FROM_CONF(opt, var, tr) do { const char *value = getenv("uReport_"opt); \
0c9110
+        if (!value) { value = get_map_string_item_or_NULL(settings, opt); } if (value) { var = tr(value); } \
0c9110
+    } while(0)
0c9110
+
0c9110
+static char *puppet_config_print(const char *key)
0c9110
+{
0c9110
+    char *command = xasprintf("puppet config print %s", key);
0c9110
+    char *result = run_in_shell_and_save_output(0, command, NULL, NULL);
0c9110
+    free(command);
0c9110
+
0c9110
+    /* run_in_shell_and_save_output always returns non-NULL */
0c9110
+    if (result[0] != '/')
0c9110
+        goto error;
0c9110
+
0c9110
+    char *newline = strchrnul(result, '\n');
0c9110
+    if (!newline)
0c9110
+        goto error;
0c9110
+
0c9110
+    *newline = '\0';
0c9110
+    return result;
0c9110
+error:
0c9110
+    free(result);
0c9110
+    error_msg_and_die("Unable to determine puppet %s path (puppet not installed?)", key);
0c9110
+}
0c9110
+
0c9110
+static void parse_client_auth_paths(struct ureport_server_config *config, const char *client_auth)
0c9110
+{
0c9110
+    if (client_auth == NULL)
0c9110
+        return;
0c9110
+
0c9110
+    if (strcmp(client_auth, "") == 0)
0c9110
+    {
0c9110
+        config->ur_client_cert = NULL;
0c9110
+        config->ur_client_key = NULL;
0c9110
+        log_notice("Not using client authentication");
0c9110
+    }
0c9110
+    else if (strcmp(client_auth, "rhsm") == 0)
0c9110
+    {
0c9110
+        config->ur_client_cert = xstrdup(RHSM_CERT_PATH);
0c9110
+        config->ur_client_key = xstrdup(RHSM_KEY_PATH);
0c9110
+    }
0c9110
+    else if (strcmp(client_auth, "rhsm-entitlement") == 0)
0c9110
+    {
0c9110
+        GList *certs = get_file_list(RHAP_PEM_DIR_PATH, "pem");
0c9110
+        if (g_list_length(certs) != 2)
0c9110
+        {
0c9110
+            log_notice(RHAP_PEM_DIR_PATH" does not contain unique cert-key files pair");
0c9110
+            log_notice("Not using client authentication");
0c9110
+            return;
0c9110
+        }
0c9110
+
0c9110
+        const char *cert = NULL;
0c9110
+        const char *key = NULL;
0c9110
+
0c9110
+        file_obj_t *fst = (file_obj_t *)certs->data;
0c9110
+        file_obj_t *scn = (file_obj_t *)certs->next->data;
0c9110
+
0c9110
+        if (strlen(fo_get_filename(fst)) < strlen(fo_get_filename(scn)))
0c9110
+        {
0c9110
+            cert = fo_get_filename(fst);
0c9110
+            key = fo_get_filename(scn);
0c9110
+
0c9110
+            config->ur_client_cert = xstrdup(fo_get_fullpath(fst));
0c9110
+            config->ur_client_key = xstrdup(fo_get_fullpath(scn));
0c9110
+        }
0c9110
+        else
0c9110
+        {
0c9110
+            cert = fo_get_filename(scn);
0c9110
+            key = fo_get_filename(fst);
0c9110
+
0c9110
+            config->ur_client_cert = xstrdup(fo_get_fullpath(scn));
0c9110
+            config->ur_client_key = xstrdup(fo_get_fullpath(fst));
0c9110
+        }
0c9110
+
0c9110
+        const bool iscomplement = prefixcmp(key, cert) != 0 || strcmp("-key", key + strlen(cert)) != 0;
0c9110
+        g_list_free_full(certs, (GDestroyNotify)free_file_obj);
0c9110
+
0c9110
+        if (iscomplement)
0c9110
+        {
0c9110
+            log_notice("Key file '%s' isn't complement to cert file '%s'",
0c9110
+                    config->ur_client_key, config->ur_client_cert);
0c9110
+            log_notice("Not using client authentication");
0c9110
+
0c9110
+            free(config->ur_client_cert);
0c9110
+            free(config->ur_client_key);
0c9110
+            config->ur_client_cert = NULL;
0c9110
+            config->ur_client_key = NULL;
0c9110
+
0c9110
+            return;
0c9110
+        }
0c9110
+
0c9110
+        char *certdata = xmalloc_open_read_close(config->ur_client_cert, /*no size limit*/NULL);
0c9110
+        if (certdata != NULL)
0c9110
+        {
0c9110
+            char *ent_data = xstrdup_between(certdata,
0c9110
+                    RHAP_ENT_DATA_BEGIN_TAG, RHAP_ENT_DATA_END_TAG);
0c9110
+
0c9110
+            char *sig_data = xstrdup_between(certdata,
0c9110
+                    RHAP_SIG_DATA_BEGIN_TAG, RHAP_SIG_DATA_END_TAG);
0c9110
+
0c9110
+            if (ent_data != NULL && sig_data != NULL)
0c9110
+            {
0c9110
+                ent_data = strremovech(ent_data, '\n');
0c9110
+                insert_map_string(config->ur_http_headers,
0c9110
+                        xstrdup("X-RH-Entitlement-Data"),
0c9110
+                        xasprintf(RHAP_ENT_DATA_BEGIN_TAG"%s"RHAP_ENT_DATA_END_TAG, ent_data));
0c9110
+
0c9110
+                sig_data = strremovech(sig_data, '\n');
0c9110
+                insert_map_string(config->ur_http_headers,
0c9110
+                        xstrdup("X-RH-Entitlement-Sig"),
0c9110
+                        xasprintf(RHAP_SIG_DATA_BEGIN_TAG"%s"RHAP_SIG_DATA_END_TAG, sig_data));
0c9110
+            }
0c9110
+            else
0c9110
+            {
0c9110
+                log_notice("Cert file '%s' doesn't contain Entitlement and RSA Signature sections", config->ur_client_cert);
0c9110
+                log_notice("Not using HTTP authentication headers");
0c9110
+            }
0c9110
+
0c9110
+            free(sig_data);
0c9110
+            free(ent_data);
0c9110
+            free(certdata);
0c9110
+        }
0c9110
+    }
0c9110
+    else if (strcmp(client_auth, "puppet") == 0)
0c9110
+    {
0c9110
+        config->ur_client_cert = puppet_config_print("hostcert");
0c9110
+        config->ur_client_key = puppet_config_print("hostprivkey");
0c9110
+    }
0c9110
+    else
0c9110
+    {
0c9110
+        char *scratch = xstrdup(client_auth);
0c9110
+        config->ur_client_cert = xstrdup(strtok(scratch, ":"));
0c9110
+        config->ur_client_key = xstrdup(strtok(NULL, ":"));
0c9110
+        free(scratch);
0c9110
+        if (config->ur_client_cert == NULL || config->ur_client_key == NULL)
0c9110
+            error_msg_and_die("Invalid client authentication specification");
0c9110
+    }
0c9110
+
0c9110
+    if (config->ur_client_cert && config->ur_client_key)
0c9110
+    {
0c9110
+        log_notice("Using client certificate: %s", config->ur_client_cert);
0c9110
+        log_notice("Using client private key: %s", config->ur_client_key);
0c9110
+    }
0c9110
+}
0c9110
+
0c9110
+/*
0c9110
+ * Loads uReport configuration from various sources.
0c9110
+ *
0c9110
+ * Replaces a value of an already configured option only if the
0c9110
+ * option was found in a configuration source.
0c9110
+ *
0c9110
+ * @param config a server configuration to be populated
0c9110
+ */
0c9110
+static void load_ureport_server_config(struct ureport_server_config *config, map_string_t *settings)
0c9110
+{
0c9110
+    VALUE_FROM_CONF("URL", config->ur_url, (const char *));
0c9110
+    VALUE_FROM_CONF("SSLVerify", config->ur_ssl_verify, string_to_bool);
0c9110
+
0c9110
+    bool include_auth = false;
0c9110
+    VALUE_FROM_CONF("IncludeAuthData", include_auth, string_to_bool);
0c9110
+
0c9110
+    if (include_auth)
0c9110
+    {
0c9110
+        const char *auth_items = NULL;
0c9110
+        VALUE_FROM_CONF("AuthDataItems", auth_items, (const char *));
0c9110
+        config->ur_prefs.urp_auth_items = parse_list(auth_items);
0c9110
+
0c9110
+        if (config->ur_prefs.urp_auth_items == NULL)
0c9110
+            log_warning("IncludeAuthData set to 'yes' but AuthDataItems is empty.");
0c9110
+    }
0c9110
+
0c9110
+    const char *client_auth = NULL;
0c9110
+    VALUE_FROM_CONF("SSLClientAuth", client_auth, (const char *));
0c9110
+    parse_client_auth_paths(config, client_auth);
0c9110
+}
0c9110
+
0c9110
+struct ureport_server_response {
0c9110
+    bool is_error;
0c9110
+    char *value;
0c9110
+    char *message;
0c9110
+    char *bthash;
0c9110
+    GList *reported_to_list;
0c9110
+    char *solution;
0c9110
+};
0c9110
+
0c9110
+void free_ureport_server_response(struct ureport_server_response *resp)
0c9110
+{
0c9110
+    if (!resp)
0c9110
+        return;
0c9110
+
0c9110
+    free(resp->solution);
0c9110
+    g_list_free_full(resp->reported_to_list, g_free);
0c9110
+    free(resp->bthash);
0c9110
+    free(resp->message);
0c9110
+    free(resp->value);
0c9110
+    free(resp);
0c9110
+}
0c9110
+
0c9110
+static char *parse_solution_from_json_list(struct json_object *list, GList **reported_to)
0c9110
+{
0c9110
+    json_object *list_elem, *struct_elem;
0c9110
+    const char *cause, *note, *url;
0c9110
+    struct strbuf *solution_buf = strbuf_new();
0c9110
+
0c9110
+    const unsigned length = json_object_array_length(list);
0c9110
+
0c9110
+    const char *one_format = _("Your problem seems to be caused by %s\n\n%s\n");
0c9110
+    if (length > 1)
0c9110
+    {
0c9110
+        strbuf_append_str(solution_buf, _("Your problem seems to be caused by one of the following:\n"));
0c9110
+        one_format = "\n* %s\n\n%s\n";
0c9110
+    }
0c9110
+
0c9110
+    bool empty = true;
0c9110
+    for (unsigned i = 0; i < length; ++i)
0c9110
+    {
0c9110
+        list_elem = json_object_array_get_idx(list, i);
0c9110
+        if (!list_elem)
0c9110
+            continue;
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "cause", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        cause = json_object_get_string(struct_elem);
0c9110
+            continue;
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "note", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        note = json_object_get_string(struct_elem);
0c9110
+        if (!note)
0c9110
+            continue;
0c9110
+
0c9110
+        empty = false;
0c9110
+        strbuf_append_strf(solution_buf, one_format, cause, note);
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "url", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        url = json_object_get_string(struct_elem);
0c9110
+        if (url)
0c9110
+        {
0c9110
+            char *reported_to_line = xasprintf("%s: URL=%s", cause, url);
0c9110
+            *reported_to = g_list_append(*reported_to, reported_to_line);
0c9110
+        }
0c9110
+    }
0c9110
+
0c9110
+    if (empty)
0c9110
+    {
0c9110
+        strbuf_free(solution_buf);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    return strbuf_free_nobuf(solution_buf);
0c9110
+}
0c9110
+
0c9110
+/* reported_to json element should be a list of structures
0c9110
+{ "reporter": "Bugzilla",
0c9110
+  "type": "url",
0c9110
+  "value": "https://bugzilla.redhat.com/show_bug.cgi?id=XYZ" } */
0c9110
+static GList *parse_reported_to_from_json_list(struct json_object *list)
0c9110
+{
0c9110
+    int i;
0c9110
+    json_object *list_elem, *struct_elem;
0c9110
+    const char *reporter, *value, *type;
0c9110
+    char *reported_to_line, *prefix;
0c9110
+    GList *result = NULL;
0c9110
+
0c9110
+    for (i = 0; i < json_object_array_length(list); ++i)
0c9110
+    {
0c9110
+        prefix = NULL;
0c9110
+        list_elem = json_object_array_get_idx(list, i);
0c9110
+        if (!list_elem)
0c9110
+            continue;
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "reporter", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        reporter = json_object_get_string(struct_elem);
0c9110
+        if (!reporter)
0c9110
+            continue;
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "value", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        value = json_object_get_string(struct_elem);
0c9110
+        if (!value)
0c9110
+            continue;
0c9110
+
0c9110
+        if (!json_object_object_get_ex(list_elem, "type", &struct_elem))
0c9110
+            continue;
0c9110
+
0c9110
+        type = json_object_get_string(struct_elem);
0c9110
+        if (type)
0c9110
+        {
0c9110
+            if (strcasecmp("url", type) == 0)
0c9110
+                prefix = xstrdup("URL=");
0c9110
+            else if (strcasecmp("bthash", type) == 0)
0c9110
+                prefix = xstrdup("BTHASH=");
0c9110
+        }
0c9110
+
0c9110
+        if (!prefix)
0c9110
+            prefix = xstrdup("");
0c9110
+
0c9110
+        reported_to_line = xasprintf("%s: %s%s", reporter, prefix, value);
0c9110
+        free(prefix);
0c9110
+
0c9110
+        result = g_list_append(result, reported_to_line);
0c9110
+    }
0c9110
+
0c9110
+    return result;
0c9110
+}
0c9110
+
0c9110
+/*
0c9110
+ * Reponse samples:
0c9110
+ * {"error":"field 'foo' is required"}
0c9110
+ * {"response":"true"}
0c9110
+ * {"response":"false"}
0c9110
+ */
0c9110
+static struct ureport_server_response *ureport_server_parse_json(json_object *json)
0c9110
+{
0c9110
+    json_object *obj = NULL;
0c9110
+    if (json_object_object_get_ex(json, "error", &obj))
0c9110
+    {
0c9110
+        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
0c9110
+        out_response->is_error = true;
0c9110
+        /*
0c9110
+         * Used to use json_object_to_json_string(obj), but it returns
0c9110
+         * the string in quote marks (") - IOW, json-formatted string.
0c9110
+         */
0c9110
+        out_response->value = xstrdup(json_object_get_string(obj));
0c9110
+        return out_response;
0c9110
+    }
0c9110
+
0c9110
+    if (json_object_object_get_ex(json, "result", &obj))
0c9110
+    {
0c9110
+        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
0c9110
+        out_response->value = xstrdup(json_object_get_string(obj));
0c9110
+
0c9110
+        json_object *message = NULL;
0c9110
+        if (json_object_object_get_ex(json, "message", &message))
0c9110
+            out_response->message = xstrdup(json_object_get_string(message));
0c9110
+
0c9110
+        json_object *bthash = NULL;
0c9110
+        if (json_object_object_get_ex(json, "bthash", &bthash))
0c9110
+            out_response->bthash = xstrdup(json_object_get_string(bthash));
0c9110
+
0c9110
+        json_object *reported_to_list = NULL;
0c9110
+        if (json_object_object_get_ex(json, "reported_to", &reported_to_list))
0c9110
+            out_response->reported_to_list = parse_reported_to_from_json_list(reported_to_list);
0c9110
+
0c9110
+        json_object *solutions = NULL;
0c9110
+        if (json_object_object_get_ex(json, "solutions", &solutions))
0c9110
+            out_response->solution = parse_solution_from_json_list(solutions, &(out_response->reported_to_list));
0c9110
+
0c9110
+        return out_response;
0c9110
+    }
0c9110
+
0c9110
+    return NULL;
0c9110
+}
0c9110
+
0c9110
+static struct ureport_server_response *get_server_response(post_state_t *post_state, struct ureport_server_config *config)
0c9110
+{
0c9110
+    /* Previously, the condition here was (post_state->errmsg[0] != '\0')
0c9110
+     * however when the server asks for optional client authentication and we do not have the certificates,
0c9110
+     * then post_state->errmsg contains "NSS: client certificate not found (nickname not specified)" even though
0c9110
+     * the request succeeded.
0c9110
+     */
0c9110
+    if (post_state->curl_result != CURLE_OK)
0c9110
+    {
0c9110
+        error_msg(_("Failed to upload uReport to the server '%s' with curl: %s"), config->ur_url, post_state->errmsg);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    if (post_state->http_resp_code == 404)
0c9110
+    {
0c9110
+        error_msg(_("The URL '%s' does not exist (got error 404 from server)"), config->ur_url);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    if (post_state->http_resp_code == 500)
0c9110
+    {
0c9110
+        error_msg(_("The server at '%s' encountered an internal error (got error 500)"), config->ur_url);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    if (post_state->http_resp_code == 503)
0c9110
+    {
0c9110
+        error_msg(_("The server at '%s' currently can't handle the request (got error 503)"), config->ur_url);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    if (post_state->http_resp_code != 202
0c9110
+            && post_state->http_resp_code != 400
0c9110
+            && post_state->http_resp_code != 413)
0c9110
+    {
0c9110
+        /* can't print better error message */
0c9110
+        error_msg(_("Unexpected HTTP response from '%s': %d"), config->ur_url, post_state->http_resp_code);
0c9110
+        log_notice("%s", post_state->body);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    json_object *const json = json_tokener_parse(post_state->body);
0c9110
+
0c9110
+    if (is_error(json))
0c9110
+    {
0c9110
+        error_msg(_("Unable to parse response from ureport server at '%s'"), config->ur_url);
0c9110
+        log_notice("%s", post_state->body);
0c9110
+        json_object_put(json);
0c9110
+        return NULL;
0c9110
+    }
0c9110
+
0c9110
+    struct ureport_server_response *response = ureport_server_parse_json(json);
0c9110
+    json_object_put(json);
0c9110
+
0c9110
+    if (!response)
0c9110
+        error_msg(_("The response from '%s' has invalid format"), config->ur_url);
0c9110
+    else if ((post_state->http_resp_code == 202 && response->is_error)
0c9110
+                || (post_state->http_resp_code != 202 && !response->is_error))
0c9110
+    {
0c9110
+        /* HTTP CODE 202 means that call was successful but the response */
0c9110
+        /* has an error message */
0c9110
+        error_msg(_("Type mismatch has been detected in the response from '%s'"), config->ur_url);
0c9110
+    }
0c9110
+
0c9110
+    return response;
0c9110
+}
0c9110
+
0c9110
+typedef post_state_t *(*attach_handler)(const char *, void *, struct ureport_server_config *);
0c9110
+
0c9110
+static post_state_t *wrp_ureport_attach_rhbz(const char *ureport_hash, int *rhbz_bug,
0c9110
+        struct ureport_server_config *config)
0c9110
+{
0c9110
+    return ureport_attach_rhbz(ureport_hash, *rhbz_bug, config);
0c9110
+}
0c9110
+
0c9110
+static bool perform_attach(struct ureport_server_config *config, const char *ureport_hash,
0c9110
+        attach_handler handler, void *args)
0c9110
+{
0c9110
+    char *dest_url = concat_path_file(config->ur_url, ATTACH_URL_SFX);
0c9110
+    const char *old_url = config->ur_url;
0c9110
+    config->ur_url = dest_url;
0c9110
+    post_state_t *post_state = handler(ureport_hash, args, config);
0c9110
+    config->ur_url = old_url;
0c9110
+    free(dest_url);
0c9110
+
0c9110
+    struct ureport_server_response *resp = get_server_response(post_state, config);
0c9110
+    free_post_state(post_state);
0c9110
+    /* don't use str_bo_bool() because we require "true" string */
0c9110
+    const int result = !resp || resp->is_error || strcmp(resp->value,"true") != 0;
0c9110
+
0c9110
+    if (resp && resp->is_error)
0c9110
+    {
0c9110
+        error_msg(_("The server at '%s' responded with an error: '%s'"), config->ur_url, resp->value);
0c9110
+    }
0c9110
+
0c9110
+    free_ureport_server_response(resp);
0c9110
+
0c9110
+    return result;
0c9110
+}
0c9110
+
0c9110
+int main(int argc, char **argv)
0c9110
+{
0c9110
+    setlocale(LC_ALL, "");
0c9110
+#if ENABLE_NLS
0c9110
+    bindtextdomain(PACKAGE, LOCALEDIR);
0c9110
+    textdomain(PACKAGE);
0c9110
+#endif
0c9110
+
0c9110
+    abrt_init(argv);
0c9110
+
0c9110
+    struct ureport_server_config config = {
0c9110
+        .ur_url = NULL,
0c9110
+        .ur_ssl_verify = true,
0c9110
+        .ur_client_cert = NULL,
0c9110
+        .ur_client_key = NULL,
0c9110
+        .ur_http_headers = NULL,
0c9110
+        {
0c9110
+            .urp_auth_items = NULL,
0c9110
+        },
0c9110
+    };
0c9110
+
0c9110
+    config.ur_http_headers = new_map_string();
0c9110
+
0c9110
+    enum {
0c9110
+        OPT_v = 1 << 0,
0c9110
+        OPT_d = 1 << 1,
0c9110
+        OPT_u = 1 << 2,
0c9110
+        OPT_k = 1 << 3,
0c9110
+        OPT_t = 1 << 4,
0c9110
+        OPT_i = 1 << 5,
0c9110
+    };
0c9110
+
0c9110
+    int ret = 1; /* "failure" (for now) */
0c9110
+    bool insecure = !config.ur_ssl_verify;
0c9110
+    const char *conf_file = CONF_FILE_PATH;
0c9110
+    const char *arg_server_url = NULL;
0c9110
+    const char *client_auth = NULL;
0c9110
+    GList *auth_items = NULL;
0c9110
+    const char *dump_dir_path = ".";
0c9110
+    const char *ureport_hash = NULL;
0c9110
+    bool ureport_hash_from_rt = false;
0c9110
+    int rhbz_bug = -1;
0c9110
+    bool rhbz_bug_from_rt = false;
0c9110
+    const char *email_address = NULL;
0c9110
+    bool email_address_from_env = false;
0c9110
+    struct dump_dir *dd = NULL;
0c9110
+    struct options program_options[] = {
0c9110
+        OPT__VERBOSE(&g_verbose),
0c9110
+        OPT__DUMP_DIR(&dump_dir_path),
0c9110
+        OPT_STRING('u', "url", &arg_server_url, "URL", _("Specify server URL")),
0c9110
+        OPT_BOOL('k', "insecure", &insecure,
0c9110
+                          _("Allow insecure connection to ureport server")),
0c9110
+        OPT_STRING('t', "auth", &client_auth, "SOURCE", _("Use client authentication")),
0c9110
+        OPT_LIST('i', "auth_items", &auth_items, "AUTH_ITEMS", _("Additional files included in 'auth' key")),
0c9110
+        OPT_STRING('c', NULL, &conf_file, "FILE", _("Configuration file")),
0c9110
+        OPT_STRING('a', "attach", &ureport_hash, "BTHASH",
0c9110
+                          _("bthash of uReport to attach (conflicts with -A)")),
0c9110
+        OPT_BOOL('A', "attach-rt", &ureport_hash_from_rt,
0c9110
+                          _("attach to a bthash from reported_to (conflicts with -a)")),
0c9110
+        OPT_STRING('e', "email", &email_address, "EMAIL",
0c9110
+                          _("contact e-mail address (requires -a|-A, conflicts with -E)")),
0c9110
+        OPT_BOOL('E', "email-env", &email_address_from_env,
0c9110
+                          _("contact e-mail address from environment or configuration file (requires -a|-A, conflicts with -e)")),
0c9110
+        OPT_INTEGER('b', "bug-id", &rhbz_bug,
0c9110
+                          _("attach RHBZ bug (requires -a|-A, conflicts with -B)")),
0c9110
+        OPT_BOOL('B', "bug-id-rt", &rhbz_bug_from_rt,
0c9110
+                          _("attach last RHBZ bug from reported_to (requires -a|-A, conflicts with -b)")),
0c9110
+        OPT_END(),
0c9110
+    };
0c9110
+
0c9110
+    const char *program_usage_string = _(
0c9110
+        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
+        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-i AUTH_ITEMS]\\\n"
0c9110
+        "  [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
+        "\n"
0c9110
+        "Upload micro report or add an attachment to a micro report\n"
0c9110
+        "\n"
0c9110
+        "Reads the default configuration from "CONF_FILE_PATH
0c9110
+    );
0c9110
+
0c9110
+    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
0c9110
+
0c9110
+    map_string_t *settings = new_map_string();
0c9110
+    load_conf_file(conf_file, settings, /*skip key w/o values:*/ false);
0c9110
+
0c9110
+    load_ureport_server_config(&config, settings);
0c9110
+
0c9110
+    if (opts & OPT_u)
0c9110
+        config.ur_url = arg_server_url;
0c9110
+    if (opts & OPT_k)
0c9110
+        config.ur_ssl_verify = !insecure;
0c9110
+    if (opts & OPT_t)
0c9110
+        parse_client_auth_paths(&config, client_auth);
0c9110
+    if (opts & OPT_i)
0c9110
+    {
0c9110
+        g_list_free_full(config.ur_prefs.urp_auth_items, free);
0c9110
+        config.ur_prefs.urp_auth_items = auth_items;
0c9110
+    }
0c9110
+
0c9110
+    if (!config.ur_url)
0c9110
+        error_msg_and_die("You need to specify server URL");
0c9110
+
0c9110
+    post_state_t *post_state = NULL;
0c9110
+
0c9110
+    if (ureport_hash && ureport_hash_from_rt)
0c9110
+        error_msg_and_die("You need to pass either -a bthash or -A");
0c9110
+
0c9110
+    if (rhbz_bug >= 0 && rhbz_bug_from_rt)
0c9110
+        error_msg_and_die("You need to pass either -b bug-id or -B");
0c9110
+
0c9110
+    if (email_address && email_address_from_env)
0c9110
+        error_msg_and_die("You need to pass either -e bthash or -E");
0c9110
+
0c9110
+    if (ureport_hash_from_rt || rhbz_bug_from_rt)
0c9110
+    {
0c9110
+        dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
0c9110
+        if (!dd)
0c9110
+            xfunc_die();
0c9110
+
0c9110
+        if (ureport_hash_from_rt)
0c9110
+        {
0c9110
+            report_result_t *ureport_result = find_in_reported_to(dd, "uReport");
0c9110
+
0c9110
+            if (!ureport_result || !ureport_result->bthash)
0c9110
+                error_msg_and_die(_("This problem does not have an uReport assigned."));
0c9110
+
0c9110
+            /* sorry, this will be leaked */
0c9110
+            ureport_hash = xstrdup(ureport_result->bthash);
0c9110
+
0c9110
+            free_report_result(ureport_result);
0c9110
+        }
0c9110
+
0c9110
+        if (rhbz_bug_from_rt)
0c9110
+        {
0c9110
+            report_result_t *bz_result = find_in_reported_to(dd, "Bugzilla");
0c9110
+
0c9110
+            if (!bz_result || !bz_result->url)
0c9110
+                error_msg_and_die(_("This problem has not been reported to Bugzilla."));
0c9110
+
0c9110
+            char *bugid_ptr = strstr(bz_result->url, "show_bug.cgi?id=");
0c9110
+            if (!bugid_ptr)
0c9110
+                error_msg_and_die(_("Unable to find bug ID in bugzilla URL '%s'"), bz_result->url);
0c9110
+            bugid_ptr += strlen("show_bug.cgi?id=");
0c9110
+
0c9110
+            /* we're just reading int, sscanf works fine */
0c9110
+            if (sscanf(bugid_ptr, "%d", &rhbz_bug) != 1)
0c9110
+                error_msg_and_die(_("Unable to parse bug ID from bugzilla URL '%s'"), bz_result->url);
0c9110
+
0c9110
+            free_report_result(bz_result);
0c9110
+        }
0c9110
+
0c9110
+        dd_close(dd);
0c9110
+    }
0c9110
+
0c9110
+    if (email_address_from_env)
0c9110
+    {
0c9110
+        VALUE_FROM_CONF("ContactEmail", email_address, (const char *));
0c9110
+
0c9110
+        if (!email_address)
0c9110
+            error_msg_and_die(_("Neither environment variable 'uReport_ContactEmail' nor configuration option 'ContactEmail' is set"));
0c9110
+    }
0c9110
+
0c9110
+    if (ureport_hash)
0c9110
+    {
0c9110
+        if (rhbz_bug < 0 && !email_address)
0c9110
+            error_msg_and_die(_("You need to specify bug ID, contact email or both"));
0c9110
+
0c9110
+        if (rhbz_bug >= 0)
0c9110
+        {
0c9110
+            if (perform_attach(&config, ureport_hash, (attach_handler)wrp_ureport_attach_rhbz, (void *)&rhbz_bug))
0c9110
+                goto finalize;
0c9110
+        }
0c9110
+
0c9110
+        if (email_address)
0c9110
+        {
0c9110
+            if (perform_attach(&config, ureport_hash, (attach_handler)ureport_attach_email, (void *)email_address))
0c9110
+                goto finalize;
0c9110
+        }
0c9110
+
0c9110
+        ret = 0;
0c9110
+        goto finalize;
0c9110
+    }
0c9110
+    if (!ureport_hash && (rhbz_bug >= 0 || email_address))
0c9110
+        error_msg_and_die(_("You need to specify bthash of the uReport to attach."));
0c9110
+
0c9110
+    /* -b, -a nor -r were specified - upload uReport from dump_dir */
0c9110
+    const char *server_url = config.ur_url;
0c9110
+    char *dest_url = concat_path_file(config.ur_url, REPORT_URL_SFX);
0c9110
+    config.ur_url = dest_url;
0c9110
+
0c9110
+    char *json_ureport = ureport_from_dump_dir_ext(dump_dir_path, &(config.ur_prefs));
0c9110
+    if (!json_ureport)
0c9110
+    {
0c9110
+        error_msg(_("Not uploading an empty uReport"));
0c9110
+        goto format_err;
0c9110
+    }
0c9110
+
0c9110
+    post_state = ureport_post(json_ureport, &config);
0c9110
+    free(json_ureport);
0c9110
+
0c9110
+    if (!post_state)
0c9110
+    {
0c9110
+        error_msg(_("Failed on submitting the problem"));
0c9110
+        goto format_err;
0c9110
+    }
0c9110
+
0c9110
+    struct ureport_server_response *response = get_server_response(post_state, &config);
0c9110
+
0c9110
+    if (!response)
0c9110
+        goto format_err;
0c9110
+
0c9110
+    if (!response->is_error)
0c9110
+    {
0c9110
+        log_notice("is known: %s", response->value);
0c9110
+        ret = 0; /* "success" */
0c9110
+
0c9110
+        dd = dd_opendir(dump_dir_path, /* flags */ 0);
0c9110
+        if (!dd)
0c9110
+            xfunc_die();
0c9110
+
0c9110
+        if (response->bthash)
0c9110
+        {
0c9110
+            char *msg = xasprintf("uReport: BTHASH=%s", response->bthash);
0c9110
+            add_reported_to(dd, msg);
0c9110
+            free(msg);
0c9110
+
0c9110
+            char *bthash_url = concat_path_file(server_url, BTHASH_URL_SFX);
0c9110
+            msg = xasprintf("ABRT Server: URL=%s%s", bthash_url, response->bthash);
0c9110
+            add_reported_to(dd, msg);
0c9110
+            free(msg);
0c9110
+            free(bthash_url);
0c9110
+        }
0c9110
+
0c9110
+        if (response->reported_to_list)
0c9110
+        {
0c9110
+            for (GList *e = response->reported_to_list; e; e = g_list_next(e))
0c9110
+                add_reported_to(dd, e->data);
0c9110
+        }
0c9110
+
0c9110
+        if (response->solution)
0c9110
+            dd_save_text(dd, FILENAME_NOT_REPORTABLE, response->solution);
0c9110
+
0c9110
+        dd_close(dd);
0c9110
+
0c9110
+        /* If a reported problem is not known then emit NEEDMORE */
0c9110
+        if (strcmp("true", response->value) == 0)
0c9110
+        {
0c9110
+            log(_("This problem has already been reported."));
0c9110
+            if (response->message)
0c9110
+                log(response->message);
0c9110
+
0c9110
+            ret = EXIT_STOP_EVENT_RUN;
0c9110
+        }
0c9110
+    }
0c9110
+    else
0c9110
+    {
0c9110
+        error_msg(_("Server responded with an error: '%s'"), response->value);
0c9110
+    }
0c9110
+
0c9110
+    free_ureport_server_response(response);
0c9110
+
0c9110
+format_err:
0c9110
+    free_post_state(post_state);
0c9110
+    free(dest_url);
0c9110
+
0c9110
+finalize:
0c9110
+    if (config.ur_prefs.urp_auth_items != auth_items)
0c9110
+        g_list_free_full(config.ur_prefs.urp_auth_items, free);
0c9110
+
0c9110
+    free_map_string(config.ur_http_headers);
0c9110
+
0c9110
+    free_map_string(settings);
0c9110
+    free(config.ur_client_cert);
0c9110
+    free(config.ur_client_key);
0c9110
+
0c9110
+    return ret;
0c9110
+}
0c9110
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
0c9110
deleted file mode 100644
0c9110
index 9c69cad..0000000
0c9110
--- a/src/plugins/ureport.c
0c9110
+++ /dev/null
0c9110
@@ -1,777 +0,0 @@
0c9110
-/*
0c9110
-    Copyright (C) 2012  ABRT Team
0c9110
-    Copyright (C) 2012  RedHat inc.
0c9110
-
0c9110
-    This program is free software; you can redistribute it and/or modify
0c9110
-    it under the terms of the GNU General Public License as published by
0c9110
-    the Free Software Foundation; either version 2 of the License, or
0c9110
-    (at your option) any later version.
0c9110
-
0c9110
-    This program is distributed in the hope that it will be useful,
0c9110
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
0c9110
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0c9110
-    GNU General Public License for more details.
0c9110
-
0c9110
-    You should have received a copy of the GNU General Public License along
0c9110
-    with this program; if not, write to the Free Software Foundation, Inc.,
0c9110
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
0c9110
-*/
0c9110
-
0c9110
-#include <json/json.h>
0c9110
-#include "internal_libreport.h"
0c9110
-#include "ureport.h"
0c9110
-#include "libreport_curl.h"
0c9110
-
0c9110
-#define CONF_FILE_PATH PLUGINS_CONF_DIR"/ureport.conf"
0c9110
-
0c9110
-#define REPORT_URL_SFX "reports/new/"
0c9110
-#define ATTACH_URL_SFX "reports/attach/"
0c9110
-#define BTHASH_URL_SFX "reports/bthash/"
0c9110
-
0c9110
-#define RHSM_CERT_PATH "/etc/pki/consumer/cert.pem"
0c9110
-#define RHSM_KEY_PATH "/etc/pki/consumer/key.pem"
0c9110
-
0c9110
-#define RHAP_PEM_DIR_PATH "/etc/pki/entitlement"
0c9110
-#define RHAP_ENT_DATA_BEGIN_TAG "-----BEGIN ENTITLEMENT DATA-----"
0c9110
-#define RHAP_ENT_DATA_END_TAG "-----END ENTITLEMENT DATA-----"
0c9110
-#define RHAP_SIG_DATA_BEGIN_TAG "-----BEGIN RSA SIGNATURE-----"
0c9110
-#define RHAP_SIG_DATA_END_TAG "-----END RSA SIGNATURE-----"
0c9110
-
0c9110
-#define VALUE_FROM_CONF(opt, var, tr) do { const char *value = getenv("uReport_"opt); \
0c9110
-        if (!value) { value = get_map_string_item_or_NULL(settings, opt); } if (value) { var = tr(value); } \
0c9110
-    } while(0)
0c9110
-
0c9110
-static char *puppet_config_print(const char *key)
0c9110
-{
0c9110
-    char *command = xasprintf("puppet config print %s", key);
0c9110
-    char *result = run_in_shell_and_save_output(0, command, NULL, NULL);
0c9110
-    free(command);
0c9110
-
0c9110
-    /* run_in_shell_and_save_output always returns non-NULL */
0c9110
-    if (result[0] != '/')
0c9110
-        goto error;
0c9110
-
0c9110
-    char *newline = strchrnul(result, '\n');
0c9110
-    if (!newline)
0c9110
-        goto error;
0c9110
-
0c9110
-    *newline = '\0';
0c9110
-    return result;
0c9110
-error:
0c9110
-    free(result);
0c9110
-    error_msg_and_die("Unable to determine puppet %s path (puppet not installed?)", key);
0c9110
-}
0c9110
-
0c9110
-static void parse_client_auth_paths(struct ureport_server_config *config, const char *client_auth)
0c9110
-{
0c9110
-    if (client_auth == NULL)
0c9110
-        return;
0c9110
-
0c9110
-    if (strcmp(client_auth, "") == 0)
0c9110
-    {
0c9110
-        config->ur_client_cert = NULL;
0c9110
-        config->ur_client_key = NULL;
0c9110
-        log_notice("Not using client authentication");
0c9110
-    }
0c9110
-    else if (strcmp(client_auth, "rhsm") == 0)
0c9110
-    {
0c9110
-        config->ur_client_cert = xstrdup(RHSM_CERT_PATH);
0c9110
-        config->ur_client_key = xstrdup(RHSM_KEY_PATH);
0c9110
-    }
0c9110
-    else if (strcmp(client_auth, "rhsm-entitlement") == 0)
0c9110
-    {
0c9110
-        GList *certs = get_file_list(RHAP_PEM_DIR_PATH, "pem");
0c9110
-        if (g_list_length(certs) != 2)
0c9110
-        {
0c9110
-            log_notice(RHAP_PEM_DIR_PATH" does not contain unique cert-key files pair");
0c9110
-            log_notice("Not using client authentication");
0c9110
-            return;
0c9110
-        }
0c9110
-
0c9110
-        const char *cert = NULL;
0c9110
-        const char *key = NULL;
0c9110
-
0c9110
-        file_obj_t *fst = (file_obj_t *)certs->data;
0c9110
-        file_obj_t *scn = (file_obj_t *)certs->next->data;
0c9110
-
0c9110
-        if (strlen(fo_get_filename(fst)) < strlen(fo_get_filename(scn)))
0c9110
-        {
0c9110
-            cert = fo_get_filename(fst);
0c9110
-            key = fo_get_filename(scn);
0c9110
-
0c9110
-            config->ur_client_cert = xstrdup(fo_get_fullpath(fst));
0c9110
-            config->ur_client_key = xstrdup(fo_get_fullpath(scn));
0c9110
-        }
0c9110
-        else
0c9110
-        {
0c9110
-            cert = fo_get_filename(scn);
0c9110
-            key = fo_get_filename(fst);
0c9110
-
0c9110
-            config->ur_client_cert = xstrdup(fo_get_fullpath(scn));
0c9110
-            config->ur_client_key = xstrdup(fo_get_fullpath(fst));
0c9110
-        }
0c9110
-
0c9110
-        const bool iscomplement = prefixcmp(key, cert) != 0 || strcmp("-key", key + strlen(cert)) != 0;
0c9110
-        g_list_free_full(certs, (GDestroyNotify)free_file_obj);
0c9110
-
0c9110
-        if (iscomplement)
0c9110
-        {
0c9110
-            log_notice("Key file '%s' isn't complement to cert file '%s'",
0c9110
-                    config->ur_client_key, config->ur_client_cert);
0c9110
-            log_notice("Not using client authentication");
0c9110
-
0c9110
-            free(config->ur_client_cert);
0c9110
-            free(config->ur_client_key);
0c9110
-            config->ur_client_cert = NULL;
0c9110
-            config->ur_client_key = NULL;
0c9110
-
0c9110
-            return;
0c9110
-        }
0c9110
-
0c9110
-        char *certdata = xmalloc_open_read_close(config->ur_client_cert, /*no size limit*/NULL);
0c9110
-        if (certdata != NULL)
0c9110
-        {
0c9110
-            char *ent_data = xstrdup_between(certdata,
0c9110
-                    RHAP_ENT_DATA_BEGIN_TAG, RHAP_ENT_DATA_END_TAG);
0c9110
-
0c9110
-            char *sig_data = xstrdup_between(certdata,
0c9110
-                    RHAP_SIG_DATA_BEGIN_TAG, RHAP_SIG_DATA_END_TAG);
0c9110
-
0c9110
-            if (ent_data != NULL && sig_data != NULL)
0c9110
-            {
0c9110
-                ent_data = strremovech(ent_data, '\n');
0c9110
-                insert_map_string(config->ur_http_headers,
0c9110
-                        xstrdup("X-RH-Entitlement-Data"),
0c9110
-                        xasprintf(RHAP_ENT_DATA_BEGIN_TAG"%s"RHAP_ENT_DATA_END_TAG, ent_data));
0c9110
-
0c9110
-                sig_data = strremovech(sig_data, '\n');
0c9110
-                insert_map_string(config->ur_http_headers,
0c9110
-                        xstrdup("X-RH-Entitlement-Sig"),
0c9110
-                        xasprintf(RHAP_SIG_DATA_BEGIN_TAG"%s"RHAP_SIG_DATA_END_TAG, sig_data));
0c9110
-            }
0c9110
-            else
0c9110
-            {
0c9110
-                log_notice("Cert file '%s' doesn't contain Entitlement and RSA Signature sections", config->ur_client_cert);
0c9110
-                log_notice("Not using HTTP authentication headers");
0c9110
-            }
0c9110
-
0c9110
-            free(sig_data);
0c9110
-            free(ent_data);
0c9110
-            free(certdata);
0c9110
-        }
0c9110
-    }
0c9110
-    else if (strcmp(client_auth, "puppet") == 0)
0c9110
-    {
0c9110
-        config->ur_client_cert = puppet_config_print("hostcert");
0c9110
-        config->ur_client_key = puppet_config_print("hostprivkey");
0c9110
-    }
0c9110
-    else
0c9110
-    {
0c9110
-        char *scratch = xstrdup(client_auth);
0c9110
-        config->ur_client_cert = xstrdup(strtok(scratch, ":"));
0c9110
-        config->ur_client_key = xstrdup(strtok(NULL, ":"));
0c9110
-        free(scratch);
0c9110
-        if (config->ur_client_cert == NULL || config->ur_client_key == NULL)
0c9110
-            error_msg_and_die("Invalid client authentication specification");
0c9110
-    }
0c9110
-
0c9110
-    if (config->ur_client_cert && config->ur_client_key)
0c9110
-    {
0c9110
-        log_notice("Using client certificate: %s", config->ur_client_cert);
0c9110
-        log_notice("Using client private key: %s", config->ur_client_key);
0c9110
-    }
0c9110
-}
0c9110
-
0c9110
-/*
0c9110
- * Loads uReport configuration from various sources.
0c9110
- *
0c9110
- * Replaces a value of an already configured option only if the
0c9110
- * option was found in a configuration source.
0c9110
- *
0c9110
- * @param config a server configuration to be populated
0c9110
- */
0c9110
-static void load_ureport_server_config(struct ureport_server_config *config, map_string_t *settings)
0c9110
-{
0c9110
-    VALUE_FROM_CONF("URL", config->ur_url, (const char *));
0c9110
-    VALUE_FROM_CONF("SSLVerify", config->ur_ssl_verify, string_to_bool);
0c9110
-
0c9110
-    bool include_auth = false;
0c9110
-    VALUE_FROM_CONF("IncludeAuthData", include_auth, string_to_bool);
0c9110
-
0c9110
-    if (include_auth)
0c9110
-    {
0c9110
-        const char *auth_items = NULL;
0c9110
-        VALUE_FROM_CONF("AuthDataItems", auth_items, (const char *));
0c9110
-        config->ur_prefs.urp_auth_items = parse_list(auth_items);
0c9110
-
0c9110
-        if (config->ur_prefs.urp_auth_items == NULL)
0c9110
-            log_warning("IncludeAuthData set to 'yes' but AuthDataItems is empty.");
0c9110
-    }
0c9110
-
0c9110
-    const char *client_auth = NULL;
0c9110
-    VALUE_FROM_CONF("SSLClientAuth", client_auth, (const char *));
0c9110
-    parse_client_auth_paths(config, client_auth);
0c9110
-}
0c9110
-
0c9110
-struct ureport_server_response {
0c9110
-    bool is_error;
0c9110
-    char *value;
0c9110
-    char *message;
0c9110
-    char *bthash;
0c9110
-    GList *reported_to_list;
0c9110
-    char *solution;
0c9110
-};
0c9110
-
0c9110
-void free_ureport_server_response(struct ureport_server_response *resp)
0c9110
-{
0c9110
-    if (!resp)
0c9110
-        return;
0c9110
-
0c9110
-    free(resp->solution);
0c9110
-    g_list_free_full(resp->reported_to_list, g_free);
0c9110
-    free(resp->bthash);
0c9110
-    free(resp->message);
0c9110
-    free(resp->value);
0c9110
-    free(resp);
0c9110
-}
0c9110
-
0c9110
-static char *parse_solution_from_json_list(struct json_object *list, GList **reported_to)
0c9110
-{
0c9110
-    json_object *list_elem, *struct_elem;
0c9110
-    const char *cause, *note, *url;
0c9110
-    struct strbuf *solution_buf = strbuf_new();
0c9110
-
0c9110
-    const unsigned length = json_object_array_length(list);
0c9110
-
0c9110
-    const char *one_format = _("Your problem seems to be caused by %s\n\n%s\n");
0c9110
-    if (length > 1)
0c9110
-    {
0c9110
-        strbuf_append_str(solution_buf, _("Your problem seems to be caused by one of the following:\n"));
0c9110
-        one_format = "\n* %s\n\n%s\n";
0c9110
-    }
0c9110
-
0c9110
-    bool empty = true;
0c9110
-    for (unsigned i = 0; i < length; ++i)
0c9110
-    {
0c9110
-        list_elem = json_object_array_get_idx(list, i);
0c9110
-        if (!list_elem)
0c9110
-            continue;
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "cause", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        cause = json_object_get_string(struct_elem);
0c9110
-            continue;
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "note", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        note = json_object_get_string(struct_elem);
0c9110
-        if (!note)
0c9110
-            continue;
0c9110
-
0c9110
-        empty = false;
0c9110
-        strbuf_append_strf(solution_buf, one_format, cause, note);
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "url", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        url = json_object_get_string(struct_elem);
0c9110
-        if (url)
0c9110
-        {
0c9110
-            char *reported_to_line = xasprintf("%s: URL=%s", cause, url);
0c9110
-            *reported_to = g_list_append(*reported_to, reported_to_line);
0c9110
-        }
0c9110
-    }
0c9110
-
0c9110
-    if (empty)
0c9110
-    {
0c9110
-        strbuf_free(solution_buf);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    return strbuf_free_nobuf(solution_buf);
0c9110
-}
0c9110
-
0c9110
-/* reported_to json element should be a list of structures
0c9110
-{ "reporter": "Bugzilla",
0c9110
-  "type": "url",
0c9110
-  "value": "https://bugzilla.redhat.com/show_bug.cgi?id=XYZ" } */
0c9110
-static GList *parse_reported_to_from_json_list(struct json_object *list)
0c9110
-{
0c9110
-    int i;
0c9110
-    json_object *list_elem, *struct_elem;
0c9110
-    const char *reporter, *value, *type;
0c9110
-    char *reported_to_line, *prefix;
0c9110
-    GList *result = NULL;
0c9110
-
0c9110
-    for (i = 0; i < json_object_array_length(list); ++i)
0c9110
-    {
0c9110
-        prefix = NULL;
0c9110
-        list_elem = json_object_array_get_idx(list, i);
0c9110
-        if (!list_elem)
0c9110
-            continue;
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "reporter", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        reporter = json_object_get_string(struct_elem);
0c9110
-        if (!reporter)
0c9110
-            continue;
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "value", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        value = json_object_get_string(struct_elem);
0c9110
-        if (!value)
0c9110
-            continue;
0c9110
-
0c9110
-        if (!json_object_object_get_ex(list_elem, "type", &struct_elem))
0c9110
-            continue;
0c9110
-
0c9110
-        type = json_object_get_string(struct_elem);
0c9110
-        if (type)
0c9110
-        {
0c9110
-            if (strcasecmp("url", type) == 0)
0c9110
-                prefix = xstrdup("URL=");
0c9110
-            else if (strcasecmp("bthash", type) == 0)
0c9110
-                prefix = xstrdup("BTHASH=");
0c9110
-        }
0c9110
-
0c9110
-        if (!prefix)
0c9110
-            prefix = xstrdup("");
0c9110
-
0c9110
-        reported_to_line = xasprintf("%s: %s%s", reporter, prefix, value);
0c9110
-        free(prefix);
0c9110
-
0c9110
-        result = g_list_append(result, reported_to_line);
0c9110
-    }
0c9110
-
0c9110
-    return result;
0c9110
-}
0c9110
-
0c9110
-/*
0c9110
- * Reponse samples:
0c9110
- * {"error":"field 'foo' is required"}
0c9110
- * {"response":"true"}
0c9110
- * {"response":"false"}
0c9110
- */
0c9110
-static struct ureport_server_response *ureport_server_parse_json(json_object *json)
0c9110
-{
0c9110
-    json_object *obj = NULL;
0c9110
-    if (json_object_object_get_ex(json, "error", &obj))
0c9110
-    {
0c9110
-        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
0c9110
-        out_response->is_error = true;
0c9110
-        /*
0c9110
-         * Used to use json_object_to_json_string(obj), but it returns
0c9110
-         * the string in quote marks (") - IOW, json-formatted string.
0c9110
-         */
0c9110
-        out_response->value = xstrdup(json_object_get_string(obj));
0c9110
-        return out_response;
0c9110
-    }
0c9110
-
0c9110
-    if (json_object_object_get_ex(json, "result", &obj))
0c9110
-    {
0c9110
-        struct ureport_server_response *out_response = xzalloc(sizeof(*out_response));
0c9110
-        out_response->value = xstrdup(json_object_get_string(obj));
0c9110
-
0c9110
-        json_object *message = NULL;
0c9110
-        if (json_object_object_get_ex(json, "message", &message))
0c9110
-            out_response->message = xstrdup(json_object_get_string(message));
0c9110
-
0c9110
-        json_object *bthash = NULL;
0c9110
-        if (json_object_object_get_ex(json, "bthash", &bthash))
0c9110
-            out_response->bthash = xstrdup(json_object_get_string(bthash));
0c9110
-
0c9110
-        json_object *reported_to_list = NULL;
0c9110
-        if (json_object_object_get_ex(json, "reported_to", &reported_to_list))
0c9110
-            out_response->reported_to_list = parse_reported_to_from_json_list(reported_to_list);
0c9110
-
0c9110
-        json_object *solutions = NULL;
0c9110
-        if (json_object_object_get_ex(json, "solutions", &solutions))
0c9110
-            out_response->solution = parse_solution_from_json_list(solutions, &(out_response->reported_to_list));
0c9110
-
0c9110
-        return out_response;
0c9110
-    }
0c9110
-
0c9110
-    return NULL;
0c9110
-}
0c9110
-
0c9110
-static struct ureport_server_response *get_server_response(post_state_t *post_state, struct ureport_server_config *config)
0c9110
-{
0c9110
-    /* Previously, the condition here was (post_state->errmsg[0] != '\0')
0c9110
-     * however when the server asks for optional client authentication and we do not have the certificates,
0c9110
-     * then post_state->errmsg contains "NSS: client certificate not found (nickname not specified)" even though
0c9110
-     * the request succeeded.
0c9110
-     */
0c9110
-    if (post_state->curl_result != CURLE_OK)
0c9110
-    {
0c9110
-        error_msg(_("Failed to upload uReport to the server '%s' with curl: %s"), config->ur_url, post_state->errmsg);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    if (post_state->http_resp_code == 404)
0c9110
-    {
0c9110
-        error_msg(_("The URL '%s' does not exist (got error 404 from server)"), config->ur_url);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    if (post_state->http_resp_code == 500)
0c9110
-    {
0c9110
-        error_msg(_("The server at '%s' encountered an internal error (got error 500)"), config->ur_url);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    if (post_state->http_resp_code == 503)
0c9110
-    {
0c9110
-        error_msg(_("The server at '%s' currently can't handle the request (got error 503)"), config->ur_url);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    if (post_state->http_resp_code != 202
0c9110
-            && post_state->http_resp_code != 400
0c9110
-            && post_state->http_resp_code != 413)
0c9110
-    {
0c9110
-        /* can't print better error message */
0c9110
-        error_msg(_("Unexpected HTTP response from '%s': %d"), config->ur_url, post_state->http_resp_code);
0c9110
-        log_notice("%s", post_state->body);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    json_object *const json = json_tokener_parse(post_state->body);
0c9110
-
0c9110
-    if (is_error(json))
0c9110
-    {
0c9110
-        error_msg(_("Unable to parse response from ureport server at '%s'"), config->ur_url);
0c9110
-        log_notice("%s", post_state->body);
0c9110
-        json_object_put(json);
0c9110
-        return NULL;
0c9110
-    }
0c9110
-
0c9110
-    struct ureport_server_response *response = ureport_server_parse_json(json);
0c9110
-    json_object_put(json);
0c9110
-
0c9110
-    if (!response)
0c9110
-        error_msg(_("The response from '%s' has invalid format"), config->ur_url);
0c9110
-    else if ((post_state->http_resp_code == 202 && response->is_error)
0c9110
-                || (post_state->http_resp_code != 202 && !response->is_error))
0c9110
-    {
0c9110
-        /* HTTP CODE 202 means that call was successful but the response */
0c9110
-        /* has an error message */
0c9110
-        error_msg(_("Type mismatch has been detected in the response from '%s'"), config->ur_url);
0c9110
-    }
0c9110
-
0c9110
-    return response;
0c9110
-}
0c9110
-
0c9110
-typedef post_state_t *(*attach_handler)(const char *, void *, struct ureport_server_config *);
0c9110
-
0c9110
-static post_state_t *wrp_ureport_attach_rhbz(const char *ureport_hash, int *rhbz_bug,
0c9110
-        struct ureport_server_config *config)
0c9110
-{
0c9110
-    return ureport_attach_rhbz(ureport_hash, *rhbz_bug, config);
0c9110
-}
0c9110
-
0c9110
-static bool perform_attach(struct ureport_server_config *config, const char *ureport_hash,
0c9110
-        attach_handler handler, void *args)
0c9110
-{
0c9110
-    char *dest_url = concat_path_file(config->ur_url, ATTACH_URL_SFX);
0c9110
-    const char *old_url = config->ur_url;
0c9110
-    config->ur_url = dest_url;
0c9110
-    post_state_t *post_state = handler(ureport_hash, args, config);
0c9110
-    config->ur_url = old_url;
0c9110
-    free(dest_url);
0c9110
-
0c9110
-    struct ureport_server_response *resp = get_server_response(post_state, config);
0c9110
-    free_post_state(post_state);
0c9110
-    /* don't use str_bo_bool() because we require "true" string */
0c9110
-    const int result = !resp || resp->is_error || strcmp(resp->value,"true") != 0;
0c9110
-
0c9110
-    if (resp && resp->is_error)
0c9110
-    {
0c9110
-        error_msg(_("The server at '%s' responded with an error: '%s'"), config->ur_url, resp->value);
0c9110
-    }
0c9110
-
0c9110
-    free_ureport_server_response(resp);
0c9110
-
0c9110
-    return result;
0c9110
-}
0c9110
-
0c9110
-int main(int argc, char **argv)
0c9110
-{
0c9110
-    setlocale(LC_ALL, "");
0c9110
-#if ENABLE_NLS
0c9110
-    bindtextdomain(PACKAGE, LOCALEDIR);
0c9110
-    textdomain(PACKAGE);
0c9110
-#endif
0c9110
-
0c9110
-    abrt_init(argv);
0c9110
-
0c9110
-    struct ureport_server_config config = {
0c9110
-        .ur_url = NULL,
0c9110
-        .ur_ssl_verify = true,
0c9110
-        .ur_client_cert = NULL,
0c9110
-        .ur_client_key = NULL,
0c9110
-        .ur_http_headers = NULL,
0c9110
-        {
0c9110
-            .urp_auth_items = NULL,
0c9110
-        },
0c9110
-    };
0c9110
-
0c9110
-    config.ur_http_headers = new_map_string();
0c9110
-
0c9110
-    enum {
0c9110
-        OPT_v = 1 << 0,
0c9110
-        OPT_d = 1 << 1,
0c9110
-        OPT_u = 1 << 2,
0c9110
-        OPT_k = 1 << 3,
0c9110
-        OPT_t = 1 << 4,
0c9110
-        OPT_i = 1 << 5,
0c9110
-    };
0c9110
-
0c9110
-    int ret = 1; /* "failure" (for now) */
0c9110
-    bool insecure = !config.ur_ssl_verify;
0c9110
-    const char *conf_file = CONF_FILE_PATH;
0c9110
-    const char *arg_server_url = NULL;
0c9110
-    const char *client_auth = NULL;
0c9110
-    GList *auth_items = NULL;
0c9110
-    const char *dump_dir_path = ".";
0c9110
-    const char *ureport_hash = NULL;
0c9110
-    bool ureport_hash_from_rt = false;
0c9110
-    int rhbz_bug = -1;
0c9110
-    bool rhbz_bug_from_rt = false;
0c9110
-    const char *email_address = NULL;
0c9110
-    bool email_address_from_env = false;
0c9110
-    struct dump_dir *dd = NULL;
0c9110
-    struct options program_options[] = {
0c9110
-        OPT__VERBOSE(&g_verbose),
0c9110
-        OPT__DUMP_DIR(&dump_dir_path),
0c9110
-        OPT_STRING('u', "url", &arg_server_url, "URL", _("Specify server URL")),
0c9110
-        OPT_BOOL('k', "insecure", &insecure,
0c9110
-                          _("Allow insecure connection to ureport server")),
0c9110
-        OPT_STRING('t', "auth", &client_auth, "SOURCE", _("Use client authentication")),
0c9110
-        OPT_LIST('i', "auth_items", &auth_items, "AUTH_ITEMS", _("Additional files included in 'auth' key")),
0c9110
-        OPT_STRING('c', NULL, &conf_file, "FILE", _("Configuration file")),
0c9110
-        OPT_STRING('a', "attach", &ureport_hash, "BTHASH",
0c9110
-                          _("bthash of uReport to attach (conflicts with -A)")),
0c9110
-        OPT_BOOL('A', "attach-rt", &ureport_hash_from_rt,
0c9110
-                          _("attach to a bthash from reported_to (conflicts with -a)")),
0c9110
-        OPT_STRING('e', "email", &email_address, "EMAIL",
0c9110
-                          _("contact e-mail address (requires -a|-A, conflicts with -E)")),
0c9110
-        OPT_BOOL('E', "email-env", &email_address_from_env,
0c9110
-                          _("contact e-mail address from environment or configuration file (requires -a|-A, conflicts with -e)")),
0c9110
-        OPT_INTEGER('b', "bug-id", &rhbz_bug,
0c9110
-                          _("attach RHBZ bug (requires -a|-A, conflicts with -B)")),
0c9110
-        OPT_BOOL('B', "bug-id-rt", &rhbz_bug_from_rt,
0c9110
-                          _("attach last RHBZ bug from reported_to (requires -a|-A, conflicts with -b)")),
0c9110
-        OPT_END(),
0c9110
-    };
0c9110
-
0c9110
-    const char *program_usage_string = _(
0c9110
-        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
-        "& [-v] [-c FILE] [-u URL] [-k] [-t SOURCE] [-i AUTH_ITEMS]\\\n"
0c9110
-        "  [-A -a bthash -B -b bug-id -E -e email] [-d DIR]\n"
0c9110
-        "\n"
0c9110
-        "Upload micro report or add an attachment to a micro report\n"
0c9110
-        "\n"
0c9110
-        "Reads the default configuration from "CONF_FILE_PATH
0c9110
-    );
0c9110
-
0c9110
-    unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
0c9110
-
0c9110
-    map_string_t *settings = new_map_string();
0c9110
-    load_conf_file(conf_file, settings, /*skip key w/o values:*/ false);
0c9110
-
0c9110
-    load_ureport_server_config(&config, settings);
0c9110
-
0c9110
-    if (opts & OPT_u)
0c9110
-        config.ur_url = arg_server_url;
0c9110
-    if (opts & OPT_k)
0c9110
-        config.ur_ssl_verify = !insecure;
0c9110
-    if (opts & OPT_t)
0c9110
-        parse_client_auth_paths(&config, client_auth);
0c9110
-    if (opts & OPT_i)
0c9110
-    {
0c9110
-        g_list_free_full(config.ur_prefs.urp_auth_items, free);
0c9110
-        config.ur_prefs.urp_auth_items = auth_items;
0c9110
-    }
0c9110
-
0c9110
-    if (!config.ur_url)
0c9110
-        error_msg_and_die("You need to specify server URL");
0c9110
-
0c9110
-    post_state_t *post_state = NULL;
0c9110
-
0c9110
-    if (ureport_hash && ureport_hash_from_rt)
0c9110
-        error_msg_and_die("You need to pass either -a bthash or -A");
0c9110
-
0c9110
-    if (rhbz_bug >= 0 && rhbz_bug_from_rt)
0c9110
-        error_msg_and_die("You need to pass either -b bug-id or -B");
0c9110
-
0c9110
-    if (email_address && email_address_from_env)
0c9110
-        error_msg_and_die("You need to pass either -e bthash or -E");
0c9110
-
0c9110
-    if (ureport_hash_from_rt || rhbz_bug_from_rt)
0c9110
-    {
0c9110
-        dd = dd_opendir(dump_dir_path, DD_OPEN_READONLY);
0c9110
-        if (!dd)
0c9110
-            xfunc_die();
0c9110
-
0c9110
-        if (ureport_hash_from_rt)
0c9110
-        {
0c9110
-            report_result_t *ureport_result = find_in_reported_to(dd, "uReport");
0c9110
-
0c9110
-            if (!ureport_result || !ureport_result->bthash)
0c9110
-                error_msg_and_die(_("This problem does not have an uReport assigned."));
0c9110
-
0c9110
-            /* sorry, this will be leaked */
0c9110
-            ureport_hash = xstrdup(ureport_result->bthash);
0c9110
-
0c9110
-            free_report_result(ureport_result);
0c9110
-        }
0c9110
-
0c9110
-        if (rhbz_bug_from_rt)
0c9110
-        {
0c9110
-            report_result_t *bz_result = find_in_reported_to(dd, "Bugzilla");
0c9110
-
0c9110
-            if (!bz_result || !bz_result->url)
0c9110
-                error_msg_and_die(_("This problem has not been reported to Bugzilla."));
0c9110
-
0c9110
-            char *bugid_ptr = strstr(bz_result->url, "show_bug.cgi?id=");
0c9110
-            if (!bugid_ptr)
0c9110
-                error_msg_and_die(_("Unable to find bug ID in bugzilla URL '%s'"), bz_result->url);
0c9110
-            bugid_ptr += strlen("show_bug.cgi?id=");
0c9110
-
0c9110
-            /* we're just reading int, sscanf works fine */
0c9110
-            if (sscanf(bugid_ptr, "%d", &rhbz_bug) != 1)
0c9110
-                error_msg_and_die(_("Unable to parse bug ID from bugzilla URL '%s'"), bz_result->url);
0c9110
-
0c9110
-            free_report_result(bz_result);
0c9110
-        }
0c9110
-
0c9110
-        dd_close(dd);
0c9110
-    }
0c9110
-
0c9110
-    if (email_address_from_env)
0c9110
-    {
0c9110
-        VALUE_FROM_CONF("ContactEmail", email_address, (const char *));
0c9110
-
0c9110
-        if (!email_address)
0c9110
-            error_msg_and_die(_("Neither environment variable 'uReport_ContactEmail' nor configuration option 'ContactEmail' is set"));
0c9110
-    }
0c9110
-
0c9110
-    if (ureport_hash)
0c9110
-    {
0c9110
-        if (rhbz_bug < 0 && !email_address)
0c9110
-            error_msg_and_die(_("You need to specify bug ID, contact email or both"));
0c9110
-
0c9110
-        if (rhbz_bug >= 0)
0c9110
-        {
0c9110
-            if (perform_attach(&config, ureport_hash, (attach_handler)wrp_ureport_attach_rhbz, (void *)&rhbz_bug))
0c9110
-                goto finalize;
0c9110
-        }
0c9110
-
0c9110
-        if (email_address)
0c9110
-        {
0c9110
-            if (perform_attach(&config, ureport_hash, (attach_handler)ureport_attach_email, (void *)email_address))
0c9110
-                goto finalize;
0c9110
-        }
0c9110
-
0c9110
-        ret = 0;
0c9110
-        goto finalize;
0c9110
-    }
0c9110
-    if (!ureport_hash && (rhbz_bug >= 0 || email_address))
0c9110
-        error_msg_and_die(_("You need to specify bthash of the uReport to attach."));
0c9110
-
0c9110
-    /* -b, -a nor -r were specified - upload uReport from dump_dir */
0c9110
-    const char *server_url = config.ur_url;
0c9110
-    char *dest_url = concat_path_file(config.ur_url, REPORT_URL_SFX);
0c9110
-    config.ur_url = dest_url;
0c9110
-
0c9110
-    char *json_ureport = ureport_from_dump_dir_ext(dump_dir_path, &(config.ur_prefs));
0c9110
-    if (!json_ureport)
0c9110
-    {
0c9110
-        error_msg(_("Not uploading an empty uReport"));
0c9110
-        goto format_err;
0c9110
-    }
0c9110
-
0c9110
-    post_state = post_ureport(json_ureport, &config);
0c9110
-    free(json_ureport);
0c9110
-
0c9110
-    if (!post_state)
0c9110
-    {
0c9110
-        error_msg(_("Failed on submitting the problem"));
0c9110
-        goto format_err;
0c9110
-    }
0c9110
-
0c9110
-    struct ureport_server_response *response = get_server_response(post_state, &config);
0c9110
-
0c9110
-    if (!response)
0c9110
-        goto format_err;
0c9110
-
0c9110
-    if (!response->is_error)
0c9110
-    {
0c9110
-        log_notice("is known: %s", response->value);
0c9110
-        ret = 0; /* "success" */
0c9110
-
0c9110
-        dd = dd_opendir(dump_dir_path, /* flags */ 0);
0c9110
-        if (!dd)
0c9110
-            xfunc_die();
0c9110
-
0c9110
-        if (response->bthash)
0c9110
-        {
0c9110
-            char *msg = xasprintf("uReport: BTHASH=%s", response->bthash);
0c9110
-            add_reported_to(dd, msg);
0c9110
-            free(msg);
0c9110
-
0c9110
-            char *bthash_url = concat_path_file(server_url, BTHASH_URL_SFX);
0c9110
-            msg = xasprintf("ABRT Server: URL=%s%s", bthash_url, response->bthash);
0c9110
-            add_reported_to(dd, msg);
0c9110
-            free(msg);
0c9110
-            free(bthash_url);
0c9110
-        }
0c9110
-
0c9110
-        if (response->reported_to_list)
0c9110
-        {
0c9110
-            for (GList *e = response->reported_to_list; e; e = g_list_next(e))
0c9110
-                add_reported_to(dd, e->data);
0c9110
-        }
0c9110
-
0c9110
-        if (response->solution)
0c9110
-            dd_save_text(dd, FILENAME_NOT_REPORTABLE, response->solution);
0c9110
-
0c9110
-        dd_close(dd);
0c9110
-
0c9110
-        /* If a reported problem is not known then emit NEEDMORE */
0c9110
-        if (strcmp("true", response->value) == 0)
0c9110
-        {
0c9110
-            log(_("This problem has already been reported."));
0c9110
-            if (response->message)
0c9110
-                log(response->message);
0c9110
-
0c9110
-            ret = EXIT_STOP_EVENT_RUN;
0c9110
-        }
0c9110
-    }
0c9110
-    else
0c9110
-    {
0c9110
-        error_msg(_("Server responded with an error: '%s'"), response->value);
0c9110
-    }
0c9110
-
0c9110
-    free_ureport_server_response(response);
0c9110
-
0c9110
-format_err:
0c9110
-    free_post_state(post_state);
0c9110
-    free(dest_url);
0c9110
-
0c9110
-finalize:
0c9110
-    if (config.ur_prefs.urp_auth_items != auth_items)
0c9110
-        g_list_free_full(config.ur_prefs.urp_auth_items, free);
0c9110
-
0c9110
-    free_map_string(config.ur_http_headers);
0c9110
-
0c9110
-    free_map_string(settings);
0c9110
-    free(config.ur_client_cert);
0c9110
-    free(config.ur_client_key);
0c9110
-
0c9110
-    return ret;
0c9110
-}
0c9110
-- 
0c9110
1.8.3.1
0c9110