diff options
Diffstat (limited to 'src/http.c')
-rw-r--r-- | src/http.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/src/http.c b/src/http.c new file mode 100644 index 0000000..8239ac8 --- /dev/null +++ b/src/http.c @@ -0,0 +1,145 @@ +/* + * transmission-remote-gtk - A GTK RPC client to Transmission + * Copyright (C) 2010 Alan Fitton + + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <curl/curl.h> +#include <curl/types.h> +#include <curl/easy.h> + +#include <glib-object.h> +#include <json-glib/json-glib.h> + +#include "trg-client.h" +#include "http.h" + +static struct http_response *trg_http_perform_inner(trg_client * client, + gchar * req, + gboolean recurse); + +static size_t http_receive_callback(void *ptr, size_t size, size_t nmemb, + void *data); + +static size_t header_callback(void *ptr, size_t size, size_t nmemb, + void *data); + +void http_response_free(struct http_response *response) +{ + if (response->data != NULL) + g_free(response->data); + + g_free(response); +} + +static struct http_response *trg_http_perform_inner(trg_client * tc, + gchar * req, + gboolean recurse) +{ + CURL *handle; + long httpCode; + struct http_response *response; + struct curl_slist *headers = NULL; + + response = g_new(struct http_response, 1); + response->size = 0; + response->status = -1; + response->data = NULL; + + handle = curl_easy_init(); + + curl_easy_setopt(handle, CURLOPT_USERAGENT, "trg"); + curl_easy_setopt(handle, CURLOPT_PASSWORD, tc->password); + curl_easy_setopt(handle, CURLOPT_USERNAME, tc->username); + curl_easy_setopt(handle, CURLOPT_URL, tc->url); + curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, + &http_receive_callback); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *) response); + curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, &header_callback); + curl_easy_setopt(handle, CURLOPT_WRITEHEADER, (void *) tc); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, req); + /*curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */ + + if (tc->session_id != NULL) { + headers = curl_slist_append(headers, tc->session_id); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + } + + response->status = curl_easy_perform(handle); + + curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &httpCode); + curl_easy_cleanup(handle); + + if (headers != NULL) + curl_slist_free_all(headers); + + if (response->status == CURLE_OK) { + if (httpCode == HTTP_CONFLICT && recurse == TRUE) { + http_response_free(response); + return trg_http_perform_inner(tc, req, FALSE); + } else if (httpCode != HTTP_OK) { + response->status = (-httpCode) - 100; + } + } + + return response; +} + +struct http_response *trg_http_perform(trg_client * tc, gchar * req) +{ + return trg_http_perform_inner(tc, req, TRUE); +} + +static size_t +http_receive_callback(void *ptr, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; + struct http_response *mem = (struct http_response *) data; + + mem->data = realloc(mem->data, mem->size + realsize + 1); + if (mem->data) { + memcpy(&(mem->data[mem->size]), ptr, realsize); + mem->size += realsize; + mem->data[mem->size] = 0; + } + return realsize; +} + +static size_t header_callback(void *ptr, size_t size, size_t nmemb, + void *data) +{ + char *header = (char *) (ptr); + trg_client *client = (trg_client *) data; + + if (g_str_has_prefix(header, "X-Transmission-Session-Id: ") == TRUE) { + char *nl; + + if (client->session_id != NULL) + g_free(client->session_id); + + client->session_id = g_strdup(header); + nl = strrchr(client->session_id, '\r'); + if (nl) + *nl = '\0'; + } + + return (nmemb * size); +} |