diff options
Diffstat (limited to 'protocols')
| -rw-r--r-- | protocols/msn/msn.c | 1 | ||||
| -rw-r--r-- | protocols/msn/msn.h | 8 | ||||
| -rw-r--r-- | protocols/msn/ns.c | 10 | ||||
| -rw-r--r-- | protocols/msn/sb.c | 43 | ||||
| -rw-r--r-- | protocols/twitter/twitter.c | 160 | ||||
| -rw-r--r-- | protocols/twitter/twitter.h | 1 | ||||
| -rw-r--r-- | protocols/twitter/twitter_http.c | 20 | ||||
| -rw-r--r-- | protocols/twitter/twitter_http.h | 4 | ||||
| -rw-r--r-- | protocols/twitter/twitter_lib.c | 49 | 
9 files changed, 258 insertions, 38 deletions
| diff --git a/protocols/msn/msn.c b/protocols/msn/msn.c index c7f56b7f..85dd22ec 100644 --- a/protocols/msn/msn.c +++ b/protocols/msn/msn.c @@ -37,6 +37,7 @@ static void msn_init( account_t *acc )  	set_add( &acc->set, "display_name", NULL, set_eval_display_name, acc );  	set_add( &acc->set, "local_display_name", "false", set_eval_bool, acc );  	set_add( &acc->set, "mail_notifications", "false", set_eval_bool, acc ); +	set_add( &acc->set, "switchboard_keepalives", "false", set_eval_bool, acc );  }  static void msn_login( account_t *acc ) diff --git a/protocols/msn/msn.h b/protocols/msn/msn.h index 077203c9..f3cb8635 100644 --- a/protocols/msn/msn.h +++ b/protocols/msn/msn.h @@ -30,6 +30,7 @@   */  #define TYPING_NOTIFICATION_MESSAGE "\r\r\rBEWARE, ME R TYPINK MESSAGE!!!!\r\r\r"  #define GROUPCHAT_SWITCHBOARD_MESSAGE "\r\r\rME WANT TALK TO MANY PEOPLE\r\r\r" +#define SB_KEEPALIVE_MESSAGE "\r\r\rDONT HANG UP ON ME!\r\r\r"  #ifdef DEBUG_MSN  #define debug( text... ) imcb_log( ic, text ); @@ -53,6 +54,10 @@                             "TypingUser: %s\r\n" \                             "\r\n\r\n" +#define SB_KEEPALIVE_HEADERS "MIME-Version: 1.0\r\n" \ +                             "Content-Type: text/x-ping\r\n" \ +                             "\r\n\r\n" +  #define PROFILE_URL "http://members.msn.com/"  struct msn_data @@ -83,6 +88,7 @@ struct msn_switchboard  	int fd;  	gint inp;  	struct msn_handler_data *handler; +	gint keepalive;  	int trId;  	int ready; @@ -180,6 +186,8 @@ struct groupchat *msn_sb_to_chat( struct msn_switchboard *sb );  void msn_sb_destroy( struct msn_switchboard *sb );  gboolean msn_sb_connected( gpointer data, gint source, b_input_condition cond );  int msn_sb_write_msg( struct im_connection *ic, struct msn_message *m ); +void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ); +void msn_sb_stop_keepalives( struct msn_switchboard *sb );  /* invitation.c */  void msn_ftp_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who ); diff --git a/protocols/msn/ns.c b/protocols/msn/ns.c index 8181c1af..2f656ea5 100644 --- a/protocols/msn/ns.c +++ b/protocols/msn/ns.c @@ -421,8 +421,12 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  	}  	else if( strcmp( cmd[0], "FLN" ) == 0 )  	{ -		if( cmd[1] ) -			imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); +		if( cmd[1] == NULL ) +			return 1; +		 +		imcb_buddy_status( ic, cmd[1], 0, NULL, NULL ); +		 +		msn_sb_start_keepalives( msn_sb_by_handle( ic, cmd[1] ), TRUE );  	}  	else if( strcmp( cmd[0], "NLN" ) == 0 )  	{ @@ -448,6 +452,8 @@ static int msn_ns_command( gpointer data, char **cmd, int num_parts )  		imcb_buddy_status( ic, cmd[2], OPT_LOGGED_IN |   		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ),  		                   st->name, NULL ); +		 +		msn_sb_stop_keepalives( msn_sb_by_handle( ic, cmd[2] ) );  	}  	else if( strcmp( cmd[0], "RNG" ) == 0 )  	{ diff --git a/protocols/msn/sb.c b/protocols/msn/sb.c index a935ce97..641af5e7 100644 --- a/protocols/msn/sb.c +++ b/protocols/msn/sb.c @@ -174,6 +174,11 @@ int msn_sb_sendmessage( struct msn_switchboard *sb, char *text )  			buf = g_new0( char, i );  			i = g_snprintf( buf, i, MSN_TYPING_HEADERS, sb->ic->acc->user );  		} +		else if( strcmp( text, SB_KEEPALIVE_MESSAGE ) == 0 ) +		{ +			buf = g_strdup( SB_KEEPALIVE_HEADERS ); +			i = strlen( buf ); +		}  		else if( strncmp( text, MSN_INVITE_HEADERS, sizeof( MSN_INVITE_HEADERS ) - 1 ) == 0 )   		{  			buf = g_strdup( text ); @@ -255,6 +260,7 @@ void msn_sb_destroy( struct msn_switchboard *sb )  	debug( "Destroying switchboard: %s", sb->who ? sb->who : sb->key ? sb->key : "" );  	msn_msgq_purge( ic, &sb->msgq ); +	msn_sb_stop_keepalives( sb );  	if( sb->key ) g_free( sb->key );  	if( sb->who ) g_free( sb->who ); @@ -476,6 +482,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts )  		}  		sb->ready = 1; +		 +		msn_sb_start_keepalives( sb, FALSE );  	}  	else if( strcmp( cmd[0], "CAL" ) == 0 )  	{ @@ -525,6 +533,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts )  				sb->msgq = g_slist_remove( sb->msgq, m );  			} +			msn_sb_start_keepalives( sb, FALSE ); +			  			return( st );  		}  		else if( sb->who ) @@ -586,6 +596,8 @@ static int msn_sb_command( gpointer data, char **cmd, int num_parts )  		if( sb->who )  		{ +			msn_sb_stop_keepalives( sb ); +			  			/* This is a single-person chat, and the other person is leaving. */  			g_free( sb->who );  			sb->who = NULL; @@ -751,3 +763,34 @@ static int msn_sb_message( gpointer data, char *msg, int msglen, char **cmd, int  	return( 1 );  } + +static gboolean msn_sb_keepalive( gpointer data, gint source, b_input_condition cond ) +{ +	struct msn_switchboard *sb = data; +	return sb->ready && msn_sb_sendmessage( sb, SB_KEEPALIVE_MESSAGE ); +} + +void msn_sb_start_keepalives( struct msn_switchboard *sb, gboolean initial ) +{ +	bee_user_t *bu; +	 +	if( sb && sb->who && sb->keepalive == 0 && +	    ( bu = bee_user_by_handle( sb->ic->bee, sb->ic, sb->who ) ) && +	    !( bu->flags & BEE_USER_ONLINE ) && +	    set_getbool( &sb->ic->acc->set, "switchboard_keepalives" ) ) +	{ +		if( initial ) +			msn_sb_keepalive( sb, 0, 0 ); +		 +		sb->keepalive = b_timeout_add( 20000, msn_sb_keepalive, sb ); +	} +} + +void msn_sb_stop_keepalives( struct msn_switchboard *sb ) +{ +	if( sb && sb->keepalive > 0 ) +	{ +		b_event_remove( sb->keepalive ); +		sb->keepalive = 0; +	} +} diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index 727eff91..9c7b060c 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -22,11 +22,11 @@  ****************************************************************************/  #include "nogaim.h" +#include "oauth.h"  #include "twitter.h"  #include "twitter_http.h"  #include "twitter_lib.h" -  /**   * Main loop function   */ @@ -40,7 +40,7 @@ gboolean twitter_main_loop(gpointer data, gint fd, b_input_condition cond)  	// If the user uses multiple private message windows we need to get the   	// users buddies. -	if (!set_getbool( &ic->acc->set, "use_groupchat" )) +	if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "many") == 0)  		twitter_get_statuses_friends(ic, -1);  	// Do stuff.. @@ -50,12 +50,107 @@ gboolean twitter_main_loop(gpointer data, gint fd, b_input_condition cond)  	return (ic->flags & OPT_LOGGED_IN) == OPT_LOGGED_IN;  } +static void twitter_main_loop_start( struct im_connection *ic ) +{ +	struct twitter_data *td = ic->proto_data; +	 +	imcb_log( ic, "Connecting to Twitter" ); + +	// Run this once. After this queue the main loop function. +	twitter_main_loop(ic, -1, 0); + +	// Queue the main_loop +	// Save the return value, so we can remove the timeout on logout. +	td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic); +} + + +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 ); + +static void twitter_oauth_start( struct im_connection *ic ) +{ +	struct twitter_data *td = ic->proto_data; +	 +	imcb_log( ic, "Requesting OAuth request token" ); + +	td->oauth_info = oauth_request_token( &twitter_oauth, twitter_oauth_callback, ic ); +} + +static gboolean twitter_oauth_callback( struct oauth_info *info ) +{ +	struct im_connection *ic = info->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; +		 +		if( info->request_token == NULL ) +		{ +			imcb_error( ic, "OAuth error: %s", info->http->status_string ); +			imc_logout( ic, TRUE ); +			return FALSE; +		} +		 +		sprintf( name, "twitter_%s", ic->acc->user ); +		msg = g_strdup_printf( "To finish OAuth authentication, please visit " +		                       "%s and respond with the resulting PIN code.", +		                       info->auth_url ); +		imcb_buddy_msg( ic, name, msg, 0, 0 ); +		g_free( msg ); +	} +	else if( info->stage == OAUTH_ACCESS_TOKEN ) +	{ +		if( info->token == NULL || info->token_secret == NULL ) +		{ +			imcb_error( ic, "OAuth error: %s", info->http->status_string ); +			imc_logout( ic, TRUE ); +			return FALSE; +		} +		 +		/* 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 = oauth_to_string( info ); +		 +		twitter_main_loop_start( ic ); +	} +	 +	return TRUE; +} + + +static char *set_eval_mode( set_t *set, char *value ) +{ +	if( g_strcasecmp( value, "one" ) == 0 || +	    g_strcasecmp( value, "many" ) == 0 || +	    g_strcasecmp( value, "chat" ) == 0 ) +		return value; +	else +		return NULL; +}  static void twitter_init( account_t *acc )  {  	set_t *s; -	s = set_add( &acc->set, "use_groupchat", "false", set_eval_bool, acc ); +	 +	s = set_add( &acc->set, "mode", "one", set_eval_mode, acc );  	s->flags |= ACC_SET_OFFLINE_ONLY; +	 +	s = set_add( &acc->set, "oauth", "true", set_eval_bool, acc );  }  /** @@ -66,23 +161,27 @@ static void twitter_login( account_t *acc )  {  	struct im_connection *ic = imcb_new( acc );  	struct twitter_data *td = g_new0( struct twitter_data, 1 ); +	char name[strlen(acc->user)+9];  	twitter_connections = g_slist_append( twitter_connections, ic ); - +	ic->proto_data = td; +	ic->flags |= OPT_DOES_HTML; +	  	td->user = acc->user; -	td->pass = acc->pass; +	if( !set_getbool( &acc->set, "oauth" ) ) +		td->pass = g_strdup( acc->pass ); +	else if( strstr( acc->pass, "oauth_token=" ) ) +		td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );  	td->home_timeline_id = 0; - -	ic->proto_data = td; - -	imcb_log( ic, "Connecting to Twitter" ); - -	// Run this once. After this queue the main loop function. -	twitter_main_loop(ic, -1, 0); - -	// Queue the main_loop -	// Save the return value, so we can remove the timeout on logout. -	td->main_loop_id = b_timeout_add(60000, twitter_main_loop, ic); +	 +	sprintf( name, "twitter_%s", acc->user ); +	imcb_add_buddy( ic, name, NULL ); +	imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL ); +	 +	if( td->pass || td->oauth_info ) +		twitter_main_loop_start( ic ); +	else +		twitter_oauth_start( ic );  }  /** @@ -103,6 +202,8 @@ static void twitter_logout( struct im_connection *ic )  	if( td )  	{ +		oauth_info_free( td->oauth_info ); +		g_free( td->pass );  		g_free( td );  	} @@ -114,11 +215,28 @@ static void twitter_logout( struct im_connection *ic )   */  static int twitter_buddy_msg( struct im_connection *ic, char *who, char *message, int away )  { -	// Let's just update the status. -//	if ( g_strcasecmp(who, ic->acc->user) == 0 ) -		twitter_post_status(ic, message); -//	else -//		twitter_direct_messages_new(ic, who, message); +	struct twitter_data *td = ic->proto_data; +	 +	if (g_strncasecmp(who, "twitter_", 8) == 0 && +	    g_strcasecmp(who + 8, ic->acc->user) == 0) +	{ +		if( set_getbool( &ic->acc->set, "oauth" ) && +		    td->oauth_info && td->oauth_info->token == 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 +			twitter_post_status(ic, message); +	} +	else +	{ +		twitter_direct_messages_new(ic, who, message); +	}  	return( 0 );  } diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h index 88caa104..24f61e42 100644 --- a/protocols/twitter/twitter.h +++ b/protocols/twitter/twitter.h @@ -36,6 +36,7 @@ struct twitter_data  {  	char* user;  	char* pass; +	struct oauth_info *oauth_info;  	guint64 home_timeline_id;  	gint main_loop_id;  	struct groupchat *home_timeline_gc; diff --git a/protocols/twitter/twitter_http.c b/protocols/twitter/twitter_http.c index 3632140f..51f437df 100644 --- a/protocols/twitter/twitter_http.c +++ b/protocols/twitter/twitter_http.c @@ -28,15 +28,17 @@  *                                                                           *  ****************************************************************************/  -#include "twitter_http.h"  #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" +  char *twitter_url_append(char *url, char *key, char* value); @@ -44,7 +46,7 @@ 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   */ -void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post, char* user, char* pass, 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 );  	char *tmp; @@ -109,7 +111,19 @@ void *twitter_http(char *url_string, http_input_function func, gpointer data, in  	                            is_post ? "POST" : "GET", url->file, url->host );  	// If a pass and user are given we append them to the request. -	if (userpass_base64) +	if (oi) +	{ +		char *full_header; +		 +		full_header = oauth_http_header(oi, is_post ? "POST" : "GET", +		                                url_string, url_arguments); +		 +		tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header); +		g_free(request); +		g_free(full_header); +		request = tmp; +	} +	else if (userpass_base64)  	{  		tmp = g_strdup_printf("%sAuthorization: Basic %s\r\n", request, userpass_base64);  		g_free(request); diff --git a/protocols/twitter/twitter_http.h b/protocols/twitter/twitter_http.h index ec4a0b7c..5ef2530f 100644 --- a/protocols/twitter/twitter_http.h +++ b/protocols/twitter/twitter_http.h @@ -27,8 +27,10 @@  #include "nogaim.h"  #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** arguments, int arguments_len); +                   char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);  #endif //_TWITTER_HTTP_H diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index b6863c02..40352893 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -104,12 +104,14 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char *  	// Check if the buddy is allready in the buddy list.  	if (!bee_user_by_handle( ic->bee, ic, name ))  	{ +		char *mode = set_getstr(&ic->acc->set, "mode"); +		  		// The buddy is not in the list, add the buddy and set the status to logged in.  		imcb_add_buddy( ic, name, NULL );  		imcb_rename_buddy( ic, name, fullname ); -		if (set_getbool( &ic->acc->set, "use_groupchat" )) +		if (g_strcasecmp(mode, "chat") == 0)  			imcb_chat_add_buddy( td->home_timeline_gc, name ); -		else +		else if (g_strcasecmp(mode, "many") == 0)  			imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );  	}  } @@ -127,7 +129,7 @@ void twitter_get_friends_ids(struct im_connection *ic, int next_cursor)  	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, 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]);  } @@ -393,7 +395,7 @@ void twitter_get_home_timeline(struct im_connection *ic, int next_cursor)  		args[3] = g_strdup_printf ("%llu", (long long unsigned int) td->home_timeline_id);  	} -	twitter_http(TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, td->user, td->pass, 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]);  	if (td->home_timeline_id) { @@ -451,14 +453,39 @@ static void twitter_private_message_chat(struct im_connection *ic, GSList *list)  	struct twitter_data *td = ic->proto_data;  	GSList *l = NULL;  	struct twitter_xml_status *status; +	char from[MAX_STRING]; +	gboolean mode_one; +	 +	mode_one = g_strcasecmp( set_getstr( &ic->acc->set, "mode" ), "one" ) == 0; +	if( mode_one ) +	{ +		g_snprintf( from, sizeof( from ) - 1, "twitter_%s", ic->acc->user ); +		from[MAX_STRING-1] = '\0'; +	} +	  	for ( l = list; l ; l = g_slist_next(l) )  	{ +		char *text = NULL; +		  		status = l->data; -		imcb_buddy_msg( ic, status->user->screen_name, status->text, 0, status->created_at ); +		 +		if( mode_one ) +			text = g_strdup_printf( "\002<\002%s\002>\002 %s", +			                        status->user->screen_name, status->text ); +		else +			twitter_add_buddy(ic, status->user->screen_name, status->user->name); +		 +		imcb_buddy_msg( ic, +		                mode_one ? from : status->user->screen_name, +		                mode_one ? text : status->text, +		                0, status->created_at ); +		  		// Update the home_timeline_id to hold the highest id, so that by the next request  		// we won't pick up the updates allready in the list.  		td->home_timeline_id = td->home_timeline_id < status->id ? status->id : td->home_timeline_id; +		 +		g_free( text );  	}  } @@ -482,7 +509,7 @@ static void twitter_http_get_home_timeline(struct http_request *req)  	if (req->status_code == 200)  	{  		td->http_fails = 0; -		if (!ic->flags & OPT_LOGGED_IN) +		if (!(ic->flags & OPT_LOGGED_IN))  			imcb_connected(ic);  	}  	else if (req->status_code == 401) @@ -511,7 +538,7 @@ static void twitter_http_get_home_timeline(struct http_request *req)  	xt_free( parser );  	// See if the user wants to see the messages in a groupchat window or as private messages. -	if (set_getbool( &ic->acc->set, "use_groupchat" )) +	if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)  		twitter_groupchat(ic, txl->list);  	else  		twitter_private_message_chat(ic, txl->list); @@ -592,7 +619,7 @@ void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor)  	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, 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]);  } @@ -611,7 +638,7 @@ static void twitter_http_post_status(struct http_request *req)  	// Check if the HTTP request went well.  	if (req->status_code != 200) {  		// It didn't go well, output the error and return. -		imcb_error(ic, "Could not post tweet... HTTP STATUS: %d", req->status_code); +		imcb_error(ic, "Could not post message... HTTP STATUS: %d", req->status_code);  		return;  	}  } @@ -626,7 +653,7 @@ void twitter_post_status(struct im_connection *ic, char* msg)  	char* args[2];  	args[0] = "status";  	args[1] = msg; -	twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, 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]);  } @@ -644,7 +671,7 @@ void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)  	args[2] = "text";  	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, 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]);  } | 
