Index: protocols/twitter/twitter.c
===================================================================
--- protocols/twitter/twitter.c	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter.c	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -27,4 +27,5 @@
 #include "twitter_http.h"
 #include "twitter_lib.h"
+#include "url.h"
 
 /**
@@ -70,5 +71,5 @@
 	"http://api.twitter.com/oauth/request_token",
 	"http://api.twitter.com/oauth/access_token",
-	"http://api.twitter.com/oauth/authorize",
+	"https://api.twitter.com/oauth/authorize",
 	.consumer_key = "xsDNKJuNZYkZyMcu914uEA",
 	.consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
@@ -160,4 +161,7 @@
 	set_t *s;
 	
+	s = set_add( &acc->set, "base_url", TWITTER_API_URL, NULL, acc );
+	s->flags |= ACC_SET_OFFLINE_ONLY;
+	
 	s = set_add( &acc->set, "message_length", "140", set_eval_int, acc );
 	
@@ -175,17 +179,31 @@
 {
 	struct im_connection *ic = imcb_new( acc );
-	struct twitter_data *td = g_new0( struct twitter_data, 1 );
+	struct twitter_data *td;
 	char name[strlen(acc->user)+9];
-
+	url_t url;
+
+	if( !url_set( &url, set_getstr( &ic->acc->set, "base_url" ) ) ||
+	    ( url.proto != PROTO_HTTP && url.proto != PROTO_HTTPS ) )
+	{
+		imcb_error( ic, "Incorrect API base URL: %s", set_getstr( &ic->acc->set, "base_url" ) );
+		imc_logout( ic, FALSE );
+		return;
+	}
+	
 	twitter_connections = g_slist_append( twitter_connections, ic );
+	td = g_new0( struct twitter_data, 1 );
 	ic->proto_data = td;
-	ic->flags |= OPT_DOES_HTML;
+	
+	td->url_ssl = url.proto == PROTO_HTTPS;
+	td->url_port = url.port;
+	td->url_host = g_strdup( url.host );
+	if( strcmp( url.file, "/" ) != 0 )
+		td->url_path = g_strdup( url.file );
+	else
+		td->url_path = g_strdup( "" );
 	
 	td->user = acc->user;
-	if( !set_getbool( &acc->set, "oauth" ) )
-		td->pass = g_strdup( acc->pass );
-	else if( strstr( acc->pass, "oauth_token=" ) )
+	if( strstr( acc->pass, "oauth_token=" ) )
 		td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
-	td->home_timeline_id = 0;
 	
 	sprintf( name, "twitter_%s", acc->user );
@@ -193,5 +211,5 @@
 	imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
 	
-	if( td->pass || td->oauth_info )
+	if( td->oauth_info || !set_getbool( &acc->set, "oauth" ) )
 		twitter_main_loop_start( ic );
 	else
Index: protocols/twitter/twitter.h
===================================================================
--- protocols/twitter/twitter.h	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter.h	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -42,4 +42,9 @@
 	struct groupchat *home_timeline_gc;
 	gint http_fails;
+	
+	gboolean url_ssl;
+	int url_port;
+	char *url_host;
+	char *url_path;
 };
 
Index: protocols/twitter/twitter_http.c
===================================================================
--- protocols/twitter/twitter_http.c	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter_http.c	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -41,5 +41,5 @@
 
 
-char *twitter_url_append(char *url, char *key, char* value);
+static char *twitter_url_append(char *url, char *key, char* value);
 
 /**
@@ -47,37 +47,13 @@
  * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
  */
-void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, struct oauth_info* oi, char** arguments, int arguments_len)
+void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, gpointer data, int is_post, char** arguments, int arguments_len)
 {
-	url_t *url = g_new0( url_t, 1 );
+	struct twitter_data *td = ic->proto_data;
 	char *tmp;
-	char *request;
+	GString *request = g_string_new("");
 	void *ret;
-	char *userpass = NULL;
-	char *userpass_base64;
 	char *url_arguments;
 
-	// Fill the url structure.
-	if( !url_set( url, url_string ) )
-	{
-		g_free( url );
-		return NULL;
-	}
-
-	if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
-	{
-		g_free( url );
-		return NULL;
-	}
-
-	// Concatenate user and pass
-	if (user && pass) {
-		userpass = g_strdup_printf("%s:%s", user, pass);
-		userpass_base64 = base64_encode((unsigned char*)userpass, strlen(userpass));
-	} else {
-		userpass_base64 = NULL;
-	}
-
-	url_arguments = g_malloc(1);
-	url_arguments[0] = '\0';
+	url_arguments = g_strdup("");
 
 	// Construct the url arguments.
@@ -93,40 +69,36 @@
 	}
 
-	// Do GET stuff...
-	if (!is_post)
-	{
-		// Find the char-pointer of the end of the string.
-		tmp = url->file + strlen(url->file);
-		tmp[0] = '?';
-		// append the url_arguments to the end of the url->file.
-		// TODO GM: Check the length?
-		g_stpcpy (tmp+1, url_arguments);
-	}
-
-
 	// Make the request.
-	request = g_strdup_printf(  "%s %s HTTP/1.0\r\n"
-	                            "Host: %s\r\n"
-	                            "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
-	                            is_post ? "POST" : "GET", url->file, url->host );
+	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",
+	                         td->url_path, url_string,
+	                         is_post ? "" : "?", is_post ? "" : url_arguments,
+	                         td->url_host);
 
 	// If a pass and user are given we append them to the request.
-	if (oi)
+	if (td->oauth_info)
 	{
 		char *full_header;
+		char *full_url;
 		
-		full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
-		                                url_string, url_arguments);
+		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);
 		
-		tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header);
-		g_free(request);
+		g_string_append_printf(request, "Authorization: %s\r\n", full_header);
 		g_free(full_header);
-		request = tmp;
+		g_free(full_url);
 	}
-	else if (userpass_base64)
+	else
 	{
-		tmp = g_strdup_printf("%sAuthorization: Basic %s\r\n", request, userpass_base64);
-		g_free(request);
-		request = tmp;
+		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 );
 	}
 
@@ -135,26 +107,21 @@
 	{
 		// Append the Content-Type and url-encoded arguments.
-		tmp = g_strdup_printf("%sContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %zd\r\n\r\n%s", 
-								request, strlen(url_arguments), url_arguments);
-		g_free(request);
-		request = tmp;
+		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...
-		tmp = g_strdup_printf("%s\r\n", request);
-		g_free(request);
-		request = tmp;
+		g_string_append(request, "\r\n");
 	}
 
-	ret = http_dorequest( url->host, url->port,	url->proto == PROTO_HTTPS, request, func, data );
+	ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data);
 
-	g_free( url );
-	g_free( userpass );
-	g_free( userpass_base64 );
 	g_free( url_arguments );
-	g_free( request );
+	g_string_free( request, TRUE );
 	return ret;
 }
 
-char *twitter_url_append(char *url, char *key, char* value)
+static char *twitter_url_append(char *url, char *key, char* value)
 {
 	char *key_encoded = g_strndup(key, 3 * strlen(key));
Index: protocols/twitter/twitter_http.h
===================================================================
--- protocols/twitter/twitter_http.h	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter_http.h	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -30,6 +30,6 @@
 struct oauth_info;
 
-void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, 
-                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
+void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func,
+                   gpointer data, int is_post, char** arguments, int arguments_len);
 
 #endif //_TWITTER_HTTP_H
Index: protocols/twitter/twitter_lib.c
===================================================================
--- protocols/twitter/twitter_lib.c	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter_lib.c	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -117,4 +117,35 @@
 }
 
+/* Warning: May return a malloc()ed value, which will be free()d on the next
+   call. Only for short-term use. */
+static char *twitter_parse_error(struct http_request *req)
+{
+	static char *ret = NULL;
+	struct xt_parser *xp = NULL;
+	struct xt_node *node;
+	
+	g_free(ret);
+	ret = NULL;
+	
+	if (req->body_size > 0)
+	{
+		xp = xt_new(NULL, NULL);
+		xt_feed(xp, req->reply_body, req->body_size);
+		
+		if ((node = xt_find_node(xp->root, "hash")) &&
+		    (node = xt_find_node(node->children, "error")) &&
+		    node->text_len > 0)
+		{
+			ret = g_strdup_printf("%s (%s)", req->status_string, node->text);
+			xt_free(xp);
+			return ret;
+		}
+		
+		xt_free(xp);
+	}
+	
+	return req->status_string;
+}
+
 static void twitter_http_get_friends_ids(struct http_request *req);
 
@@ -124,11 +155,9 @@
 void twitter_get_friends_ids(struct im_connection *ic, int next_cursor)
 {
-	struct twitter_data *td = ic->proto_data;
-
 	// Primitive, but hey! It works...	
 	char* args[2];
 	args[0] = "cursor";
 	args[1] = g_strdup_printf ("%d", next_cursor);
-	twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
+	twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2);
 
 	g_free(args[1]);
@@ -196,5 +225,5 @@
 		// It didn't go well, output the error and return.
 		if (++td->http_fails >= 5)
-			imcb_error(ic, "Could not retrieve friends. HTTP STATUS: %d", req->status_code);
+			imcb_error(ic, "Could not retrieve friends: %s", twitter_parse_error(req));
 		
 		return;
@@ -396,5 +425,5 @@
 	}
 
-	twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth_info, args, td->home_timeline_id ? 4 : 2);
+	twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, td->home_timeline_id ? 4 : 2);
 
 	g_free(args[1]);
@@ -434,4 +463,6 @@
 		twitter_add_buddy(ic, status->user->screen_name, status->user->name);
 		
+		strip_html(status->text);
+		
 		// Say it!
 		if (g_strcasecmp(td->user, status->user->screen_name) == 0)
@@ -471,4 +502,5 @@
 		status = l->data;
 		
+		strip_html( status->text );
 		if( mode_one )
 			text = g_strdup_printf( "\002<\002%s\002>\002 %s",
@@ -523,5 +555,5 @@
 		// It didn't go well, output the error and return.
 		if (++td->http_fails >= 5)
-			imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ". HTTP STATUS: %d", req->status_code);
+			imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ": %s", twitter_parse_error(req));
 		
 		return;
@@ -575,5 +607,5 @@
 		// It didn't go well, output the error and return.
 		if (++td->http_fails >= 5)
-			imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL " HTTP STATUS: %d", req->status_code);
+			imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL ": %s", twitter_parse_error(req));
 		
 		return;
@@ -614,11 +646,9 @@
 void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor)
 {
-	struct twitter_data *td = ic->proto_data;
-
 	char* args[2];
 	args[0] = "cursor";
 	args[1] = g_strdup_printf ("%d", next_cursor);
 
-	twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
+	twitter_http(ic, TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, args, 2);
 
 	g_free(args[1]);
@@ -639,5 +669,5 @@
 	if (req->status_code != 200) {
 		// It didn't go well, output the error and return.
-		imcb_error(ic, "HTTP Error... STATUS: %d", req->status_code);
+		imcb_error(ic, "HTTP error: %s", twitter_parse_error(req));
 		return;
 	}
@@ -649,10 +679,8 @@
 void twitter_post_status(struct im_connection *ic, char* msg)
 {
-	struct twitter_data *td = ic->proto_data;
-
 	char* args[2];
 	args[0] = "status";
 	args[1] = msg;
-	twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
+	twitter_http(ic, TWITTER_STATUS_UPDATE_URL, twitter_http_post, ic, 1, args, 2);
 //	g_free(args[1]);
 }
@@ -664,6 +692,4 @@
 void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)
 {
-	struct twitter_data *td = ic->proto_data;
-
 	char* args[4];
 	args[0] = "screen_name";
@@ -672,5 +698,5 @@
 	args[3] = msg;
 	// Use the same callback as for twitter_post_status, since it does basically the same.
-	twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
+	twitter_http(ic, TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post, ic, 1, args, 4);
 //	g_free(args[1]);
 //	g_free(args[3]);
@@ -679,12 +705,7 @@
 void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create)
 {
-	struct twitter_data *td = ic->proto_data;
-
 	char* args[2];
 	args[0] = "screen_name";
 	args[1] = who;
-	twitter_http(create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, twitter_http_post, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
-}
-
-
-
+	twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, twitter_http_post, ic, 1, args, 2);
+}
Index: protocols/twitter/twitter_lib.h
===================================================================
--- protocols/twitter/twitter_lib.h	(revision 7d53efb7ec5310b2710757cef03d7f53c94a7797)
+++ protocols/twitter/twitter_lib.h	(revision ba3233ce0b1fc34f3ad0a450bb1b661909dafb79)
@@ -32,47 +32,47 @@
 
 /* Status URLs */
-#define TWITTER_STATUS_UPDATE_URL TWITTER_API_URL "/statuses/update.xml"
-#define TWITTER_STATUS_SHOW_URL TWITTER_API_URL "/statuses/show/"
-#define TWITTER_STATUS_DESTROY_URL TWITTER_API_URL "/statuses/destroy/"
+#define TWITTER_STATUS_UPDATE_URL "/statuses/update.xml"
+#define TWITTER_STATUS_SHOW_URL "/statuses/show/"
+#define TWITTER_STATUS_DESTROY_URL "/statuses/destroy/"
 
 /* Timeline URLs */
-#define TWITTER_PUBLIC_TIMELINE_URL TWITTER_API_URL "/statuses/public_timeline.xml"
-#define TWITTER_FEATURED_USERS_URL TWITTER_API_URL "/statuses/featured.xml"
-#define TWITTER_FRIENDS_TIMELINE_URL TWITTER_API_URL "/statuses/friends_timeline.xml"
-#define TWITTER_HOME_TIMELINE_URL TWITTER_API_URL "/statuses/home_timeline.xml"
-#define TWITTER_MENTIONS_URL TWITTER_API_URL "/statuses/mentions.xml"
-#define TWITTER_USER_TIMELINE_URL TWITTER_API_URL "/statuses/user_timeline.xml"
+#define TWITTER_PUBLIC_TIMELINE_URL "/statuses/public_timeline.xml"
+#define TWITTER_FEATURED_USERS_URL "/statuses/featured.xml"
+#define TWITTER_FRIENDS_TIMELINE_URL "/statuses/friends_timeline.xml"
+#define TWITTER_HOME_TIMELINE_URL "/statuses/home_timeline.xml"
+#define TWITTER_MENTIONS_URL "/statuses/mentions.xml"
+#define TWITTER_USER_TIMELINE_URL "/statuses/user_timeline.xml"
 
 /* Users URLs */
-#define TWITTER_SHOW_USERS_URL TWITTER_API_URL "/users/show.xml"
-#define TWITTER_SHOW_FRIENDS_URL TWITTER_API_URL "/statuses/friends.xml"
-#define TWITTER_SHOW_FOLLOWERS_URL TWITTER_API_URL "/statuses/followers.xml"
+#define TWITTER_SHOW_USERS_URL "/users/show.xml"
+#define TWITTER_SHOW_FRIENDS_URL "/statuses/friends.xml"
+#define TWITTER_SHOW_FOLLOWERS_URL "/statuses/followers.xml"
 
 /* Direct messages URLs */
-#define TWITTER_DIRECT_MESSAGES_URL TWITTER_API_URL "/direct_messages.xml"
-#define TWITTER_DIRECT_MESSAGES_NEW_URL TWITTER_API_URL "/direct_messages/new.xml"
-#define TWITTER_DIRECT_MESSAGES_SENT_URL TWITTER_API_URL "/direct_messages/sent.xml"
-#define TWITTER_DIRECT_MESSAGES_DESTROY_URL TWITTER_API_URL "/direct_messages/destroy/"
+#define TWITTER_DIRECT_MESSAGES_URL "/direct_messages.xml"
+#define TWITTER_DIRECT_MESSAGES_NEW_URL "/direct_messages/new.xml"
+#define TWITTER_DIRECT_MESSAGES_SENT_URL "/direct_messages/sent.xml"
+#define TWITTER_DIRECT_MESSAGES_DESTROY_URL "/direct_messages/destroy/"
 
 /* Friendships URLs */
-#define TWITTER_FRIENDSHIPS_CREATE_URL TWITTER_API_URL "/friendships/create.xml"
-#define TWITTER_FRIENDSHIPS_DESTROY_URL TWITTER_API_URL "/friendships/destroy.xml"
-#define TWITTER_FRIENDSHIPS_SHOW_URL TWITTER_API_URL "/friendships/show.xml"
+#define TWITTER_FRIENDSHIPS_CREATE_URL "/friendships/create.xml"
+#define TWITTER_FRIENDSHIPS_DESTROY_URL "/friendships/destroy.xml"
+#define TWITTER_FRIENDSHIPS_SHOW_URL "/friendships/show.xml"
 
 /* Social graphs URLs */
-#define TWITTER_FRIENDS_IDS_URL TWITTER_API_URL "/friends/ids.xml"
-#define TWITTER_FOLLOWERS_IDS_URL TWITTER_API_URL "/followers/ids.xml"
+#define TWITTER_FRIENDS_IDS_URL "/friends/ids.xml"
+#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.xml"
 
 /* Account URLs */
-#define TWITTER_ACCOUNT_RATE_LIMIT_URL TWITTER_API_URL "/account/rate_limit_status.xml"
+#define TWITTER_ACCOUNT_RATE_LIMIT_URL "/account/rate_limit_status.xml"
 
 /* Favorites URLs */
-#define TWITTER_FAVORITES_GET_URL TWITTER_API_URL "/favorites.xml"
-#define TWITTER_FAVORITE_CREATE_URL TWITTER_API_URL "/favorites/create/"
-#define TWITTER_FAVORITE_DESTROY_URL TWITTER_API_URL "/favorites/destroy/"
+#define TWITTER_FAVORITES_GET_URL "/favorites.xml"
+#define TWITTER_FAVORITE_CREATE_URL "/favorites/create/"
+#define TWITTER_FAVORITE_DESTROY_URL "/favorites/destroy/"
 
 /* Block URLs */
-#define TWITTER_BLOCKS_CREATE_URL TWITTER_API_URL "/blocks/create/"
-#define TWITTER_BLOCKS_DESTROY_URL TWITTER_API_URL "/blocks/destroy/"
+#define TWITTER_BLOCKS_CREATE_URL "/blocks/create/"
+#define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/"
 
 void twitter_get_friends_ids(struct im_connection *ic, int next_cursor);
