Changeset 704dd38 for protocols/twitter


Ignore:
Timestamp:
2010-06-01T21:51:27Z (15 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
ad404ab
Parents:
3429b58 (diff), ba3233c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merging head.

Location:
protocols/twitter
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter.c

    r3429b58 r704dd38  
    2727#include "twitter_http.h"
    2828#include "twitter_lib.h"
     29#include "url.h"
    2930
    3031/**
     
    7071        "http://api.twitter.com/oauth/request_token",
    7172        "http://api.twitter.com/oauth/access_token",
    72         "http://api.twitter.com/oauth/authorize",
     73        "https://api.twitter.com/oauth/authorize",
    7374        .consumer_key = "xsDNKJuNZYkZyMcu914uEA",
    7475        .consumer_secret = "FCxqcr0pXKzsF9ajmP57S3VQ8V6Drk4o2QYtqMcOszo",
     
    160161        set_t *s;
    161162       
     163        s = set_add( &acc->set, "base_url", TWITTER_API_URL, NULL, acc );
     164        s->flags |= ACC_SET_OFFLINE_ONLY;
     165       
    162166        s = set_add( &acc->set, "message_length", "140", set_eval_int, acc );
    163167       
     
    175179{
    176180        struct im_connection *ic = imcb_new( acc );
    177         struct twitter_data *td = g_new0( struct twitter_data, 1 );
     181        struct twitter_data *td;
    178182        char name[strlen(acc->user)+9];
    179 
     183        url_t url;
     184
     185        if( !url_set( &url, set_getstr( &ic->acc->set, "base_url" ) ) ||
     186            ( url.proto != PROTO_HTTP && url.proto != PROTO_HTTPS ) )
     187        {
     188                imcb_error( ic, "Incorrect API base URL: %s", set_getstr( &ic->acc->set, "base_url" ) );
     189                imc_logout( ic, FALSE );
     190                return;
     191        }
     192       
    180193        twitter_connections = g_slist_append( twitter_connections, ic );
     194        td = g_new0( struct twitter_data, 1 );
    181195        ic->proto_data = td;
    182         ic->flags |= OPT_DOES_HTML;
     196       
     197        td->url_ssl = url.proto == PROTO_HTTPS;
     198        td->url_port = url.port;
     199        td->url_host = g_strdup( url.host );
     200        if( strcmp( url.file, "/" ) != 0 )
     201                td->url_path = g_strdup( url.file );
     202        else
     203                td->url_path = g_strdup( "" );
    183204       
    184205        td->user = acc->user;
    185         if( !set_getbool( &acc->set, "oauth" ) )
    186                 td->pass = g_strdup( acc->pass );
    187         else if( strstr( acc->pass, "oauth_token=" ) )
     206        if( strstr( acc->pass, "oauth_token=" ) )
    188207                td->oauth_info = oauth_from_string( acc->pass, &twitter_oauth );
    189         td->home_timeline_id = 0;
    190208       
    191209        sprintf( name, "twitter_%s", acc->user );
     
    193211        imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
    194212       
    195         if( td->pass || td->oauth_info )
     213        if( td->oauth_info || !set_getbool( &acc->set, "oauth" ) )
    196214                twitter_main_loop_start( ic );
    197215        else
     
    268286static void twitter_add_buddy( struct im_connection *ic, char *who, char *group )
    269287{
     288        twitter_friendships_create_destroy(ic, who, 1);
    270289}
    271290
    272291static void twitter_remove_buddy( struct im_connection *ic, char *who, char *group )
    273292{
     293        twitter_friendships_create_destroy(ic, who, 0);
    274294}
    275295
  • protocols/twitter/twitter.h

    r3429b58 r704dd38  
    4242        struct groupchat *home_timeline_gc;
    4343        gint http_fails;
     44       
     45        gboolean url_ssl;
     46        int url_port;
     47        char *url_host;
     48        char *url_path;
    4449};
    4550
  • protocols/twitter/twitter_http.c

    r3429b58 r704dd38  
    4141
    4242
    43 char *twitter_url_append(char *url, char *key, char* value);
     43static char *twitter_url_append(char *url, char *key, char* value);
    4444
    4545/**
     
    4747 * This is actually pretty generic function... Perhaps it should move to the lib/http_client.c
    4848 */
    49 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)
     49void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func, gpointer data, int is_post, char** arguments, int arguments_len)
    5050{
    51         url_t *url = g_new0( url_t, 1 );
     51        struct twitter_data *td = ic->proto_data;
    5252        char *tmp;
    53         char *request;
     53        GString *request = g_string_new("");
    5454        void *ret;
    55         char *userpass = NULL;
    56         char *userpass_base64;
    5755        char *url_arguments;
    5856
    59         // Fill the url structure.
    60         if( !url_set( url, url_string ) )
    61         {
    62                 g_free( url );
    63                 return NULL;
    64         }
    65 
    66         if( url->proto != PROTO_HTTP && url->proto != PROTO_HTTPS )
    67         {
    68                 g_free( url );
    69                 return NULL;
    70         }
    71 
    72         // Concatenate user and pass
    73         if (user && pass) {
    74                 userpass = g_strdup_printf("%s:%s", user, pass);
    75                 userpass_base64 = base64_encode((unsigned char*)userpass, strlen(userpass));
    76         } else {
    77                 userpass_base64 = NULL;
    78         }
    79 
    80         url_arguments = g_malloc(1);
    81         url_arguments[0] = '\0';
     57        url_arguments = g_strdup("");
    8258
    8359        // Construct the url arguments.
     
    9369        }
    9470
    95         // Do GET stuff...
    96         if (!is_post)
    97         {
    98                 // Find the char-pointer of the end of the string.
    99                 tmp = url->file + strlen(url->file);
    100                 tmp[0] = '?';
    101                 // append the url_arguments to the end of the url->file.
    102                 // TODO GM: Check the length?
    103                 g_stpcpy (tmp+1, url_arguments);
    104         }
    105 
    106 
    10771        // Make the request.
    108         request = g_strdup_printf(  "%s %s HTTP/1.0\r\n"
    109                                     "Host: %s\r\n"
    110                                     "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
    111                                     is_post ? "POST" : "GET", url->file, url->host );
     72        g_string_printf(request, "%s %s%s%s%s HTTP/1.0\r\n"
     73                                 "Host: %s\r\n"
     74                                 "User-Agent: BitlBee " BITLBEE_VERSION " " ARCH "/" CPU "\r\n",
     75                                 is_post ? "POST" : "GET",
     76                                 td->url_path, url_string,
     77                                 is_post ? "" : "?", is_post ? "" : url_arguments,
     78                                 td->url_host);
    11279
    11380        // If a pass and user are given we append them to the request.
    114         if (oi)
     81        if (td->oauth_info)
    11582        {
    11683                char *full_header;
     84                char *full_url;
    11785               
    118                 full_header = oauth_http_header(oi, is_post ? "POST" : "GET",
    119                                                 url_string, url_arguments);
     86                full_url = g_strconcat(set_getstr(&ic->acc->set, "base_url" ), url_string, NULL);
     87                full_header = oauth_http_header(td->oauth_info, is_post ? "POST" : "GET",
     88                                                full_url, url_arguments);
    12089               
    121                 tmp = g_strdup_printf("%sAuthorization: %s\r\n", request, full_header);
    122                 g_free(request);
     90                g_string_append_printf(request, "Authorization: %s\r\n", full_header);
    12391                g_free(full_header);
    124                 request = tmp;
     92                g_free(full_url);
    12593        }
    126         else if (userpass_base64)
     94        else
    12795        {
    128                 tmp = g_strdup_printf("%sAuthorization: Basic %s\r\n", request, userpass_base64);
    129                 g_free(request);
    130                 request = tmp;
     96                char userpass[strlen(ic->acc->user)+2+strlen(ic->acc->pass)];
     97                char *userpass_base64;
     98               
     99                g_snprintf(userpass, sizeof(userpass), "%s:%s", ic->acc->user, ic->acc->pass);
     100                userpass_base64 = base64_encode((unsigned char*)userpass, strlen(userpass));
     101                g_string_append_printf(request, "Authorization: Basic %s\r\n", userpass_base64);
     102                g_free( userpass_base64 );
    131103        }
    132104
     
    135107        {
    136108                // Append the Content-Type and url-encoded arguments.
    137                 tmp = g_strdup_printf("%sContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %zd\r\n\r\n%s",
    138                                                                 request, strlen(url_arguments), url_arguments);
    139                 g_free(request);
    140                 request = tmp;
     109                g_string_append_printf(request,
     110                                       "Content-Type: application/x-www-form-urlencoded\r\n"
     111                                       "Content-Length: %zd\r\n\r\n%s",
     112                                       strlen(url_arguments), url_arguments);
    141113        } else {
    142114                // Append an extra \r\n to end the request...
    143                 tmp = g_strdup_printf("%s\r\n", request);
    144                 g_free(request);
    145                 request = tmp;
     115                g_string_append(request, "\r\n");
    146116        }
    147117
    148         ret = http_dorequest( url->host, url->port,     url->proto == PROTO_HTTPS, request, func, data );
     118        ret = http_dorequest(td->url_host, td->url_port, td->url_ssl, request->str, func, data);
    149119
    150         g_free( url );
    151         g_free( userpass );
    152         g_free( userpass_base64 );
    153120        g_free( url_arguments );
    154         g_free( request );
     121        g_string_free( request, TRUE );
    155122        return ret;
    156123}
    157124
    158 char *twitter_url_append(char *url, char *key, char* value)
     125static char *twitter_url_append(char *url, char *key, char* value)
    159126{
    160127        char *key_encoded = g_strndup(key, 3 * strlen(key));
  • protocols/twitter/twitter_http.h

    r3429b58 r704dd38  
    3030struct oauth_info;
    3131
    32 void *twitter_http(char *url_string, http_input_function func, gpointer data, int is_post,
    33                    char* user, char* pass, struct oauth_info *oi, char** arguments, int arguments_len);
     32void *twitter_http(struct im_connection *ic, char *url_string, http_input_function func,
     33                   gpointer data, int is_post, char** arguments, int arguments_len);
    3434
    3535#endif //_TWITTER_HTTP_H
  • protocols/twitter/twitter_lib.c

    r3429b58 r704dd38  
    117117}
    118118
     119/* Warning: May return a malloc()ed value, which will be free()d on the next
     120   call. Only for short-term use. */
     121static char *twitter_parse_error(struct http_request *req)
     122{
     123        static char *ret = NULL;
     124        struct xt_parser *xp = NULL;
     125        struct xt_node *node;
     126       
     127        g_free(ret);
     128        ret = NULL;
     129       
     130        if (req->body_size > 0)
     131        {
     132                xp = xt_new(NULL, NULL);
     133                xt_feed(xp, req->reply_body, req->body_size);
     134               
     135                if ((node = xt_find_node(xp->root, "hash")) &&
     136                    (node = xt_find_node(node->children, "error")) &&
     137                    node->text_len > 0)
     138                {
     139                        ret = g_strdup_printf("%s (%s)", req->status_string, node->text);
     140                        xt_free(xp);
     141                        return ret;
     142                }
     143               
     144                xt_free(xp);
     145        }
     146       
     147        return req->status_string;
     148}
     149
    119150static void twitter_http_get_friends_ids(struct http_request *req);
    120151
     
    124155void twitter_get_friends_ids(struct im_connection *ic, int next_cursor)
    125156{
    126         struct twitter_data *td = ic->proto_data;
    127 
    128157        // Primitive, but hey! It works...     
    129158        char* args[2];
    130159        args[0] = "cursor";
    131160        args[1] = g_strdup_printf ("%d", next_cursor);
    132         twitter_http(TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
     161        twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2);
    133162
    134163        g_free(args[1]);
     
    196225                // It didn't go well, output the error and return.
    197226                if (++td->http_fails >= 5)
    198                         imcb_error(ic, "Could not retrieve friends. HTTP STATUS: %d", req->status_code);
     227                        imcb_error(ic, "Could not retrieve friends: %s", twitter_parse_error(req));
    199228               
    200229                return;
     
    396425        }
    397426
    398         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);
     427        twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, td->home_timeline_id ? 4 : 2);
    399428
    400429        g_free(args[1]);
     
    434463                twitter_add_buddy(ic, status->user->screen_name, status->user->name);
    435464               
     465                strip_html(status->text);
     466               
    436467                // Say it!
    437468                if (g_strcasecmp(td->user, status->user->screen_name) == 0)
     
    471502                status = l->data;
    472503               
     504                strip_html( status->text );
    473505                if( mode_one )
    474506                        text = g_strdup_printf( "\002<\002%s\002>\002 %s",
     
    523555                // It didn't go well, output the error and return.
    524556                if (++td->http_fails >= 5)
    525                         imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ". HTTP STATUS: %d", req->status_code);
     557                        imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ": %s", twitter_parse_error(req));
    526558               
    527559                return;
     
    575607                // It didn't go well, output the error and return.
    576608                if (++td->http_fails >= 5)
    577                         imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL " HTTP STATUS: %d", req->status_code);
     609                        imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL ": %s", twitter_parse_error(req));
    578610               
    579611                return;
     
    614646void twitter_get_statuses_friends(struct im_connection *ic, int next_cursor)
    615647{
    616         struct twitter_data *td = ic->proto_data;
    617 
    618648        char* args[2];
    619649        args[0] = "cursor";
    620650        args[1] = g_strdup_printf ("%d", next_cursor);
    621651
    622         twitter_http(TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, td->user, td->pass, td->oauth_info, args, 2);
     652        twitter_http(ic, TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, args, 2);
    623653
    624654        g_free(args[1]);
     
    626656
    627657/**
    628  * Callback after sending a new update to twitter.
    629  */
    630 static void twitter_http_post_status(struct http_request *req)
     658 * Callback to use after sending a post request to twitter.
     659 */
     660static void twitter_http_post(struct http_request *req)
    631661{
    632662        struct im_connection *ic = req->data;
     
    639669        if (req->status_code != 200) {
    640670                // It didn't go well, output the error and return.
    641                 imcb_error(ic, "Could not post message... HTTP STATUS: %d", req->status_code);
     671                imcb_error(ic, "HTTP error: %s", twitter_parse_error(req));
    642672                return;
    643673        }
     
    649679void twitter_post_status(struct im_connection *ic, char* msg)
    650680{
    651         struct twitter_data *td = ic->proto_data;
    652 
    653681        char* args[2];
    654682        args[0] = "status";
    655683        args[1] = msg;
    656         twitter_http(TWITTER_STATUS_UPDATE_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 2);
     684        twitter_http(ic, TWITTER_STATUS_UPDATE_URL, twitter_http_post, ic, 1, args, 2);
    657685//      g_free(args[1]);
    658686}
     
    664692void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)
    665693{
    666         struct twitter_data *td = ic->proto_data;
    667 
    668694        char* args[4];
    669695        args[0] = "screen_name";
     
    672698        args[3] = msg;
    673699        // Use the same callback as for twitter_post_status, since it does basically the same.
    674         twitter_http(TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post_status, ic, 1, td->user, td->pass, td->oauth_info, args, 4);
     700        twitter_http(ic, TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post, ic, 1, args, 4);
    675701//      g_free(args[1]);
    676702//      g_free(args[3]);
    677703}
     704
     705void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create)
     706{
     707        char* args[2];
     708        args[0] = "screen_name";
     709        args[1] = who;
     710        twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, twitter_http_post, ic, 1, args, 2);
     711}
  • protocols/twitter/twitter_lib.h

    r3429b58 r704dd38  
    3232
    3333/* Status URLs */
    34 #define TWITTER_STATUS_UPDATE_URL TWITTER_API_URL "/statuses/update.xml"
    35 #define TWITTER_STATUS_SHOW_URL TWITTER_API_URL "/statuses/show/"
    36 #define TWITTER_STATUS_DESTROY_URL TWITTER_API_URL "/statuses/destroy/"
     34#define TWITTER_STATUS_UPDATE_URL "/statuses/update.xml"
     35#define TWITTER_STATUS_SHOW_URL "/statuses/show/"
     36#define TWITTER_STATUS_DESTROY_URL "/statuses/destroy/"
    3737
    3838/* Timeline URLs */
    39 #define TWITTER_PUBLIC_TIMELINE_URL TWITTER_API_URL "/statuses/public_timeline.xml"
    40 #define TWITTER_FEATURED_USERS_URL TWITTER_API_URL "/statuses/featured.xml"
    41 #define TWITTER_FRIENDS_TIMELINE_URL TWITTER_API_URL "/statuses/friends_timeline.xml"
    42 #define TWITTER_HOME_TIMELINE_URL TWITTER_API_URL "/statuses/home_timeline.xml"
    43 #define TWITTER_MENTIONS_URL TWITTER_API_URL "/statuses/mentions.xml"
    44 #define TWITTER_USER_TIMELINE_URL TWITTER_API_URL "/statuses/user_timeline.xml"
     39#define TWITTER_PUBLIC_TIMELINE_URL "/statuses/public_timeline.xml"
     40#define TWITTER_FEATURED_USERS_URL "/statuses/featured.xml"
     41#define TWITTER_FRIENDS_TIMELINE_URL "/statuses/friends_timeline.xml"
     42#define TWITTER_HOME_TIMELINE_URL "/statuses/home_timeline.xml"
     43#define TWITTER_MENTIONS_URL "/statuses/mentions.xml"
     44#define TWITTER_USER_TIMELINE_URL "/statuses/user_timeline.xml"
    4545
    4646/* Users URLs */
    47 #define TWITTER_SHOW_USERS_URL TWITTER_API_URL "/users/show.xml"
    48 #define TWITTER_SHOW_FRIENDS_URL TWITTER_API_URL "/statuses/friends.xml"
    49 #define TWITTER_SHOW_FOLLOWERS_URL TWITTER_API_URL "/statuses/followers.xml"
     47#define TWITTER_SHOW_USERS_URL "/users/show.xml"
     48#define TWITTER_SHOW_FRIENDS_URL "/statuses/friends.xml"
     49#define TWITTER_SHOW_FOLLOWERS_URL "/statuses/followers.xml"
    5050
    5151/* Direct messages URLs */
    52 #define TWITTER_DIRECT_MESSAGES_URL TWITTER_API_URL "/direct_messages.xml"
    53 #define TWITTER_DIRECT_MESSAGES_NEW_URL TWITTER_API_URL "/direct_messages/new.xml"
    54 #define TWITTER_DIRECT_MESSAGES_SENT_URL TWITTER_API_URL "/direct_messages/sent.xml"
    55 #define TWITTER_DIRECT_MESSAGES_DESTROY_URL TWITTER_API_URL "/direct_messages/destroy/"
     52#define TWITTER_DIRECT_MESSAGES_URL "/direct_messages.xml"
     53#define TWITTER_DIRECT_MESSAGES_NEW_URL "/direct_messages/new.xml"
     54#define TWITTER_DIRECT_MESSAGES_SENT_URL "/direct_messages/sent.xml"
     55#define TWITTER_DIRECT_MESSAGES_DESTROY_URL "/direct_messages/destroy/"
    5656
    5757/* Friendships URLs */
    58 #define TWITTER_FRIENDSHIPS_CREATE_URL TWITTER_API_URL "/friendships/create.xml"
    59 #define TWITTER_FRIENDSHIPS_DESTROY_URL TWITTER_API_URL "/friendships/destroy.xml"
    60 #define TWITTER_FRIENDSHIPS_SHOW_URL TWITTER_API_URL "/friendships/show.xml"
     58#define TWITTER_FRIENDSHIPS_CREATE_URL "/friendships/create.xml"
     59#define TWITTER_FRIENDSHIPS_DESTROY_URL "/friendships/destroy.xml"
     60#define TWITTER_FRIENDSHIPS_SHOW_URL "/friendships/show.xml"
    6161
    6262/* Social graphs URLs */
    63 #define TWITTER_FRIENDS_IDS_URL TWITTER_API_URL "/friends/ids.xml"
    64 #define TWITTER_FOLLOWERS_IDS_URL TWITTER_API_URL "/followers/ids.xml"
     63#define TWITTER_FRIENDS_IDS_URL "/friends/ids.xml"
     64#define TWITTER_FOLLOWERS_IDS_URL "/followers/ids.xml"
    6565
    6666/* Account URLs */
    67 #define TWITTER_ACCOUNT_RATE_LIMIT_URL TWITTER_API_URL "/account/rate_limit_status.xml"
     67#define TWITTER_ACCOUNT_RATE_LIMIT_URL "/account/rate_limit_status.xml"
    6868
    6969/* Favorites URLs */
    70 #define TWITTER_FAVORITES_GET_URL TWITTER_API_URL "/favorites.xml"
    71 #define TWITTER_FAVORITE_CREATE_URL TWITTER_API_URL "/favorites/create/"
    72 #define TWITTER_FAVORITE_DESTROY_URL TWITTER_API_URL "/favorites/destroy/"
     70#define TWITTER_FAVORITES_GET_URL "/favorites.xml"
     71#define TWITTER_FAVORITE_CREATE_URL "/favorites/create/"
     72#define TWITTER_FAVORITE_DESTROY_URL "/favorites/destroy/"
    7373
    7474/* Block URLs */
    75 #define TWITTER_BLOCKS_CREATE_URL TWITTER_API_URL "/blocks/create/"
    76 #define TWITTER_BLOCKS_DESTROY_URL TWITTER_API_URL "/blocks/destroy/"
     75#define TWITTER_BLOCKS_CREATE_URL "/blocks/create/"
     76#define TWITTER_BLOCKS_DESTROY_URL "/blocks/destroy/"
    7777
    7878void twitter_get_friends_ids(struct im_connection *ic, int next_cursor);
     
    8282void twitter_post_status(struct im_connection *ic, char *msg);
    8383void twitter_direct_messages_new(struct im_connection *ic, char *who, char *message);
     84void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create);
    8485
    8586#endif //_TWITTER_LIB_H
Note: See TracChangeset for help on using the changeset viewer.