Index: lib/oauth.c
===================================================================
--- lib/oauth.c	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ lib/oauth.c	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -33,12 +33,8 @@
 #include "oauth.h"
 
-#define CONSUMER_KEY "xsDNKJuNZYkZyMcu914uEA"
-#define CONSUMER_SECRET "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo"
-/* How can it be a secret if it's right here in the source code? No clue... */
-
 #define HMAC_BLOCK_SIZE 64
 
 static char *oauth_sign( const char *method, const char *url,
-                         const char *params, const char *token_secret )
+                         const char *params, struct oauth_info *oi )
 {
 	sha1_state_t sha1;
@@ -51,12 +47,12 @@
 	   otherwise just pad. */
 	memset( key, 0, HMAC_BLOCK_SIZE );
-	i = strlen( CONSUMER_SECRET ) + 1 + ( token_secret ? strlen( token_secret ) : 0 );
+	i = strlen( oi->sp->consumer_secret ) + 1 + ( oi->token_secret ? strlen( oi->token_secret ) : 0 );
 	if( i > HMAC_BLOCK_SIZE )
 	{
 		sha1_init( &sha1 );
-		sha1_append( &sha1, (uint8_t*) CONSUMER_SECRET, strlen( CONSUMER_SECRET ) );
+		sha1_append( &sha1, (uint8_t*) oi->sp->consumer_secret, strlen( oi->sp->consumer_secret ) );
 		sha1_append( &sha1, (uint8_t*) "&", 1 );
-		if( token_secret )
-			sha1_append( &sha1, (uint8_t*) token_secret, strlen( token_secret ) );
+		if( oi->token_secret )
+			sha1_append( &sha1, (uint8_t*) oi->token_secret, strlen( oi->token_secret ) );
 		sha1_finish( &sha1, key );
 	}
@@ -64,5 +60,5 @@
 	{
 		g_snprintf( (gchar*) key, HMAC_BLOCK_SIZE + 1, "%s&%s",
-		            CONSUMER_SECRET, token_secret ? : "" );
+		            oi->sp->consumer_secret, oi->token_secret ? : "" );
 	}
 	
@@ -229,16 +225,17 @@
 	if( info )
 	{
-		g_free( info->auth_params );
+		g_free( info->auth_url );
 		g_free( info->request_token );
-		g_free( info->access_token );
+		g_free( info->token );
+		g_free( info->token_secret );
 		g_free( info );
 	}
 }
 
-static void oauth_add_default_params( GSList **params )
+static void oauth_add_default_params( GSList **params, const struct oauth_service *sp )
 {
 	char *s;
 	
-	oauth_params_set( params, "oauth_consumer_key", CONSUMER_KEY );
+	oauth_params_set( params, "oauth_consumer_key", sp->consumer_key );
 	oauth_params_set( params, "oauth_signature_method", "HMAC-SHA1" );
 	
@@ -254,5 +251,5 @@
 }
 
-static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, void *data )
+static void *oauth_post_request( const char *url, GSList **params_, http_input_function func, struct oauth_info *oi )
 {
 	GSList *params = NULL;
@@ -270,10 +267,10 @@
 		params = *params_;
 	
-	oauth_add_default_params( &params );
+	oauth_add_default_params( &params, oi->sp );
 	
 	params_s = oauth_params_string( params );
 	oauth_params_free( &params );
 	
-	s = oauth_sign( "POST", url, params_s, NULL );
+	s = oauth_sign( "POST", url, params_s, oi );
 	post = g_strdup_printf( "%s&oauth_signature=%s", params_s, s );
 	g_free( params_s );
@@ -289,5 +286,5 @@
 	
 	req = http_dorequest( url_p.host, url_p.port, url_p.proto == PROTO_HTTPS,
-	                      s, func, data );
+	                      s, func, oi );
 	g_free( s );
 	
@@ -297,5 +294,5 @@
 static void oauth_request_token_done( struct http_request *req );
 
-struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data )
+struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data )
 {
 	struct oauth_info *st = g_new0( struct oauth_info, 1 );
@@ -304,8 +301,9 @@
 	st->func = func;
 	st->data = data;
+	st->sp = sp;
 	
 	oauth_params_add( &params, "oauth_callback", "oob" );
 	
-	if( !oauth_post_request( url, &params, oauth_request_token_done, st ) )
+	if( !oauth_post_request( sp->url_request_token, &params, oauth_request_token_done, st ) )
 	{
 		oauth_info_free( st );
@@ -326,6 +324,6 @@
 		GSList *params = NULL;
 		
-		st->auth_params = g_strdup( req->reply_body );
-		oauth_params_parse( &params, st->auth_params );
+		st->auth_url = g_strdup_printf( "%s?%s", st->sp->url_authorize, req->reply_body );
+		oauth_params_parse( &params, req->reply_body );
 		st->request_token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
 		oauth_params_free( &params );
@@ -333,11 +331,10 @@
 	
 	st->stage = OAUTH_REQUEST_TOKEN;
-	if( !st->func( st ) )
-		oauth_info_free( st );
+	st->func( st );
 }
 
 static void oauth_access_token_done( struct http_request *req );
 
-void oauth_access_token( const char *url, const char *pin, struct oauth_info *st )
+gboolean oauth_access_token( const char *pin, struct oauth_info *st )
 {
 	GSList *params = NULL;
@@ -346,6 +343,5 @@
 	oauth_params_add( &params, "oauth_verifier", pin );
 	
-	if( !oauth_post_request( url, &params, oauth_access_token_done, st ) )
-		oauth_info_free( st );
+	return oauth_post_request( st->sp->url_access_token, &params, oauth_access_token_done, st ) != NULL;
 }
 
@@ -359,37 +355,30 @@
 	{
 		GSList *params = NULL;
-		const char *token, *token_secret;
 		
 		oauth_params_parse( &params, req->reply_body );
-		token = oauth_params_get( &params, "oauth_token" );
-		token_secret = oauth_params_get( &params, "oauth_token_secret" );
-		st->access_token = g_strdup_printf(
-			"oauth_token=%s&oauth_token_secret=%s", token, token_secret );
+		st->token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
+		st->token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
 		oauth_params_free( &params );
 	}
 	
 	st->stage = OAUTH_ACCESS_TOKEN;
-	st->func( st );
-	oauth_info_free( st );
-}
-
-char *oauth_http_header( char *access_token, const char *method, const char *url, char *args )
+	if( st->func( st ) )
+	{
+		/* Don't need these anymore, but keep the rest. */
+		g_free( st->auth_url );
+		st->auth_url = NULL;
+		g_free( st->request_token );
+		st->request_token = NULL;
+	}
+}
+
+char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args )
 {
 	GSList *params = NULL, *l;
-	char *token_secret = NULL, *sig = NULL, *params_s, *s;
+	char *sig = NULL, *params_s, *s;
 	GString *ret = NULL;
 	
-	/* First, get the two pieces of info from the access token that we need. */
-	oauth_params_parse( &params, access_token );
-	if( params == NULL )
-		goto err;
-	
-	/* Pick out the token secret, we shouldn't include it but use it for signing. */
-	token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
-	if( token_secret == NULL )
-		goto err;
-	oauth_params_del( &params, "oauth_token_secret" );
-	
-	oauth_add_default_params( &params );
+	oauth_params_add( &params, "oauth_token", oi->token );
+	oauth_add_default_params( &params, oi->sp );
 	
 	/* Start building the OAuth header. 'key="value", '... */
@@ -421,5 +410,5 @@
 	{
 		s = g_strdup( s + 1 );
-		oauth_params_parse( &params, s + 1 );
+		oauth_params_parse( &params, s );
 		g_free( s );
 	}
@@ -427,13 +416,38 @@
 	/* Append the signature and we're done! */
 	params_s = oauth_params_string( params );
-	sig = oauth_sign( method, url, params_s, token_secret );
+	sig = oauth_sign( method, url, params_s, oi );
 	g_string_append_printf( ret, "oauth_signature=\"%s\"", sig );
 	g_free( params_s );
 	
-err:
 	oauth_params_free( &params );
 	g_free( sig );
-	g_free( token_secret );
 	
 	return ret ? g_string_free( ret, FALSE ) : NULL;
 }
+
+char *oauth_to_string( struct oauth_info *oi )
+{
+	GSList *params = NULL;
+	char *ret;
+	
+	oauth_params_add( &params, "oauth_token", oi->token );
+	oauth_params_add( &params, "oauth_token_secret", oi->token_secret );
+	ret = oauth_params_string( params );
+	oauth_params_free( &params );
+	
+	return ret;
+}
+
+struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp )
+{
+	struct oauth_info *oi = g_new0( struct oauth_info, 1 );
+	GSList *params = NULL;
+	
+	oauth_params_parse( &params, in );
+	oi->token = g_strdup( oauth_params_get( &params, "oauth_token" ) );
+	oi->token_secret = g_strdup( oauth_params_get( &params, "oauth_token_secret" ) );
+	oauth_params_free( &params );
+	oi->sp = sp;
+	
+	return oi;
+}
Index: lib/oauth.h
===================================================================
--- lib/oauth.h	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ lib/oauth.h	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -40,4 +40,5 @@
 {
 	oauth_stage_t stage;
+	const struct oauth_service *sp;
 	
 	oauth_cb func;
@@ -46,8 +47,19 @@
 	struct http_request *http;
 	
-	char *auth_params;
+	char *auth_url;
 	char *request_token;
 	
-	char *access_token;
+	char *token;
+	char *token_secret;
+};
+
+struct oauth_service
+{
+	char *url_request_token;
+	char *url_access_token;
+	char *url_authorize;
+	
+	char *consumer_key;
+	char *consumer_secret;
 };
 
@@ -56,5 +68,5 @@
    authorization URL for the user. This is passed to the callback function
    in a struct oauth_info. */
-struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data );
+struct oauth_info *oauth_request_token( const struct oauth_service *sp, oauth_cb func, void *data );
 
 /* http://oauth.net/core/1.0a/#auth_step3 (section 6.3)
@@ -62,5 +74,5 @@
    token. This is passed to the callback function in the same
    struct oauth_info. */
-void oauth_access_token( const char *url, const char *pin, struct oauth_info *st );
+gboolean oauth_access_token( const char *pin, struct oauth_info *st );
 
 /* http://oauth.net/core/1.0a/#anchor12 (section 7)
@@ -69,6 +81,10 @@
    whatever's going to be in the POST body of the request. GET args will
    automatically be grabbed from url. */
-char *oauth_http_header( char *access_token, const char *method, const char *url, char *args );
+char *oauth_http_header( struct oauth_info *oi, const char *method, const char *url, char *args );
 
 /* Shouldn't normally be required unless the process is aborted by the user. */
 void oauth_info_free( struct oauth_info *info );
+
+/* Convert to and back from strings, for easier saving. */
+char *oauth_to_string( struct oauth_info *oi );
+struct oauth_info *oauth_from_string( char *in, const struct oauth_service *sp );
Index: protocols/twitter/twitter.c
===================================================================
--- protocols/twitter/twitter.c	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ protocols/twitter/twitter.c	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -28,5 +28,4 @@
 #include "twitter_lib.h"
 
-
 /**
  * Main loop function
@@ -66,4 +65,14 @@
 }
 
+
+static const struct oauth_service twitter_oauth =
+{
+	"http://api.twitter.com/oauth/request_token",
+	"http://api.twitter.com/oauth/access_token",
+	"http://api.twitter.com/oauth/authorize",
+	.consumer_key = "xsDNKJuNZYkZyMcu914uEA",
+	.consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
+};
+
 static gboolean twitter_oauth_callback( struct oauth_info *info );
 
@@ -74,6 +83,5 @@
 	imcb_log( ic, "Requesting OAuth request token" );
 
-	td->oauth_info = oauth_request_token(
-		TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic );
+	td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic );
 }
 
@@ -100,6 +108,6 @@
 		sprintf( name, "twitter_%s", ic->acc->user );
 		msg = g_strdup_printf( "To finish OAuth authentication, please visit "
-		                       "%s?%s and respond with the resulting PIN code.",
-		                       TWITTER_OAUTH_AUTHORIZE, info->auth_params );
+		                       "%s and respond with the resulting PIN code.",
+		                       info->auth_url );
 		imcb_buddy_msg( ic, name, msg, 0, 0 );
 		g_free( msg );
@@ -107,5 +115,5 @@
 	else if( info->stage == OAUTH_ACCESS_TOKEN )
 	{
-		if( info->access_token == NULL )
+		if( info->token == NULL || info->token_secret == NULL )
 		{
 			imcb_error( ic, "OAuth error: %s", info->http->status_string );
@@ -114,10 +122,8 @@
 		}
 		
-		td->oauth = g_strdup( info->access_token );
-		
 		/* IM mods didn't do this so far and it's ugly but I should
 		   be able to get away with it... */
 		g_free( ic->acc->pass );
-		ic->acc->pass = g_strdup( info->access_token );
+		ic->acc->pass = oauth_to_string( info );
 		
 		twitter_main_loop_start( ic );
@@ -126,4 +132,5 @@
 	return TRUE;
 }
+
 
 static char *set_eval_mode( set_t *set, char *value )
@@ -165,5 +172,5 @@
 		td->pass = g_strdup( acc->pass );
 	else if( strstr( acc->pass, "oauth_token=" ) )
-		td->oauth = g_strdup( acc->pass );
+		td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
 	td->home_timeline_id = 0;
 	
@@ -172,5 +179,5 @@
 	imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
 	
-	if( td->pass || td->oauth )
+	if( td->pass || td->oauth_info )
 		twitter_main_loop_start( ic );
 	else
@@ -197,7 +204,5 @@
 	{
 		oauth_info_free( td->oauth_info );
-		
 		g_free( td->pass );
-		g_free( td->oauth );
 		g_free( td );
 	}
@@ -216,8 +221,13 @@
 	    g_strcasecmp(who + 8, ic->acc->user) == 0)
 	{
-		if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth_info )
+		if( set_getbool( &ic->acc->set, "oauth" ) &&
+		    td->oauth_info && td->oauth_info->token == NULL )
 		{
-			oauth_access_token( TWITTER_OAUTH_ACCESS_TOKEN, message, td->oauth_info );
-			td->oauth_info = NULL;
+			if( !oauth_access_token( message, td->oauth_info ) )
+			{
+				imcb_error( ic, "OAuth error: %s", "Failed to send access token request" );
+				imc_logout( ic, TRUE );
+				return FALSE;
+			}
 		}
 		else
Index: protocols/twitter/twitter.h
===================================================================
--- protocols/twitter/twitter.h	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ protocols/twitter/twitter.h	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -37,5 +37,4 @@
 	char* user;
 	char* pass;
-	char* oauth;
 	struct oauth_info *oauth_info;
 	guint64 home_timeline_id;
@@ -52,7 +51,3 @@
 GSList *twitter_connections;
 
-#define TWITTER_OAUTH_REQUEST_TOKEN "http://api.twitter.com/oauth/request_token"
-#define TWITTER_OAUTH_ACCESS_TOKEN  "http://api.twitter.com/oauth/access_token"
-#define TWITTER_OAUTH_AUTHORIZE     "http://api.twitter.com/oauth/authorize"
-
 #endif //_TWITTER_H
Index: protocols/twitter/twitter_http.c
===================================================================
--- protocols/twitter/twitter_http.c	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ protocols/twitter/twitter_http.c	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -29,5 +29,4 @@
 ****************************************************************************/ 
 
-#include "twitter_http.h"
 #include "twitter.h"
 #include "bitlbee.h"
@@ -39,4 +38,6 @@
 #include <errno.h>
 
+#include "twitter_http.h"
+
 
 char *twitter_url_append(char *url, char *key, char* value);
@@ -46,5 +47,5 @@
  * 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, char* oauth_token, char** arguments, int arguments_len)
+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)
 {
 	url_t *url = g_new0( url_t, 1 );
@@ -111,10 +112,9 @@
 
 	// If a pass and user are given we append them to the request.
-	if (oauth_token)
+	if (oi)
 	{
 		char *full_header;
 		
-		full_header = oauth_http_header(oauth_token,
-		                                is_post ? "POST" : "GET",
+		full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
 		                                url_string, url_arguments);
 		
Index: protocols/twitter/twitter_http.h
===================================================================
--- protocols/twitter/twitter_http.h	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ protocols/twitter/twitter_http.h	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -28,6 +28,8 @@
 #include "http_client.h"
 
+struct oauth_info;
+
 void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, 
-                   char* user, char* pass, char *oauth_token, char** arguments, int arguments_len);
+                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
 
 #endif //_TWITTER_HTTP_H
Index: protocols/twitter/twitter_lib.c
===================================================================
--- protocols/twitter/twitter_lib.c	(revision 839189b091ee82937666bcaa328a7d3ecd1c573b)
+++ protocols/twitter/twitter_lib.c	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
@@ -130,5 +130,5 @@
 	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, args, 2);
+	twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
 
 	g_free(args[1]);
@@ -396,5 +396,5 @@
 	}
 
-	twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, td->oauth, args, td->home_timeline_id ? 4 : 2);
+	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);
 
 	g_free(args[1]);
@@ -510,5 +510,5 @@
 	{
 		td->http_fails = 0;
-		if (!ic->flags & OPT_LOGGED_IN)
+		if (!(ic->flags & OPT_LOGGED_IN))
 			imcb_connected(ic);
 	}
@@ -620,5 +620,5 @@
 	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, args, 2);
+	twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
 
 	g_free(args[1]);
@@ -654,5 +654,5 @@
 	args[0] = "status";
 	args[1] = msg;
-	twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth, args, 2);
+	twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
 //	g_free(args[1]);
 }
@@ -672,5 +672,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_status, ic, 1, td->user, td->pass, td->oauth, args, 4);
+	twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
 //	g_free(args[1]);
 //	g_free(args[3]);
