diff options
| -rw-r--r-- | lib/oauth.c | 40 | ||||
| -rw-r--r-- | lib/oauth.h | 12 | ||||
| -rw-r--r-- | protocols/twitter/twitter.c | 30 | 
3 files changed, 64 insertions, 18 deletions
diff --git a/lib/oauth.c b/lib/oauth.c index 0ab94c96..97017043 100644 --- a/lib/oauth.c +++ b/lib/oauth.c @@ -224,6 +224,17 @@ char *oauth_params_string( GSList *params )  	return g_string_free( str, FALSE );  } +void oauth_info_free( struct oauth_info *info ) +{ +	if( info ) +	{ +		g_free( info->auth_params ); +		g_free( info->request_token ); +		g_free( info->access_token ); +		g_free( info ); +	} +} +  static void oauth_add_default_params( GSList **params )  {  	char *s; @@ -285,7 +296,7 @@ static void *oauth_post_request( const char *url, GSList **params_, http_input_f  static void oauth_request_token_done( struct http_request *req ); -void *oauth_request_token( const char *url, oauth_cb func, void *data ) +struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data )  {  	struct oauth_info *st = g_new0( struct oauth_info, 1 );  	GSList *params = NULL; @@ -295,7 +306,13 @@ void *oauth_request_token( const char *url, oauth_cb func, void *data )  	oauth_params_add( ¶ms, "oauth_callback", "oob" ); -	return oauth_post_request( url, NULL, oauth_request_token_done, st ); +	if( !oauth_post_request( url, ¶ms, oauth_request_token_done, st ) ) +	{ +		oauth_info_free( st ); +		return NULL; +	} +	 +	return st;  }  static void oauth_request_token_done( struct http_request *req ) @@ -315,19 +332,21 @@ static void oauth_request_token_done( struct http_request *req )  	}  	st->stage = OAUTH_REQUEST_TOKEN; -	st->func( st ); +	if( !st->func( st ) ) +		oauth_info_free( 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 ) +void oauth_access_token( const char *url, const char *pin, struct oauth_info *st )  {  	GSList *params = NULL;  	oauth_params_add( ¶ms, "oauth_token", st->request_token );  	oauth_params_add( ¶ms, "oauth_verifier", pin ); -	return oauth_post_request( url, ¶ms, oauth_access_token_done, st ); +	if( !oauth_post_request( url, ¶ms, oauth_access_token_done, st ) ) +		oauth_info_free( st );  }  static void oauth_access_token_done( struct http_request *req ) @@ -336,7 +355,7 @@ static void oauth_access_token_done( struct http_request *req )  	if( req->status_code == 200 )  	{ -		GSList *params; +		GSList *params = NULL;  		const char *token, *token_secret;  		oauth_params_parse( ¶ms, req->reply_body ); @@ -349,6 +368,7 @@ static void oauth_access_token_done( struct http_request *req )  	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 ) @@ -357,9 +377,12 @@ char *oauth_http_header( char *access_token, const char *method, const char *url  	char *token_secret, *sig, *params_s, *s;  	GString *ret = NULL; +	/* First, get the two pieces of info from the access token that we need. */  	oauth_params_parse( ¶ms, 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( ¶ms, "oauth_token_secret" ) );  	if( token_secret == NULL )  		goto err; @@ -367,6 +390,7 @@ char *oauth_http_header( char *access_token, const char *method, const char *url  	oauth_add_default_params( ¶ms ); +	/* Start building the OAuth header. 'key="value", '... */  	ret = g_string_new( "OAuth " );  	for( l = params; l; l = l->next )  	{ @@ -386,6 +410,9 @@ char *oauth_http_header( char *access_token, const char *method, const char *url  		g_string_append( ret, "\", " );  	} +	/* Now, before generating the signature, add GET/POST arguments to params +	   since they should be included in the base signature string (but not in +	   the HTTP header). */  	if( args )  		oauth_params_parse( ¶ms, args );  	if( ( s = strchr( url, '?' ) ) ) @@ -395,6 +422,7 @@ char *oauth_http_header( char *access_token, const char *method, const char *url  		g_free( s );  	} +	/* Append the signature and we're done! */  	params_s = oauth_params_string( params );  	sig = oauth_sign( method, url, params_s, token_secret );  	g_string_append_printf( ret, "oauth_signature=\"%s\"", sig ); diff --git a/lib/oauth.h b/lib/oauth.h index 30486b98..a61650cc 100644 --- a/lib/oauth.h +++ b/lib/oauth.h @@ -24,7 +24,10 @@  /* http://oauth.net/core/1.0a/ */  struct oauth_info; -typedef void (*oauth_cb)( struct oauth_info * ); + +/* Callback function called twice during the access token request process. +   Return FALSE if something broke and the process must be aborted. */ +typedef gboolean (*oauth_cb)( struct oauth_info * );  typedef enum  { @@ -52,13 +55,13 @@ struct oauth_info     Request an initial anonymous token which can be used to construct an     authorization URL for the user. This is passed to the callback function     in a struct oauth_info. */ -void *oauth_request_token( const char *url, oauth_cb func, void *data ); +struct oauth_info *oauth_request_token( const char *url, oauth_cb func, void *data );  /* http://oauth.net/core/1.0a/#auth_step3 (section 6.3)     The user gets a PIN or so which we now exchange for the final access     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 ); +void oauth_access_token( const char *url, const char *pin, struct oauth_info *st );  /* http://oauth.net/core/1.0a/#anchor12 (section 7)     Generate an OAuth Authorization: HTTP header. access_token should be @@ -66,3 +69,6 @@ void *oauth_access_token( const char *url, const char *pin, struct oauth_info *s     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 ); + +/* Shouldn't normally be required unless the process is aborted by the user. */ +void oauth_info_free( struct oauth_info *info ); diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index 54bee2f1..8ea1a56e 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -65,20 +65,27 @@ static void twitter_main_loop_start( struct im_connection *ic )  	td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic);  } -static void twitter_oauth_callback( struct oauth_info *info ); +static gboolean twitter_oauth_callback( struct oauth_info *info );  static void twitter_oauth_start( struct im_connection *ic )  { +	struct twitter_data *td = ic->proto_data; +	  	imcb_log( ic, "Requesting OAuth request token" ); -	oauth_request_token( TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic ); +	td->oauth_info = oauth_request_token( +		TWITTER_OAUTH_REQUEST_TOKEN, twitter_oauth_callback, ic );  } -static void twitter_oauth_callback( struct oauth_info *info ) +static gboolean twitter_oauth_callback( struct oauth_info *info )  {  	struct im_connection *ic = info->data; -	struct twitter_data *td = ic->proto_data; +	struct twitter_data *td; +	if( !g_slist_find( twitter_connections, ic ) ) +		return FALSE; +	 +	td = ic->proto_data;  	if( info->stage == OAUTH_REQUEST_TOKEN )  	{  		char name[strlen(ic->acc->user)+9], *msg; @@ -87,11 +94,9 @@ static void twitter_oauth_callback( struct oauth_info *info )  		{  			imcb_error( ic, "OAuth error: %s", info->http->status_string );  			imc_logout( ic, TRUE ); -			return; +			return FALSE;  		} -		td->oauth_info = info; -		  		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.", @@ -105,7 +110,7 @@ static void twitter_oauth_callback( struct oauth_info *info )  		{  			imcb_error( ic, "OAuth error: %s", info->http->status_string );  			imc_logout( ic, TRUE ); -			return; +			return FALSE;  		}  		td->oauth = g_strdup( info->access_token ); @@ -117,6 +122,8 @@ static void twitter_oauth_callback( struct oauth_info *info )  		twitter_main_loop_start( ic );  	} +	 +	return TRUE;  }  static char *set_eval_mode( set_t *set, char *value ) @@ -187,6 +194,8 @@ static void twitter_logout( struct im_connection *ic )  	if( td )  	{ +		oauth_info_free( td->oauth_info ); +		  		g_free( td->pass );  		g_free( td->oauth );  		g_free( td ); @@ -205,8 +214,11 @@ static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message  	if (g_strncasecmp(who, "twitter_", 8) == 0 &&  	    g_strcasecmp(who + 8, ic->acc->user) == 0)  	{ -		if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth == NULL ) +		if( set_getbool( &ic->acc->set, "oauth" ) && td->oauth_info ) +		{  			oauth_access_token( TWITTER_OAUTH_ACCESS_TOKEN, message, td->oauth_info ); +			td->oauth_info = NULL; +		}  		else  			twitter_post_status(ic, message);  	}  | 
