aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/twitter/twitter_http.c
blob: 0f1ab51848011eea1764ac69f67379e624b294a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.hig
/***************************************************************************\
*                                                                           *
*  BitlBee - An IRC to IM gateway                                           *
*  Simple module to facilitate twitter functionality.                       *
*                                                                           *
*  Copyright 2009 Geert Mulders <g.c.w.m.mulders@gmail.com>                 *
*                                                                           *
*  This library is free software; you can redistribute it and/or            *
*  modify it under the terms of the GNU Lesser General Public               *
*  License as published by the Free Software Foundation, version            *
*  2.1.                                                                     *
*                                                                           *
*  This library 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        *
*  Lesser General Public License for more details.                          *
*                                                                           *
*  You should have received a copy of the GNU Lesser General Public License *
*  along with this library; if not, write to the Free Software Foundation,  *
*  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA           *
*                                                                           *
****************************************************************************/

/***************************************************************************\
*                                                                           *
*  Some funtions within this file have been copied from other files within  *
*  BitlBee.                                                                 *
*                                                                           *
****************************************************************************/

#include "twitter.h"
#include "bitlbee.h"
#include "url.h"
#include "misc.h"
#include "base64.h"
#include "oauth.h"
#include <ctype.h>
#include <errno.h>

#include "twitter_http.h"


static char *twitter_url_append(char *url, char *key, char *value);

/**
 * Do a request.
 * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
 */
struct http_request *twitter_http(struct im_connection *ic, char *url_string, http_input_function func,
		                  gpointer data, int is_post, char **arguments, int arguments_len)
{
	struct twitter_data *td = ic->proto_data;
	char *tmp;
	GString *request = g_string_new("");
	void *ret;
	char *url_arguments;
	url_t *base_url = NULL;

	url_arguments = g_strdup("");

	// Construct the url arguments.
	if (arguments_len != 0) {
		int i;
		for (i = 0; i < arguments_len; i += 2) {
			tmp = twitter_url_append(url_arguments, arguments[i], arguments[i + 1]);
			g_free(url_arguments);
			url_arguments = tmp;
		}
	}
	
	if (strstr(url_string, "://")) {
		base_url = g_new0(url_t, 1);
		if (!url_set(base_url, url_string)) {
			g_free(base_url);
			return NULL;
		}
	}
	
	// Make the request.
	g_string_printf(request, "%s %s%s%s%s HTTP/1.0\r\n"
			"Host: %s\r\n"
			"User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
			is_post ? "POST" : "GET",
			base_url ? base_url->file : td->url_path,
			base_url ? "" : url_string,
			is_post ? "" : "?", is_post ? "" : url_arguments,
			base_url ? base_url->host : td->url_host);

	// If a pass and user are given we append them to the request.
	if (td->oauth_info) {
		char *full_header;
		char *full_url;

		if (base_url)
			full_url = g_strdup(url_string);
		else
			full_url = g_strconcat(set_getstr(&ic->acc->set, "base_url"), url_string, NULL);
		full_header = oauth_http_header(td->oauth_info, is_post ? "POST" : "GET",
						full_url, url_arguments);

		g_string_append_printf(request, "Authorization: %s\r\n", full_header);
		g_free(full_header);
		g_free(full_url);
	} else {
		char userpass[strlen(ic->acc->user) + 2 + strlen(ic->acc->pass)];
		char *userpass_base64;

		g_snprintf(userpass, sizeof(userpass), "%s:%s", ic->acc->user, ic->acc->pass);
		userpass_base64 = base64_encode((unsigned char *) userpass, strlen(userpass));
		g_string_append_printf(request, "Authorization: Basic %s\r\n", userpass_base64);
		g_free(userpass_base64);
	}

	// Do POST stuff..
	if (is_post) {
		// Append the Content-Type and url-encoded arguments.
		g_string_append_printf(request,
				       "Content-Type: application/x-www-form-urlencoded\r\n"
				       "Content-Length: %zd\r\n\r\n%s",
				       strlen(url_arguments), url_arguments);
	} else {
		// Append an extra \r\n to end the request...
		g_string_append(request, "\r\n");
	}

	if (base_url)
		ret = http_dorequest(base_url->host, base_url->port, base_url->proto == PROTO_HTTPS, request->str, func, data);
	else
		ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data);

	g_free(url_arguments);
	g_string_free(request, TRUE);
	g_free(base_url);
	return ret;
}

struct http_request *twitter_http_f(struct im_connection *ic, char *url_string, http_input_function func,
		                    gpointer data, int is_post, char **arguments, int arguments_len, twitter_http_flags_t flags)
{
	struct http_request *ret = twitter_http(ic, url_string, func, data, is_post, arguments, arguments_len);
	if (ret)
		ret->flags |= flags;
	return ret;
}

static char *twitter_url_append(char *url, char *key, char *value)
{
	char *key_encoded = g_strndup(key, 3 * strlen(key));
	http_encode(key_encoded);
	char *value_encoded = g_strndup(value, 3 * strlen(value));
	http_encode(value_encoded);

	char *retval;
	if (strlen(url) != 0)
		retval = g_strdup_printf("%s&%s=%s", url, key_encoded, value_encoded);
	else
		retval = g_strdup_printf("%s=%s", key_encoded, value_encoded);

	g_free(key_encoded);
	g_free(value_encoded);

	return retval;
}