diff options
author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-06-06 00:26:07 +0100 |
---|---|---|
committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-06-06 00:26:07 +0100 |
commit | 1fdb0a48438d6dc4a4795d195737890ed3e46a96 (patch) | |
tree | 8a50bf83b78ee1c0e516e8ae6e9f9a079a3fe6df | |
parent | b308cf9bafbdf76da73a57607b65c4763aa3057b (diff) | |
parent | 3dc6d86076dbea16c313bb87aa2f37166f289a8e (diff) |
Merging mainline.
-rw-r--r-- | bitlbee.h | 4 | ||||
-rw-r--r-- | debian/changelog | 7 | ||||
-rw-r--r-- | debian/control | 12 | ||||
-rw-r--r-- | doc/CHANGES | 14 | ||||
-rw-r--r-- | doc/bitlbee.8 | 5 | ||||
-rw-r--r-- | doc/user-guide/commands.xml | 2 | ||||
-rw-r--r-- | doc/user-guide/quickstart.xml | 4 | ||||
-rw-r--r-- | irc_commands.c | 20 | ||||
-rw-r--r-- | lib/misc.c | 5 | ||||
-rw-r--r-- | protocols/jabber/iq.c | 1 | ||||
-rw-r--r-- | protocols/msn/passport.c | 4 | ||||
-rw-r--r-- | protocols/oscar/auth.c | 3 | ||||
-rw-r--r-- | protocols/oscar/oscar.c | 10 | ||||
-rw-r--r-- | protocols/twitter/twitter.c | 36 | ||||
-rw-r--r-- | protocols/twitter/twitter.h | 5 | ||||
-rw-r--r-- | protocols/twitter/twitter_http.c | 103 | ||||
-rw-r--r-- | protocols/twitter/twitter_http.h | 4 | ||||
-rw-r--r-- | protocols/twitter/twitter_lib.c | 72 | ||||
-rw-r--r-- | protocols/twitter/twitter_lib.h | 55 |
19 files changed, 217 insertions, 149 deletions
@@ -34,10 +34,10 @@ #define _WIN32_WINNT 0x0501 #define PACKAGE "BitlBee" -#define BITLBEE_VERSION "1.2.6a" +#define BITLBEE_VERSION "1.2.7" #define VERSION BITLBEE_VERSION #define BITLBEE_VER(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#define BITLBEE_VERSION_CODE BITLBEE_VER(1, 2, 6) +#define BITLBEE_VERSION_CODE BITLBEE_VER(1, 2, 7) #define MAX_STRING 511 diff --git a/debian/changelog b/debian/changelog index ffb23ed8..4bcaa5d0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,13 @@ bitlbee (1.3-0) unstable; urgency=low -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 05 Jun 2010 15:16:38 +0100 +bitlbee (1.2.7-1) unstable; urgency=high + + * New upstream version. + * Fixes MSN Messenger login issues, so uploading at high priority. + + -- Wilmer van der Gaast <wilmer@gaast.net> Sat, 15 May 2010 16:15:57 +0100 + bitlbee (1.2.6a-1) unstable; urgency=low * New upstream version. diff --git a/debian/control b/debian/control index 05689940..689f83f2 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,8 @@ Conflicts: bitlbee-libpurple Replaces: bitlbee-libpurple Description: An IRC to other chat networks gateway (default version) This program can be used as an IRC server which forwards everything you - say to people on other chat networks: Jabber, ICQ, AIM, MSN and Yahoo. + say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and + Twitter. Package: bitlbee-libpurple Architecture: any @@ -25,7 +26,8 @@ Conflicts: bitlbee Replaces: bitlbee Description: An IRC to other chat networks gateway (using libpurple) This program can be used as an IRC server which forwards everything you - say to people on other chat networks: Jabber, ICQ, AIM, MSN and Yahoo. + say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and + Twitter. . This package contains a version of BitlBee that uses the libpurple instant messaging library instead of built-in code, which adds support for more IM @@ -41,7 +43,8 @@ Depends: ${misc:Depends}, net-tools Replaces: bitlbee Description: An IRC to other chat networks gateway (common files/docs) This program can be used as an IRC server which forwards everything you - say to people on other chat networks: Jabber, ICQ, AIM, MSN and Yahoo. + say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and + Twitter. . This package contains common files (mostly documentation) for bitlbee and bitlbee-libpurple. @@ -51,6 +54,7 @@ Architecture: all Depends: ${misc:Depends}, bitlbee (>= ${bee:Version}), bitlbee (<< ${bee:Version}.1~) Description: An IRC to other chat networks gateway (dev files) This program can be used as an IRC server which forwards everything you - say to people on other chat networks: Jabber, ICQ, AIM, MSN and Yahoo. + say to people on other chat networks: Jabber, ICQ, AIM, MSN, Yahoo! and + Twitter. . This package holds development stuff for compiling plug-ins. diff --git a/doc/CHANGES b/doc/CHANGES index 45b16e28..7359a050 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -3,6 +3,20 @@ found in the bzr commit logs, for example you can try: http://bugs.bitlbee.org/bitlbee/timeline?daysback=90&changeset=on +Version 1.2.7: +- Fixed problems with MSN Messenger authentication. ("Could not parse + Passport server response") +- Fixed broken typing notifications when talking to GTalk contacts. +- Fixed an issue with non-anonymous Jabber chatrooms polluting the nick + namespace, sometimes generating odd warning messages. +- Restored ability to start groupchats on ICQ. +- Added show_offline setting that will also show offline contacts in the + control channel. +- OAuth support for Twitter: This means the module will keep working after + June (this also changes "via API" under your tweets into "via BitlBee"). + +Finished 15 May 2010 + Version 1.2.6a: - Fixed a typo that renders the Twitter groupchat mode unusable. A last- minute change that came a few minutes late. diff --git a/doc/bitlbee.8 b/doc/bitlbee.8 index 9e634844..36576e59 100644 --- a/doc/bitlbee.8 +++ b/doc/bitlbee.8 @@ -38,9 +38,8 @@ BitlBee \- IRC gateway to IM chat networks BitlBee is an IRC daemon that can talk to instant messaging networks and acts as a gateway. Users can connect to the server with any normal IRC client and see their 'buddy list' in -&bitlbee. BitlBee's protocol support is based on the gaim -protocol plugins. BitlBee currently supports Oscar (aim and icq), -MSN, Jabber and Yahoo. +&bitlbee. It currently supports Oscar (AIM and ICQ), +MSN, Jabber, Yahoo! and Twitter. \fBbitlbee\fP should be called by .BR inetd (8), diff --git a/doc/user-guide/commands.xml b/doc/user-guide/commands.xml index f3633971..4746e2c3 100644 --- a/doc/user-guide/commands.xml +++ b/doc/user-guide/commands.xml @@ -619,7 +619,7 @@ </bitlbee-setting> <bitlbee-setting name="ignore_auth_requests" type="boolean" scope="account"> - <default>true</default> + <default>false</default> <description> <para> diff --git a/doc/user-guide/quickstart.xml b/doc/user-guide/quickstart.xml index 0539a7c7..80c16ffb 100644 --- a/doc/user-guide/quickstart.xml +++ b/doc/user-guide/quickstart.xml @@ -2,7 +2,7 @@ <title>Quickstart</title> <para> -Welcome to BitlBee, your IRC gateway to ICQ, MSN, AOL, Jabber and Yahoo Instant Messaging Systems. +Welcome to BitlBee, your IRC gateway to ICQ, MSN, AOL, Jabber, Yahoo! and Twitter. </para> <para> @@ -42,7 +42,7 @@ For instance, suppose you have a Jabber account at jabber.org with handle <empha </ircexample> <para> -Other available IM protocols are msn, oscar, and yahoo. OSCAR is the protocol used by ICQ and AOL. For more information about the <emphasis>account add</emphasis> command, see <emphasis>help account add</emphasis>. +Other available IM protocols are msn, oscar, yahoo and twitter. OSCAR is the protocol used by ICQ and AOL. For more information about the <emphasis>account add</emphasis> command, see <emphasis>help account add</emphasis>. </para> <para> diff --git a/irc_commands.c b/irc_commands.c index 319d549a..7a286ce2 100644 --- a/irc_commands.c +++ b/irc_commands.c @@ -72,19 +72,29 @@ static void irc_cmd_user( irc_t *irc, char **cmd ) static void irc_cmd_nick( irc_t *irc, char **cmd ) { - if( irc->nick ) + if( irc->status & USTATUS_IDENTIFIED && irc->nick ) { - irc_reply( irc, 438, ":The hand of the deity is upon thee, thy nick may not change" ); + irc_reply( irc, 438, "%s %s :You can only change your nick if you're not " + "logged in (i.e. pre-identify)", irc->nick, cmd[1] ); } /* This is not clean, but for now it'll have to be like this... */ - else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) ) + else if( ( nick_cmp( cmd[1], irc->mynick ) == 0 ) || ( nick_cmp( cmd[1], NS_NICK ) == 0 ) || ( user_find( irc, cmd[1] ) != NULL ) ) { - irc_reply( irc, 433, ":This nick is already in use" ); + irc_reply( irc, 433, "%s :This nick is already in use", cmd[1] ); } else if( !nick_ok( cmd[1] ) ) { /* [SH] Invalid characters. */ - irc_reply( irc, 432, ":This nick contains invalid characters" ); + irc_reply( irc, 432, "%s :This nick contains invalid characters", cmd[1] ); + } + else if(irc->nick) + { + if( user_find( irc, irc->nick ) ) + user_rename(irc, irc->nick, cmd[1]); + + irc_write( irc, ":%s!%s@%s NICK %s", irc->nick, irc->user, irc->host, cmd[1] ); + g_free(irc->nick); + irc->nick = g_strdup( cmd[1] ); } else { @@ -153,11 +153,11 @@ static const htmlentity_t ent[] = void strip_html( char *in ) { char *start = in; - char *out = g_malloc( strlen( in ) + 1 ); + char out[strlen(in)+1]; char *s = out, *cs; int i, matched; - memset( out, 0, strlen( in ) + 1 ); + memset( out, 0, sizeof( out ) ); while( *in ) { @@ -219,7 +219,6 @@ void strip_html( char *in ) } strcpy( start, out ); - g_free( out ); } char *escape_html( const char *html ) diff --git a/protocols/jabber/iq.c b/protocols/jabber/iq.c index f5fbdc13..77c0d628 100644 --- a/protocols/jabber/iq.c +++ b/protocols/jabber/iq.c @@ -135,7 +135,6 @@ xt_status jabber_pkt_iq( struct xt_node *node, gpointer data ) else if( !( c = xt_find_node( node->children, "query" ) ) || !( s = xt_find_attr( c, "xmlns" ) ) ) { - imcb_log( ic, "Warning: Received incomplete IQ-%s packet", type ); return XT_HANDLED; } else if( strcmp( s, XMLNS_ROSTER ) == 0 ) diff --git a/protocols/msn/passport.c b/protocols/msn/passport.c index 565d15f3..7c896db1 100644 --- a/protocols/msn/passport.c +++ b/protocols/msn/passport.c @@ -144,7 +144,9 @@ static xt_status passport_xt_extract_token( struct xt_node *node, gpointer data struct msn_auth_data *mad = data; char *s; - if( ( s = xt_find_attr( node, "Id" ) ) && strcmp( s, "PPToken1" ) == 0 ) + if( ( s = xt_find_attr( node, "Id" ) ) && + ( strncmp( s, "Compact", 7 ) == 0 || + strncmp( s, "PPToken", 7 ) == 0 ) ) mad->token = g_memdup( node->text, node->text_len + 1 ); return XT_HANDLED; diff --git a/protocols/oscar/auth.c b/protocols/oscar/auth.c index eb6a9d64..0f7c8d0f 100644 --- a/protocols/oscar/auth.c +++ b/protocols/oscar/auth.c @@ -119,11 +119,12 @@ int aim_request_login(aim_session_t *sess, aim_conn_t *conn, const char *sn) aim_frame_t *fr; aim_snacid_t snacid; aim_tlvlist_t *tl = NULL; + struct im_connection *ic = sess->aux_data; if (!sess || !conn || !sn) return -EINVAL; - if ((sn[0] >= '0') && (sn[0] <= '9')) + if (isdigit(sn[0]) && set_getbool(&ic->acc->set, "old_icq_auth")) return goddamnicq(sess, conn, sn); sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; diff --git a/protocols/oscar/oscar.c b/protocols/oscar/oscar.c index 5633d399..7086657a 100644 --- a/protocols/oscar/oscar.c +++ b/protocols/oscar/oscar.c @@ -373,6 +373,7 @@ static void oscar_init(account_t *acc) if (isdigit(acc->user[0])) { set_add(&acc->set, "ignore_auth_requests", "false", set_eval_bool, acc); + set_add(&acc->set, "old_icq_auth", "false", set_eval_bool, acc); } s = set_add(&acc->set, "server", AIM_DEFAULT_LOGIN_SERVER, set_eval_account, acc); @@ -1029,16 +1030,21 @@ static int incomingim_chan2(aim_session_t *sess, aim_conn_t *conn, aim_userinfo_ *exch = args->info.chat.roominfo.exchange; m = g_list_append(m, exch); - g_snprintf( txt, 1024, "Got an invitation to chatroom %s from %s: %s", name, userinfo->sn, args->msg ); + g_snprintf(txt, 1024, "Got an invitation to chatroom %s from %s: %s", name, userinfo->sn, args->msg); inv->ic = ic; inv->exchange = *exch; inv->name = g_strdup(name); - imcb_ask( ic, txt, inv, oscar_accept_chat, oscar_reject_chat); + imcb_ask(ic, txt, inv, oscar_accept_chat, oscar_reject_chat); if (name) g_free(name); + } else if (args->reqclass & AIM_CAPS_ICQRTF) { + // TODO: constify + char text[strlen(args->info.rtfmsg.rtfmsg)+1]; + strncpy(text, args->info.rtfmsg.rtfmsg, sizeof(text)); + imcb_buddy_msg(ic, normalize(userinfo->sn), text, 0, 0); } return 1; diff --git a/protocols/twitter/twitter.c b/protocols/twitter/twitter.c index 98e85641..a5fc68ab 100644 --- a/protocols/twitter/twitter.c +++ b/protocols/twitter/twitter.c @@ -26,6 +26,7 @@ #include "twitter.h" #include "twitter_http.h" #include "twitter_lib.h" +#include "url.h" /** * Main loop function @@ -69,7 +70,7 @@ 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", + "https://api.twitter.com/oauth/authorize", .consumer_key = "xsDNKJuNZYkZyMcu914uEA", .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo", }; @@ -159,6 +160,9 @@ static void twitter_init( account_t *acc ) { 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 ); s = set_add( &acc->set, "mode", "one", set_eval_mode, acc ); @@ -174,25 +178,39 @@ static void twitter_init( account_t *acc ) static void twitter_login( account_t *acc ) { 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 ); imcb_add_buddy( ic, name, NULL ); 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 twitter_oauth_start( ic ); @@ -267,10 +285,12 @@ static void twitter_get_info(struct im_connection *ic, char *who) static void twitter_add_buddy( struct im_connection *ic, char *who, char *group ) { + twitter_friendships_create_destroy(ic, who, 1); } static void twitter_remove_buddy( struct im_connection *ic, char *who, char *group ) { + twitter_friendships_create_destroy(ic, who, 0); } static void twitter_chat_msg( struct groupchat *c, char *message, int flags ) diff --git a/protocols/twitter/twitter.h b/protocols/twitter/twitter.h index 24f61e42..614919f9 100644 --- a/protocols/twitter/twitter.h +++ b/protocols/twitter/twitter.h @@ -41,6 +41,11 @@ struct twitter_data gint main_loop_id; struct groupchat *home_timeline_gc; gint http_fails; + + gboolean url_ssl; + int url_port; + char *url_host; + char *url_path; }; /** diff --git a/protocols/twitter/twitter_http.c b/protocols/twitter/twitter_http.c index 51f437df..ff17f5f4 100644 --- a/protocols/twitter/twitter_http.c +++ b/protocols/twitter/twitter_http.c @@ -40,45 +40,21 @@ #include "twitter_http.h" -char *twitter_url_append(char *url, char *key, char* value); +static 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, 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. if (arguments_len != 0) @@ -92,70 +68,61 @@ void *twitter_http(char *url_string, http_input_function func, gpointer data, in } } - // 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 ); } // Do POST stuff.. if (is_post) { // 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)); http_encode(key_encoded); diff --git a/protocols/twitter/twitter_http.h b/protocols/twitter/twitter_http.h index 5ef2530f..393a1c26 100644 --- a/protocols/twitter/twitter_http.h +++ b/protocols/twitter/twitter_http.h @@ -29,8 +29,8 @@ 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 diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c index ee6e39fe..585bdd43 100644 --- a/protocols/twitter/twitter_lib.c +++ b/protocols/twitter/twitter_lib.c @@ -116,6 +116,37 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char * } } +/* 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); /** @@ -123,13 +154,11 @@ static void twitter_http_get_friends_ids(struct http_request *req); */ 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]); } @@ -195,7 +224,7 @@ static void twitter_http_get_friends_ids(struct http_request *req) if (req->status_code != 200) { // 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; } else { @@ -395,7 +424,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, 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]); if (td->home_timeline_id) { @@ -433,6 +462,8 @@ static void twitter_groupchat(struct im_connection *ic, GSList *list) status = l->data; 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) imcb_chat_log (gc, "Your Tweet: %s", status->text); @@ -470,6 +501,7 @@ static void twitter_private_message_chat(struct im_connection *ic, GSList *list) status = l->data; + strip_html( status->text ); if( mode_one ) text = g_strdup_printf( "\002<\002%s\002>\002 %s", status->user->screen_name, status->text ); @@ -522,7 +554,7 @@ static void twitter_http_get_home_timeline(struct http_request *req) { // 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; } @@ -574,7 +606,7 @@ static void twitter_http_get_statuses_friends(struct http_request *req) if (req->status_code != 200) { // 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; } else { @@ -613,21 +645,19 @@ static void twitter_http_get_statuses_friends(struct http_request *req) */ 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]); } /** - * Callback after sending a new update to twitter. + * Callback to use after sending a post request to twitter. */ -static void twitter_http_post_status(struct http_request *req) +static void twitter_http_post(struct http_request *req) { struct im_connection *ic = req->data; @@ -638,7 +668,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 message... HTTP STATUS: %d", req->status_code); + imcb_error(ic, "HTTP error: %s", twitter_parse_error(req)); return; } } @@ -648,12 +678,10 @@ static void twitter_http_post_status(struct http_request *req) */ 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_status, 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]); } @@ -663,15 +691,21 @@ void twitter_post_status(struct im_connection *ic, char* msg) */ 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"; args[1] = who; 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, 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]); } + +void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create) +{ + char* args[2]; + args[0] = "screen_name"; + args[1] = who; + twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, twitter_http_post, ic, 1, args, 2); +}
\ No newline at end of file diff --git a/protocols/twitter/twitter_lib.h b/protocols/twitter/twitter_lib.h index e47bfd95..65a596cc 100644 --- a/protocols/twitter/twitter_lib.h +++ b/protocols/twitter/twitter_lib.h @@ -31,49 +31,49 @@ #define TWITTER_API_URL "http://twitter.com" /* 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); void twitter_get_home_timeline(struct im_connection *ic, int next_cursor); @@ -81,6 +81,7 @@ void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor); void twitter_post_status(struct im_connection *ic, char *msg); void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message); +void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create); #endif //_TWITTER_LIB_H |