Changes in / [2f99f23:b75671d]


Ignore:
Files:
7 added
4 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r2f99f23 rb75671d  
    3232bitlbee.service
    3333bitlbee@.service
     34*.pyc
  • configure

    r2f99f23 rb75671d  
    3232jabber="default-on"
    3333oscar="default-on"
     34rpc="rpc-on"
    3435yahoo="default-on"
    3536
     
    130131--purple=0/1    Disable/enable libpurple support        $purple
    131132                (automatically disables other protocol modules)
     133--rpc=0/1       Disable/enable RPC interface            $rpc
    132134
    133135--doc=0/1       Disable/enable help.txt generation      $doc
     
    820822        protocols=$protocols'twitter '
    821823        protoobjs=$protoobjs'twitter_mod.o '
     824fi
     825
     826if [ "$rpc" = 0 ]; then
     827        echo '#undef WITH_RPC' >> config.h
     828else
     829        echo '#define WITH_RPC' >> config.h
     830        protocols=$protocols'rpc '
     831        protoobjs=$protoobjs'rpc_mod.o '
    822832fi
    823833
  • irc_channel.c

    r2f99f23 rb75671d  
    724724        }
    725725
     726        if (!bu->ic->acc->prpl->add_buddy) {
     727                irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name);
     728                return FALSE;
     729        }
     730
    726731        bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle,
    727732                                     icc->group ? icc->group->name : NULL);
     
    741746        if (icc->type != IRC_CC_TYPE_GROUP) {
    742747                irc_send_num(ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name);
     748                return;
     749        }
     750
     751        if (!bu->ic->acc->prpl->remove_buddy) {
     752                irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name);
    743753                return;
    744754        }
  • lib/Makefile

    r2f99f23 rb75671d  
    1313
    1414# [SH] Program variables
    15 objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o json.o json_util.o md5.o misc.o oauth.o oauth2.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ns_parse.o
     15objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o oauth2.o parson.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o ns_parse.o
    1616
    1717LFLAGS += -r
  • lib/misc.c

    r2f99f23 rb75671d  
    427427}
    428428
    429 int is_bool(char *value)
     429int is_bool(const char *value)
    430430{
    431431        if (*value == 0) {
     
    453453}
    454454
    455 int bool2int(char *value)
     455int bool2int(const char *value)
    456456{
    457457        int i;
  • lib/misc.h

    r2f99f23 rb75671d  
    137137G_MODULE_EXPORT void random_bytes(unsigned char *buf, int count);
    138138
    139 G_MODULE_EXPORT int is_bool(char *value);
    140 G_MODULE_EXPORT int bool2int(char *value);
     139G_MODULE_EXPORT int is_bool(const char *value);
     140G_MODULE_EXPORT int bool2int(const char *value);
    141141
    142142G_MODULE_EXPORT struct ns_srv_reply **srv_lookup(char *service, char *protocol, char *domain);
  • lib/oauth2.c

    r2f99f23 rb75671d  
    4242#include "oauth2.h"
    4343#include "oauth.h"
    44 #include "json.h"
    45 #include "json_util.h"
     44#include "parson.h"
    4645#include "url.h"
     46
     47#define JSON_O_FOREACH(o, k, v) \
     48    const char *k; const JSON_Value *v; int __i; \
     49    for (__i = 0; json_object_get_tuple(o, __i, &k, &v); __i++)
    4750
    4851char *oauth2_url(const struct oauth2_service *sp)
     
    113116}
    114117
    115 static char* oauth2_parse_error(json_value *e)
     118static char* oauth2_parse_error(const JSON_Value *e)
    116119{
    117120        /* This does a reasonable job with some of the flavours of error
    118121           responses I've seen. Because apparently it's not standardised. */
    119122
    120         if (e->type == json_object) {
     123        if (json_type(e) == JSONObject) {
    121124                /* Facebook style */
    122                 const char *msg = json_o_str(e, "message");
    123                 const char *type = json_o_str(e, "type");
    124                 json_value *code_o = json_o_get(e, "code");
    125                 int code = 0;
    126 
    127                 if (code_o && code_o->type == json_integer) {
    128                         code = code_o->u.integer;
    129                 }
    130 
     125                const char *msg = json_object_get_string(json_object(e), "message");
     126                const char *type = json_object_get_string(json_object(e), "type");
     127                JSON_Value *code_o = json_object_get_value(json_object(e), "code");
     128                int code = json_value_get_integer(code_o);
    131129                return g_strdup_printf("Error %d: %s", code, msg ? msg : type ? type : "Unknown error");
    132         } else if (e->type == json_string) {
    133                 return g_strdup(e->u.string.ptr);
     130        } else if (json_type(e) == JSONString) {
     131                return g_strdup(json_string(e));
    134132        }
    135133        return NULL;
     
    156154        if (content_type && (strstr(content_type, "application/json") ||
    157155                             strstr(content_type, "text/javascript"))) {
    158                 json_value *js = json_parse(req->reply_body, req->body_size);
    159                 if (js && js->type == json_object) {
    160                         JSON_O_FOREACH(js, k, v){
     156                JSON_Value *js = json_parse_string(req->reply_body);
     157                if (js && json_type(js) == JSONObject) {
     158                        JSON_O_FOREACH(json_object(js), k, v){
    161159                                if (strcmp(k, "error") == 0) {
    162160                                        error = oauth2_parse_error(v);
    163161                                }
    164                                 if (v->type != json_string) {
     162                                if (json_type(v) != JSONString) {
    165163                                        continue;
    166164                                }
    167165                                if (strcmp(k, "access_token") == 0) {
    168                                         atoken = g_strdup(v->u.string.ptr);
     166                                        atoken = g_strdup(json_string(v));
    169167                                }
    170168                                if (strcmp(k, "refresh_token") == 0) {
    171                                         rtoken = g_strdup(v->u.string.ptr);
     169                                        rtoken = g_strdup(json_string(v));
    172170                                }
    173171                        }
  • protocols/account.c

    r2f99f23 rb75671d  
    2727#include "bitlbee.h"
    2828#include "account.h"
    29 
    30 static const char* account_protocols_local[] = {
    31         "gg", "whatsapp", NULL
    32 };
    3329
    3430static char *set_eval_nick_source(set_t *set, char *value);
     
    463459        return a->auto_reconnect_delay;
    464460}
    465 
    466 int protocol_account_islocal(const char* protocol)
    467 {
    468         const char** p = account_protocols_local;
    469 
    470         do {
    471                 if (strcmp(*p, protocol) == 0) {
    472                         return 1;
    473                 }
    474         } while (*(++p));
    475         return 0;
    476 }
  • protocols/account.h

    r2f99f23 rb75671d  
    5858int account_reconnect_delay(account_t *a);
    5959
    60 int protocol_account_islocal(const char* protocol);
    61 
    6260typedef enum {
    6361        ACC_SET_OFFLINE_ONLY = 0x02,    /* Allow changes only if the acct is offline. */
     
    6967        ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */
    7068        ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */
    71         ACC_FLAG_LOCAL = 0x08,          /* Contact list is local. */
     69        ACC_FLAG_LOCAL_CONTACTS = 0x08, /* Contact list is local. */
    7270} account_flag_t;
    7371
  • protocols/nogaim.c

    r2f99f23 rb75671d  
    132132        extern void twitter_initmodule();
    133133        extern void purple_initmodule();
     134        extern void rpc_initmodule();
    134135
    135136#ifdef WITH_MSN
     
    155156#ifdef WITH_PURPLE
    156157        purple_initmodule();
     158#endif
     159
     160#ifdef WITH_RPC
     161        rpc_initmodule();
    157162#endif
    158163
     
    307312        }
    308313
    309         if (ic->acc->flags & ACC_FLAG_LOCAL) {
     314        if ((ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS) &&
     315            !(ic->flags & OPT_LOCAL_CONTACTS_SENT) &&
     316            ic->acc->prpl->add_buddy) {
    310317                GHashTableIter nicks;
    311                 gpointer k, v;
     318                gpointer handle;
    312319                g_hash_table_iter_init(&nicks, ic->acc->nicks);
    313                 while (g_hash_table_iter_next(&nicks, &k, &v)) {
    314                         ic->acc->prpl->add_buddy(ic, (char *) k, NULL);
     320                while (g_hash_table_iter_next(&nicks, &handle, NULL)) {
     321                        ic->acc->prpl->add_buddy(ic, (char *) handle, NULL);
    315322                }
    316323        }
     
    492499}
    493500
     501/* Returns the local contacts for an IM account (based on assigned nicks).
     502   Linked list should be freed, the strings themselves not! So look at it
     503   like a GSList<const char*> I guess? Empty list means NULL retval (as
     504   always with GSList). */
     505GSList *imcb_get_local_contacts(struct im_connection *ic)
     506{
     507        GHashTableIter nicks;
     508        GSList *ret = NULL;
     509       
     510        if (!(ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS)) {
     511                /* Only allow protocols that indicate local contact list
     512                   support to use this function. */
     513                return ret;
     514        }
     515       
     516        g_hash_table_iter_init(&nicks, ic->acc->nicks);
     517        gpointer handle;
     518        while (g_hash_table_iter_next(&nicks, &handle, NULL)) {
     519                ret = g_slist_prepend(ret, (char *) handle);
     520        }
     521       
     522        /* If the protocol asked for the list, assume we won't have to send it
     523           anymore in imcb_connected(). */
     524        ic->flags |= OPT_LOCAL_CONTACTS_SENT;
     525       
     526        return ret;
     527}
     528
    494529
    495530struct imcb_ask_cb_data {
     
    550585        struct imcb_ask_cb_data *cbd = data;
    551586
    552         cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL);
     587        if (cbd->ic->acc->prpl->add_buddy) {
     588                cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL);
     589        }
    553590
    554591        imcb_ask_cb_free(data);
  • protocols/nogaim.h

    r2f99f23 rb75671d  
    5757
    5858/* Sharing flags between all kinds of things. I just hope I won't hit any
    59    limits before 32-bit machines become extinct. ;-) */
     59   limits before 32-bit machines become extinct. ;-)
     60   
     61   Argh! This needs to be renamed to be more clear which field they're used
     62   for. As said it's currently mixed which is nonsense. Some are for the
     63   im_connection flags field, some for imcb_buddy_status(), some for typing
     64   notifications, and who knows what else... */
    6065#define OPT_LOGGED_IN   0x00000001
    6166#define OPT_LOGGING_OUT 0x00000002
     
    7075#define OPT_PONGS       0x00010000 /* Service sends us keep-alives */
    7176#define OPT_PONGED      0x00020000 /* Received a keep-alive during last interval */
     77#define OPT_LOCAL_CONTACTS_SENT 0x00040000 /* Protocol already requested local contact list, so don't send it after finishing login. */
    7278
    7379/* ok. now the fun begins. first we create a connection structure */
     
    324330G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick);
    325331G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
     332G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic);
    326333
    327334G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags);
  • protocols/purple/purple.c

    r2f99f23 rb75671d  
    264264        }
    265265        purple_accounts_remove(pa);
     266       
     267        /* Last, some protocols want their contact lists locally. */
     268        if (strcmp(acc->prpl->name, "whatsapp") == 0 || strcmp(acc->prpl->name, "gg") == 0) {
     269                acc->flags |= ACC_FLAG_LOCAL_CONTACTS;
     270        }
    266271}
    267272
  • protocols/twitter/twitter_lib.c

    r2f99f23 rb75671d  
    3636#include "base64.h"
    3737#include "twitter_lib.h"
    38 #include "json_util.h"
     38#include "parson.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++)
    6670
    6771/**
     
    166170{
    167171        static char *ret = NULL;
    168         json_value *root, *err;
     172        JSON_Value *root, *err;
    169173
    170174        g_free(ret);
     
    172176
    173177        if (req->body_size > 0) {
    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");
     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");
    179184                        if (msg) {
    180185                                ret = g_strdup_printf("%s (%s)", req->status_string, msg);
     
    189194/* WATCH OUT: This function might or might not destroy your connection.
    190195   Sub-optimal indeed, but just be careful when this returns NULL! */
    191 static json_value *twitter_parse_response(struct im_connection *ic, struct http_request *req)
     196static JSON_Value *twitter_parse_response(struct im_connection *ic, struct http_request *req)
    192197{
    193198        gboolean logging_in = !(ic->flags & OPT_LOGGED_IN);
    194199        gboolean periodic;
    195200        struct twitter_data *td = ic->proto_data;
    196         json_value *ret;
     201        JSON_Value *ret;
    197202        char path[64] = "", *s;
    198203
     
    232237        }
    233238
    234         if ((ret = json_parse(req->reply_body, req->body_size)) == NULL) {
     239        if ((ret = json_parse_string(req->reply_body)) == NULL) {
    235240                imcb_error(ic, "Could not retrieve %s: %s",
    236241                           path, "XML parse error");
     
    259264 * Fill a list of ids.
    260265 */
    261 static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl)
    262 {
    263         json_value *c;
     266static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl)
     267{
     268        JSON_Array *c;
    264269        int i;
    265270
     
    267272        txl->type = TXL_ID;
    268273
    269         c = json_o_get(node, "ids");
    270         if (!c || c->type != json_array) {
     274        if (!(c = json_object_get_array(json_object(node), "ids"))) {
    271275                return FALSE;
    272276        }
    273277
    274         for (i = 0; i < c->u.array.length; i++) {
    275                 if (c->u.array.values[i]->type != json_integer) {
    276                         continue;
    277                 }
     278        for (i = 0; i < json_array_get_count(c); i++) {
     279                jint id = json_array_get_integer(c, i);
    278280
    279281                txl->list = g_slist_prepend(txl->list,
    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;
     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);
    286288        } else {
    287289                txl->next_cursor = -1;
     
    299301{
    300302        struct im_connection *ic;
    301         json_value *parsed;
     303        JSON_Value *parsed;
    302304        struct twitter_xml_list *txl;
    303305        struct twitter_data *td;
     
    337339}
    338340
    339 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl);
     341static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl);
    340342static void twitter_http_get_users_lookup(struct http_request *req);
    341343
     
    378380{
    379381        struct im_connection *ic = req->data;
    380         json_value *parsed;
     382        JSON_Value *parsed;
    381383        struct twitter_xml_list *txl;
    382384        GSList *l = NULL;
     
    410412}
    411413
    412 struct twitter_xml_user *twitter_xt_get_user(const json_value *node)
     414struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node)
    413415{
    414416        struct twitter_xml_user *txu;
    415         json_value *jv;
     417       
     418        if (!node)
     419                return NULL;
    416420
    417421        txu = g_new0(struct twitter_xml_user, 1);
    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;
     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");
    423425
    424426        return txu;
     
    430432 *  - all <user>s from the <users> element.
    431433 */
    432 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl)
     434static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl)
    433435{
    434436        struct twitter_xml_user *txu;
     
    438440        txl->type = TXL_USER;
    439441
    440         if (!node || node->type != json_array) {
     442        if (json_type(node) != JSONArray) {
    441443                return FALSE;
    442444        }
    443 
     445       
    444446        // The root <users> node should hold the list of users <user>
    445447        // Walk over the nodes children.
    446         for (i = 0; i < node->u.array.length; i++) {
    447                 txu = twitter_xt_get_user(node->u.array.values[i]);
     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);
    448454                if (txu) {
    449455                        txl->list = g_slist_prepend(txl->list, txu);
     
    460466#endif
    461467
    462 static void expand_entities(char **text, const json_value *node);
     468static void expand_entities(char **text, const JSON_Object *node);
    463469
    464470/**
     
    470476 *  - the user in a twitter_xml_user struct.
    471477 */
    472 static struct twitter_xml_status *twitter_xt_get_status(const json_value *node)
     478static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node)
    473479{
    474480        struct twitter_xml_status *txs;
    475         const json_value *rt = NULL;
    476 
    477         if (node->type != json_object) {
     481        const JSON_Object *rt = NULL;
     482
     483        if (!node) {
    478484                return FALSE;
    479485        }
     
    481487
    482488        JSON_O_FOREACH(node, k, v) {
    483                 if (strcmp("text", k) == 0 && v->type == json_string) {
    484                         txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);
     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..
    485491                        strip_html(txs->text);
    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) {
     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) {
    489495                        struct tm parsed;
    490496
     
    492498                           this field. :-( Also assumes the timezone used
    493499                           is UTC since C time handling functions suck. */
    494                         if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
     500                        if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
    495501                                txs->created_at = mktime_utc(&parsed);
    496502                        }
    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;
     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);
    503509                }
    504510        }
     
    529535 * Function to fill a twitter_xml_status struct (DM variant).
    530536 */
    531 static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node)
     537static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node)
    532538{
    533539        struct twitter_xml_status *txs;
    534540
    535         if (node->type != json_object) {
     541        if (!node) {
    536542                return FALSE;
    537543        }
     
    539545
    540546        JSON_O_FOREACH(node, k, 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);
     547                if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
    543548                        strip_html(txs->text);
    544                 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {
     549                } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {
    545550                        struct tm parsed;
    546551
     
    548553                           this field. :-( Also assumes the timezone used
    549554                           is UTC since C time handling functions suck. */
    550                         if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
     555                        if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
    551556                                txs->created_at = mktime_utc(&parsed);
    552557                        }
    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;
     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);
    557562                }
    558563        }
     
    568573}
    569574
    570 static void expand_entities(char **text, const json_value *node)
    571 {
    572         json_value *entities, *quoted;
     575static void expand_entities(char **text, const JSON_Object *node)
     576{
     577        JSON_Object *entities, *quoted;
    573578        char *quote_url = NULL, *quote_text = NULL;
    574579
    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) {
     580        if (!(entities = json_object_get_object(node, "entities")))
     581                return;
     582        if ((quoted = json_object_get_object(node, "quoted_status"))) {
    578583                /* New "retweets with comments" feature. Note that this info
    579584                 * seems to be included in the streaming API only! Grab the
     
    591596                int i;
    592597
    593                 if (v->type != json_array) {
     598                if (json_type(v) != JSONArray) {
    594599                        continue;
    595600                }
     
    598603                }
    599604
    600                 for (i = 0; i < v->u.array.length; i++) {
     605                for (i = 0; i < json_array_get_count(json_array(v)); i++) {
    601606                        const char *format = "%s%s <%s>%s";
    602 
    603                         if (v->u.array.values[i]->type != json_object) {
     607                        JSON_Object *r = json_array_get_object(json_array(v), i);
     608
     609                        if (!r) {
    604610                                continue;
    605611                        }
    606612
    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");
     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");
    610616                        char *pos, *new;
    611617
     
    636642 *  - the next_cursor.
    637643 */
    638 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,
     644static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node,
    639645                                           struct twitter_xml_list *txl)
    640646{
     
    645651        txl->type = TXL_STATUS;
    646652
    647         if (node->type != json_array) {
     653        if (json_type(node) != JSONArray) {
    648654                return FALSE;
    649655        }
     
    651657        // The root <statuses> node should hold the list of statuses <status>
    652658        // Walk over the nodes children.
    653         for (i = 0; i < node->u.array.length; i++) {
    654                 txs = twitter_xt_get_status(node->u.array.values[i]);
     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));
    655661                if (!txs) {
    656662                        continue;
     
    858864}
    859865
    860 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter);
     866static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter);
    861867
    862868static void twitter_http_stream(struct http_request *req)
     
    864870        struct im_connection *ic = req->data;
    865871        struct twitter_data *td;
    866         json_value *parsed;
     872        JSON_Value *parsed;
    867873        int len = 0;
    868874        char c, *nl;
     
    902908                req->reply_body[len] = '\0';
    903909
    904                 if ((parsed = json_parse(req->reply_body, req->body_size))) {
     910                if ((parsed = json_parse_string(req->reply_body))) {
    905911                        from_filter = (req == td->filter_stream);
    906                         twitter_stream_handle_object(ic, parsed, from_filter);
     912                        twitter_stream_handle_object(ic, json_object(parsed), from_filter);
    907913                }
    908914                json_value_free(parsed);
     
    918924}
    919925
    920 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o);
     926static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o);
    921927static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs);
    922928
    923 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter)
     929static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter)
    924930{
    925931        struct twitter_data *td = ic->proto_data;
    926932        struct twitter_xml_status *txs;
    927         json_value *c;
     933        JSON_Object *c;
    928934
    929935        if ((txs = twitter_xt_get_status(o))) {
     
    932938                txs_free(txs);
    933939                return ret;
    934         } else if ((c = json_o_get(o, "direct_message")) &&
     940        } else if ((c = json_object_get_object(o, "direct_message")) &&
    935941                   (txs = twitter_xt_get_dm(c))) {
    936942                if (g_strcasecmp(txs->user->screen_name, td->user) != 0) {
     
    940946                txs_free(txs);
    941947                return TRUE;
    942         } else if ((c = json_o_get(o, "event")) && c->type == json_string) {
     948        } else if (json_object_get_string(o, "event")) {
    943949                twitter_stream_handle_event(ic, o);
    944950                return TRUE;
    945         } else if ((c = json_o_get(o, "disconnect")) && c->type == json_object) {
     951        } else if ((c = json_object_get_object(o, "disconnect"))) {
    946952                /* HACK: Because we're inside an event handler, we can't just
    947953                   disconnect here. Instead, just change the HTTP status string
    948954                   into a Twitter status string. */
    949                 char *reason = json_o_strdup(c, "reason");
     955                char *reason = g_strdup(json_object_get_string(c, "reason"));
    950956                if (reason) {
    951957                        g_free(td->stream->status_string);
     
    986992}
    987993
    988 static 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) {
     994static 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) {
    9971002                return FALSE;
    9981003        }
     
    10911096        struct twitter_filter *tf;
    10921097        GList *users = NULL;
    1093         json_value *parsed;
    1094         json_value *id;
    1095         const char *name;
     1098        JSON_Value *parsed;
    10961099        GString *fstr;
    10971100        GSList *l;
     
    11181121        }
    11191122
    1120         if (parsed->type != json_array) {
     1123        if (json_type(parsed) != JSONArray) {
    11211124                goto finish;
    11221125        }
    11231126
    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) {
     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) {
    11291133                        continue;
    11301134                }
     
    11341138
    11351139                        if (g_strcasecmp(tf->text, name) == 0) {
    1136                                 tf->uid = id->u.integer;
     1140                                tf->uid = id;
    11371141                                users = g_list_delete_link(users, u);
    11381142                                break;
     
    13751379        struct im_connection *ic = req->data;
    13761380        struct twitter_data *td;
    1377         json_value *parsed;
     1381        JSON_Value *parsed;
    13781382        struct twitter_xml_list *txl;
    13791383
     
    14141418        struct im_connection *ic = req->data;
    14151419        struct twitter_data *td;
    1416         json_value *parsed;
     1420        JSON_Value *parsed;
    14171421        struct twitter_xml_list *txl;
    14181422
     
    14541458        struct im_connection *ic = req->data;
    14551459        struct twitter_data *td;
    1456         json_value *parsed, *id;
     1460        JSON_Value *parsed;
     1461        jint id;
    14571462
    14581463        // Check if the connection is still active.
     
    14681473        }
    14691474
    1470         if ((id = json_o_get(parsed, "id")) && id->type == json_integer) {
    1471                 td->last_status_id = id->u.integer;
     1475        if ((id = json_object_get_integer(json_object(parsed), "id"))) {
     1476                td->last_status_id = id;
    14721477        }
    14731478
  • root_commands.c

    r2f99f23 rb75671d  
    460460
    461461                for (a = irc->b->accounts; a; a = a->next) {
    462                         char *con;
     462                        char *con = NULL, *protocol = NULL;
    463463
    464464                        if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) {
     
    471471                                con = "";
    472472                        }
    473 
    474                         irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con);
     473                        if (a->prpl == &protocol_missing) {
     474                                protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name"));
     475                        } else {
     476                                protocol = g_strdup(a->prpl->name);
     477                        }
     478
     479                        irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con);
     480                        g_free(protocol);
    475481
    476482                        i++;
     
    486492
    487493                        for (a = irc->b->accounts; a; a = a->next) {
    488                                 if (!a->ic && a->auto_connect) {
     494                                if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) {
    489495                                        if (strcmp(a->pass, PASSWORD_PENDING) == 0) {
    490496                                                irc_rootmsg(irc, "Enter password for account %s "
     
    543549                        irc_rootmsg(irc, "Enter password for account %s "
    544550                                    "first (use /OPER)", a->tag);
     551                } else if (a->prpl == &protocol_missing) {
     552                        irc_rootmsg(irc, "Protocol `%s' not recognised (plugin may be missing or not running?)",
     553                                    set_getstr(&a->set, "_protocol_name"));
    545554                } else {
    546555                        account_on(irc->b, a);
     
    647656                irc_rootmsg(irc, "That account is not on-line");
    648657                return;
     658        } else if (add_on_server && !a->prpl->add_buddy) {
     659                irc_rootmsg(irc, "IM protocol does not support contact list modification");
     660                return;
    649661        }
    650662
     
    717729        s = g_strdup(bu->handle);
    718730
    719         bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL);
     731        if (bu->ic->acc->prpl->remove_buddy) {
     732                bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL);
     733        } else {
     734                irc_rootmsg(irc, "IM protocol does not support contact list modification, "
     735                                 "removal will likely not be permanent");
     736        }
     737
    720738        nick_del(bu);
    721739        if (g_slist_find(irc->users, iu)) {
  • storage.c

    r2f99f23 rb75671d  
    3333
    3434static GList *storage_backends = NULL;
     35
     36const struct prpl protocol_missing = {
     37        .name = "_unknown",
     38};
    3539
    3640void register_storage_backend(storage_t *backend)
  • storage.h

    r2f99f23 rb75671d  
    6262G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate);
    6363
     64extern const struct prpl protocol_missing;
     65
    6466#endif /* __STORAGE_H__ */
  • storage_xml.c

    r2f99f23 rb75671d  
    8383}
    8484
     85/* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */
     86static void handle_settings_raw(struct xt_node *node, set_t **head)
     87{
     88        struct xt_node *c;
     89
     90        for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) {
     91                char *name = xt_find_attr(c, "name");
     92
     93                if (!name) {
     94                        continue;
     95                }
     96
     97                set_t *s = set_add(head, name, NULL, NULL, NULL);
     98                set_setstr(head, name, c->text);
     99                s->flags |= SET_HIDDEN |
     100                            ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
     101        }
     102}
     103
    85104static xt_status handle_account(struct xt_node *node, gpointer data)
    86105{
     
    89108        char *pass_b64 = NULL;
    90109        unsigned char *pass_cr = NULL;
    91         int pass_len, local = 0;
     110        int pass_len;
    92111        struct prpl *prpl = NULL;
    93112        account_t *acc;
     
    104123                prpl = find_protocol(protocol);
    105124                if (!prpl) {
    106                         irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol);
    107                         return XT_ABORT;
    108                 }
    109                 local = protocol_account_islocal(protocol);
     125                        irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol);
     126                        prpl = (struct prpl*) &protocol_missing;
     127                }
    110128        }
    111129
     
    124142                        set_setstr(&acc->set, "tag", tag);
    125143                }
    126                 if (local) {
    127                         acc->flags |= ACC_FLAG_LOCAL;
     144                if (prpl == &protocol_missing) {
     145                        set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL);
     146                        s->flags |= SET_HIDDEN | SET_NOSAVE |
     147                                    ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY;
    128148                }
    129149        } else {
     
    136156        g_free(password);
    137157
    138         handle_settings(node, &acc->set);
     158        if (prpl == &protocol_missing) {
     159                handle_settings_raw(node, &acc->set);
     160        } else {
     161                handle_settings(node, &acc->set);
     162        }
    139163
    140164        for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) {
     
    312336
    313337                cur = xt_new_node("account", NULL, NULL);
    314                 xt_add_attr(cur, "protocol", acc->prpl->name);
     338                if (acc->prpl == &protocol_missing) {
     339                        xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name"));
     340                } else {
     341                        xt_add_attr(cur, "protocol", acc->prpl->name);
     342                }
    315343                xt_add_attr(cur, "handle", acc->user);
    316344                xt_add_attr(cur, "password", pass_b64);
Note: See TracChangeset for help on using the changeset viewer.