summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-03-25 14:20:40 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-03-25 14:20:40 +0100
commit7b721840773a6faf2fa93562aeae1cc4c7d05804 (patch)
tree2c2a631f2e33def142f5e3d235884c14790ab88b /lib
parent8481061ffa1ea3fb84952dae88c817e9049325b1 (diff)
downloadabrt-7b721840773a6faf2fa93562aeae1cc4c7d05804.tar.gz
abrt-7b721840773a6faf2fa93562aeae1cc4c7d05804.tar.xz
abrt-7b721840773a6faf2fa93562aeae1cc4c7d05804.zip
rhticket: factor out HTTP POST code into abrt_curl.{h,cpp}
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Plugins/Catcut.cpp1
-rw-r--r--lib/Plugins/FileTransfer.cpp2
-rw-r--r--lib/Plugins/KerneloopsReporter.cpp2
-rw-r--r--lib/Plugins/TicketUploader.cpp2
-rw-r--r--lib/Plugins/rhticket.cpp147
-rw-r--r--lib/Utils/Makefile.am1
-rw-r--r--lib/Utils/abrt_curl.cpp193
-rw-r--r--lib/Utils/abrt_curl.h45
-rw-r--r--lib/Utils/abrt_xmlrpc.cpp10
-rw-r--r--lib/Utils/abrt_xmlrpc.h1
10 files changed, 254 insertions, 150 deletions
diff --git a/lib/Plugins/Catcut.cpp b/lib/Plugins/Catcut.cpp
index 48546367..6c655f2b 100644
--- a/lib/Plugins/Catcut.cpp
+++ b/lib/Plugins/Catcut.cpp
@@ -17,6 +17,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "abrtlib.h"
+#include "abrt_curl.h"
#include "abrt_xmlrpc.h"
#include "Catcut.h"
#include "CrashTypes.h"
diff --git a/lib/Plugins/FileTransfer.cpp b/lib/Plugins/FileTransfer.cpp
index 8f5bc6db..f0bb047b 100644
--- a/lib/Plugins/FileTransfer.cpp
+++ b/lib/Plugins/FileTransfer.cpp
@@ -26,7 +26,7 @@
#include <bzlib.h>
#include <zlib.h>
#include "abrtlib.h"
-#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
+#include "abrt_curl.h"
#include "FileTransfer.h"
#include "DebugDump.h"
#include "ABRTException.h"
diff --git a/lib/Plugins/KerneloopsReporter.cpp b/lib/Plugins/KerneloopsReporter.cpp
index 4271e1d9..8c4fe114 100644
--- a/lib/Plugins/KerneloopsReporter.cpp
+++ b/lib/Plugins/KerneloopsReporter.cpp
@@ -18,7 +18,7 @@
*/
#include "abrtlib.h"
-#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
+#include "abrt_curl.h"
#include "KerneloopsReporter.h"
#include "CommLayerInner.h"
#include "ABRTException.h"
diff --git a/lib/Plugins/TicketUploader.cpp b/lib/Plugins/TicketUploader.cpp
index a7151b5e..2acb7b49 100644
--- a/lib/Plugins/TicketUploader.cpp
+++ b/lib/Plugins/TicketUploader.cpp
@@ -18,7 +18,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "abrtlib.h"
-#include "abrt_xmlrpc.h" /* for xcurl_easy_init */
+#include "abrt_curl.h"
#include "TicketUploader.h"
#include "DebugDump.h"
#include "ABRTException.h"
diff --git a/lib/Plugins/rhticket.cpp b/lib/Plugins/rhticket.cpp
index e0e72ff2..b5abf9df 100644
--- a/lib/Plugins/rhticket.cpp
+++ b/lib/Plugins/rhticket.cpp
@@ -19,7 +19,7 @@
#define _GNU_SOURCE 1 /* for stpcpy */
#include "abrtlib.h"
-#include "abrt_xmlrpc.h" /* for xcurl_easy_handle */
+#include "abrt_curl.h"
#include "rhticket.h"
#include "CrashTypes.h"
#include "DebugDump.h"
@@ -81,136 +81,6 @@ static char *xml_escape(const char *str)
return result;
}
-static char*
-check_curl_error(CURLcode err, const char* msg)
-{
- if (err)
- {
- return xasprintf("%s: %s", msg, curl_easy_strerror(err));
- }
- return NULL;
-}
-
-//
-// Examine each header looking for "Location:" header
-//
-struct Headerdata {
- char *location;
-};
-
-static size_t
-headerfunction(void *buffer_pv, size_t count, size_t nmemb, void *headerdata_pv)
-{
- struct Headerdata* headerdata = (struct Headerdata*)headerdata_pv;
- const char* buffer = (const char*)buffer_pv;
- const char location_key[] = "Location:";
- const size_t location_key_size = sizeof(location_key)-1;
-
- size_t size = count * nmemb;
- if (size >= location_key_size
- && 0 == memcmp(buffer, location_key, location_key_size)
- ) {
- const char* start = (const char*) buffer + location_key_size + 1;
- const char* end;
-
- // skip over any leading space
- while (start < buffer+size && isspace(*start))
- ++start;
-
- end = start;
-
- // skip till we find the end of the url (first space or end of buffer)
- while (end < buffer+size && !isspace(*end))
- ++end;
-
- headerdata->location = xstrndup(start, end - start);
- }
-
- return size;
-}
-
-static char*
-post(int *http_resp_code, const char* url, const char* data)
-{
- char *retval;
- CURLcode curl_err;
- struct curl_slist *httpheader_list = NULL;
- struct Headerdata headerdata = { NULL };
-
- if (http_resp_code)
- *http_resp_code = -1;
-
- CURL *handle = xcurl_easy_init();
-
- curl_err = curl_easy_setopt(handle, CURLOPT_VERBOSE, 0);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_VERBOSE)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 1);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_NOPROGRESS)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_POST, 1);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_POST)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_URL, url);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_URL)");
- if (retval)
- goto ret;
-
- httpheader_list = curl_slist_append(httpheader_list, "Content-Type: application/xml");
- curl_err = curl_easy_setopt(handle, CURLOPT_HTTPHEADER, httpheader_list);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_HTTPHEADER)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_POSTFIELDS)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, headerfunction);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_HEADERFUNCTION)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_setopt(handle, CURLOPT_WRITEHEADER, &headerdata);
- retval = check_curl_error(curl_err, "curl_easy_setopt(CURLOPT_WRITEHEADER)");
- if (retval)
- goto ret;
-
- curl_err = curl_easy_perform(handle);
- retval = check_curl_error(curl_err, "curl_easy_perform");
- if (retval)
- goto ret;
-
- long response_code;
- curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
- retval = check_curl_error(curl_err, "curl_easy_getinfo(CURLINFO_RESPONSE_CODE)");
- if (retval)
- goto ret;
-
- if (http_resp_code)
- *http_resp_code = response_code;
- switch (response_code)
- {
- case 200:
- case 201:
- retval = headerdata.location;
- break;
- /* default: */
- /* TODO: extract meaningful error string from server reply */
- }
-
- ret:
- curl_easy_cleanup(handle);
- curl_slist_free_all(httpheader_list);
- return retval;
-}
/*
* CReporterRHticket
@@ -266,17 +136,22 @@ string CReporterRHticket::Report(const map_crash_data_t& pCrashData,
free(xml_description);
string url = concat_path_file(m_sStrataURL.c_str(), "cases");
- int http_resp_code;
- char *res = post(&http_resp_code, url.c_str(), postdata.c_str());
- string result = res ? res : "";
- free(res);
+ curl_post_state *state = new_curl_post_state(0
+ + ABRT_CURL_POST_WANT_HEADERS
+ + ABRT_CURL_POST_WANT_ERROR_MSG);
+ int http_resp_code = curl_post(state, url.c_str(), postdata.c_str());
+
if (http_resp_code / 100 != 2)
{
/* not 2xx */
+ string errmsg = state->curl_error_msg ? state->curl_error_msg : "(none)";
+ free_curl_post_state(state);
throw CABRTException(EXCEP_PLUGIN, _("server returned HTTP code %u, error message: %s"),
- http_resp_code, res ? result.c_str() : "(none)");
+ http_resp_code, errmsg.c_str());
}
+ string result = find_header_in_curl_post_state(state, "Location:") ? : "";
+ free_curl_post_state(state);
return result;
}
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index 976cf318..aff324d6 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -45,6 +45,7 @@ libABRTdUtils_la_SOURCES = \
make_descr.cpp \
CommLayerInner.h CommLayerInner.cpp \
abrt_xmlrpc.h abrt_xmlrpc.cpp \
+ abrt_curl.h abrt_curl.cpp \
Plugin.h Plugin.cpp \
Polkit.h Polkit.cpp \
Action.h Database.h Reporter.h Analyzer.h \
diff --git a/lib/Utils/abrt_curl.cpp b/lib/Utils/abrt_curl.cpp
new file mode 100644
index 00000000..f327bd8c
--- /dev/null
+++ b/lib/Utils/abrt_curl.cpp
@@ -0,0 +1,193 @@
+/*
+ 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 "abrtlib.h"
+#include "abrt_curl.h"
+#include "CommLayerInner.h"
+
+using namespace std;
+
+/*
+ * Utility function
+ */
+CURL* xcurl_easy_init()
+{
+ CURL* curl = curl_easy_init();
+ if (!curl)
+ {
+ error_msg_and_die("Can't create curl handle");
+ }
+ return curl;
+}
+
+
+/*
+ * curl_post: perform HTTP POST transaction
+ */
+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)
+{
+ char *msg = check_curl_error(err, "curl");
+ if (msg)
+ error_msg_and_die("%s", msg);
+}
+
+/* "save headers" callback */
+static size_t
+save_headers(void *buffer_pv, size_t count, size_t nmemb, void *ptr)
+{
+ curl_post_state_t* state = (curl_post_state_t*)ptr;
+ size_t size = count * nmemb;
+
+
+ unsigned cnt = state->header_cnt;
+ state->headers = (char**)xrealloc(state->headers, (cnt+2) * sizeof(state->headers[0]));
+
+ char *h = xstrndup((char*)buffer_pv, size);
+ strchrnul(h, '\r')[0] = '\0';
+ strchrnul(h, '\n')[0] = '\0';
+ VERB3 log("save_headers: state:%p header %d: '%s'", state, cnt, h);
+ state->headers[cnt] = h;
+ state->header_cnt = ++cnt;
+ state->headers[cnt] = NULL;
+
+ return size;
+}
+
+int
+curl_post(curl_post_state_t* state, const char* url, const char* data)
+{
+ CURLcode curl_err;
+ struct curl_slist *httpheader_list = NULL;
+ FILE* body_stream = NULL;
+ long response_code;
+ curl_post_state_t localstate;
+
+ VERB3 log("curl_post('%s','%s')", url, data);
+
+ if (!state)
+ {
+ memset(&localstate, 0, sizeof(localstate));
+ state = &localstate;
+ }
+
+ state->http_resp_code = response_code = -1;
+ state->curl_error_msg = NULL;
+
+ CURL *handle = xcurl_easy_init();
+
+ curl_err = curl_easy_setopt(handle, CURLOPT_VERBOSE, 0);
+ die_if_curl_error(curl_err);
+ curl_err = curl_easy_setopt(handle, CURLOPT_NOPROGRESS, 1);
+ die_if_curl_error(curl_err);
+ curl_err = curl_easy_setopt(handle, CURLOPT_URL, url);
+ die_if_curl_error(curl_err);
+ curl_err = curl_easy_setopt(handle, CURLOPT_POST, 1);
+ die_if_curl_error(curl_err);
+ curl_err = curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data);
+ die_if_curl_error(curl_err);
+
+ httpheader_list = curl_slist_append(httpheader_list, "Content-Type: application/xml");
+ curl_err = curl_easy_setopt(handle, CURLOPT_HTTPHEADER, httpheader_list);
+ die_if_curl_error(curl_err);
+
+ if (state->flags & ABRT_CURL_POST_WANT_HEADERS)
+ {
+ curl_err = curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, save_headers);
+ die_if_curl_error(curl_err);
+ curl_err = curl_easy_setopt(handle, CURLOPT_WRITEHEADER, state);
+ die_if_curl_error(curl_err);
+ }
+ if (state->flags & ABRT_CURL_POST_WANT_BODY)
+ {
+ body_stream = open_memstream(&state->body, &state->body_size);
+ if (!body_stream)
+ error_msg_and_die("out of memory");
+ curl_err = curl_easy_setopt(handle, CURLOPT_WRITEDATA, body_stream);
+ die_if_curl_error(curl_err);
+ }
+
+ /* 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(handle);
+ if (curl_err)
+ {
+ if (state->flags & ABRT_CURL_POST_WANT_ERROR_MSG)
+ state->curl_error_msg = check_curl_error(curl_err, "curl_easy_perform");
+ goto ret;
+ }
+
+ curl_err = curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &response_code);
+ die_if_curl_error(curl_err);
+ state->http_resp_code = response_code;
+
+ ret:
+ curl_easy_cleanup(handle);
+ curl_slist_free_all(httpheader_list);
+ if (body_stream)
+ fclose(body_stream);
+
+ return response_code;
+}
+
+curl_post_state_t *new_curl_post_state(int flags)
+{
+ curl_post_state_t *state = (curl_post_state_t *)xzalloc(sizeof(*state));
+ state->flags = flags;
+ return state;
+}
+
+void free_curl_post_state(curl_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_curl_post_state(curl_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;
+}
diff --git a/lib/Utils/abrt_curl.h b/lib/Utils/abrt_curl.h
new file mode 100644
index 00000000..3c302453
--- /dev/null
+++ b/lib/Utils/abrt_curl.h
@@ -0,0 +1,45 @@
+/*
+ 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>
+
+CURL* xcurl_easy_init();
+
+typedef struct curl_post_state {
+ int flags;
+ int http_resp_code;
+ unsigned header_cnt;
+ char **headers;
+ char *curl_error_msg;
+ char *body;
+ size_t body_size;
+} curl_post_state_t;
+enum {
+ ABRT_CURL_POST_WANT_HEADERS = (1 << 0),
+ ABRT_CURL_POST_WANT_ERROR_MSG = (1 << 1),
+ ABRT_CURL_POST_WANT_BODY = (1 << 2),
+};
+curl_post_state_t *new_curl_post_state(int flags);
+void free_curl_post_state(curl_post_state_t *state);
+int curl_post(curl_post_state_t* state, const char* url, const char* data);
+char *find_header_in_curl_post_state(curl_post_state_t *state, const char *str);
+
+#endif
diff --git a/lib/Utils/abrt_xmlrpc.cpp b/lib/Utils/abrt_xmlrpc.cpp
index 8be74d85..cbe09907 100644
--- a/lib/Utils/abrt_xmlrpc.cpp
+++ b/lib/Utils/abrt_xmlrpc.cpp
@@ -23,16 +23,6 @@
#include "abrt_xmlrpc.h"
#include "ABRTException.h"
-CURL* xcurl_easy_init()
-{
- CURL* curl = curl_easy_init();
- if (!curl)
- {
- error_msg_and_die("Can't create curl handle");
- }
- return curl;
-}
-
void throw_xml_fault(xmlrpc_env *env)
{
std::string errmsg = ssprintf("XML-RPC Fault(%d): %s", env->fault_code, env->fault_string);
diff --git a/lib/Utils/abrt_xmlrpc.h b/lib/Utils/abrt_xmlrpc.h
index 4d20d4e8..ce770384 100644
--- a/lib/Utils/abrt_xmlrpc.h
+++ b/lib/Utils/abrt_xmlrpc.h
@@ -44,6 +44,5 @@ struct abrt_xmlrpc_conn {
/* Utility functions */
void throw_xml_fault(xmlrpc_env *env);
void throw_if_xml_fault_occurred(xmlrpc_env *env);
-CURL* xcurl_easy_init();
#endif