Changeset 2a6da96


Ignore:
Timestamp:
2012-09-25T00:08:54Z (12 years ago)
Author:
Wilmer van der Gaast <wilmer@…>
Branches:
master
Children:
a992d7a, ba86713
Parents:
6f55bec
Message:

Move Twitter XML parsing/error checking into a separate function and use it
everywhere. This should be a more thorough fix for #953.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter_lib.c

    r6f55bec r2a6da96  
    55*                                                                           *
    66*  Copyright 2009-2010 Geert Mulders <g.c.w.m.mulders@gmail.com>            *
    7 *  Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net>              *
     7*  Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net>              *
    88*                                                                           *
    99*  This library is free software; you can redistribute it and/or            *
     
    188188}
    189189
     190static struct xt_node *twitter_parse_response(struct im_connection *ic, struct http_request *req)
     191{
     192        gboolean logging_in = !(ic->flags & OPT_LOGGED_IN);
     193        gboolean periodic;
     194        struct twitter_data *td = ic->proto_data;
     195        struct xt_node *ret;
     196        char path[64] = "", *s;
     197       
     198        if ((s = strchr(req->request, ' '))) {
     199                path[sizeof(path)-1] = '\0';
     200                strncpy(path, s + 1, sizeof(path) - 1);
     201                if ((s = strchr(path, '?')) || (s = strchr(path, ' ')))
     202                        *s = '\0';
     203        }
     204       
     205        /* Kinda nasty. :-( Trying to suppress error messages, but only
     206           for periodic (i.e. mentions/timeline) queries. */
     207        periodic = strstr(path, "timeline") || strstr(path, "mentions");
     208       
     209        if (req->status_code == 401 && logging_in) {
     210                /* IIRC Twitter once had an outage where they were randomly
     211                   throwing 401s so I'll keep treating this one as fatal
     212                   only during login. */
     213                imcb_error(ic, "Authentication failure");
     214                imc_logout(ic, FALSE);
     215                return NULL;
     216        } else if (req->status_code != 200) {
     217                // It didn't go well, output the error and return.
     218                if (!periodic || logging_in || ++td->http_fails >= 5)
     219                        imcb_error(ic, "Could not retrieve %s: %s",
     220                                   path, twitter_parse_error(req));
     221               
     222                if (logging_in)
     223                        imc_logout(ic, TRUE);
     224                return NULL;
     225        } else {
     226                td->http_fails = 0;
     227        }
     228
     229        if ((ret = xt_from_string(req->reply_body, req->body_size)) == NULL) {
     230                imcb_error(ic, "Could not retrieve %s: %s",
     231                           path, "XML parse error");
     232        }
     233        return ret;
     234}
     235
    190236static void twitter_http_get_friends_ids(struct http_request *req);
    191237
     
    266312        td = ic->proto_data;
    267313
    268         // Check if the HTTP request went well. More strict checks as this is
    269         // the first request we do in a session.
    270         if (req->status_code == 401) {
    271                 imcb_error(ic, "Authentication failure");
    272                 imc_logout(ic, FALSE);
    273                 return;
    274         } else if (req->status_code != 200) {
    275                 // It didn't go well, output the error and return.
    276                 imcb_error(ic, "Could not retrieve %s: %s",
    277                            TWITTER_FRIENDS_IDS_URL, twitter_parse_error(req));
    278                 imc_logout(ic, TRUE);
    279                 return;
    280         } else {
    281                 td->http_fails = 0;
    282         }
    283 
    284314        /* Create the room now that we "logged in". */
    285315        if (!td->timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)
     
    290320
    291321        // Parse the data.
    292         parsed = xt_from_string(req->reply_body, req->body_size);
     322        if (!(parsed = twitter_parse_response(ic, req)))
     323                return;
    293324        twitter_xt_get_friends_id_list(parsed, txl);
    294325        xt_free_node(parsed);
     
    348379{
    349380        struct im_connection *ic = req->data;
    350         struct twitter_data *td;
    351381        struct xt_node *parsed;
    352382        struct twitter_xml_list *txl;
     
    358388                return;
    359389
    360         td = ic->proto_data;
    361 
    362         if (req->status_code != 200) {
    363                 // It didn't go well, output the error and return.
    364                 imcb_error(ic, "Could not retrieve %s: %s",
    365                            TWITTER_USERS_LOOKUP_URL, twitter_parse_error(req));
    366                 imc_logout(ic, TRUE);
    367                 return;
    368         } else {
    369                 td->http_fails = 0;
    370         }
    371 
    372390        txl = g_new0(struct twitter_xml_list, 1);
    373391        txl->list = NULL;
    374392
    375         // Parse the data.
    376         parsed = xt_from_string(req->reply_body, req->body_size);
    377 
    378393        // Get the user list from the parsed xml feed.
     394        if (!(parsed = twitter_parse_response(ic, req)))
     395                return;
    379396        twitter_xt_get_users(parsed, txl);
    380397        xt_free_node(parsed);
     
    787804                }
    788805        }
     806       
     807        if (!(ic->flags & OPT_LOGGED_IN))
     808                imcb_connected(ic);
    789809
    790810        // See if the user wants to see the messages in a groupchat window or as private messages.
     
    894914        td = ic->proto_data;
    895915
    896         // Check if the HTTP request went well.
    897         if (req->status_code == 200) {
    898                 td->http_fails = 0;
    899                 if (!(ic->flags & OPT_LOGGED_IN))
    900                         imcb_connected(ic);
    901         } else {
    902                 // It didn't go well, output the error and return.
    903                 if (++td->http_fails >= 5)
    904                         imcb_error(ic, "Could not retrieve %s: %s",
    905                                    TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req));
    906 
    907                 goto end;
    908         }
    909 
    910916        txl = g_new0(struct twitter_xml_list, 1);
    911917        txl->list = NULL;
    912918
    913         // Parse the data.
    914         parsed = xt_from_string(req->reply_body, req->body_size);
    915919        // The root <statuses> node should hold the list of statuses <status>
     920        if (!(parsed = twitter_parse_response(ic, req)))
     921                goto end;
    916922        twitter_xt_get_status_list(ic, parsed, txl);
    917923        xt_free_node(parsed);
     
    941947        td = ic->proto_data;
    942948
    943         // Check if the HTTP request went well.
    944         if (req->status_code == 200) {
    945                 td->http_fails = 0;
    946                 if (!(ic->flags & OPT_LOGGED_IN))
    947                         imcb_connected(ic);
    948         } else {
    949                 // It didn't go well, output the error and return.
    950                 if (++td->http_fails >= 5)
    951                         imcb_error(ic, "Could not retrieve %s: %s",
    952                                    TWITTER_MENTIONS_URL, twitter_parse_error(req));
    953 
    954                 goto end;
    955         }
    956 
    957949        txl = g_new0(struct twitter_xml_list, 1);
    958950        txl->list = NULL;
    959951
    960         // Parse the data.
    961         parsed = xt_from_string(req->reply_body, req->body_size);
    962952        // The root <statuses> node should hold the list of statuses <status>
     953        if (!(parsed = twitter_parse_response(ic, req)))
     954                goto end;
    963955        twitter_xt_get_status_list(ic, parsed, txl);
    964956        xt_free_node(parsed);
     
    980972        struct im_connection *ic = req->data;
    981973        struct twitter_data *td;
     974        struct xt_node *parsed, *node;
    982975
    983976        // Check if the connection is still active.
     
    988981        td->last_status_id = 0;
    989982
    990         // Check if the HTTP request went well.
    991         if (req->status_code != 200) {
    992                 // It didn't go well, output the error and return.
    993                 imcb_error(ic, "HTTP error: %s", twitter_parse_error(req));
    994                 return;
    995         }
    996 
    997         if (req->body_size > 0) {
    998                 struct xt_node *parsed, *node;
    999 
    1000                 parsed = xt_from_string(req->reply_body, req->body_size);
    1001 
    1002                 if ((node = xt_find_node(parsed, "status")) &&
    1003                     (node = xt_find_node(node->children, "id")) && node->text)
    1004                         td->last_status_id = g_ascii_strtoull(node->text, NULL, 10);
    1005 
    1006                 xt_free_node(parsed);
    1007         }
     983        if (!(parsed = twitter_parse_response(ic, req)))
     984                return;
     985       
     986        if ((node = xt_find_node(parsed, "status")) &&
     987            (node = xt_find_node(node->children, "id")) && node->text)
     988                td->last_status_id = g_ascii_strtoull(node->text, NULL, 10);
    1008989}
    1009990
Note: See TracChangeset for help on using the changeset viewer.