aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/oauth.c40
-rw-r--r--lib/oauth.h12
-rw-r--r--protocols/twitter/twitter.c30
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( &params, "oauth_callback", "oob" );
- return oauth_post_request( url, NULL, oauth_request_token_done, st );
+ if( !oauth_post_request( url, &params, 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( &params, "oauth_token", st->request_token );
oauth_params_add( &params, "oauth_verifier", pin );
- return oauth_post_request( url, &params, oauth_access_token_done, st );
+ if( !oauth_post_request( url, &params, 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( &params, 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( &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;
@@ -367,6 +390,7 @@ char *oauth_http_header( char *access_token, const char *method, const char *url
oauth_add_default_params( &params );
+ /* 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( &params, 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);
}