Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
- --- a/libpurple/Makefile.am
- +++ b/libpurple/Makefile.am
- @@ -46,6 +46,7 @@
- connection.c \
- conversation.c \
- core.c \
- + curl.c \
- debug.c \
- desktopitem.c \
- eventloop.c \
- @@ -112,6 +113,7 @@
- connection.h \
- conversation.h \
- core.h \
- + curl.h \
- dbus-maybe.h \
- debug.h \
- desktopitem.h \
- @@ -309,6 +311,7 @@
- $(GSTREAMER_LIBS) \
- $(GSTINTERFACES_LIBS) \
- $(IDN_LIBS) \
- + $(LIBCURL_LIBS) \
- ciphers/libpurple-ciphers.la \
- -lm
- @@ -325,7 +328,8 @@
- $(GSTREAMER_CFLAGS) \
- $(GSTINTERFACES_CFLAGS) \
- $(IDN_CFLAGS) \
- - $(NETWORKMANAGER_CFLAGS)
- + $(NETWORKMANAGER_CFLAGS) \
- + $(LIBCURL_CFLAGS)
- # INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
- # We want to use SSL_CERTIFICATES_DIR when it's not empty.
- diff --git a/libpurple/core.c b/libpurple/core.c
- --- a/libpurple/core.c
- +++ b/libpurple/core.c
- @@ -52,6 +52,7 @@
- #include "stun.h"
- #include "theme-manager.h"
- #include "util.h"
- +#include "curl.h"
- #ifdef HAVE_DBUS
- # ifndef DBUS_API_SUBJECT_TO_CHANGE
- @@ -172,6 +173,7 @@
- purple_sound_init();
- purple_ssl_init();
- purple_stun_init();
- + purple_curl_init_global();
- purple_xfers_init();
- purple_idle_init();
- purple_smileys_init();
- @@ -228,6 +230,7 @@
- purple_ciphers_uninit();
- purple_notify_uninit();
- purple_conversations_uninit();
- + purple_curl_uninit();
- purple_connections_uninit();
- purple_buddy_icons_uninit();
- purple_savedstatuses_uninit();
- diff --git a/libpurple/curl.c b/libpurple/curl.c
- new file mode 100644
- --- /dev/null
- +++ b/libpurple/curl.c
- @@ -0,0 +1,324 @@
- +/**
- + * @file curl.c cURL wrapper API
- + * @ingroup core
- + */
- +
- +/* purple
- + *
- + * Purple is the legal property of its developers, whose names are too numerous
- + * to list here. Please refer to the COPYRIGHT file distributed with this
- + * source distribution.
- + *
- + * 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 02111-1301 USA
- + */
- +#include "internal.h"
- +#include "curl.h"
- +
- +#include <debug.h>
- +#include <sys/select.h>
- +
- +static CURLM *multi_handle = NULL;
- +
- +static GHashTable *running_requests = NULL;
- +
- +static GPtrArray *input_handlers = NULL;
- +
- +static gint special_input_timer = -1;
- +
- +struct _purple_curl_results
- +{
- + gboolean success;
- + GString *data;
- +};
- +
- +typedef struct
- +{
- + CURL *curl;
- + purple_curl_cb cb;
- + gpointer user_data;
- +
- + purple_curl_results *results;
- +} purple_curl_request;
- +
- +static void purple_curl_select(void);
- +
- +static purple_curl_results * purple_curl_results_new(void);
- +static void purple_curl_results_free(purple_curl_results *results);
- +static void purple_curl_results_callcb(purple_curl_request *request);
- +static size_t purple_curl_results_write(char *ptr, size_t size, size_t nmemb,
- + void *userdata);
- +
- +CURL * purple_curl_init(void)
- +{
- + CURL *curl;
- +
- + curl = curl_easy_init();
- + if (!curl) {
- + purple_debug_fatal("curl", "curl_easy_init failed\n");
- + return NULL;
- + }
- +
- + return curl;
- +}
- +
- +void purple_curl_cleanup(CURL *curl)
- +{
- + CURLMcode ret;
- +
- + ret = curl_multi_remove_handle(multi_handle, curl);
- + if (ret != CURLM_OK) {
- + purple_debug_fatal("curl", "curl_multi_remove_handle failed "
- + "with error code %d\n", ret);
- + }
- +
- + curl_easy_cleanup(curl);
- +}
- +
- +void purple_curl_perform(CURL *curl, purple_curl_cb cb, gpointer user_data)
- +{
- + CURLMcode ret;
- + purple_curl_request *request;
- +
- + g_return_if_fail(running_requests != NULL);
- +
- + request = g_new0(purple_curl_request, 1);
- +
- + if (running_requests == NULL) {
- + purple_debug_fatal("curl", "purple_curl_perform: "
- + "subsystem not initialized\n");
- + purple_curl_results_callcb(request);
- + return;
- + }
- +
- + if (g_hash_table_lookup(running_requests, curl) != NULL) {
- + purple_debug_fatal("curl", "purple_curl_perform: "
- + "request %p already running\n", curl);
- + purple_curl_results_callcb(request);
- + return;
- + }
- +
- + g_hash_table_insert(running_requests, curl, request);
- +
- + request->curl = curl;
- + request->cb = cb;
- + request->user_data = user_data;
- + request->results = purple_curl_results_new();
- +
- + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, purple_curl_results_write);
- + curl_easy_setopt(curl, CURLOPT_WRITEDATA, request);
- +
- + ret = curl_multi_add_handle(multi_handle, curl);
- + if (ret != CURLM_OK) {
- + purple_debug_fatal("curl", "curl_multi_add_handle failed with "
- + "error code %d\n", ret);
- + purple_curl_results_callcb(request);
- + return;
- + }
- +
- + purple_curl_select();
- +}
- +
- +static void purple_curl_input_remove(gpointer data, gpointer user_data)
- +{
- + guint handle = GPOINTER_TO_INT(data);
- + purple_input_remove(handle);
- +}
- +
- +static void purple_curl_select_call(gpointer data, gint source,
- + PurpleInputCondition cond)
- +{
- + purple_curl_select();
- +}
- +
- +static gboolean purple_curl_select_call_timer(gpointer data)
- +{
- + special_input_timer = -1;
- + purple_curl_select();
- + return FALSE;
- +}
- +
- +static void purple_curl_select(void)
- +{
- + fd_set fdread, fdwrite, fdexcep;
- + int fd, maxfd = -1;
- + int r, running_requests_count;
- + CURLMcode ret;
- + CURLMsg *curl_msg;
- + gboolean add_timer;
- +
- + g_return_if_fail(running_requests != NULL);
- +
- + g_ptr_array_foreach(input_handlers, purple_curl_input_remove, NULL);
- + g_ptr_array_set_size(input_handlers, 0);
- +
- + do {
- + ret = curl_multi_perform(multi_handle, &running_requests_count);
- + } while (ret == CURLM_CALL_MULTI_PERFORM);
- +
- + if (ret != CURLM_OK) {
- + purple_debug_fatal("curl", "curl_multi_perform failed with "
- + "error code %d\n", ret);
- + //purple_curl_results_callcb(request); TODO fail for all
- + return;
- + }
- +
- + while (NULL != (curl_msg = curl_multi_info_read(multi_handle, &r))) {
- + purple_curl_request *request;
- + if (curl_msg->msg != CURLMSG_DONE)
- + continue;
- +
- + request = g_hash_table_lookup(running_requests, curl_msg->easy_handle);
- +
- + if (curl_msg->data.result == CURLE_OK)
- + request->results->success = TRUE;
- + purple_curl_results_callcb(request);
- + }
- +
- + if (running_requests_count == 0)
- + {
- + //purple_debug_info("curl", "no more running requests\n");
- + return;
- + }
- +
- + FD_ZERO(&fdread);
- + FD_ZERO(&fdwrite);
- + FD_ZERO(&fdexcep);
- +
- + ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
- + if (ret != CURLM_OK) {
- + purple_debug_fatal("curl", "curl_multi_fdset failed with "
- + "error code %d\n", ret);
- + //purple_curl_results_callcb(request); TODO fail for all
- + return;
- + }
- +
- + if (maxfd == -1)
- + add_timer = TRUE;
- +
- + for (fd = 0; fd <= maxfd; fd++) {
- + PurpleInputCondition cond = 0;
- + if (FD_ISSET(fd, &fdread))
- + cond |= PURPLE_INPUT_READ;
- + if (FD_ISSET(fd, &fdwrite))
- + cond |= PURPLE_INPUT_WRITE;
- + if (FD_ISSET(fd, &fdexcep)) {
- + purple_debug_warning("curl",
- + "fdexcep is not supported\n");
- + add_timer = TRUE;
- + }
- + if (cond != 0) {
- + guint handle;
- + handle = purple_input_add(fd, cond,
- + purple_curl_select_call, NULL);
- + g_ptr_array_add(input_handlers, GINT_TO_POINTER(handle));
- + }
- + }
- +
- + if (add_timer && special_input_timer < 0) {
- + special_input_timer = purple_timeout_add(100,
- + purple_curl_select_call_timer, NULL);
- + }
- +}
- +
- +gboolean purple_curl_results_succeeded(purple_curl_results *results)
- +{
- + return TRUE;
- +}
- +
- +static purple_curl_results * purple_curl_results_new(void)
- +{
- + purple_curl_results *results = g_new0(purple_curl_results, 1);
- +
- + results->data = g_string_new("");
- +
- + return results;
- +}
- +
- +static void purple_curl_results_free(purple_curl_results *results)
- +{
- + g_string_free(results->data, TRUE);
- + g_free(results);
- +}
- +
- +static void purple_curl_results_callcb(purple_curl_request *request)
- +{
- + if (running_requests)
- + g_hash_table_remove(running_requests, request->curl);
- +
- + request->cb(request->curl, request->results, request->user_data);
- + purple_curl_cleanup(request->curl);
- + purple_curl_results_free(request->results);
- + g_free(request);
- +}
- +
- +static size_t purple_curl_results_write(char *ptr, size_t size, size_t nmemb,
- + void *userdata)
- +{
- + purple_curl_request *request = userdata;
- + size_t len = size * nmemb;
- +
- + if (request == NULL || request->results == NULL ||
- + request->results->data == NULL)
- + return 0;
- +
- + g_string_append_len(request->results->data, ptr, len);
- + return len;
- +}
- +
- +const gchar * purple_curl_results_get_data(purple_curl_results *results)
- +{
- + return results->data->str;
- +}
- +
- +static void purple_curl_running_request_stop(gpointer key, gpointer value, gpointer user_data)
- +{
- + purple_curl_request *request = value;
- +
- + // TODO: stop curl request
- +
- + request->results->success = FALSE;
- +
- + purple_curl_results_callcb(request);
- +}
- +
- +void purple_curl_init_global(void)
- +{
- + multi_handle = curl_multi_init();
- + if (!multi_handle)
- + purple_debug_fatal("curl", "curl_multi_init failed\n");
- +
- + input_handlers = g_ptr_array_new();
- +
- + running_requests = g_hash_table_new_full(
- + g_direct_hash, g_direct_equal, NULL, NULL);
- +}
- +
- +void purple_curl_uninit(void)
- +{
- + static GHashTable *stopping_requests;
- +
- + stopping_requests = running_requests;
- + running_requests = NULL;
- + g_hash_table_foreach(stopping_requests, purple_curl_running_request_stop, NULL);
- + g_hash_table_destroy(stopping_requests);
- +
- + g_ptr_array_free(input_handlers, TRUE);
- +
- + curl_multi_cleanup(multi_handle);
- + multi_handle = NULL;
- +
- + if (special_input_timer > -1)
- + purple_timeout_remove(special_input_timer);
- +}
- diff --git a/libpurple/curl.h b/libpurple/curl.h
- new file mode 100644
- --- /dev/null
- +++ b/libpurple/curl.h
- @@ -0,0 +1,82 @@
- +/**
- + * @file curl.h cURL wrapper API
- + * @ingroup core
- + */
- +
- +/* purple
- + *
- + * Purple is the legal property of its developers, whose names are too numerous
- + * to list here. Please refer to the COPYRIGHT file distributed with this
- + * source distribution.
- + *
- + * 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 02111-1301 USA
- + */
- +#ifndef _PURPLE_CURL_H_
- +#define _PURPLE_CURL_H_
- +
- +#include <glib.h>
- +#include <curl/curl.h>
- +
- +typedef struct _purple_curl_results purple_curl_results;
- +
- +typedef void (*purple_curl_cb)(CURL *curl, purple_curl_results *results,
- + gpointer user_data);
- +
- +G_BEGIN_DECLS
- +
- +/**************************************************************************/
- +/** @name cURL wrapper API */
- +/**************************************************************************/
- +/*@{*/
- +
- +CURL * purple_curl_init(void);
- +
- +void purple_curl_cleanup(CURL *curl);
- +
- +void purple_curl_perform(CURL *curl, purple_curl_cb cb, gpointer user_data);
- +
- +/*@}*/
- +
- +/**************************************************************************/
- +/** @name cURL results API */
- +/**************************************************************************/
- +/*@{*/
- +
- +gboolean purple_curl_results_succeeded(purple_curl_results *results);
- +
- +const gchar * purple_curl_results_get_data(purple_curl_results *results);
- +
- +/*@}*/
- +
- +/**************************************************************************/
- +/** @name cURL wrapper subsystem */
- +/**************************************************************************/
- +/*@{*/
- +
- +/**
- + * Initializes the cURL wrapper system.
- + */
- +void purple_curl_init_global(void);
- +
- +/**
- + * Uninitializes the cURL wrapper system.
- + */
- +void purple_curl_uninit(void);
- +
- +/*@}*/
- +
- +G_END_DECLS
- +
- +#endif /* _PURPLE_CURL_H_ */
- diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
- --- a/libpurple/protocols/gg/gg.c
- +++ b/libpurple/protocols/gg/gg.c
- @@ -53,6 +53,56 @@
- #include "servconn.h"
- #include "pubdir-prpl.h"
- +#include <curl.h>
- +
- +static void ggp_curl_test_legacy_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
- + const gchar *url_text, gsize len, const gchar *error_message)
- +{
- + if (!url_text)
- + url_text = "(null)";
- + purple_debug_info("curltest", "legacy-got: [%s]\n", url_text);
- +}
- +
- +static void ggp_curl_test_legacy(PurpleConnection *gc)
- +{
- + PurpleAccount *account = purple_connection_get_account(gc);
- +
- + purple_util_fetch_url_request(account,
- + "http://www.wasilczyk.pl/x_ip_simple.htm",
- + TRUE, /* full */
- + NULL, /* user_agent */
- + TRUE, /* http11 */
- + NULL, /* request */
- + FALSE, /* include_headers */
- + -1, /* max_len */
- + ggp_curl_test_legacy_cb,
- + NULL); /* user_data */
- +}
- +
- +static void ggp_curl_test_cb(CURL *curl, purple_curl_results *results, gpointer user_data)
- +{
- + purple_debug_info("curltest", "success=%d\n", purple_curl_results_succeeded(results));
- + purple_debug_info("curltest", "data=[%s]\n", purple_curl_results_get_data(results));
- +}
- +
- +static void ggp_curl_test(PurpleConnection *gc)
- +{
- + int i;
- + CURL *curl;
- +
- + ggp_curl_test_legacy(gc);
- +
- + for (i = 0; i < 20; i++) {
- + curl = purple_curl_init();
- + if (!curl)
- + return;
- + curl_easy_setopt(curl, CURLOPT_URL, "http://www.wasilczyk.pl/x_ip_simple.htm");
- + purple_curl_perform(curl, ggp_curl_test_cb, NULL);
- + }
- +
- + purple_debug_info("curltest", "test ended\n");
- +}
- +
- /* ---------------------------------------------------------------------- */
- ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy)
- @@ -875,6 +925,10 @@
- const char *address;
- const gchar *encryption_type;
- + ggp_curl_test(gc);
- +
- + return;
- +
- if (!ggp_deprecated_setup_proxy(gc))
- return;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement