Signed-off-by: Nikola Pajkovsky <[email protected]>
---
 libreport.spec.in                 |    2 +-
 po/POTFILES.in                    |    2 +-
 src/include/Makefile.am           |    2 +-
 src/include/abrt_curl.h           |  117 ---------
 src/include/libreport_curl.h      |  117 +++++++++
 src/lib/Makefile.am               |    2 +-
 src/lib/abrt_curl.c               |  499 -------------------------------------
 src/lib/curl.c                    |  499 +++++++++++++++++++++++++++++++++++++
 src/lib/json.c                    |    2 +-
 src/plugins/abrt-bodhi.c          |    2 +-
 src/plugins/abrt_rh_support.c     |    2 +-
 src/plugins/reporter-kerneloops.c |    2 +-
 src/plugins/reporter-rhtsupport.c |    2 +-
 src/plugins/reporter-upload.c     |    2 +-
 src/plugins/ureport.c             |    2 +-
 15 files changed, 627 insertions(+), 627 deletions(-)
 delete mode 100644 src/include/abrt_curl.h
 create mode 100644 src/include/libreport_curl.h
 delete mode 100644 src/lib/abrt_curl.c
 create mode 100644 src/lib/curl.c

diff --git a/libreport.spec.in b/libreport.spec.in
index f758d2e..599986d 100644
--- a/libreport.spec.in
+++ b/libreport.spec.in
@@ -321,7 +321,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null 
|| :
 
 %files web-devel
 %defattr(-,root,root,-)
-%{_includedir}/libreport/abrt_curl.h
+%{_includedir}/libreport/libreport_curl.h
 %{_libdir}/pkgconfig/libreport-web.pc
 
 %files python
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9fac721..f32ba57 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -11,7 +11,7 @@ src/gui-wizard-gtk/wizard.c
 src/gui-wizard-gtk/wizard.glade
 src/lib/event_config.c
 src/lib/parse_options.c
-src/lib/abrt_curl.c
+src/lib/curl.c
 src/lib/client.c
 src/lib/run_event.c
 src/lib/problem_data.c
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index fc73545..61b49a3 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -6,7 +6,7 @@ libreport_include_HEADERS = \
     problem_data.h \
     report.h \
     run_event.h \
-    abrt_curl.h \
+    libreport_curl.h \
     \
     internal_libreport.h \
     internal_abrt_dbus.h
diff --git a/src/include/abrt_curl.h b/src/include/abrt_curl.h
deleted file mode 100644
index ca3c5b8..0000000
--- a/src/include/abrt_curl.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-    Copyright (C) 2010  ABRT team
-    Copyright (C) 2010  RedHat Inc
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#ifndef ABRT_CURL_H_
-#define ABRT_CURL_H_
-
-#include <curl/curl.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-CURL* xcurl_easy_init();
-
-/* Set proxy according to the url and call curl_easy_perform */
-CURLcode curl_easy_perform_with_proxy(CURL *handle, const char *url);
-
-typedef struct abrt_post_state {
-    /* Supplied by caller: */
-    int         flags;
-    const char  *username;
-    const char  *password;
-    /* Results of POST transaction: */
-    int         http_resp_code;
-    unsigned    header_cnt;
-    char        **headers;
-    char        *curl_error_msg;
-    char        *body;
-    size_t      body_size;
-    char        errmsg[CURL_ERROR_SIZE];
-} abrt_post_state_t;
-
-abrt_post_state_t *new_abrt_post_state(int flags);
-void free_abrt_post_state(abrt_post_state_t *state);
-char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char 
*str);
-
-enum {
-    ABRT_POST_WANT_HEADERS    = (1 << 0),
-    ABRT_POST_WANT_ERROR_MSG  = (1 << 1),
-    ABRT_POST_WANT_BODY       = (1 << 2),
-    ABRT_POST_WANT_SSL_VERIFY = (1 << 3),
-};
-enum {
-    /* Must be -1! CURLOPT_POSTFIELDSIZE interprets -1 as "use strlen" */
-    ABRT_POST_DATA_STRING = -1,
-    ABRT_POST_DATA_FROMFILE = -2,
-    ABRT_POST_DATA_FROMFILE_AS_FORM_DATA = -3,
-    ABRT_POST_DATA_STRING_AS_FORM_DATA = -4,
-};
-int
-abrt_post(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *data,
-                off_t data_size);
-static inline int
-abrt_post_string(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *str)
-{
-    return abrt_post(state, url, content_type, additional_headers,
-                     str, ABRT_POST_DATA_STRING);
-}
-static inline int
-abrt_post_string_as_form_data(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *str)
-{
-    return abrt_post(state, url, content_type, additional_headers,
-                     str, ABRT_POST_DATA_STRING_AS_FORM_DATA);
-}
-static inline int
-abrt_post_file(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *filename)
-{
-    return abrt_post(state, url, content_type, additional_headers,
-                     filename, ABRT_POST_DATA_FROMFILE);
-}
-static inline int
-abrt_post_file_as_form(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *filename)
-{
-    return abrt_post(state, url, content_type, additional_headers,
-                     filename, ABRT_POST_DATA_FROMFILE_AS_FORM_DATA);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/include/libreport_curl.h b/src/include/libreport_curl.h
new file mode 100644
index 0000000..ca3c5b8
--- /dev/null
+++ b/src/include/libreport_curl.h
@@ -0,0 +1,117 @@
+/*
+    Copyright (C) 2010  ABRT team
+    Copyright (C) 2010  RedHat Inc
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_CURL_H_
+#define ABRT_CURL_H_
+
+#include <curl/curl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+CURL* xcurl_easy_init();
+
+/* Set proxy according to the url and call curl_easy_perform */
+CURLcode curl_easy_perform_with_proxy(CURL *handle, const char *url);
+
+typedef struct abrt_post_state {
+    /* Supplied by caller: */
+    int         flags;
+    const char  *username;
+    const char  *password;
+    /* Results of POST transaction: */
+    int         http_resp_code;
+    unsigned    header_cnt;
+    char        **headers;
+    char        *curl_error_msg;
+    char        *body;
+    size_t      body_size;
+    char        errmsg[CURL_ERROR_SIZE];
+} abrt_post_state_t;
+
+abrt_post_state_t *new_abrt_post_state(int flags);
+void free_abrt_post_state(abrt_post_state_t *state);
+char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char 
*str);
+
+enum {
+    ABRT_POST_WANT_HEADERS    = (1 << 0),
+    ABRT_POST_WANT_ERROR_MSG  = (1 << 1),
+    ABRT_POST_WANT_BODY       = (1 << 2),
+    ABRT_POST_WANT_SSL_VERIFY = (1 << 3),
+};
+enum {
+    /* Must be -1! CURLOPT_POSTFIELDSIZE interprets -1 as "use strlen" */
+    ABRT_POST_DATA_STRING = -1,
+    ABRT_POST_DATA_FROMFILE = -2,
+    ABRT_POST_DATA_FROMFILE_AS_FORM_DATA = -3,
+    ABRT_POST_DATA_STRING_AS_FORM_DATA = -4,
+};
+int
+abrt_post(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *data,
+                off_t data_size);
+static inline int
+abrt_post_string(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *str)
+{
+    return abrt_post(state, url, content_type, additional_headers,
+                     str, ABRT_POST_DATA_STRING);
+}
+static inline int
+abrt_post_string_as_form_data(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *str)
+{
+    return abrt_post(state, url, content_type, additional_headers,
+                     str, ABRT_POST_DATA_STRING_AS_FORM_DATA);
+}
+static inline int
+abrt_post_file(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *filename)
+{
+    return abrt_post(state, url, content_type, additional_headers,
+                     filename, ABRT_POST_DATA_FROMFILE);
+}
+static inline int
+abrt_post_file_as_form(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *filename)
+{
+    return abrt_post(state, url, content_type, additional_headers,
+                     filename, ABRT_POST_DATA_FROMFILE_AS_FORM_DATA);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index cd19e90..d2282db 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -91,7 +91,7 @@ libabrt_dbus_la_LIBADD = \
     $(DBUS_LIBS)
 
 libreport_web_la_SOURCES = \
-    abrt_curl.c \
+    curl.c \
     abrt_xmlrpc.h abrt_xmlrpc.c \
     proxies.h proxies.c \
     ureport.h json.c
diff --git a/src/lib/abrt_curl.c b/src/lib/abrt_curl.c
deleted file mode 100644
index 1ae773d..0000000
--- a/src/lib/abrt_curl.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
-    Copyright (C) 2010  ABRT team
-    Copyright (C) 2010  RedHat Inc
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License along
-    with this program; if not, write to the Free Software Foundation, Inc.,
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include "internal_libreport.h"
-#include "abrt_curl.h"
-#include "proxies.h"
-
-/*
- * Utility functions
- */
-CURL* xcurl_easy_init()
-{
-    CURL* curl = curl_easy_init();
-    if (!curl)
-    {
-        error_msg_and_die("Can't create curl handle");
-    }
-    return curl;
-}
-
-static char*
-check_curl_error(CURLcode err, const char* msg)
-{
-    if (err)
-        return xasprintf("%s: %s", msg, curl_easy_strerror(err));
-    return NULL;
-}
-
-static void
-die_if_curl_error(CURLcode err)
-{
-    if (err) {
-        char *msg = check_curl_error(err, "curl");
-        error_msg_and_die("%s", msg);
-    }
-}
-
-static void
-xcurl_easy_setopt_ptr(CURL *handle, CURLoption option, const void *parameter)
-{
-    CURLcode err = curl_easy_setopt(handle, option, parameter);
-    if (err) {
-        char *msg = check_curl_error(err, "curl");
-        error_msg_and_die("%s", msg);
-    }
-}
-static inline void
-xcurl_easy_setopt_long(CURL *handle, CURLoption option, long parameter)
-{
-    xcurl_easy_setopt_ptr(handle, option, (void*)parameter);
-}
-
-static void
-xcurl_easy_setopt_off_t(CURL *handle, CURLoption option, curl_off_t parameter)
-{
-    /* Can't reuse xcurl_easy_setopt_ptr: paramter is too wide */
-    CURLcode err = curl_easy_setopt(handle, option, parameter);
-    if (err) {
-        char *msg = check_curl_error(err, "curl");
-        error_msg_and_die("%s", msg);
-    }
-}
-
-CURLcode curl_easy_perform_with_proxy(CURL *handle, const char *url)
-{
-    GList *proxy_list, *li;
-    CURLcode curl_err;
-
-    proxy_list = get_proxy_list(url);
-
-    if (proxy_list)
-    {
-        /* Try with each proxy before giving up. */
-        /* TODO: Should we repeat the perform call only on certain errors? */
-        for (li = proxy_list, curl_err = 1; curl_err && li; li = 
g_list_next(li))
-        {
-            xcurl_easy_setopt_ptr(handle, CURLOPT_PROXY, li->data);
-            VERB3 log("Proxy set to: '%s'", (const char *)li->data);
-
-            curl_err = curl_easy_perform(handle);
-        }
-    } else
-        curl_err = curl_easy_perform(handle);
-
-    list_free_with_free(proxy_list);
-
-    return curl_err;
-}
-
-/*
- * post_state utility functions
- */
-
-abrt_post_state_t *new_abrt_post_state(int flags)
-{
-    abrt_post_state_t *state = (abrt_post_state_t *)xzalloc(sizeof(*state));
-    state->flags = flags;
-    return state;
-}
-
-void free_abrt_post_state(abrt_post_state_t *state)
-{
-    char **headers = state->headers;
-    if (headers)
-    {
-        while (*headers)
-            free(*headers++);
-        free(state->headers);
-    }
-    free(state->curl_error_msg);
-    free(state->body);
-    free(state);
-}
-
-char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str)
-{
-    char **headers = state->headers;
-    if (headers)
-    {
-        unsigned len = strlen(str);
-        while (*headers)
-        {
-            if (strncmp(*headers, str, len) == 0)
-                return skip_whitespace(*headers + len);
-            headers++;
-        }
-    }
-    return NULL;
-}
-
-/*
- * abrt_post: perform HTTP POST transaction
- */
-
-/* "save headers" callback */
-static size_t
-save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr)
-{
-    abrt_post_state_t* state = (abrt_post_state_t*)ptr;
-    size_t size = count * nmemb;
-
-    char *h = xstrndup((char*)buffer_pv, size);
-    strchrnul(h, '\r')[0] = '\0';
-    strchrnul(h, '\n')[0] = '\0';
-
-    unsigned cnt = state->header_cnt;
-
-    /* Check for the case when curl follows a redirect:
-     * header 0: 'HTTP/1.1 301 Moved Permanently'
-     * header 1: 'Connection: close'
-     * header 2: 'Location: NEW_URL'
-     * header 3: ''
-     * header 0: 'HTTP/1.1 200 OK' <-- we need to forget all hdrs and start 
anew
-     */
-    if (cnt != 0
-     && strncmp(h, "HTTP/", 5) == 0
-     && state->headers[cnt-1][0] == '\0' /* prev header is an empty string */
-    ) {
-        char **headers = state->headers;
-        if (headers)
-        {
-            while (*headers)
-                free(*headers++);
-        }
-        cnt = 0;
-    }
-
-    VERB3 log("save_headers: header %d: '%s'", cnt, h);
-    state->headers = (char**)xrealloc(state->headers, (cnt+2) * 
sizeof(state->headers[0]));
-    state->headers[cnt] = h;
-    state->header_cnt = ++cnt;
-    state->headers[cnt] = NULL;
-
-    return size;
-}
-
-/* "read local data from a file" callback */
-static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void 
*userdata)
-{
-    static time_t last_t; // hack
-
-    FILE *fp = (FILE*)userdata;
-    time_t t = time(NULL);
-
-    // Report current file position every 16 seconds
-    if (!(t & 0xf) && last_t != t)
-    {
-        last_t = t;
-        off_t cur_pos = ftello(fp);
-        fseeko(fp, 0, SEEK_END);
-        off_t sz = ftello(fp);
-        fseeko(fp, cur_pos, SEEK_SET);
-        log(_("Uploaded: %llu of %llu kbytes"),
-                (unsigned long long)cur_pos / 1024,
-                (unsigned long long)sz / 1024);
-    }
-
-    return fread(ptr, size, nmemb, fp);
-}
-
-static int curl_debug(CURL *handle, curl_infotype it, char *buf, size_t 
bufsize, void *unused)
-{
-    if (logmode == 0)
-        return 0;
-
-    switch (it) {
-    case CURLINFO_TEXT: /* The data is informational text. */
-        log("curl: %.*s", (int) bufsize, buf);
-        break;
-    case CURLINFO_HEADER_IN: /* The data is header (or header-like) data 
received from the peer. */
-        log("curl rcvd header: '%.*s'", (int) bufsize, buf);
-        break;
-    case CURLINFO_HEADER_OUT: /* The data is header (or header-like) data sent 
to the peer. */
-        log("curl sent header: '%.*s'", (int) bufsize, buf);
-        break;
-    case CURLINFO_DATA_IN: /* The data is protocol data received from the 
peer. */
-        if (g_verbose >= 3)
-            log("curl rcvd data: '%.*s'", (int) bufsize, buf);
-        else
-            log("curl rcvd data %u bytes", (int) bufsize);
-        break;
-    case CURLINFO_DATA_OUT: /* The data is protocol data sent to the peer. */
-        if (g_verbose >= 3)
-            log("curl sent data: '%.*s'", (int) bufsize, buf);
-        else
-            log("curl sent data %u bytes", (int) bufsize);
-        break;
-    default:
-        break;
-    }
-
-    return 0;
-}
-
-int
-abrt_post(abrt_post_state_t *state,
-                const char *url,
-                const char *content_type,
-                const char **additional_headers,
-                const char *data,
-                off_t data_size)
-{
-    CURLcode curl_err;
-    long response_code;
-    abrt_post_state_t localstate;
-
-    VERB3 log("abrt_post('%s','%s')", url, data);
-
-    if (!state)
-    {
-        memset(&localstate, 0, sizeof(localstate));
-        state = &localstate;
-    }
-
-    state->http_resp_code = response_code = -1;
-
-    CURL *handle = xcurl_easy_init();
-
-    // Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in.
-    // This may be more helpful than just return code from curl_easy_perform.
-    // curl will need it until curl_easy_cleanup.
-    state->errmsg[0] = '\0';
-    xcurl_easy_setopt_ptr(handle, CURLOPT_ERRORBUFFER, state->errmsg);
-    // Shut off the built-in progress meter completely
-    xcurl_easy_setopt_long(handle, CURLOPT_NOPROGRESS, 1);
-
-    if (g_verbose >= 2) {
-        // "Display a lot of verbose information about its operations.
-        // Very useful for libcurl and/or protocol debugging and understanding.
-        // The verbose information will be sent to stderr, or the stream set
-        // with CURLOPT_STDERR"
-        xcurl_easy_setopt_long(handle, CURLOPT_VERBOSE, 1);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_DEBUGFUNCTION, curl_debug);
-    }
-
-    // TODO: do we need to check for CURLE_URL_MALFORMAT error *here*,
-    // not in curl_easy_perform?
-    xcurl_easy_setopt_ptr(handle, CURLOPT_URL, url);
-
-    // Auth if configured
-    if (state->username) {
-        // bitmask of allowed auth methods
-        xcurl_easy_setopt_long(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_USERNAME, state->username);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_PASSWORD, (state->password ? 
state->password : ""));
-    }
-
-    // Do a regular HTTP post. This also makes curl use
-    // a "Content-Type: application/x-www-form-urlencoded" header.
-    // (This is by far the most commonly used POST method).
-    xcurl_easy_setopt_long(handle, CURLOPT_POST, 1);
-    // Supply POST data...
-    struct curl_httppost* post = NULL;
-    struct curl_httppost* last = NULL;
-    FILE* data_file = NULL;
-    if (data_size == ABRT_POST_DATA_FROMFILE) {
-        // ...from a file
-        data_file = fopen(data, "r");
-        if (!data_file)
-//FIXME:
-            perror_msg_and_die("Can't open '%s'", data);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_READDATA, data_file);
-        // Want to use custom read function
-        xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const 
void*)fread_with_reporting);
-        // Without this, curl would send "Content-Length: -1"
-        // servers don't like that: "413 Request Entity Too Large"
-        fseeko(data_file, 0, SEEK_END);
-        off_t sz = ftello(data_file);
-        fseeko(data_file, 0, SEEK_SET);
-        xcurl_easy_setopt_off_t(handle, CURLOPT_POSTFIELDSIZE_LARGE, sz);
-    } else if (data_size == ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) {
-        // ...from a file, in multipart/formdata format
-        const char *basename = strrchr(data, '/');
-        if (basename) basename++;
-        else basename = data;
-#if 0
-        // Simple way, without custom reader function
-        CURLFORMcode curlform_err = curl_formadd(&post, &last,
-                        CURLFORM_PTRNAME, "file", // element name
-                        CURLFORM_FILE, data, // filename to read from
-                        CURLFORM_CONTENTTYPE, content_type,
-                        CURLFORM_FILENAME, basename, // filename to put in the 
form
-                        CURLFORM_END);
-#else
-        data_file = fopen(data, "r");
-        if (!data_file)
-//FIXME:
-            perror_msg_and_die("Can't open '%s'", data);
-        // Want to use custom read function
-        xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const 
void*)fread_with_reporting);
-        // Need to know file size
-        fseeko(data_file, 0, SEEK_END);
-        off_t sz = ftello(data_file);
-        fseeko(data_file, 0, SEEK_SET);
-        // Create formdata
-        CURLFORMcode curlform_err = curl_formadd(&post, &last,
-                        CURLFORM_PTRNAME, "file", // element name
-                        // use CURLOPT_READFUNCTION for reading, pass 
data_file as its last param:
-                        CURLFORM_STREAM, data_file,
-                        CURLFORM_CONTENTSLENGTH, (long)sz, // a must if we use 
CURLFORM_STREAM option
-//FIXME: what if file size doesn't fit in long?
-                        CURLFORM_CONTENTTYPE, content_type,
-                        CURLFORM_FILENAME, basename, // filename to put in the 
form
-                        CURLFORM_END);
-#endif
-        if (curlform_err != 0)
-//FIXME:
-            error_msg_and_die("out of memory or read error (curl_formadd error 
code: %d)", (int)curlform_err);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
-    } else if (data_size == ABRT_POST_DATA_STRING_AS_FORM_DATA) {
-        CURLFORMcode curlform_err = curl_formadd(&post, &last,
-                        CURLFORM_PTRNAME, "file", // element name
-                        // curl bug - missing filename 
-                        // http://curl.haxx.se/mail/lib-2011-07/0176.html
-                        // https://github.com/bagder/curl/commit/45d883d
-                        // fixed in curl-7.22.0~144
-                        // tested with curl-7.24.0-3
-                        // should be working on F17
-                        CURLFORM_BUFFER, "*buffer*", // provides filename
-                        CURLFORM_BUFFERPTR, data,
-                        CURLFORM_BUFFERLENGTH, (long)strlen(data),
-//FIXME: what if file size doesn't fit in long?
-                        CURLFORM_CONTENTTYPE, content_type,
-                        CURLFORM_END);
-        if (curlform_err != 0)
-            error_msg_and_die("out of memory or read error (curl_formadd error 
code: %d)", (int)curlform_err);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
-    } else {
-        // .. from a blob in memory
-        xcurl_easy_setopt_ptr(handle, CURLOPT_POSTFIELDS, data);
-        // note1: if data_size == ABRT_POST_DATA_STRING == -1, curl will use 
strlen(data)
-        xcurl_easy_setopt_long(handle, CURLOPT_POSTFIELDSIZE, data_size);
-        // We don't use CURLOPT_POSTFIELDSIZE_LARGE because
-        // I'm not sure CURLOPT_POSTFIELDSIZE_LARGE special-cases -1.
-        // Not a big problem: memory blobs >4GB are very unlikely.
-    }
-
-    struct curl_slist *httpheader_list = NULL;
-
-    // Override "Content-Type:"
-    if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA
-        && data_size != ABRT_POST_DATA_STRING_AS_FORM_DATA)
-    {
-        char *content_type_header = xasprintf("Content-Type: %s", 
content_type);
-        // Note: curl_slist_append() copies content_type_header
-        httpheader_list = curl_slist_append(httpheader_list, 
content_type_header);
-        if (!httpheader_list)
-            error_msg_and_die("out of memory");
-        free(content_type_header);
-    }
-
-    for (; additional_headers && *additional_headers; additional_headers++)
-    {
-        httpheader_list = curl_slist_append(httpheader_list, 
*additional_headers);
-        if (!httpheader_list)
-            error_msg_and_die("out of memory");
-    }
-
-    // Add User-Agent: ABRT/N.M
-    httpheader_list = curl_slist_append(httpheader_list, "User-Agent: 
ABRT/"VERSION);
-    if (!httpheader_list)
-        error_msg_and_die("out of memory");
-
-    if (httpheader_list)
-        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPHEADER, httpheader_list);
-
-// Disabled: was observed to also handle "305 Use proxy" redirect,
-// apparently with POST->GET remapping - which server didn't like at all.
-// Attempted to suppress remapping on 305 using CURLOPT_POSTREDIR of -1,
-// but it still did not work.
-#if 0
-    // Please handle 301/302 redirects for me
-    xcurl_easy_setopt_long(handle, CURLOPT_FOLLOWLOCATION, 1);
-    xcurl_easy_setopt_long(handle, CURLOPT_MAXREDIRS, 10);
-    // Bitmask to control how libcurl acts on redirects after POSTs.
-    // Bit 0 set (value CURL_REDIR_POST_301) makes libcurl
-    // not convert POST requests into GET requests when following
-    // a 301 redirection. Bit 1 (value CURL_REDIR_POST_302) makes libcurl
-    // maintain the request method after a 302 redirect.
-    // CURL_REDIR_POST_ALL is a convenience define that sets both bits.
-    // The non-RFC behaviour is ubiquitous in web browsers, so the library
-    // does the conversion by default to maintain consistency.
-    // However, a server may require a POST to remain a POST.
-    xcurl_easy_setopt_long(handle, CURLOPT_POSTREDIR, -1L 
/*CURL_REDIR_POST_ALL*/ );
-#endif
-
-    // Prepare for saving information
-    if (state->flags & ABRT_POST_WANT_HEADERS)
-    {
-        xcurl_easy_setopt_ptr(handle, CURLOPT_HEADERFUNCTION, 
(void*)save_headers);
-        xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEHEADER, state);
-    }
-    FILE* body_stream = NULL;
-    if (state->flags & ABRT_POST_WANT_BODY)
-    {
-        body_stream = open_memstream(&state->body, &state->body_size);
-        if (!body_stream)
-            error_msg_and_die("out of memory");
-        xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEDATA, body_stream);
-    }
-    if (!(state->flags & ABRT_POST_WANT_SSL_VERIFY))
-    {
-        xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYPEER, 0);
-        xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYHOST, 0);
-    }
-
-    // This is the place where everything happens.
-    // Here errors are not limited to "out of memory", can't just die.
-    curl_err = curl_easy_perform_with_proxy(handle, url);
-    if (curl_err)
-    {
-        VERB2 log("curl_easy_perform: error %d", (int)curl_err);
-        if (state->flags & ABRT_POST_WANT_ERROR_MSG)
-        {
-            state->curl_error_msg = check_curl_error(curl_err, 
"curl_easy_perform");
-            VERB3 log("curl_easy_perform: error_msg: %s", 
state->curl_error_msg);
-        }
-        goto ret;
-    }
-
-    // curl-7.20.1 doesn't do it, we get NULL body in the log message below
-    // unless we fflush the body memstream ourself
-    if (body_stream)
-        fflush(body_stream);
-
-    // Headers/body are already saved (if requested), extract more info
-    curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, 
&response_code);
-    die_if_curl_error(curl_err);
-    state->http_resp_code = response_code;
-    VERB3 log("after curl_easy_perform: http code %ld body:'%s'", 
response_code, state->body);
-
- ret:
-    curl_easy_cleanup(handle);
-    if (httpheader_list)
-        curl_slist_free_all(httpheader_list);
-    if (body_stream)
-        fclose(body_stream);
-    if (data_file)
-        fclose(data_file);
-    if (post)
-        curl_formfree(post);
-
-    return response_code;
-}
diff --git a/src/lib/curl.c b/src/lib/curl.c
new file mode 100644
index 0000000..98b24f5
--- /dev/null
+++ b/src/lib/curl.c
@@ -0,0 +1,499 @@
+/*
+    Copyright (C) 2010  ABRT team
+    Copyright (C) 2010  RedHat Inc
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "internal_libreport.h"
+#include "libreport_curl.h"
+#include "proxies.h"
+
+/*
+ * Utility functions
+ */
+CURL* xcurl_easy_init()
+{
+    CURL* curl = curl_easy_init();
+    if (!curl)
+    {
+        error_msg_and_die("Can't create curl handle");
+    }
+    return curl;
+}
+
+static char*
+check_curl_error(CURLcode err, const char* msg)
+{
+    if (err)
+        return xasprintf("%s: %s", msg, curl_easy_strerror(err));
+    return NULL;
+}
+
+static void
+die_if_curl_error(CURLcode err)
+{
+    if (err) {
+        char *msg = check_curl_error(err, "curl");
+        error_msg_and_die("%s", msg);
+    }
+}
+
+static void
+xcurl_easy_setopt_ptr(CURL *handle, CURLoption option, const void *parameter)
+{
+    CURLcode err = curl_easy_setopt(handle, option, parameter);
+    if (err) {
+        char *msg = check_curl_error(err, "curl");
+        error_msg_and_die("%s", msg);
+    }
+}
+static inline void
+xcurl_easy_setopt_long(CURL *handle, CURLoption option, long parameter)
+{
+    xcurl_easy_setopt_ptr(handle, option, (void*)parameter);
+}
+
+static void
+xcurl_easy_setopt_off_t(CURL *handle, CURLoption option, curl_off_t parameter)
+{
+    /* Can't reuse xcurl_easy_setopt_ptr: paramter is too wide */
+    CURLcode err = curl_easy_setopt(handle, option, parameter);
+    if (err) {
+        char *msg = check_curl_error(err, "curl");
+        error_msg_and_die("%s", msg);
+    }
+}
+
+CURLcode curl_easy_perform_with_proxy(CURL *handle, const char *url)
+{
+    GList *proxy_list, *li;
+    CURLcode curl_err;
+
+    proxy_list = get_proxy_list(url);
+
+    if (proxy_list)
+    {
+        /* Try with each proxy before giving up. */
+        /* TODO: Should we repeat the perform call only on certain errors? */
+        for (li = proxy_list, curl_err = 1; curl_err && li; li = 
g_list_next(li))
+        {
+            xcurl_easy_setopt_ptr(handle, CURLOPT_PROXY, li->data);
+            VERB3 log("Proxy set to: '%s'", (const char *)li->data);
+
+            curl_err = curl_easy_perform(handle);
+        }
+    } else
+        curl_err = curl_easy_perform(handle);
+
+    list_free_with_free(proxy_list);
+
+    return curl_err;
+}
+
+/*
+ * post_state utility functions
+ */
+
+abrt_post_state_t *new_abrt_post_state(int flags)
+{
+    abrt_post_state_t *state = (abrt_post_state_t *)xzalloc(sizeof(*state));
+    state->flags = flags;
+    return state;
+}
+
+void free_abrt_post_state(abrt_post_state_t *state)
+{
+    char **headers = state->headers;
+    if (headers)
+    {
+        while (*headers)
+            free(*headers++);
+        free(state->headers);
+    }
+    free(state->curl_error_msg);
+    free(state->body);
+    free(state);
+}
+
+char *find_header_in_abrt_post_state(abrt_post_state_t *state, const char *str)
+{
+    char **headers = state->headers;
+    if (headers)
+    {
+        unsigned len = strlen(str);
+        while (*headers)
+        {
+            if (strncmp(*headers, str, len) == 0)
+                return skip_whitespace(*headers + len);
+            headers++;
+        }
+    }
+    return NULL;
+}
+
+/*
+ * abrt_post: perform HTTP POST transaction
+ */
+
+/* "save headers" callback */
+static size_t
+save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr)
+{
+    abrt_post_state_t* state = (abrt_post_state_t*)ptr;
+    size_t size = count * nmemb;
+
+    char *h = xstrndup((char*)buffer_pv, size);
+    strchrnul(h, '\r')[0] = '\0';
+    strchrnul(h, '\n')[0] = '\0';
+
+    unsigned cnt = state->header_cnt;
+
+    /* Check for the case when curl follows a redirect:
+     * header 0: 'HTTP/1.1 301 Moved Permanently'
+     * header 1: 'Connection: close'
+     * header 2: 'Location: NEW_URL'
+     * header 3: ''
+     * header 0: 'HTTP/1.1 200 OK' <-- we need to forget all hdrs and start 
anew
+     */
+    if (cnt != 0
+     && strncmp(h, "HTTP/", 5) == 0
+     && state->headers[cnt-1][0] == '\0' /* prev header is an empty string */
+    ) {
+        char **headers = state->headers;
+        if (headers)
+        {
+            while (*headers)
+                free(*headers++);
+        }
+        cnt = 0;
+    }
+
+    VERB3 log("save_headers: header %d: '%s'", cnt, h);
+    state->headers = (char**)xrealloc(state->headers, (cnt+2) * 
sizeof(state->headers[0]));
+    state->headers[cnt] = h;
+    state->header_cnt = ++cnt;
+    state->headers[cnt] = NULL;
+
+    return size;
+}
+
+/* "read local data from a file" callback */
+static size_t fread_with_reporting(void *ptr, size_t size, size_t nmemb, void 
*userdata)
+{
+    static time_t last_t; // hack
+
+    FILE *fp = (FILE*)userdata;
+    time_t t = time(NULL);
+
+    // Report current file position every 16 seconds
+    if (!(t & 0xf) && last_t != t)
+    {
+        last_t = t;
+        off_t cur_pos = ftello(fp);
+        fseeko(fp, 0, SEEK_END);
+        off_t sz = ftello(fp);
+        fseeko(fp, cur_pos, SEEK_SET);
+        log(_("Uploaded: %llu of %llu kbytes"),
+                (unsigned long long)cur_pos / 1024,
+                (unsigned long long)sz / 1024);
+    }
+
+    return fread(ptr, size, nmemb, fp);
+}
+
+static int curl_debug(CURL *handle, curl_infotype it, char *buf, size_t 
bufsize, void *unused)
+{
+    if (logmode == 0)
+        return 0;
+
+    switch (it) {
+    case CURLINFO_TEXT: /* The data is informational text. */
+        log("curl: %.*s", (int) bufsize, buf);
+        break;
+    case CURLINFO_HEADER_IN: /* The data is header (or header-like) data 
received from the peer. */
+        log("curl rcvd header: '%.*s'", (int) bufsize, buf);
+        break;
+    case CURLINFO_HEADER_OUT: /* The data is header (or header-like) data sent 
to the peer. */
+        log("curl sent header: '%.*s'", (int) bufsize, buf);
+        break;
+    case CURLINFO_DATA_IN: /* The data is protocol data received from the 
peer. */
+        if (g_verbose >= 3)
+            log("curl rcvd data: '%.*s'", (int) bufsize, buf);
+        else
+            log("curl rcvd data %u bytes", (int) bufsize);
+        break;
+    case CURLINFO_DATA_OUT: /* The data is protocol data sent to the peer. */
+        if (g_verbose >= 3)
+            log("curl sent data: '%.*s'", (int) bufsize, buf);
+        else
+            log("curl sent data %u bytes", (int) bufsize);
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+int
+abrt_post(abrt_post_state_t *state,
+                const char *url,
+                const char *content_type,
+                const char **additional_headers,
+                const char *data,
+                off_t data_size)
+{
+    CURLcode curl_err;
+    long response_code;
+    abrt_post_state_t localstate;
+
+    VERB3 log("abrt_post('%s','%s')", url, data);
+
+    if (!state)
+    {
+        memset(&localstate, 0, sizeof(localstate));
+        state = &localstate;
+    }
+
+    state->http_resp_code = response_code = -1;
+
+    CURL *handle = xcurl_easy_init();
+
+    // Buffer[CURL_ERROR_SIZE] curl stores human readable error messages in.
+    // This may be more helpful than just return code from curl_easy_perform.
+    // curl will need it until curl_easy_cleanup.
+    state->errmsg[0] = '\0';
+    xcurl_easy_setopt_ptr(handle, CURLOPT_ERRORBUFFER, state->errmsg);
+    // Shut off the built-in progress meter completely
+    xcurl_easy_setopt_long(handle, CURLOPT_NOPROGRESS, 1);
+
+    if (g_verbose >= 2) {
+        // "Display a lot of verbose information about its operations.
+        // Very useful for libcurl and/or protocol debugging and understanding.
+        // The verbose information will be sent to stderr, or the stream set
+        // with CURLOPT_STDERR"
+        xcurl_easy_setopt_long(handle, CURLOPT_VERBOSE, 1);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_DEBUGFUNCTION, curl_debug);
+    }
+
+    // TODO: do we need to check for CURLE_URL_MALFORMAT error *here*,
+    // not in curl_easy_perform?
+    xcurl_easy_setopt_ptr(handle, CURLOPT_URL, url);
+
+    // Auth if configured
+    if (state->username) {
+        // bitmask of allowed auth methods
+        xcurl_easy_setopt_long(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_USERNAME, state->username);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_PASSWORD, (state->password ? 
state->password : ""));
+    }
+
+    // Do a regular HTTP post. This also makes curl use
+    // a "Content-Type: application/x-www-form-urlencoded" header.
+    // (This is by far the most commonly used POST method).
+    xcurl_easy_setopt_long(handle, CURLOPT_POST, 1);
+    // Supply POST data...
+    struct curl_httppost* post = NULL;
+    struct curl_httppost* last = NULL;
+    FILE* data_file = NULL;
+    if (data_size == ABRT_POST_DATA_FROMFILE) {
+        // ...from a file
+        data_file = fopen(data, "r");
+        if (!data_file)
+//FIXME:
+            perror_msg_and_die("Can't open '%s'", data);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_READDATA, data_file);
+        // Want to use custom read function
+        xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const 
void*)fread_with_reporting);
+        // Without this, curl would send "Content-Length: -1"
+        // servers don't like that: "413 Request Entity Too Large"
+        fseeko(data_file, 0, SEEK_END);
+        off_t sz = ftello(data_file);
+        fseeko(data_file, 0, SEEK_SET);
+        xcurl_easy_setopt_off_t(handle, CURLOPT_POSTFIELDSIZE_LARGE, sz);
+    } else if (data_size == ABRT_POST_DATA_FROMFILE_AS_FORM_DATA) {
+        // ...from a file, in multipart/formdata format
+        const char *basename = strrchr(data, '/');
+        if (basename) basename++;
+        else basename = data;
+#if 0
+        // Simple way, without custom reader function
+        CURLFORMcode curlform_err = curl_formadd(&post, &last,
+                        CURLFORM_PTRNAME, "file", // element name
+                        CURLFORM_FILE, data, // filename to read from
+                        CURLFORM_CONTENTTYPE, content_type,
+                        CURLFORM_FILENAME, basename, // filename to put in the 
form
+                        CURLFORM_END);
+#else
+        data_file = fopen(data, "r");
+        if (!data_file)
+//FIXME:
+            perror_msg_and_die("Can't open '%s'", data);
+        // Want to use custom read function
+        xcurl_easy_setopt_ptr(handle, CURLOPT_READFUNCTION, (const 
void*)fread_with_reporting);
+        // Need to know file size
+        fseeko(data_file, 0, SEEK_END);
+        off_t sz = ftello(data_file);
+        fseeko(data_file, 0, SEEK_SET);
+        // Create formdata
+        CURLFORMcode curlform_err = curl_formadd(&post, &last,
+                        CURLFORM_PTRNAME, "file", // element name
+                        // use CURLOPT_READFUNCTION for reading, pass 
data_file as its last param:
+                        CURLFORM_STREAM, data_file,
+                        CURLFORM_CONTENTSLENGTH, (long)sz, // a must if we use 
CURLFORM_STREAM option
+//FIXME: what if file size doesn't fit in long?
+                        CURLFORM_CONTENTTYPE, content_type,
+                        CURLFORM_FILENAME, basename, // filename to put in the 
form
+                        CURLFORM_END);
+#endif
+        if (curlform_err != 0)
+//FIXME:
+            error_msg_and_die("out of memory or read error (curl_formadd error 
code: %d)", (int)curlform_err);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
+    } else if (data_size == ABRT_POST_DATA_STRING_AS_FORM_DATA) {
+        CURLFORMcode curlform_err = curl_formadd(&post, &last,
+                        CURLFORM_PTRNAME, "file", // element name
+                        // curl bug - missing filename 
+                        // http://curl.haxx.se/mail/lib-2011-07/0176.html
+                        // https://github.com/bagder/curl/commit/45d883d
+                        // fixed in curl-7.22.0~144
+                        // tested with curl-7.24.0-3
+                        // should be working on F17
+                        CURLFORM_BUFFER, "*buffer*", // provides filename
+                        CURLFORM_BUFFERPTR, data,
+                        CURLFORM_BUFFERLENGTH, (long)strlen(data),
+//FIXME: what if file size doesn't fit in long?
+                        CURLFORM_CONTENTTYPE, content_type,
+                        CURLFORM_END);
+        if (curlform_err != 0)
+            error_msg_and_die("out of memory or read error (curl_formadd error 
code: %d)", (int)curlform_err);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPPOST, post);
+    } else {
+        // .. from a blob in memory
+        xcurl_easy_setopt_ptr(handle, CURLOPT_POSTFIELDS, data);
+        // note1: if data_size == ABRT_POST_DATA_STRING == -1, curl will use 
strlen(data)
+        xcurl_easy_setopt_long(handle, CURLOPT_POSTFIELDSIZE, data_size);
+        // We don't use CURLOPT_POSTFIELDSIZE_LARGE because
+        // I'm not sure CURLOPT_POSTFIELDSIZE_LARGE special-cases -1.
+        // Not a big problem: memory blobs >4GB are very unlikely.
+    }
+
+    struct curl_slist *httpheader_list = NULL;
+
+    // Override "Content-Type:"
+    if (data_size != ABRT_POST_DATA_FROMFILE_AS_FORM_DATA
+        && data_size != ABRT_POST_DATA_STRING_AS_FORM_DATA)
+    {
+        char *content_type_header = xasprintf("Content-Type: %s", 
content_type);
+        // Note: curl_slist_append() copies content_type_header
+        httpheader_list = curl_slist_append(httpheader_list, 
content_type_header);
+        if (!httpheader_list)
+            error_msg_and_die("out of memory");
+        free(content_type_header);
+    }
+
+    for (; additional_headers && *additional_headers; additional_headers++)
+    {
+        httpheader_list = curl_slist_append(httpheader_list, 
*additional_headers);
+        if (!httpheader_list)
+            error_msg_and_die("out of memory");
+    }
+
+    // Add User-Agent: ABRT/N.M
+    httpheader_list = curl_slist_append(httpheader_list, "User-Agent: 
ABRT/"VERSION);
+    if (!httpheader_list)
+        error_msg_and_die("out of memory");
+
+    if (httpheader_list)
+        xcurl_easy_setopt_ptr(handle, CURLOPT_HTTPHEADER, httpheader_list);
+
+// Disabled: was observed to also handle "305 Use proxy" redirect,
+// apparently with POST->GET remapping - which server didn't like at all.
+// Attempted to suppress remapping on 305 using CURLOPT_POSTREDIR of -1,
+// but it still did not work.
+#if 0
+    // Please handle 301/302 redirects for me
+    xcurl_easy_setopt_long(handle, CURLOPT_FOLLOWLOCATION, 1);
+    xcurl_easy_setopt_long(handle, CURLOPT_MAXREDIRS, 10);
+    // Bitmask to control how libcurl acts on redirects after POSTs.
+    // Bit 0 set (value CURL_REDIR_POST_301) makes libcurl
+    // not convert POST requests into GET requests when following
+    // a 301 redirection. Bit 1 (value CURL_REDIR_POST_302) makes libcurl
+    // maintain the request method after a 302 redirect.
+    // CURL_REDIR_POST_ALL is a convenience define that sets both bits.
+    // The non-RFC behaviour is ubiquitous in web browsers, so the library
+    // does the conversion by default to maintain consistency.
+    // However, a server may require a POST to remain a POST.
+    xcurl_easy_setopt_long(handle, CURLOPT_POSTREDIR, -1L 
/*CURL_REDIR_POST_ALL*/ );
+#endif
+
+    // Prepare for saving information
+    if (state->flags & ABRT_POST_WANT_HEADERS)
+    {
+        xcurl_easy_setopt_ptr(handle, CURLOPT_HEADERFUNCTION, 
(void*)save_headers);
+        xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEHEADER, state);
+    }
+    FILE* body_stream = NULL;
+    if (state->flags & ABRT_POST_WANT_BODY)
+    {
+        body_stream = open_memstream(&state->body, &state->body_size);
+        if (!body_stream)
+            error_msg_and_die("out of memory");
+        xcurl_easy_setopt_ptr(handle, CURLOPT_WRITEDATA, body_stream);
+    }
+    if (!(state->flags & ABRT_POST_WANT_SSL_VERIFY))
+    {
+        xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYPEER, 0);
+        xcurl_easy_setopt_long(handle, CURLOPT_SSL_VERIFYHOST, 0);
+    }
+
+    // This is the place where everything happens.
+    // Here errors are not limited to "out of memory", can't just die.
+    curl_err = curl_easy_perform_with_proxy(handle, url);
+    if (curl_err)
+    {
+        VERB2 log("curl_easy_perform: error %d", (int)curl_err);
+        if (state->flags & ABRT_POST_WANT_ERROR_MSG)
+        {
+            state->curl_error_msg = check_curl_error(curl_err, 
"curl_easy_perform");
+            VERB3 log("curl_easy_perform: error_msg: %s", 
state->curl_error_msg);
+        }
+        goto ret;
+    }
+
+    // curl-7.20.1 doesn't do it, we get NULL body in the log message below
+    // unless we fflush the body memstream ourself
+    if (body_stream)
+        fflush(body_stream);
+
+    // Headers/body are already saved (if requested), extract more info
+    curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, 
&response_code);
+    die_if_curl_error(curl_err);
+    state->http_resp_code = response_code;
+    VERB3 log("after curl_easy_perform: http code %ld body:'%s'", 
response_code, state->body);
+
+ ret:
+    curl_easy_cleanup(handle);
+    if (httpheader_list)
+        curl_slist_free_all(httpheader_list);
+    if (body_stream)
+        fclose(body_stream);
+    if (data_file)
+        fclose(data_file);
+    if (post)
+        curl_formfree(post);
+
+    return response_code;
+}
diff --git a/src/lib/json.c b/src/lib/json.c
index 659eda2..651010d 100644
--- a/src/lib/json.c
+++ b/src/lib/json.c
@@ -23,7 +23,7 @@
 
 #include "internal_libreport.h"
 #include "ureport.h"
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 
 
 /* on success 1 returned, on error zero is returned and appropriate value
diff --git a/src/plugins/abrt-bodhi.c b/src/plugins/abrt-bodhi.c
index 91f0eed..632a351 100644
--- a/src/plugins/abrt-bodhi.c
+++ b/src/plugins/abrt-bodhi.c
@@ -24,7 +24,7 @@
 #include <rpm/rpmpgp.h>
 
 #include "internal_libreport.h"
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 #include "client.h"
 
 //699198,705037,705036
diff --git a/src/plugins/abrt_rh_support.c b/src/plugins/abrt_rh_support.c
index 8d05e84..233edfa 100644
--- a/src/plugins/abrt_rh_support.c
+++ b/src/plugins/abrt_rh_support.c
@@ -20,7 +20,7 @@
 #include <libxml/xmlwriter.h>
 #include <curl/curl.h>
 #include "internal_libreport.h"
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 #include "abrt_rh_support.h"
 
 struct reportfile {
diff --git a/src/plugins/reporter-kerneloops.c 
b/src/plugins/reporter-kerneloops.c
index 81ab93e..843c10b 100644
--- a/src/plugins/reporter-kerneloops.c
+++ b/src/plugins/reporter-kerneloops.c
@@ -16,7 +16,7 @@
        Anton Arapov <[email protected]>
        Arjan van de Ven <[email protected]>
  */
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 #include "internal_libreport.h"
 
 /* helpers */
diff --git a/src/plugins/reporter-rhtsupport.c 
b/src/plugins/reporter-rhtsupport.c
index 4e4cccb..215b7c1 100644
--- a/src/plugins/reporter-rhtsupport.c
+++ b/src/plugins/reporter-rhtsupport.c
@@ -19,7 +19,7 @@
 #include <libtar.h>
 #include "internal_libreport.h"
 #include "client.h"
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 #include "abrt_xmlrpc.h"
 #include "abrt_rh_support.h"
 #include "reporter-rhtsupport.h"
diff --git a/src/plugins/reporter-upload.c b/src/plugins/reporter-upload.c
index 16b588d..38de383 100644
--- a/src/plugins/reporter-upload.c
+++ b/src/plugins/reporter-upload.c
@@ -17,7 +17,7 @@
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 #include <libtar.h>
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 #include "internal_libreport.h"
 
 //TODO: use this for better logging
diff --git a/src/plugins/ureport.c b/src/plugins/ureport.c
index 5ffcea3..c75af63 100644
--- a/src/plugins/ureport.c
+++ b/src/plugins/ureport.c
@@ -20,7 +20,7 @@
 #include <json/json.h>
 #include "internal_libreport.h"
 #include "ureport.h"
-#include "abrt_curl.h"
+#include "libreport_curl.h"
 
 /*
  * Loads uReport configuration from various sources.
-- 
1.7.10.2

Reply via email to