Advertisement
tomkiewicz

pidgin-curl-1

Sep 28th, 2012
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 14.13 KB | None | 0 0
  1. diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
  2. --- a/libpurple/Makefile.am
  3. +++ b/libpurple/Makefile.am
  4. @@ -46,6 +46,7 @@
  5.     connection.c \
  6.     conversation.c \
  7.     core.c \
  8. +   curl.c \
  9.     debug.c \
  10.     desktopitem.c \
  11.     eventloop.c \
  12. @@ -112,6 +113,7 @@
  13.     connection.h \
  14.     conversation.h \
  15.     core.h \
  16. +   curl.h \
  17.     dbus-maybe.h \
  18.     debug.h \
  19.     desktopitem.h \
  20. @@ -309,6 +311,7 @@
  21.     $(GSTREAMER_LIBS) \
  22.     $(GSTINTERFACES_LIBS) \
  23.     $(IDN_LIBS) \
  24. +   $(LIBCURL_LIBS) \
  25.     ciphers/libpurple-ciphers.la \
  26.     -lm
  27.  
  28. @@ -325,7 +328,8 @@
  29.     $(GSTREAMER_CFLAGS) \
  30.     $(GSTINTERFACES_CFLAGS) \
  31.     $(IDN_CFLAGS) \
  32. -   $(NETWORKMANAGER_CFLAGS)
  33. +   $(NETWORKMANAGER_CFLAGS) \
  34. +   $(LIBCURL_CFLAGS)
  35.  
  36.  # INSTALL_SSL_CERTIFICATES is true when SSL_CERTIFICATES_DIR is empty.
  37.  # We want to use SSL_CERTIFICATES_DIR when it's not empty.
  38. diff --git a/libpurple/core.c b/libpurple/core.c
  39. --- a/libpurple/core.c
  40. +++ b/libpurple/core.c
  41. @@ -52,6 +52,7 @@
  42.  #include "stun.h"
  43.  #include "theme-manager.h"
  44.  #include "util.h"
  45. +#include "curl.h"
  46.  
  47.  #ifdef HAVE_DBUS
  48.  #  ifndef DBUS_API_SUBJECT_TO_CHANGE
  49. @@ -172,6 +173,7 @@
  50.     purple_sound_init();
  51.     purple_ssl_init();
  52.     purple_stun_init();
  53. +   purple_curl_init_global();
  54.     purple_xfers_init();
  55.     purple_idle_init();
  56.     purple_smileys_init();
  57. @@ -228,6 +230,7 @@
  58.     purple_ciphers_uninit();
  59.     purple_notify_uninit();
  60.     purple_conversations_uninit();
  61. +   purple_curl_uninit();
  62.     purple_connections_uninit();
  63.     purple_buddy_icons_uninit();
  64.     purple_savedstatuses_uninit();
  65. diff --git a/libpurple/curl.c b/libpurple/curl.c
  66. new file mode 100644
  67. --- /dev/null
  68. +++ b/libpurple/curl.c
  69. @@ -0,0 +1,324 @@
  70. +/**
  71. + * @file curl.c cURL wrapper API
  72. + * @ingroup core
  73. + */
  74. +
  75. +/* purple
  76. + *
  77. + * Purple is the legal property of its developers, whose names are too numerous
  78. + * to list here.  Please refer to the COPYRIGHT file distributed with this
  79. + * source distribution.
  80. + *
  81. + * This program is free software; you can redistribute it and/or modify
  82. + * it under the terms of the GNU General Public License as published by
  83. + * the Free Software Foundation; either version 2 of the License, or
  84. + * (at your option) any later version.
  85. + *
  86. + * This program is distributed in the hope that it will be useful,
  87. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  88. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  89. + * GNU General Public License for more details.
  90. + *
  91. + * You should have received a copy of the GNU General Public License
  92. + * along with this program; if not, write to the Free Software
  93. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
  94. + */
  95. +#include "internal.h"
  96. +#include "curl.h"
  97. +
  98. +#include <debug.h>
  99. +#include <sys/select.h>
  100. +
  101. +static CURLM *multi_handle = NULL;
  102. +
  103. +static GHashTable *running_requests = NULL;
  104. +
  105. +static GPtrArray *input_handlers = NULL;
  106. +
  107. +static gint special_input_timer = -1;
  108. +
  109. +struct _purple_curl_results
  110. +{
  111. +   gboolean success;
  112. +   GString *data;
  113. +};
  114. +
  115. +typedef struct
  116. +{
  117. +   CURL *curl;
  118. +   purple_curl_cb cb;
  119. +   gpointer user_data;
  120. +  
  121. +   purple_curl_results *results;
  122. +} purple_curl_request;
  123. +
  124. +static void purple_curl_select(void);
  125. +
  126. +static purple_curl_results * purple_curl_results_new(void);
  127. +static void purple_curl_results_free(purple_curl_results *results);
  128. +static void purple_curl_results_callcb(purple_curl_request *request);
  129. +static size_t purple_curl_results_write(char *ptr, size_t size, size_t nmemb,
  130. +   void *userdata);
  131. +
  132. +CURL * purple_curl_init(void)
  133. +{
  134. +   CURL *curl;
  135. +
  136. +   curl = curl_easy_init();
  137. +   if (!curl) {
  138. +       purple_debug_fatal("curl", "curl_easy_init failed\n");
  139. +       return NULL;
  140. +   }
  141. +
  142. +   return curl;
  143. +}
  144. +
  145. +void purple_curl_cleanup(CURL *curl)
  146. +{
  147. +   CURLMcode ret;
  148. +
  149. +   ret = curl_multi_remove_handle(multi_handle, curl);
  150. +   if (ret != CURLM_OK) {
  151. +       purple_debug_fatal("curl", "curl_multi_remove_handle failed "
  152. +           "with error code %d\n", ret);
  153. +   }
  154. +
  155. +   curl_easy_cleanup(curl);
  156. +}
  157. +
  158. +void purple_curl_perform(CURL *curl, purple_curl_cb cb, gpointer user_data)
  159. +{
  160. +   CURLMcode ret;
  161. +   purple_curl_request *request;
  162. +
  163. +   g_return_if_fail(running_requests != NULL);
  164. +
  165. +   request = g_new0(purple_curl_request, 1);
  166. +
  167. +   if (running_requests == NULL) {
  168. +       purple_debug_fatal("curl", "purple_curl_perform: "
  169. +           "subsystem not initialized\n");
  170. +       purple_curl_results_callcb(request);
  171. +       return;
  172. +   }
  173. +
  174. +   if (g_hash_table_lookup(running_requests, curl) != NULL) {
  175. +       purple_debug_fatal("curl", "purple_curl_perform: "
  176. +           "request %p already running\n", curl);
  177. +       purple_curl_results_callcb(request);
  178. +       return;
  179. +   }
  180. +
  181. +   g_hash_table_insert(running_requests, curl, request);
  182. +
  183. +   request->curl = curl;
  184. +   request->cb = cb;
  185. +   request->user_data = user_data;
  186. +   request->results = purple_curl_results_new();
  187. +
  188. +   curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, purple_curl_results_write);
  189. +   curl_easy_setopt(curl, CURLOPT_WRITEDATA, request);
  190. +
  191. +   ret = curl_multi_add_handle(multi_handle, curl);
  192. +   if (ret != CURLM_OK) {
  193. +       purple_debug_fatal("curl", "curl_multi_add_handle failed with "
  194. +           "error code %d\n", ret);
  195. +       purple_curl_results_callcb(request);
  196. +       return;
  197. +   }
  198. +
  199. +   purple_curl_select();
  200. +}
  201. +
  202. +static void purple_curl_input_remove(gpointer data, gpointer user_data)
  203. +{
  204. +   guint handle = GPOINTER_TO_INT(data);
  205. +   purple_input_remove(handle);
  206. +}
  207. +
  208. +static void purple_curl_select_call(gpointer data, gint source,
  209. +   PurpleInputCondition cond)
  210. +{
  211. +   purple_curl_select();
  212. +}
  213. +
  214. +static gboolean purple_curl_select_call_timer(gpointer data)
  215. +{
  216. +   special_input_timer = -1;
  217. +   purple_curl_select();
  218. +   return FALSE;
  219. +}
  220. +
  221. +static void purple_curl_select(void)
  222. +{
  223. +   fd_set fdread, fdwrite, fdexcep;
  224. +   int fd, maxfd = -1;
  225. +   int r, running_requests_count;
  226. +   CURLMcode ret;
  227. +   CURLMsg *curl_msg;
  228. +   gboolean add_timer;
  229. +
  230. +   g_return_if_fail(running_requests != NULL);
  231. +
  232. +   g_ptr_array_foreach(input_handlers, purple_curl_input_remove, NULL);
  233. +   g_ptr_array_set_size(input_handlers, 0);
  234. +
  235. +   do {
  236. +       ret = curl_multi_perform(multi_handle, &running_requests_count);
  237. +   } while (ret == CURLM_CALL_MULTI_PERFORM);
  238. +
  239. +   if (ret != CURLM_OK) {
  240. +       purple_debug_fatal("curl", "curl_multi_perform failed with "
  241. +           "error code %d\n", ret);
  242. +       //purple_curl_results_callcb(request); TODO fail for all
  243. +       return;
  244. +   }
  245. +
  246. +   while (NULL != (curl_msg = curl_multi_info_read(multi_handle, &r))) {
  247. +       purple_curl_request *request;
  248. +       if (curl_msg->msg != CURLMSG_DONE)
  249. +           continue;
  250. +      
  251. +       request = g_hash_table_lookup(running_requests, curl_msg->easy_handle);
  252. +      
  253. +       if (curl_msg->data.result == CURLE_OK)
  254. +           request->results->success = TRUE;
  255. +       purple_curl_results_callcb(request);
  256. +   }
  257. +
  258. +   if (running_requests_count == 0)
  259. +   {
  260. +       //purple_debug_info("curl", "no more running requests\n");
  261. +       return;
  262. +   }
  263. +
  264. +   FD_ZERO(&fdread);
  265. +   FD_ZERO(&fdwrite);
  266. +   FD_ZERO(&fdexcep);
  267. +
  268. +   ret = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
  269. +   if (ret != CURLM_OK) {
  270. +       purple_debug_fatal("curl", "curl_multi_fdset failed with "
  271. +           "error code %d\n", ret);
  272. +       //purple_curl_results_callcb(request); TODO fail for all
  273. +       return;
  274. +   }
  275. +  
  276. +   if (maxfd == -1)
  277. +       add_timer = TRUE;
  278. +
  279. +   for (fd = 0; fd <= maxfd; fd++) {
  280. +       PurpleInputCondition cond = 0;
  281. +       if (FD_ISSET(fd, &fdread))
  282. +           cond |= PURPLE_INPUT_READ;
  283. +       if (FD_ISSET(fd, &fdwrite))
  284. +           cond |= PURPLE_INPUT_WRITE;
  285. +       if (FD_ISSET(fd, &fdexcep)) {
  286. +           purple_debug_warning("curl",
  287. +               "fdexcep is not supported\n");
  288. +           add_timer = TRUE;
  289. +       }
  290. +       if (cond != 0) {
  291. +           guint handle;
  292. +           handle = purple_input_add(fd, cond,
  293. +               purple_curl_select_call, NULL);
  294. +           g_ptr_array_add(input_handlers, GINT_TO_POINTER(handle));
  295. +       }
  296. +   }
  297. +
  298. +   if (add_timer && special_input_timer < 0) {
  299. +       special_input_timer = purple_timeout_add(100,
  300. +           purple_curl_select_call_timer, NULL);
  301. +   }
  302. +}
  303. +
  304. +gboolean purple_curl_results_succeeded(purple_curl_results *results)
  305. +{
  306. +   return TRUE;
  307. +}
  308. +
  309. +static purple_curl_results * purple_curl_results_new(void)
  310. +{
  311. +   purple_curl_results *results = g_new0(purple_curl_results, 1);
  312. +
  313. +   results->data = g_string_new("");
  314. +
  315. +   return results;
  316. +}
  317. +
  318. +static void purple_curl_results_free(purple_curl_results *results)
  319. +{
  320. +   g_string_free(results->data, TRUE);
  321. +   g_free(results);
  322. +}
  323. +
  324. +static void purple_curl_results_callcb(purple_curl_request *request)
  325. +{
  326. +   if (running_requests)
  327. +       g_hash_table_remove(running_requests, request->curl);
  328. +
  329. +   request->cb(request->curl, request->results, request->user_data);
  330. +   purple_curl_cleanup(request->curl);
  331. +   purple_curl_results_free(request->results);
  332. +   g_free(request);
  333. +}
  334. +
  335. +static size_t purple_curl_results_write(char *ptr, size_t size, size_t nmemb,
  336. +   void *userdata)
  337. +{
  338. +   purple_curl_request *request = userdata;
  339. +   size_t len = size * nmemb;
  340. +  
  341. +   if (request == NULL || request->results == NULL ||
  342. +       request->results->data == NULL)
  343. +       return 0;
  344. +  
  345. +   g_string_append_len(request->results->data, ptr, len);
  346. +   return len;
  347. +}
  348. +
  349. +const gchar * purple_curl_results_get_data(purple_curl_results *results)
  350. +{
  351. +   return results->data->str;
  352. +}
  353. +
  354. +static void purple_curl_running_request_stop(gpointer key, gpointer value, gpointer user_data)
  355. +{
  356. +   purple_curl_request *request = value;
  357. +  
  358. +   // TODO: stop curl request
  359. +  
  360. +   request->results->success = FALSE;
  361. +  
  362. +   purple_curl_results_callcb(request);
  363. +}
  364. +
  365. +void purple_curl_init_global(void)
  366. +{
  367. +   multi_handle = curl_multi_init();
  368. +   if (!multi_handle)
  369. +       purple_debug_fatal("curl", "curl_multi_init failed\n");
  370. +
  371. +   input_handlers = g_ptr_array_new();
  372. +
  373. +   running_requests = g_hash_table_new_full(
  374. +       g_direct_hash, g_direct_equal, NULL, NULL);
  375. +}
  376. +
  377. +void purple_curl_uninit(void)
  378. +{
  379. +   static GHashTable *stopping_requests;
  380. +  
  381. +   stopping_requests = running_requests;
  382. +   running_requests = NULL;
  383. +   g_hash_table_foreach(stopping_requests, purple_curl_running_request_stop, NULL);
  384. +   g_hash_table_destroy(stopping_requests);
  385. +
  386. +   g_ptr_array_free(input_handlers, TRUE);
  387. +
  388. +   curl_multi_cleanup(multi_handle);
  389. +   multi_handle = NULL;
  390. +
  391. +   if (special_input_timer > -1)
  392. +       purple_timeout_remove(special_input_timer);
  393. +}
  394. diff --git a/libpurple/curl.h b/libpurple/curl.h
  395. new file mode 100644
  396. --- /dev/null
  397. +++ b/libpurple/curl.h
  398. @@ -0,0 +1,82 @@
  399. +/**
  400. + * @file curl.h cURL wrapper API
  401. + * @ingroup core
  402. + */
  403. +
  404. +/* purple
  405. + *
  406. + * Purple is the legal property of its developers, whose names are too numerous
  407. + * to list here.  Please refer to the COPYRIGHT file distributed with this
  408. + * source distribution.
  409. + *
  410. + * This program is free software; you can redistribute it and/or modify
  411. + * it under the terms of the GNU General Public License as published by
  412. + * the Free Software Foundation; either version 2 of the License, or
  413. + * (at your option) any later version.
  414. + *
  415. + * This program is distributed in the hope that it will be useful,
  416. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  417. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  418. + * GNU General Public License for more details.
  419. + *
  420. + * You should have received a copy of the GNU General Public License
  421. + * along with this program; if not, write to the Free Software
  422. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
  423. + */
  424. +#ifndef _PURPLE_CURL_H_
  425. +#define _PURPLE_CURL_H_
  426. +
  427. +#include <glib.h>
  428. +#include <curl/curl.h>
  429. +
  430. +typedef struct _purple_curl_results purple_curl_results;
  431. +
  432. +typedef void (*purple_curl_cb)(CURL *curl, purple_curl_results *results,
  433. +   gpointer user_data);
  434. +
  435. +G_BEGIN_DECLS
  436. +
  437. +/**************************************************************************/
  438. +/** @name cURL wrapper API                                                */
  439. +/**************************************************************************/
  440. +/*@{*/
  441. +
  442. +CURL * purple_curl_init(void);
  443. +
  444. +void purple_curl_cleanup(CURL *curl);
  445. +
  446. +void purple_curl_perform(CURL *curl, purple_curl_cb cb, gpointer user_data);
  447. +
  448. +/*@}*/
  449. +
  450. +/**************************************************************************/
  451. +/** @name cURL results API                                                */
  452. +/**************************************************************************/
  453. +/*@{*/
  454. +
  455. +gboolean purple_curl_results_succeeded(purple_curl_results *results);
  456. +
  457. +const gchar * purple_curl_results_get_data(purple_curl_results *results);
  458. +
  459. +/*@}*/
  460. +
  461. +/**************************************************************************/
  462. +/** @name cURL wrapper subsystem                                          */
  463. +/**************************************************************************/
  464. +/*@{*/
  465. +
  466. +/**
  467. + * Initializes the cURL wrapper system.
  468. + */
  469. +void purple_curl_init_global(void);
  470. +
  471. +/**
  472. + * Uninitializes the cURL wrapper system.
  473. + */
  474. +void purple_curl_uninit(void);
  475. +
  476. +/*@}*/
  477. +
  478. +G_END_DECLS
  479. +
  480. +#endif /* _PURPLE_CURL_H_ */
  481. diff --git a/libpurple/protocols/gg/gg.c b/libpurple/protocols/gg/gg.c
  482. --- a/libpurple/protocols/gg/gg.c
  483. +++ b/libpurple/protocols/gg/gg.c
  484. @@ -53,6 +53,56 @@
  485.  #include "servconn.h"
  486.  #include "pubdir-prpl.h"
  487.  
  488. +#include <curl.h>
  489. +
  490. +static void ggp_curl_test_legacy_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
  491. +   const gchar *url_text, gsize len, const gchar *error_message)
  492. +{
  493. +   if (!url_text)
  494. +       url_text = "(null)";
  495. +   purple_debug_info("curltest", "legacy-got: [%s]\n", url_text);
  496. +}
  497. +
  498. +static void ggp_curl_test_legacy(PurpleConnection *gc)
  499. +{
  500. +   PurpleAccount *account = purple_connection_get_account(gc);
  501. +
  502. +   purple_util_fetch_url_request(account,
  503. +       "http://www.wasilczyk.pl/x_ip_simple.htm",
  504. +       TRUE, /* full */
  505. +       NULL, /* user_agent */
  506. +       TRUE, /* http11 */
  507. +       NULL, /* request */
  508. +       FALSE, /* include_headers */
  509. +       -1, /* max_len */
  510. +       ggp_curl_test_legacy_cb,
  511. +       NULL); /* user_data */
  512. +}
  513. +
  514. +static void ggp_curl_test_cb(CURL *curl, purple_curl_results *results, gpointer user_data)
  515. +{
  516. +   purple_debug_info("curltest", "success=%d\n", purple_curl_results_succeeded(results));
  517. +   purple_debug_info("curltest", "data=[%s]\n", purple_curl_results_get_data(results));
  518. +}
  519. +
  520. +static void ggp_curl_test(PurpleConnection *gc)
  521. +{
  522. +   int i;
  523. +   CURL *curl;
  524. +
  525. +   ggp_curl_test_legacy(gc);
  526. +
  527. +   for (i = 0; i < 20; i++) {
  528. +       curl = purple_curl_init();
  529. +       if (!curl)
  530. +           return;
  531. +       curl_easy_setopt(curl, CURLOPT_URL, "http://www.wasilczyk.pl/x_ip_simple.htm");
  532. +       purple_curl_perform(curl, ggp_curl_test_cb, NULL);
  533. +   }
  534. +
  535. +   purple_debug_info("curltest", "test ended\n");
  536. +}
  537. +
  538.  /* ---------------------------------------------------------------------- */
  539.  
  540.  ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy)
  541. @@ -875,6 +925,10 @@
  542.     const char *address;
  543.     const gchar *encryption_type;
  544.  
  545. +   ggp_curl_test(gc);
  546. +
  547. +   return;
  548. +
  549.     if (!ggp_deprecated_setup_proxy(gc))
  550.         return;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement