Changes in / [5a8afc3:3f44e43]


Ignore:
Files:
7 added
4 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    r5a8afc3 r3f44e43  
    3232bitlbee.service
    3333bitlbee@.service
     34*.pyc
  • configure

    r5a8afc3 r3f44e43  
    1616config='/var/lib/bitlbee/'
    1717plugindir='$prefix/lib/bitlbee/'
     18rpcplugindir='$plugindir/rpc/'
    1819includedir='$prefix/include/bitlbee/'
    1920systemdsystemunitdir=''
     
    3839twitter=1
    3940purple=0
     41rpc=1
    4042
    4143doc=1
     
    122124--datadir=...                                           $datadir
    123125--plugindir=...                                         $plugindir
     126--rpcplugindir=...                                      $rpcplugindir
    124127--systemdsystemunitdir=...                              $systemdsystemunitdir
    125128--pidfile=...                                           $pidfile
     
    133136--purple=0/1    Disable/enable libpurple support        $purple
    134137                (automatically disables other protocol modules)
     138--rpc=0/1       Disable/enable RPC plugin interface     $rpc
    135139
    136140--pam=0/1       Disable/enable PAM authentication       $pam
     
    171175config=$(eval echo "$config/" | sed 's/\/\{1,\}/\//g')
    172176plugindir=$(eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g')
     177rpcplugindir=$(eval echo "$rpcplugindir/" | sed 's/\/\{1,\}/\//g')
    173178includedir=$(eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g')
    174179libevent=$(eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g')
     
    192197DATADIR=$datadir
    193198PLUGINDIR=$plugindir
     199RPCPLUGINDIR=$rpcplugindir
    194200CONFIG=$config
    195201INCLUDEDIR=$includedir
     
    241247#define VARDIR "$datadir"
    242248#define PLUGINDIR "$plugindir"
     249#define RPCPLUGINDIR "$rpcplugindir"
    243250#define PIDFILE "$pidfile"
    244251#define IPCSOCKET "$ipcsocket"
     
    281288        LDFLAGS="$LDFLAGS -fsanitize=address"
    282289        debug=1
     290fi
     291
     292if [ "$tsan" = "1" ]; then
     293        echo
     294        echo "Threaded BitlBee? Have a nice tall glass of http://imgur.com/gallery/tX4qxzS"
     295        echo "No need to sanitise threads in a single-threaded process!"
    283296fi
    284297
     
    704717fi
    705718
     719if [ "$rpc" = 0 ]; then
     720        # Somewhat pointless at this stage already but at least this keeps it
     721        # out of bitlbee.pc which is probably a good thing.
     722        rpcplugindir=""
     723fi
     724
    706725otrprefix=""
    707726if [ "$otr" = "auto" ]; then
     
    782801includedir=$includedir
    783802plugindir=$plugindir
     803rpcplugindir=$rpcplugindir
    784804
    785805Name: bitlbee
     
    865885        protocols=$protocols'twitter '
    866886        protoobjs=$protoobjs'twitter_mod.o '
     887fi
     888
     889if [ "$rpc" = 0 ]; then
     890        echo '#undef WITH_RPC' >> config.h
     891else
     892        echo '#define WITH_RPC' >> config.h
     893        protocols=$protocols'rpc '
     894        protoobjs=$protoobjs'rpc_mod.o '
    867895fi
    868896
     
    954982echo '  Using event handler: '$events
    955983echo '  Using SSL library: '$ssl
    956 #echo '  Building with these storage backends: '$STORAGES
    957984
    958985if [ -n "$protocols" ]; then
  • irc_channel.c

    r5a8afc3 r3f44e43  
    757757        }
    758758
     759        if (!bu->ic->acc->prpl->add_buddy) {
     760                irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name);
     761                return FALSE;
     762        }
     763
    759764        bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle,
    760765                                     icc->group ? icc->group->name : NULL);
     
    774779        if (icc->type != IRC_CC_TYPE_GROUP) {
    775780                irc_send_num(ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name);
     781                return;
     782        }
     783
     784        if (!bu->ic->acc->prpl->remove_buddy) {
     785                irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name);
    776786                return;
    777787        }
  • irc_commands.c

    r5a8afc3 r3f44e43  
    287287                           showed an error message, or is doing some work
    288288                           before the join should be confirmed. (In the
    289                            latter case, the caller should take care of that
     289                           latter case, the callee should take care of that
    290290                           confirmation.) TRUE means all's good, let the
    291291                           user join the channel right away. */
  • lib/Makefile

    r5a8afc3 r3f44e43  
    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

    r5a8afc3 r3f44e43  
    431431}
    432432
    433 int is_bool(char *value)
     433int is_bool(const char *value)
    434434{
    435435        if (*value == 0) {
     
    457457}
    458458
    459 int bool2int(char *value)
     459int bool2int(const char *value)
    460460{
    461461        int i;
  • lib/misc.h

    r5a8afc3 r3f44e43  
    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

    r5a8afc3 r3f44e43  
    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

    r5a8afc3 r3f44e43  
    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);
     
    466462        return a->auto_reconnect_delay;
    467463}
    468 
    469 int protocol_account_islocal(const char* protocol)
    470 {
    471         const char** p = account_protocols_local;
    472 
    473         do {
    474                 if (strcmp(*p, protocol) == 0) {
    475                         return 1;
    476                 }
    477         } while (*(++p));
    478         return 0;
    479 }
  • protocols/account.h

    r5a8afc3 r3f44e43  
    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. */
     
    7068        ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */
    7169        ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */
    72         ACC_FLAG_LOCAL = 0x08,          /* Contact list is local. */
     70        ACC_FLAG_LOCAL_CONTACTS = 0x08, /* Contact list is local. */
    7371        ACC_FLAG_LOCKED = 0x10,         /* Account is locked (cannot be deleted, certain settings can't changed) */
    7472} account_flag_t;
  • protocols/nogaim.c

    r5a8afc3 r3f44e43  
    241241        extern void twitter_initmodule();
    242242        extern void purple_initmodule();
     243        extern void rpc_initmodule();
    243244
    244245#ifdef WITH_MSN
     
    260261#ifdef WITH_PURPLE
    261262        purple_initmodule();
     263#endif
     264
     265#ifdef WITH_RPC
     266        rpc_initmodule();
    262267#endif
    263268
     
    425430        }
    426431
    427         if (ic->acc->flags & ACC_FLAG_LOCAL) {
     432        if ((ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS) &&
     433            !(ic->flags & OPT_LOCAL_CONTACTS_SENT) &&
     434            ic->acc->prpl->add_buddy) {
    428435                GHashTableIter nicks;
    429                 gpointer k, v;
     436                gpointer handle;
    430437                g_hash_table_iter_init(&nicks, ic->acc->nicks);
    431                 while (g_hash_table_iter_next(&nicks, &k, &v)) {
    432                         ic->acc->prpl->add_buddy(ic, (char *) k, NULL);
     438                while (g_hash_table_iter_next(&nicks, &handle, NULL)) {
     439                        ic->acc->prpl->add_buddy(ic, (char *) handle, NULL);
    433440                }
    434441        }
     
    525532        query_del_by_conn((irc_t *) ic->bee->ui_data, ic);
    526533
     534        /* Throw away groupchats owned by this account. Historically this was only
     535           ever done by IM modules which is a bug. But it gives them opportunity
     536           to clean up protocol-specific bits as well so keep it that way, just
     537           do another cleanup here as a fallback. Don't want to leave any dangling
     538           pointers! */
     539        while (ic->groupchats) {
     540                imcb_chat_free(ic->groupchats->data);
     541        }
     542
    527543        if (!a) {
    528544                /* Uhm... This is very sick. */
     
    623639}
    624640
     641/* Returns the local contacts for an IM account (based on assigned nicks).
     642   Linked list should be freed, the strings themselves not! So look at it
     643   like a GSList<const char*> I guess? Empty list means NULL retval (as
     644   always with GSList). */
     645GSList *imcb_get_local_contacts(struct im_connection *ic)
     646{
     647        GHashTableIter nicks;
     648        GSList *ret = NULL;
     649       
     650        if (!(ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS)) {
     651                /* Only allow protocols that indicate local contact list
     652                   support to use this function. */
     653                return ret;
     654        }
     655       
     656        g_hash_table_iter_init(&nicks, ic->acc->nicks);
     657        gpointer handle;
     658        while (g_hash_table_iter_next(&nicks, &handle, NULL)) {
     659                ret = g_slist_prepend(ret, (char *) handle);
     660        }
     661       
     662        /* If the protocol asked for the list, assume we won't have to send it
     663           anymore in imcb_connected(). */
     664        ic->flags |= OPT_LOCAL_CONTACTS_SENT;
     665       
     666        return ret;
     667}
     668
     669
    625670struct imcb_ask_cb_data {
    626671        struct im_connection *ic;
     
    680725        struct imcb_ask_cb_data *cbd = data;
    681726
    682         cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL);
     727        if (cbd->ic->acc->prpl->add_buddy) {
     728                cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL);
     729        }
    683730
    684731        imcb_ask_cb_free(data);
  • protocols/nogaim.h

    r5a8afc3 r3f44e43  
    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#define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */
    7379
     
    372378G_MODULE_EXPORT void imcb_buddy_nick_change(struct im_connection *ic, const char *handle, const char *nick);
    373379G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data);
     380G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic);
    374381
    375382G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags);
  • protocols/purple/purple.c

    r5a8afc3 r3f44e43  
    298298        }
    299299        purple_accounts_remove(pa);
     300       
     301        /* Last, some protocols want their contact lists locally. */
     302        if (strcmp(acc->prpl->name, "whatsapp") == 0 || strcmp(acc->prpl->name, "gg") == 0) {
     303                acc->flags |= ACC_FLAG_LOCAL_CONTACTS;
     304        }
    300305}
    301306
  • protocols/twitter/twitter_lib.c

    r5a8afc3 r3f44e43  
    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");
     
    289294 * Fill a list of ids.
    290295 */
    291 static gboolean twitter_xt_get_friends_id_list(json_value *node, struct twitter_xml_list *txl)
    292 {
    293         json_value *c;
     296static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl)
     297{
     298        JSON_Array *c;
    294299        int i;
    295300
     
    297302        txl->type = TXL_ID;
    298303
    299         c = json_o_get(node, "ids");
    300         if (!c || c->type != json_array) {
     304        if (!(c = json_object_get_array(json_object(node), "ids"))) {
    301305                return FALSE;
    302306        }
    303307
    304         for (i = 0; i < c->u.array.length; i++) {
    305                 if (c->u.array.values[i]->type != json_integer) {
    306                         continue;
    307                 }
     308        for (i = 0; i < json_array_get_count(c); i++) {
     309                jint id = json_array_get_integer(c, i);
    308310
    309311                txl->list = g_slist_prepend(txl->list,
    310                                             g_strdup_printf("%" PRIu64, c->u.array.values[i]->u.integer));
    311         }
    312 
    313         c = json_o_get(node, "next_cursor");
    314         if (c && c->type == json_integer) {
    315                 txl->next_cursor = c->u.integer;
     312                                            g_strdup_printf("%lld", id));
     313        }
     314
     315        JSON_Value *next = json_object_get_value(json_object(node), "next_cursor");
     316        if (next && json_type(next) == JSONInteger) {
     317                txl->next_cursor = json_integer(next);
    316318        } else {
    317319                txl->next_cursor = -1;
     
    329331{
    330332        struct im_connection *ic;
    331         json_value *parsed;
     333        JSON_Value *parsed;
    332334        struct twitter_xml_list *txl;
    333335        struct twitter_data *td;
     
    373375{
    374376        struct im_connection *ic = req->data;
    375         json_value *parsed;
     377        JSON_Value *parsed;
    376378        struct twitter_xml_list *txl;
    377379        struct twitter_data *td;
     
    418420{
    419421        struct im_connection *ic = req->data;
    420         json_value *parsed;
     422        JSON_Value *parsed;
    421423        struct twitter_xml_list *txl;
    422424        struct twitter_data *td;
     
    444446        // Process the retweet ids
    445447        txl->type = TXL_ID;
    446         if (parsed->type == json_array) {
     448        if (json_type(parsed) == JSONArray) {
     449                JSON_Array *arr = json_array(parsed);
    447450                unsigned int i;
    448                 for (i = 0; i < parsed->u.array.length; i++) {
    449                         json_value *c = parsed->u.array.values[i];
    450                         if (c->type != json_integer) {
    451                                 continue;
    452                         }
     451                for (i = 0; i < json_array_get_count(arr); i++) {
     452                        jint id = json_array_get_integer(arr, i);
    453453                        txl->list = g_slist_prepend(txl->list,
    454                                                     g_strdup_printf("%"PRIu64, c->u.integer));
     454                                                    g_strdup_printf("%lld", id));
    455455                }
    456456        }
     
    463463}
    464464
    465 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl);
     465static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl);
    466466static void twitter_http_get_users_lookup(struct http_request *req);
    467467
     
    504504{
    505505        struct im_connection *ic = req->data;
    506         json_value *parsed;
     506        JSON_Value *parsed;
    507507        struct twitter_xml_list *txl;
    508508        GSList *l = NULL;
     
    537537}
    538538
    539 struct twitter_xml_user *twitter_xt_get_user(const json_value *node)
     539struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node)
    540540{
    541541        struct twitter_xml_user *txu;
    542         json_value *jv;
     542       
     543        if (!node)
     544                return NULL;
    543545
    544546        txu = g_new0(struct twitter_xml_user, 1);
    545         txu->name = g_strdup(json_o_str(node, "name"));
    546         txu->screen_name = g_strdup(json_o_str(node, "screen_name"));
    547 
    548         jv = json_o_get(node, "id");
    549         txu->uid = jv->u.integer;
     547        txu->name = g_strdup(json_object_get_string(node, "name"));
     548        txu->screen_name = g_strdup(json_object_get_string(node, "screen_name"));
     549        txu->uid = json_object_get_integer(node, "id");
    550550
    551551        return txu;
     
    557557 *  - all <user>s from the <users> element.
    558558 */
    559 static gboolean twitter_xt_get_users(json_value *node, struct twitter_xml_list *txl)
     559static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl)
    560560{
    561561        struct twitter_xml_user *txu;
     
    565565        txl->type = TXL_USER;
    566566
    567         if (!node || node->type != json_array) {
     567        if (json_type(node) != JSONArray) {
    568568                return FALSE;
    569569        }
    570 
     570       
    571571        // The root <users> node should hold the list of users <user>
    572572        // Walk over the nodes children.
    573         for (i = 0; i < node->u.array.length; i++) {
    574                 txu = twitter_xt_get_user(node->u.array.values[i]);
     573        JSON_Array *arr = json_array(node);
     574        for (i = 0; i < json_array_get_count(arr); i++) {
     575                JSON_Object *o = json_array_get_object(arr, i);
     576                if (!o)
     577                        continue;
     578                txu = twitter_xt_get_user(o);
    575579                if (txu) {
    576580                        txl->list = g_slist_prepend(txl->list, txu);
     
    587591#endif
    588592
    589 static void expand_entities(char **text, const json_value *node, const json_value *extended_node);
     593static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node);
    590594
    591595/**
     
    597601 *  - the user in a twitter_xml_user struct.
    598602 */
    599 static struct twitter_xml_status *twitter_xt_get_status(const json_value *node)
     603static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node)
    600604{
    601605        struct twitter_xml_status *txs = {0};
    602         const json_value *rt = NULL;
    603         const json_value *text_value = NULL;
    604         const json_value *extended_node = NULL;
    605 
    606         if (node->type != json_object) {
     606        const JSON_Object *rt = NULL;
     607        const JSON_Value *text_value = NULL;
     608        const JSON_Object *extended_node = NULL;
     609
     610        if (!node) {
    607611                return FALSE;
    608612        }
     
    610614
    611615        JSON_O_FOREACH(node, k, v) {
    612                 if (strcmp("text", k) == 0 && v->type == json_string && text_value == NULL) {
     616                if (strcmp("text", k) == 0 && json_type(v) == JSONString && text_value == NULL) {
    613617                        text_value = v;
    614                 } else if (strcmp("full_text", k) == 0 && v->type == json_string) {
     618                } else if (strcmp("full_text", k) == 0 && json_type(v) == JSONString) {
    615619                        text_value = v;
    616                 } else if (strcmp("extended_tweet", k) == 0 && v->type == json_object) {
    617                         text_value = json_o_get(v, "full_text");
    618                         extended_node = v;
    619                 } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {
    620                         rt = v;
    621                 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {
     620                } else if (strcmp("extended_tweet", k) == 0 && json_type(v) == JSONObject) {
     621                        text_value = json_object_get_value(json_object(v), "full_text");
     622                        extended_node = json_object(v);
     623                } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) {
     624                        // Handling below.
     625                } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {
    622626                        struct tm parsed;
    623627
     
    625629                           this field. :-( Also assumes the timezone used
    626630                           is UTC since C time handling functions suck. */
    627                         if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
     631                        if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
    628632                                txs->created_at = mktime_utc(&parsed);
    629633                        }
    630                 } else if (strcmp("user", k) == 0 && v->type == json_object) {
    631                         txs->user = twitter_xt_get_user(v);
    632                 } else if (strcmp("id", k) == 0 && v->type == json_integer) {
    633                         txs->rt_id = txs->id = v->u.integer;
    634                 } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {
    635                         txs->reply_to = v->u.integer;
     634                } else if (strcmp("user", k) == 0 && json_type(v) == JSONObject) {
     635                        txs->user = twitter_xt_get_user(json_object(v));
     636                } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) {
     637                        txs->rt_id = txs->id = json_integer(v);
     638                } else if (strcmp("in_reply_to_status_id", k) == 0 && json_type(v) == JSONInteger) {
     639                        txs->reply_to = json_integer(v);
    636640                }
    637641        }
     
    646650                        txs_free(rtxs);
    647651                }
    648         } else if (text_value && text_value->type == json_string) {
    649                 txs->text = g_memdup(text_value->u.string.ptr, text_value->u.string.length + 1);
     652        } else if (text_value && json_type(text_value) == JSONString) {
     653                txs->text = g_strdup(json_string(text_value));
    650654                strip_html(txs->text);
    651655                expand_entities(&txs->text, node, extended_node);
     
    663667 * Function to fill a twitter_xml_status struct (DM variant).
    664668 */
    665 static struct twitter_xml_status *twitter_xt_get_dm(const json_value *node)
     669static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node)
    666670{
    667671        struct twitter_xml_status *txs;
    668672
    669         if (node->type != json_object) {
     673        if (!node) {
    670674                return FALSE;
    671675        }
     
    673677
    674678        JSON_O_FOREACH(node, k, v) {
    675                 if (strcmp("text", k) == 0 && v->type == json_string) {
    676                         txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);
     679                if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) {
    677680                        strip_html(txs->text);
    678                 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {
     681                } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) {
    679682                        struct tm parsed;
    680683
     
    682685                           this field. :-( Also assumes the timezone used
    683686                           is UTC since C time handling functions suck. */
    684                         if (strptime(v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {
     687                        if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) {
    685688                                txs->created_at = mktime_utc(&parsed);
    686689                        }
    687                 } else if (strcmp("sender", k) == 0 && v->type == json_object) {
    688                         txs->user = twitter_xt_get_user(v);
    689                 } else if (strcmp("id", k) == 0 && v->type == json_integer) {
    690                         txs->id = v->u.integer;
     690                } else if (strcmp("sender", k) == 0 && json_type(v) == JSONObject) {
     691                        txs->user = twitter_xt_get_user(json_object(v));
     692                } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) {
     693                        txs->id = json_integer(v);
    691694                }
    692695        }
     
    702705}
    703706
    704 static void expand_entities(char **text, const json_value *node, const json_value *extended_node)
    705 {
    706         json_value *entities, *extended_entities, *quoted;
     707static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node)
     708{
     709        JSON_Object *entities, *extended_entities, *quoted;
    707710        char *quote_url = NULL, *quote_text = NULL;
    708711
    709         if (!((entities = json_o_get(node, "entities")) && entities->type == json_object))
    710                 return;
    711         if ((quoted = json_o_get(node, "quoted_status")) && quoted->type == json_object) {
     712        if (!(entities = json_object_get_object(node, "entities")))
     713                return;
     714        if ((quoted = json_object_get_object(node, "quoted_status"))) {
    712715                /* New "retweets with comments" feature. Note that this info
    713716                 * seems to be included in the streaming API only! Grab the
     
    723726
    724727        if (extended_node) {
    725                 extended_entities = json_o_get(extended_node, "entities");
    726                 if (extended_entities && extended_entities->type == json_object) {
     728                extended_entities = json_object_get_object(extended_node, "entities");
     729                if (extended_entities) {
    727730                        entities = extended_entities;
    728731                }
     
    732735                int i;
    733736
    734                 if (v->type != json_array) {
     737                if (json_type(v) != JSONArray) {
    735738                        continue;
    736739                }
     
    739742                }
    740743
    741                 for (i = 0; i < v->u.array.length; i++) {
     744                for (i = 0; i < json_array_get_count(json_array(v)); i++) {
    742745                        const char *format = "%s%s <%s>%s";
    743 
    744                         if (v->u.array.values[i]->type != json_object) {
     746                        JSON_Object *r = json_array_get_object(json_array(v), i);
     747
     748                        if (!r) {
    745749                                continue;
    746750                        }
    747751
    748                         const char *kort = json_o_str(v->u.array.values[i], "url");
    749                         const char *disp = json_o_str(v->u.array.values[i], "display_url");
    750                         const char *full = json_o_str(v->u.array.values[i], "expanded_url");
     752                        const char *kort = json_object_get_string(r, "url");
     753                        const char *disp = json_object_get_string(r, "display_url");
     754                        const char *full = json_object_get_string(r, "expanded_url");
    751755                        char *pos, *new;
    752756
     
    777781 *  - the next_cursor.
    778782 */
    779 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,
     783static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node,
    780784                                           struct twitter_xml_list *txl)
    781785{
     
    786790        txl->type = TXL_STATUS;
    787791
    788         if (node->type != json_array) {
     792        if (json_type(node) != JSONArray) {
    789793                return FALSE;
    790794        }
     
    792796        // The root <statuses> node should hold the list of statuses <status>
    793797        // Walk over the nodes children.
    794         for (i = 0; i < node->u.array.length; i++) {
    795                 txs = twitter_xt_get_status(node->u.array.values[i]);
     798        for (i = 0; i < json_array_get_count(json_array(node)); i++) {
     799                txs = twitter_xt_get_status(json_array_get_object(json_array(node), i));
    796800                if (!txs) {
    797801                        continue;
     
    978982       
    979983        /* Check this is not a tweet that should be muted */
    980         uid_str = g_strdup_printf("%" PRIu64, status->user->uid);
     984        uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, status->user->uid);
    981985
    982986        if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) {
     
    10131017}
    10141018
    1015 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter);
     1019static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter);
    10161020
    10171021static void twitter_http_stream(struct http_request *req)
     
    10191023        struct im_connection *ic = req->data;
    10201024        struct twitter_data *td;
    1021         json_value *parsed;
     1025        JSON_Value *parsed;
    10221026        int len = 0;
    10231027        char c, *nl;
     
    10601064                req->reply_body[len] = '\0';
    10611065
    1062                 if ((parsed = json_parse(req->reply_body, req->body_size))) {
     1066                if ((parsed = json_parse_string(req->reply_body))) {
    10631067                        from_filter = (req == td->filter_stream);
    1064                         twitter_stream_handle_object(ic, parsed, from_filter);
     1068                        twitter_stream_handle_object(ic, json_object(parsed), from_filter);
    10651069                }
    10661070                json_value_free(parsed);
     
    10761080}
    10771081
    1078 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o);
     1082static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o);
    10791083static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs);
    10801084
    1081 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value *o, gboolean from_filter)
     1085static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter)
    10821086{
    10831087        struct twitter_data *td = ic->proto_data;
    10841088        struct twitter_xml_status *txs;
    1085         json_value *c;
     1089        JSON_Object *c;
    10861090
    10871091        if ((txs = twitter_xt_get_status(o))) {
     
    10901094                txs_free(txs);
    10911095                return ret;
    1092         } else if ((c = json_o_get(o, "direct_message")) &&
     1096        } else if ((c = json_object_get_object(o, "direct_message")) &&
    10931097                   (txs = twitter_xt_get_dm(c))) {
    10941098                if (g_strcasecmp(txs->user->screen_name, td->user) != 0) {
     
    10981102                txs_free(txs);
    10991103                return TRUE;
    1100         } else if ((c = json_o_get(o, "event")) && c->type == json_string) {
     1104        } else if (json_object_get_string(o, "event")) {
    11011105                twitter_stream_handle_event(ic, o);
    11021106                return TRUE;
    1103         } else if ((c = json_o_get(o, "disconnect")) && c->type == json_object) {
     1107        } else if ((c = json_object_get_object(o, "disconnect"))) {
    11041108                /* HACK: Because we're inside an event handler, we can't just
    11051109                   disconnect here. Instead, just change the HTTP status string
    11061110                   into a Twitter status string. */
    1107                 char *reason = json_o_strdup(c, "reason");
     1111                char *reason = g_strdup(json_object_get_string(c, "reason"));
    11081112                if (reason) {
    11091113                        g_free(td->stream->status_string);
     
    11441148}
    11451149
    1146 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o)
     1150static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o)
    11471151{
    11481152        struct twitter_data *td = ic->proto_data;
    1149         json_value *source = json_o_get(o, "source");
    1150         json_value *target = json_o_get(o, "target");
    1151         const char *type = json_o_str(o, "event");
     1153        JSON_Object *source = json_object_get_object(o, "source");
     1154        JSON_Object *target = json_object_get_object(o, "target");
     1155        const char *type = json_object_get_string(o, "event");
    11521156        struct twitter_xml_user *us = NULL;
    11531157        struct twitter_xml_user *ut = NULL;
    11541158
    1155         if (!type || !source || source->type != json_object
    1156             || !target || target->type != json_object) {
     1159        if (!type || !source || !target) {
    11571160                return FALSE;
    11581161        }
     
    11681171                char *uid_str;
    11691172                ut = twitter_xt_get_user(target);
    1170                 uid_str = g_strdup_printf("%" PRIu64, ut->uid);
     1173                uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
    11711174                if (!(found = g_slist_find_custom(td->mutes_ids, uid_str,
    11721175                                                  (GCompareFunc)strcmp))) {
     
    11751178                twitter_log(ic, "Muted user %s", ut->screen_name);
    11761179                if (getenv("BITLBEE_DEBUG")) {
    1177                         fprintf(stderr, "New mute: %s %"PRIu64"\n",
     1180                        fprintf(stderr, "New mute: %s %"G_GUINT64_FORMAT"\n",
    11781181                                ut->screen_name, ut->uid);
    11791182                }
     
    11821185                char *uid_str;
    11831186                ut = twitter_xt_get_user(target);
    1184                 uid_str = g_strdup_printf("%" PRIu64, ut->uid);
     1187                uid_str = g_strdup_printf("%" G_GUINT64_FORMAT, ut->uid);
    11851188                if ((found = g_slist_find_custom(td->mutes_ids, uid_str,
    11861189                                                (GCompareFunc)strcmp))) {
     
    11921195                twitter_log(ic, "Unmuted user %s", ut->screen_name);
    11931196                if (getenv("BITLBEE_DEBUG")) {
    1194                         fprintf(stderr, "New unmute: %s %"PRIu64"\n",
     1197                        fprintf(stderr, "New unmute: %s %"G_GUINT64_FORMAT"\n",
    11951198                                ut->screen_name, ut->uid);
    11961199                }
     
    12831286        struct twitter_filter *tf;
    12841287        GList *users = NULL;
    1285         json_value *parsed;
    1286         json_value *id;
    1287         const char *name;
     1288        JSON_Value *parsed;
    12881289        GString *fstr;
    12891290        GSList *l;
     
    13101311        }
    13111312
    1312         if (parsed->type != json_array) {
     1313        if (json_type(parsed) != JSONArray) {
    13131314                goto finish;
    13141315        }
    13151316
    1316         for (i = 0; i < parsed->u.array.length; i++) {
    1317                 id = json_o_get(parsed->u.array.values[i], "id");
    1318                 name = json_o_str(parsed->u.array.values[i], "screen_name");
    1319 
    1320                 if (!name || !id || id->type != json_integer) {
     1317        for (i = 0; i < json_array_get_count(json_array(parsed)); i++) {
     1318                JSON_Object *o = json_array_get_object(json_array(parsed), i);
     1319                jint id = json_object_get_integer(o, "id");
     1320                const char *name = json_object_get_string(o, "screen_name");
     1321
     1322                if (!name || !id) {
    13211323                        continue;
    13221324                }
     
    13261328
    13271329                        if (g_strcasecmp(tf->text, name) == 0) {
    1328                                 tf->uid = id->u.integer;
     1330                                tf->uid = id;
    13291331                                users = g_list_delete_link(users, u);
    13301332                                break;
     
    15711573        struct im_connection *ic = req->data;
    15721574        struct twitter_data *td;
    1573         json_value *parsed;
     1575        JSON_Value *parsed;
    15741576        struct twitter_xml_list *txl;
    15751577
     
    16111613        struct im_connection *ic = req->data;
    16121614        struct twitter_data *td;
    1613         json_value *parsed;
     1615        JSON_Value *parsed;
    16141616        struct twitter_xml_list *txl;
    16151617
     
    16521654        struct im_connection *ic = req->data;
    16531655        struct twitter_data *td;
    1654         json_value *parsed, *id;
     1656        JSON_Value *parsed;
     1657        jint id;
    16551658
    16561659        // Check if the connection is still active.
     
    16661669        }
    16671670
    1668         if ((id = json_o_get(parsed, "id")) && id->type == json_integer) {
    1669                 td->last_status_id = id->u.integer;
     1671        if ((id = json_object_get_integer(json_object(parsed), "id"))) {
     1672                td->last_status_id = id;
    16701673        }
    16711674
     
    17881791{
    17891792        struct im_connection *ic = req->data;
    1790         json_value *parsed, *id;
     1793        JSON_Value *parsed;
     1794        uint64_t id;
    17911795        const char *name;
    17921796
     
    18001804        }
    18011805
    1802         /* for the parson branch:
    18031806        name = json_object_dotget_string(json_object(parsed), "user.screen_name");
    18041807        id = json_object_get_integer(json_object(parsed), "id");
    1805         */
    1806 
    1807         name = json_o_str(json_o_get(parsed, "user"), "screen_name");
    1808         id = json_o_get(parsed, "id");
    1809 
    1810         if (name && id && id->type == json_integer) {
    1811                 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer);
     1808
     1809        if (name && id) {
     1810                twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id);
    18121811        } else {
    18131812                twitter_log(ic, "Error: could not fetch tweet url.");
  • root_commands.c

    r5a8afc3 r3f44e43  
    509509                                con = "";
    510510                        }
    511 
    512511                        if (a->prpl == &protocol_missing) {
    513512                                protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name"));
     
    701700                irc_rootmsg(irc, "That account is not on-line");
    702701                return;
     702        } else if (add_on_server && !a->prpl->add_buddy) {
     703                irc_rootmsg(irc, "IM protocol does not support contact list modification");
     704                return;
     705        }
     706
     707        if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' &&
     708            (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) {
     709                /* If there's no @ or it's the last char, append the user's
     710                   domain name now. Exclude handles starting with a _ so
     711                   adding _xmlconsole will keep working. */
     712                if (s) {
     713                        *s = '\0';
     714                }
     715                if ((s = strchr(a->user, '@'))) {
     716                        cmd[2] = handle = g_strconcat(cmd[2], s, NULL);
     717                }
    703718        }
    704719
     
    715730        }
    716731
    717         if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' &&
    718             (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) {
    719                 /* If there's no @ or it's the last char, append the user's
    720                    domain name now. Exclude handles starting with a _ so
    721                    adding _xmlconsole will keep working. */
    722                 if (s) {
    723                         *s = '\0';
    724                 }
    725                 if ((s = strchr(a->user, '@'))) {
    726                         cmd[2] = handle = g_strconcat(cmd[2], s, NULL);
    727                 }
    728         }
    729 
    730732        if (add_on_server) {
    731733                irc_channel_t *ic;
     
    771773        s = g_strdup(bu->handle);
    772774
    773         bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL);
     775        if (bu->ic->acc->prpl->remove_buddy) {
     776                bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL);
     777        } else {
     778                irc_rootmsg(irc, "IM protocol does not support contact list modification, "
     779                                 "removal will likely not be permanent");
     780        }
     781
    774782        nick_del(bu);
    775783        if (g_slist_find(irc->users, iu)) {
  • storage_xml.c

    r5a8afc3 r3f44e43  
    114114        char *pass_b64 = NULL;
    115115        unsigned char *pass_cr = NULL;
    116         int pass_len, local = 0;
     116        int pass_len;
    117117        struct prpl *prpl = NULL;
    118118        account_t *acc;
     
    133133                        prpl = (struct prpl*) &protocol_missing;
    134134                }
    135                 local = protocol_account_islocal(protocol);
    136135        }
    137136
     
    161160        if (tag) {
    162161                set_setstr(&acc->set, "tag", tag);
    163         }
    164         if (local) {
    165                 acc->flags |= ACC_FLAG_LOCAL;
    166162        }
    167163        if (locked && !g_strcasecmp(locked, "true")) {
Note: See TracChangeset for help on using the changeset viewer.