Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocols/twitter/twitter_lib.c

    red83279 r1201fcb  
    3636#include "base64.h"
    3737#include "twitter_lib.h"
    38 #include "parson.h"
     38#include "json_util.h"
    3939#include <ctype.h>
    4040#include <errno.h>
     
    6464        gboolean from_filter;
    6565};
    66 
    67 #define JSON_O_FOREACH(o, k, v) \
    68     const char *k; const JSON_Value *v; int __i; \
    69     for (__i = 0; json_object_get_tuple(o, __i, &k, &v); __i++)
    7066
    7167/**
     
    170166{
    171167        static char *ret = NULL;
    172         JSON_Value *root, *err;
     168        json_value *root, *err;
    173169
    174170        g_free(ret);
     
    176172
    177173        if (req->body_size > 0) {
    178                 root = json_parse_string(req->reply_body);
    179                 err = json_object_get_value(json_object(root), "errors");
    180                 if (err && json_type(err) == JSONArray &&
    181                     (err = json_array_get_value(json_array(err), 0)) &&
    182                     json_type(err) == JSONObject) {
    183                         const char *msg = json_object_get_string(json_object(err), "message");
     174                root = json_parse(req->reply_body, req->body_size);
     175                err = json_o_get(root, "errors");
     176                if (err && err->type == json_array && (err = err->u.array.values[0]) &&
     177                    err->type == json_object) {
     178                        const char *msg = json_o_str(err, "message");
    184179                        if (msg) {
    185180                                ret = g_strdup_printf("%s (%s)", req->status_string, msg);
     
    194189/* WATCH OUT: This function might or might not destroy your connection.
    195190   Sub-optimal indeed, but just be careful when this returns NULL! */
    196 static JSON_Value *twitter_parse_response(struct im_connection *ic, struct http_request *req)
     191static json_value *twitter_parse_response(struct im_connection *ic, struct http_request *req)
    197192{
    198193        gboolean logging_in = !(ic->flags & OPT_LOGGED_IN);
    199194        gboolean periodic;
    200195        struct twitter_data *td = ic->proto_data;
    201         JSON_Value *ret;
     196        json_value *ret;
    202197        char path[64] = "", *s;
    203198
     
    237232        }
    238233
    239         if ((ret = json_parse_string(req->reply_body)) == NULL) {
     234        if ((ret = json_parse(req->reply_body, req->body_size)) == NULL) {
    240235                imcb_error(ic, "Could not retrieve %s: %s",
    241236                           path, "XML parse error");
     
    264259 * Fill a list of ids.
    265260 */
    266 static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl)
    267 {
    268         JSON_Array *c;
     261static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl)
     262{
     263        json_value *c;
    269264        int i;
    270265
     
    272267        txl->type = TXL_ID;
    273268
    274         if (!(c = json_object_get_array(json_object(node), "ids"))) {
     269        c = json_o_get(node, "ids");
     270        if (!c || c->type != json_array) {
    275271                return FALSE;
    276272        }
    277273
    278         for (i = 0; i < json_array_get_count(c); i++) {
    279                 jint id = json_array_get_integer(c, i);
     274        for (i = 0; i < c->u.array.length; i++) {
     275                if (c->u.array.values[i]->type != json_integer) {
     276                        continue;
     277                }
    280278
    281279                txl->list = g_slist_prepend(txl->list,
    282                                             g_strdup_printf("%lld", id));
    283         }
    284 
    285         JSON_Value *next = json_object_get_value(json_object(node), "next_cursor");
    286         if (next && json_type(next) == JSONInteger) {
    287                 txl->next_cursor = json_integer(next);
     280                                            g_strdup_printf("%" PRIu64, c->u.array.values[i]->u.integer));
     281        }
     282
     283        c = json_o_get(node, "next_cursor");
     284        if (c && c->type == json_integer) {
     285                txl->next_cursor = c->u.integer;
    288286        } else {
    289287                txl->next_cursor = -1;
     
    301299{
    302300        struct im_connection *ic;
    303         JSON_Value *parsed;
     301        json_value *parsed;
    304302        struct twitter_xml_list *txl;
    305303        struct twitter_data *td;
     
    339337}
    340338
    341 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl);
     339static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl);
    342340static void twitter_http_get_users_lookup(struct http_request *req);
    343341
     
    380378{
    381379        struct im_connection *ic = req->data;
    382         JSON_Value *parsed;
     380        json_value *parsed;
    383381        struct twitter_xml_list *txl;
    384382        GSList *l = NULL;
     
    412410}
    413411
    414 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node)
     412struct twitter_xml_user *twitter_xt_get_user(const json_value *node)
    415413{
    416414        struct twitter_xml_user *txu;
    417        
    418         if (!node)
    419                 return NULL;
     415        json_value *jv;
    420416
    421417        txu = g_new0(struct twitter_xml_user, 1);
    422         txu->name = g_strdup(json_object_get_string(node, "name"));
    423         txu->screen_name = g_strdup(json_object_get_string(node, "screen_name"));
    424         txu->uid = json_object_get_integer(node, "id");
     418        txu->name = g_strdup(json_o_str(node, "name"));
     419        txu->screen_name = g_strdup(json_o_str(node, "screen_name"));
     420
     421        jv = json_o_get(node, "id");
     422        txu->uid = jv->u.integer;
    425423
    426424        return txu;
     
    432430 *  - all <user>s from the <users> element.
    433431 */
    434 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl)
     432static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl)
    435433{
    436434        struct twitter_xml_user *txu;
     
    440438        txl->type = TXL_USER;
    441439
    442         if (json_type(node) != JSONArray) {
     440        if (!node || node->type != json_array) {
    443441                return FALSE;
    444442        }
    445        
     443
    446444        // The root <users> node should hold the list of users <user>
    447445        // Walk over the nodes children.
    448         JSON_Array *arr = json_array(node);
    449         for (i = 0; i < json_array_get_count(arr); i++) {
    450                 JSON_Object *o = json_array_get_object(arr, i);
    451                 if (!o)
    452                         continue;
    453                 txu = twitter_xt_get_user(o);
     446        for (i = 0; i < node->u.array.length; i++) {
     447                txu = twitter_xt_get_user(node->u.array.values[i]);
    454448                if (txu) {
    455449                        txl->list = g_slist_prepend(txl->list, txu);
     
    466460#endif
    467461
    468 static void expand_entities(char **text, const JSON_Object *node);
     462static void expand_entities(char **text, const json_value *node);
    469463
    470464/**
     
    476470 *  - the user in a twitter_xml_user struct.
    477471 */
    478 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node)
     472static struct twitter_xml_status *twitter_xt_get_status(const json_value *node)
    479473{
    480474        struct twitter_xml_status *txs;
    481         const JSON_Object *rt = NULL;
    482 
    483         if (!node) {
     475        const json_value *rt = NULL;
     476
     477        if (node->type != json_object) {
    484478                return FALSE;
    485479        }
     
    487481
    488482        JSON_O_FOREACH(node, k, v) {
    489                 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
    490                         // TODO: Huh strip html? In json? Not sure whether I have to..
     483                if (strcmp("text", k) == 0 && v->type == json_string) {
     484                        txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);
    491485                        strip_html(txs->text);
    492                 } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) {
    493                         // Handling below.
    494                 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {
     486                } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {
     487                        rt = v;
     488                } else if (strcmp("created_at", k) == 0 && v->type == json_string) {
    495489                        struct tm parsed;
    496490
     
    498492                           this field. :-( Also assumes the timezone used
    499493                           is UTC since C time handling functions suck. */
    500                         if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
     494                        if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
    501495                                txs->created_at = mktime_utc(&parsed);
    502496                        }
    503                 } else if (strcmp("user", k) == 0 && json_type(v) == JSONObject) {
    504                         txs->user = twitter_xt_get_user(json_object(v));
    505                 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) {
    506                         txs->rt_id = txs->id = json_integer(v);
    507                 } else if (strcmp("in_reply_to_status_id", k) == 0 && json_type(v) == JSONInteger) {
    508                         txs->reply_to = json_integer(v);
     497                } else if (strcmp("user", k) == 0 && v->type == json_object) {
     498                        txs->user = twitter_xt_get_user(v);
     499                } else if (strcmp("id", k) == 0 && v->type == json_integer) {
     500                        txs->rt_id = txs->id = v->u.integer;
     501                } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {
     502                        txs->reply_to = v->u.integer;
    509503                }
    510504        }
     
    535529 * Function to fill a twitter_xml_status struct (DM variant).
    536530 */
    537 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node)
     531static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node)
    538532{
    539533        struct twitter_xml_status *txs;
    540534
    541         if (!node) {
     535        if (node->type != json_object) {
    542536                return FALSE;
    543537        }
     
    545539
    546540        JSON_O_FOREACH(node, k, v) {
    547                 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
     541                if (strcmp("text", k) == 0 && v->type == json_string) {
     542                        txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);
    548543                        strip_html(txs->text);
    549                 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {
     544                } else if (strcmp("created_at", k) == 0 && v->type == json_string) {
    550545                        struct tm parsed;
    551546
     
    553548                           this field. :-( Also assumes the timezone used
    554549                           is UTC since C time handling functions suck. */
    555                         if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
     550                        if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
    556551                                txs->created_at = mktime_utc(&parsed);
    557552                        }
    558                 } else if (strcmp("sender", k) == 0 && json_type(v) == JSONObject) {
    559                         txs->user = twitter_xt_get_user(json_object(v));
    560                 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) {
    561                         txs->id = json_integer(v);
     553                } else if (strcmp("sender", k) == 0 && v->type == json_object) {
     554                        txs->user = twitter_xt_get_user(v);
     555                } else if (strcmp("id", k) == 0 && v->type == json_integer) {
     556                        txs->id = v->u.integer;
    562557                }
    563558        }
     
    573568}
    574569
    575 static void expand_entities(char **text, const JSON_Object *node)
    576 {
    577         JSON_Object *entities, *quoted;
     570static void expand_entities(char **text, const json_value *node)
     571{
     572        json_value *entities, *quoted;
    578573        char *quote_url = NULL, *quote_text = NULL;
    579574
    580         if (!(entities = json_object_get_object(node, "entities")))
    581                 return;
    582         if ((quoted = json_object_get_object(node, "quoted_status"))) {
     575        if (!((entities = json_o_get(node, "entities")) && entities->type == json_object))
     576                return;
     577        if ((quoted = json_o_get(node, "quoted_status")) && quoted->type == json_object) {
    583578                /* New "retweets with comments" feature. Note that this info
    584579                 * seems to be included in the streaming API only! Grab the
     
    596591                int i;
    597592
    598                 if (json_type(v) != JSONArray) {
     593                if (v->type != json_array) {
    599594                        continue;
    600595                }
     
    603598                }
    604599
    605                 for (i = 0; i < json_array_get_count(json_array(v)); i++) {
     600                for (i = 0; i < v->u.array.length; i++) {
    606601                        const char *format = "%s%s <%s>%s";
    607                         JSON_Object *r = json_array_get_object(json_array(v), i);
    608 
    609                         if (!r) {
     602
     603                        if (v->u.array.values[i]->type != json_object) {
    610604                                continue;
    611605                        }
    612606
    613                         const char *kort = json_object_get_string(r, "url");
    614                         const char *disp = json_object_get_string(r, "display_url");
    615                         const char *full = json_object_get_string(r, "expanded_url");
     607                        const char *kort = json_o_str(v->u.array.values[i], "url");
     608                        const char *disp = json_o_str(v->u.array.values[i], "display_url");
     609                        const char *full = json_o_str(v->u.array.values[i], "expanded_url");
    616610                        char *pos, *new;
    617611
     
    642636 *  - the next_cursor.
    643637 */
    644 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node,
     638static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,
    645639                                           struct twitter_xml_list *txl)
    646640{
     
    651645        txl->type = TXL_STATUS;
    652646
    653         if (json_type(node) != JSONArray) {
     647        if (node->type != json_array) {
    654648                return FALSE;
    655649        }
     
    657651        // The root <statuses> node should hold the list of statuses <status>
    658652        // Walk over the nodes children.
    659         for (i = 0; i < json_array_get_count(json_array(node)); i++) {
    660                 txs = twitter_xt_get_status(json_array_get_object(json_array(node), i));
     653        for (i = 0; i < node->u.array.length; i++) {
     654                txs = twitter_xt_get_status(node->u.array.values[i]);
    661655                if (!txs) {
    662656                        continue;
     
    864858}
    865859
    866 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter);
     860static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter);
    867861
    868862static void twitter_http_stream(struct http_request *req)
     
    870864        struct im_connection *ic = req->data;
    871865        struct twitter_data *td;
    872         JSON_Value *parsed;
     866        json_value *parsed;
    873867        int len = 0;
    874868        char c, *nl;
     
    908902                req->reply_body[len] = '\0';
    909903
    910                 if ((parsed = json_parse_string(req->reply_body))) {
     904                if ((parsed = json_parse(req->reply_body, req->body_size))) {
    911905                        from_filter = (req == td->filter_stream);
    912                         twitter_stream_handle_object(ic, json_object(parsed), from_filter);
     906                        twitter_stream_handle_object(ic, parsed, from_filter);
    913907                }
    914908                json_value_free(parsed);
     
    924918}
    925919
    926 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o);
     920static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o);
    927921static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs);
    928922
    929 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter)
     923static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter)
    930924{
    931925        struct twitter_data *td = ic->proto_data;
    932926        struct twitter_xml_status *txs;
    933         JSON_Object *c;
     927        json_value *c;
    934928
    935929        if ((txs = twitter_xt_get_status(o))) {
     
    938932                txs_free(txs);
    939933                return ret;
    940         } else if ((c = json_object_get_object(o, "direct_message")) &&
     934        } else if ((c = json_o_get(o, "direct_message")) &&
    941935                   (txs = twitter_xt_get_dm(c))) {
    942936                if (g_strcasecmp(txs->user->screen_name, td->user) != 0) {
     
    946940                txs_free(txs);
    947941                return TRUE;
    948         } else if (json_object_get_string(o, "event")) {
     942        } else if ((c = json_o_get(o, "event")) && c->type == json_string) {
    949943                twitter_stream_handle_event(ic, o);
    950944                return TRUE;
    951         } else if ((c = json_object_get_object(o, "disconnect"))) {
     945        } else if ((c = json_o_get(o, "disconnect")) && c->type == json_object) {
    952946                /* HACK: Because we're inside an event handler, we can't just
    953947                   disconnect here. Instead, just change the HTTP status string
    954948                   into a Twitter status string. */
    955                 char *reason = g_strdup(json_object_get_string(c, "reason"));
     949                char *reason = json_o_strdup(c, "reason");
    956950                if (reason) {
    957951                        g_free(td->stream->status_string);
     
    992986}
    993987
    994 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o)
    995 {
    996         struct twitter_data *td = ic->proto_data;
    997         JSON_Object *source = json_object_get_object(o, "source");
    998         JSON_Object *target = json_object_get_object(o, "target");
    999         const char *type = json_object_get_string(o, "event");
    1000 
    1001         if (!type || !source || !target) {
     988static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o)
     989{
     990        struct twitter_data *td = ic->proto_data;
     991        json_value *source = json_o_get(o, "source");
     992        json_value *target = json_o_get(o, "target");
     993        const char *type = json_o_str(o, "event");
     994
     995        if (!type || !source || source->type != json_object
     996            || !target || target->type != json_object) {
    1002997                return FALSE;
    1003998        }
     
    10961091        struct twitter_filter *tf;
    10971092        GList *users = NULL;
    1098         JSON_Value *parsed;
     1093        json_value *parsed;
     1094        json_value *id;
     1095        const char *name;
    10991096        GString *fstr;
    11001097        GSList *l;
     
    11211118        }
    11221119
    1123         if (json_type(parsed) != JSONArray) {
     1120        if (parsed->type != json_array) {
    11241121                goto finish;
    11251122        }
    11261123
    1127         for (i = 0; i < json_array_get_count(json_array(parsed)); i++) {
    1128                 JSON_Object *o = json_array_get_object(json_array(parsed), i);
    1129                 jint id = json_object_get_integer(o, "id");
    1130                 const char *name = json_object_get_string(o, "screen_name");
    1131 
    1132                 if (!name || !id) {
     1124        for (i = 0; i < parsed->u.array.length; i++) {
     1125                id = json_o_get(parsed->u.array.values[i], "id");
     1126                name = json_o_str(parsed->u.array.values[i], "screen_name");
     1127
     1128                if (!name || !id || id->type != json_integer) {
    11331129                        continue;
    11341130                }
     
    11381134
    11391135                        if (g_strcasecmp(tf->text, name) == 0) {
    1140                                 tf->uid = id;
     1136                                tf->uid = id->u.integer;
    11411137                                users = g_list_delete_link(users, u);
    11421138                                break;
     
    13791375        struct im_connection *ic = req->data;
    13801376        struct twitter_data *td;
    1381         JSON_Value *parsed;
     1377        json_value *parsed;
    13821378        struct twitter_xml_list *txl;
    13831379
     
    14181414        struct im_connection *ic = req->data;
    14191415        struct twitter_data *td;
    1420         JSON_Value *parsed;
     1416        json_value *parsed;
    14211417        struct twitter_xml_list *txl;
    14221418
     
    14581454        struct im_connection *ic = req->data;
    14591455        struct twitter_data *td;
    1460         JSON_Value *parsed;
    1461         jint id;
     1456        json_value *parsed, *id;
    14621457
    14631458        // Check if the connection is still active.
     
    14731468        }
    14741469
    1475         if ((id = json_object_get_integer(json_object(parsed), "id"))) {
    1476                 td->last_status_id = id;
     1470        if ((id = json_o_get(parsed, "id")) && id->type == json_integer) {
     1471                td->last_status_id = id->u.integer;
    14771472        }
    14781473
     
    15821577{
    15831578        struct im_connection *ic = req->data;
    1584         JSON_Value *parsed;
    1585         uint64_t id;
     1579        json_value *parsed, *id;
    15861580        const char *name;
    15871581
     
    15951589        }
    15961590
     1591        /* for the parson branch:
    15971592        name = json_object_dotget_string(json_object(parsed), "user.screen_name");
    15981593        id = json_object_get_integer(json_object(parsed), "id");
    1599 
    1600         if (name && id) {
    1601                 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id);
     1594        */
     1595
     1596        name = json_o_str(json_o_get(parsed, "user"), "screen_name");
     1597        id = json_o_get(parsed, "id");
     1598
     1599        if (name && id && id->type == json_integer) {
     1600                twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer);
    16021601        } else {
    16031602                twitter_log(ic, "Error: could not fetch tweet url.");
Note: See TracChangeset for help on using the changeset viewer.