Changes in / [9f03c47:537d9b9]
- Files:
-
- 7 added
- 4 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r9f03c47 r537d9b9 32 32 bitlbee.service 33 33 bitlbee@.service 34 *.pyc -
configure
r9f03c47 r537d9b9 16 16 config='/var/lib/bitlbee/' 17 17 plugindir='$prefix/lib/bitlbee/' 18 rpcplugindir='$plugindir/rpc/' 18 19 includedir='$prefix/include/bitlbee/' 19 20 systemdsystemunitdir='' … … 39 40 twitter=1 40 41 purple=0 42 rpc=1 41 43 42 44 doc=1 … … 123 125 --datadir=... $datadir 124 126 --plugindir=... $plugindir 127 --rpcplugindir=... $rpcplugindir 125 128 --systemdsystemunitdir=... $systemdsystemunitdir 126 129 --pidfile=... $pidfile … … 135 138 --purple=0/1 Disable/enable libpurple support $purple 136 139 (automatically disables other protocol modules) 140 --rpc=0/1 Disable/enable RPC plugin interface $rpc 137 141 138 142 --pam=0/1 Disable/enable PAM authentication $pam … … 173 177 config=$(eval echo "$config/" | sed 's/\/\{1,\}/\//g') 174 178 plugindir=$(eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g') 179 rpcplugindir=$(eval echo "$rpcplugindir/" | sed 's/\/\{1,\}/\//g') 175 180 includedir=$(eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g') 176 181 libevent=$(eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g') … … 194 199 DATADIR=$datadir 195 200 PLUGINDIR=$plugindir 201 RPCPLUGINDIR=$rpcplugindir 196 202 CONFIG=$config 197 203 INCLUDEDIR=$includedir … … 243 249 #define VARDIR "$datadir" 244 250 #define PLUGINDIR "$plugindir" 251 #define RPCPLUGINDIR "$rpcplugindir" 245 252 #define PIDFILE "$pidfile" 246 253 #define IPCSOCKET "$ipcsocket" … … 283 290 LDFLAGS="$LDFLAGS -fsanitize=address" 284 291 debug=1 292 fi 293 294 if [ "$tsan" = "1" ]; then 295 echo 296 echo "Threaded BitlBee? Have a nice tall glass of http://imgur.com/gallery/tX4qxzS" 297 echo "No need to sanitise threads in a single-threaded process!" 285 298 fi 286 299 … … 706 719 fi 707 720 721 if [ "$rpc" = 0 ]; then 722 # Somewhat pointless at this stage already but at least this keeps it 723 # out of bitlbee.pc which is probably a good thing. 724 rpcplugindir="" 725 fi 726 708 727 otrprefix="" 709 728 if [ "$otr" = "auto" ]; then … … 784 803 includedir=$includedir 785 804 plugindir=$plugindir 805 rpcplugindir=$rpcplugindir 786 806 787 807 Name: bitlbee … … 876 896 protocols=$protocols'twitter ' 877 897 protoobjs=$protoobjs'twitter_mod.o ' 898 fi 899 900 if [ "$rpc" = 0 ]; then 901 echo '#undef WITH_RPC' >> config.h 902 else 903 echo '#define WITH_RPC' >> config.h 904 protocols=$protocols'rpc ' 905 protoobjs=$protoobjs'rpc_mod.o ' 878 906 fi 879 907 … … 965 993 echo ' Using event handler: '$events 966 994 echo ' Using SSL library: '$ssl 967 #echo ' Building with these storage backends: '$STORAGES968 995 969 996 if [ -n "$protocols" ]; then -
irc_channel.c
r9f03c47 r537d9b9 757 757 } 758 758 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 759 764 bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle, 760 765 icc->group ? icc->group->name : NULL); … … 774 779 if (icc->type != IRC_CC_TYPE_GROUP) { 775 780 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); 776 786 return; 777 787 } -
irc_commands.c
r9f03c47 r537d9b9 287 287 showed an error message, or is doing some work 288 288 before the join should be confirmed. (In the 289 latter case, the calle rshould take care of that289 latter case, the callee should take care of that 290 290 confirmation.) TRUE means all's good, let the 291 291 user join the channel right away. */ -
lib/Makefile
r9f03c47 r537d9b9 13 13 14 14 # [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.o15 objects = 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 16 16 17 17 LFLAGS += -r -
lib/misc.c
r9f03c47 r537d9b9 431 431 } 432 432 433 int is_bool(c har *value)433 int is_bool(const char *value) 434 434 { 435 435 if (*value == 0) { … … 457 457 } 458 458 459 int bool2int(c har *value)459 int bool2int(const char *value) 460 460 { 461 461 int i; -
lib/misc.h
r9f03c47 r537d9b9 137 137 G_MODULE_EXPORT void random_bytes(unsigned char *buf, int count); 138 138 139 G_MODULE_EXPORT int is_bool(c har *value);140 G_MODULE_EXPORT int bool2int(c har *value);139 G_MODULE_EXPORT int is_bool(const char *value); 140 G_MODULE_EXPORT int bool2int(const char *value); 141 141 142 142 G_MODULE_EXPORT struct ns_srv_reply **srv_lookup(char *service, char *protocol, char *domain); -
lib/oauth2.c
r9f03c47 r537d9b9 42 42 #include "oauth2.h" 43 43 #include "oauth.h" 44 #include "json.h" 45 #include "json_util.h" 44 #include "parson.h" 46 45 #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++) 47 50 48 51 char *oauth2_url(const struct oauth2_service *sp) … … 113 116 } 114 117 115 static char* oauth2_parse_error( json_value *e)118 static char* oauth2_parse_error(const JSON_Value *e) 116 119 { 117 120 /* This does a reasonable job with some of the flavours of error 118 121 responses I've seen. Because apparently it's not standardised. */ 119 122 120 if ( e->type == json_object) {123 if (json_type(e) == JSONObject) { 121 124 /* 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); 131 129 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)); 134 132 } 135 133 return NULL; … … 156 154 if (content_type && (strstr(content_type, "application/json") || 157 155 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){ 161 159 if (strcmp(k, "error") == 0) { 162 160 error = oauth2_parse_error(v); 163 161 } 164 if ( v->type != json_string) {162 if (json_type(v) != JSONString) { 165 163 continue; 166 164 } 167 165 if (strcmp(k, "access_token") == 0) { 168 atoken = g_strdup( v->u.string.ptr);166 atoken = g_strdup(json_string(v)); 169 167 } 170 168 if (strcmp(k, "refresh_token") == 0) { 171 rtoken = g_strdup( v->u.string.ptr);169 rtoken = g_strdup(json_string(v)); 172 170 } 173 171 } -
protocols/account.c
r9f03c47 r537d9b9 27 27 #include "bitlbee.h" 28 28 #include "account.h" 29 30 static const char* account_protocols_local[] = {31 "gg", "whatsapp", NULL32 };33 29 34 30 static char *set_eval_nick_source(set_t *set, char *value); … … 461 457 return a->auto_reconnect_delay; 462 458 } 463 464 int protocol_account_islocal(const char* protocol)465 {466 const char** p = account_protocols_local;467 468 do {469 if (strcmp(*p, protocol) == 0) {470 return 1;471 }472 } while (*(++p));473 return 0;474 } -
protocols/account.h
r9f03c47 r537d9b9 58 58 int account_reconnect_delay(account_t *a); 59 59 60 int protocol_account_islocal(const char* protocol);61 62 60 typedef enum { 63 61 ACC_SET_OFFLINE_ONLY = 0x02, /* Allow changes only if the acct is offline. */ … … 70 68 ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */ 71 69 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. */ 73 71 ACC_FLAG_LOCKED = 0x10, /* Account is locked (cannot be deleted, certain settings can't changed) */ 74 72 } account_flag_t; -
protocols/nogaim.c
r9f03c47 r537d9b9 204 204 extern void twitter_initmodule(); 205 205 extern void purple_initmodule(); 206 extern void rpc_initmodule(); 206 207 207 208 #ifdef WITH_MSN … … 227 228 #ifdef WITH_PURPLE 228 229 purple_initmodule(); 230 #endif 231 232 #ifdef WITH_RPC 233 rpc_initmodule(); 229 234 #endif 230 235 … … 392 397 } 393 398 394 if (ic->acc->flags & ACC_FLAG_LOCAL) { 399 if ((ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS) && 400 !(ic->flags & OPT_LOCAL_CONTACTS_SENT) && 401 ic->acc->prpl->add_buddy) { 395 402 GHashTableIter nicks; 396 gpointer k, v;403 gpointer handle; 397 404 g_hash_table_iter_init(&nicks, ic->acc->nicks); 398 while (g_hash_table_iter_next(&nicks, & k, &v)) {399 ic->acc->prpl->add_buddy(ic, (char *) k, NULL);405 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 406 ic->acc->prpl->add_buddy(ic, (char *) handle, NULL); 400 407 } 401 408 } … … 492 499 query_del_by_conn((irc_t *) ic->bee->ui_data, ic); 493 500 501 /* Throw away groupchats owned by this account. Historically this was only 502 ever done by IM modules which is a bug. But it gives them opportunity 503 to clean up protocol-specific bits as well so keep it that way, just 504 do another cleanup here as a fallback. Don't want to leave any dangling 505 pointers! */ 506 while (ic->groupchats) { 507 imcb_chat_free(ic->groupchats->data); 508 } 509 494 510 if (!a) { 495 511 /* Uhm... This is very sick. */ … … 590 606 } 591 607 608 /* Returns the local contacts for an IM account (based on assigned nicks). 609 Linked list should be freed, the strings themselves not! So look at it 610 like a GSList<const char*> I guess? Empty list means NULL retval (as 611 always with GSList). */ 612 GSList *imcb_get_local_contacts(struct im_connection *ic) 613 { 614 GHashTableIter nicks; 615 GSList *ret = NULL; 616 617 if (!(ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS)) { 618 /* Only allow protocols that indicate local contact list 619 support to use this function. */ 620 return ret; 621 } 622 623 g_hash_table_iter_init(&nicks, ic->acc->nicks); 624 gpointer handle; 625 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 626 ret = g_slist_prepend(ret, (char *) handle); 627 } 628 629 /* If the protocol asked for the list, assume we won't have to send it 630 anymore in imcb_connected(). */ 631 ic->flags |= OPT_LOCAL_CONTACTS_SENT; 632 633 return ret; 634 } 635 636 592 637 struct imcb_ask_cb_data { 593 638 struct im_connection *ic; … … 647 692 struct imcb_ask_cb_data *cbd = data; 648 693 649 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 694 if (cbd->ic->acc->prpl->add_buddy) { 695 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 696 } 650 697 651 698 imcb_ask_cb_free(data); -
protocols/nogaim.h
r9f03c47 r537d9b9 57 57 58 58 /* 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... */ 60 65 #define OPT_LOGGED_IN 0x00000001 61 66 #define OPT_LOGGING_OUT 0x00000002 … … 70 75 #define OPT_PONGS 0x00010000 /* Service sends us keep-alives */ 71 76 #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. */ 72 78 #define OPT_SELFMESSAGE 0x00080000 /* A message sent by self from another location */ 73 79 … … 371 377 G_MODULE_EXPORT void imcb_buddy_nick_change(struct im_connection *ic, const char *handle, const char *nick); 372 378 G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data); 379 G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic); 373 380 374 381 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags); -
protocols/purple/purple.c
r9f03c47 r537d9b9 298 298 } 299 299 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 } 300 305 } 301 306 -
protocols/twitter/twitter_lib.c
r9f03c47 r537d9b9 36 36 #include "base64.h" 37 37 #include "twitter_lib.h" 38 #include " json_util.h"38 #include "parson.h" 39 39 #include <ctype.h> 40 40 #include <errno.h> … … 64 64 gboolean from_filter; 65 65 }; 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++) 66 70 67 71 /** … … 166 170 { 167 171 static char *ret = NULL; 168 json_value *root, *err;172 JSON_Value *root, *err; 169 173 170 174 g_free(ret); … … 172 176 173 177 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"); 179 184 if (msg) { 180 185 ret = g_strdup_printf("%s (%s)", req->status_string, msg); … … 189 194 /* WATCH OUT: This function might or might not destroy your connection. 190 195 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)196 static JSON_Value *twitter_parse_response(struct im_connection *ic, struct http_request *req) 192 197 { 193 198 gboolean logging_in = !(ic->flags & OPT_LOGGED_IN); 194 199 gboolean periodic; 195 200 struct twitter_data *td = ic->proto_data; 196 json_value *ret;201 JSON_Value *ret; 197 202 char path[64] = "", *s; 198 203 … … 232 237 } 233 238 234 if ((ret = json_parse (req->reply_body, req->body_size)) == NULL) {239 if ((ret = json_parse_string(req->reply_body)) == NULL) { 235 240 imcb_error(ic, "Could not retrieve %s: %s", 236 241 path, "XML parse error"); … … 289 294 * Fill a list of ids. 290 295 */ 291 static gboolean twitter_xt_get_friends_id_list( json_value *node, struct twitter_xml_list *txl)292 { 293 json_value*c;296 static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl) 297 { 298 JSON_Array *c; 294 299 int i; 295 300 … … 297 302 txl->type = TXL_ID; 298 303 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"))) { 301 305 return FALSE; 302 306 } 303 307 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); 308 310 309 311 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); 316 318 } else { 317 319 txl->next_cursor = -1; … … 329 331 { 330 332 struct im_connection *ic; 331 json_value *parsed;333 JSON_Value *parsed; 332 334 struct twitter_xml_list *txl; 333 335 struct twitter_data *td; … … 373 375 { 374 376 struct im_connection *ic = req->data; 375 json_value *parsed;377 JSON_Value *parsed; 376 378 struct twitter_xml_list *txl; 377 379 struct twitter_data *td; … … 418 420 { 419 421 struct im_connection *ic = req->data; 420 json_value *parsed;422 JSON_Value *parsed; 421 423 struct twitter_xml_list *txl; 422 424 struct twitter_data *td; … … 444 446 // Process the retweet ids 445 447 txl->type = TXL_ID; 446 if (parsed->type == json_array) { 448 if (json_type(parsed) == JSONArray) { 449 JSON_Array *arr = json_array(parsed); 447 450 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); 453 453 txl->list = g_slist_prepend(txl->list, 454 g_strdup_printf("% "PRIu64, c->u.integer));454 g_strdup_printf("%lld", id)); 455 455 } 456 456 } … … 463 463 } 464 464 465 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl);465 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl); 466 466 static void twitter_http_get_users_lookup(struct http_request *req); 467 467 … … 504 504 { 505 505 struct im_connection *ic = req->data; 506 json_value *parsed;506 JSON_Value *parsed; 507 507 struct twitter_xml_list *txl; 508 508 GSList *l = NULL; … … 537 537 } 538 538 539 struct twitter_xml_user *twitter_xt_get_user(const json_value*node)539 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node) 540 540 { 541 541 struct twitter_xml_user *txu; 542 json_value *jv; 542 543 if (!node) 544 return NULL; 543 545 544 546 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"); 550 550 551 551 return txu; … … 557 557 * - all <user>s from the <users> element. 558 558 */ 559 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl)559 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl) 560 560 { 561 561 struct twitter_xml_user *txu; … … 565 565 txl->type = TXL_USER; 566 566 567 if ( !node || node->type != json_array) {567 if (json_type(node) != JSONArray) { 568 568 return FALSE; 569 569 } 570 570 571 571 // The root <users> node should hold the list of users <user> 572 572 // 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); 575 579 if (txu) { 576 580 txl->list = g_slist_prepend(txl->list, txu); … … 587 591 #endif 588 592 589 static void expand_entities(char **text, const json_value *node, const json_value*extended_node);593 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node); 590 594 591 595 /** … … 597 601 * - the user in a twitter_xml_user struct. 598 602 */ 599 static struct twitter_xml_status *twitter_xt_get_status(const json_value*node)603 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node) 600 604 { 601 605 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) { 607 611 return FALSE; 608 612 } … … 610 614 611 615 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) { 613 617 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) { 615 619 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) { 622 626 struct tm parsed; 623 627 … … 625 629 this field. :-( Also assumes the timezone used 626 630 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) { 628 632 txs->created_at = mktime_utc(&parsed); 629 633 } 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); 636 640 } 637 641 } … … 646 650 txs_free(rtxs); 647 651 } 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)); 650 654 strip_html(txs->text); 651 655 expand_entities(&txs->text, node, extended_node); … … 663 667 * Function to fill a twitter_xml_status struct (DM variant). 664 668 */ 665 static struct twitter_xml_status *twitter_xt_get_dm(const json_value*node)669 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node) 666 670 { 667 671 struct twitter_xml_status *txs; 668 672 669 if ( node->type != json_object) {673 if (!node) { 670 674 return FALSE; 671 675 } … … 673 677 674 678 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)))) { 677 680 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) { 679 682 struct tm parsed; 680 683 … … 682 685 this field. :-( Also assumes the timezone used 683 686 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) { 685 688 txs->created_at = mktime_utc(&parsed); 686 689 } 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); 691 694 } 692 695 } … … 702 705 } 703 706 704 static void expand_entities(char **text, const json_value *node, const json_value*extended_node)705 { 706 json_value*entities, *extended_entities, *quoted;707 static void expand_entities(char **text, const JSON_Object *node, const JSON_Object *extended_node) 708 { 709 JSON_Object *entities, *extended_entities, *quoted; 707 710 char *quote_url = NULL, *quote_text = NULL; 708 711 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"))) { 712 715 /* New "retweets with comments" feature. Note that this info 713 716 * seems to be included in the streaming API only! Grab the … … 723 726 724 727 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) { 727 730 entities = extended_entities; 728 731 } … … 732 735 int i; 733 736 734 if ( v->type != json_array) {737 if (json_type(v) != JSONArray) { 735 738 continue; 736 739 } … … 739 742 } 740 743 741 for (i = 0; i < v->u.array.length; i++) {744 for (i = 0; i < json_array_get_count(json_array(v)); i++) { 742 745 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) { 745 749 continue; 746 750 } 747 751 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"); 751 755 char *pos, *new; 752 756 … … 777 781 * - the next_cursor. 778 782 */ 779 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,783 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node, 780 784 struct twitter_xml_list *txl) 781 785 { … … 786 790 txl->type = TXL_STATUS; 787 791 788 if ( node->type != json_array) {792 if (json_type(node) != JSONArray) { 789 793 return FALSE; 790 794 } … … 792 796 // The root <statuses> node should hold the list of statuses <status> 793 797 // 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)); 796 800 if (!txs) { 797 801 continue; … … 978 982 979 983 /* 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); 981 985 982 986 if (g_slist_find_custom(td->mutes_ids, uid_str, (GCompareFunc)strcmp)) { … … 1013 1017 } 1014 1018 1015 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter);1019 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter); 1016 1020 1017 1021 static void twitter_http_stream(struct http_request *req) … … 1019 1023 struct im_connection *ic = req->data; 1020 1024 struct twitter_data *td; 1021 json_value *parsed;1025 JSON_Value *parsed; 1022 1026 int len = 0; 1023 1027 char c, *nl; … … 1060 1064 req->reply_body[len] = '\0'; 1061 1065 1062 if ((parsed = json_parse (req->reply_body, req->body_size))) {1066 if ((parsed = json_parse_string(req->reply_body))) { 1063 1067 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); 1065 1069 } 1066 1070 json_value_free(parsed); … … 1076 1080 } 1077 1081 1078 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value*o);1082 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o); 1079 1083 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 1080 1084 1081 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter)1085 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter) 1082 1086 { 1083 1087 struct twitter_data *td = ic->proto_data; 1084 1088 struct twitter_xml_status *txs; 1085 json_value*c;1089 JSON_Object *c; 1086 1090 1087 1091 if ((txs = twitter_xt_get_status(o))) { … … 1090 1094 txs_free(txs); 1091 1095 return ret; 1092 } else if ((c = json_o _get(o, "direct_message")) &&1096 } else if ((c = json_object_get_object(o, "direct_message")) && 1093 1097 (txs = twitter_xt_get_dm(c))) { 1094 1098 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 1098 1102 txs_free(txs); 1099 1103 return TRUE; 1100 } else if ( (c = json_o_get(o, "event")) && c->type == json_string) {1104 } else if (json_object_get_string(o, "event")) { 1101 1105 twitter_stream_handle_event(ic, o); 1102 1106 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"))) { 1104 1108 /* HACK: Because we're inside an event handler, we can't just 1105 1109 disconnect here. Instead, just change the HTTP status string 1106 1110 into a Twitter status string. */ 1107 char *reason = json_o_strdup(c, "reason");1111 char *reason = g_strdup(json_object_get_string(c, "reason")); 1108 1112 if (reason) { 1109 1113 g_free(td->stream->status_string); … … 1144 1148 } 1145 1149 1146 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value*o)1150 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o) 1147 1151 { 1148 1152 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"); 1152 1156 struct twitter_xml_user *us = NULL; 1153 1157 struct twitter_xml_user *ut = NULL; 1154 1158 1155 if (!type || !source || source->type != json_object 1156 || !target || target->type != json_object) { 1159 if (!type || !source || !target) { 1157 1160 return FALSE; 1158 1161 } … … 1168 1171 char *uid_str; 1169 1172 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); 1171 1174 if (!(found = g_slist_find_custom(td->mutes_ids, uid_str, 1172 1175 (GCompareFunc)strcmp))) { … … 1175 1178 twitter_log(ic, "Muted user %s", ut->screen_name); 1176 1179 if (getenv("BITLBEE_DEBUG")) { 1177 fprintf(stderr, "New mute: %s %" PRIu64"\n",1180 fprintf(stderr, "New mute: %s %"G_GUINT64_FORMAT"\n", 1178 1181 ut->screen_name, ut->uid); 1179 1182 } … … 1182 1185 char *uid_str; 1183 1186 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); 1185 1188 if ((found = g_slist_find_custom(td->mutes_ids, uid_str, 1186 1189 (GCompareFunc)strcmp))) { … … 1192 1195 twitter_log(ic, "Unmuted user %s", ut->screen_name); 1193 1196 if (getenv("BITLBEE_DEBUG")) { 1194 fprintf(stderr, "New unmute: %s %" PRIu64"\n",1197 fprintf(stderr, "New unmute: %s %"G_GUINT64_FORMAT"\n", 1195 1198 ut->screen_name, ut->uid); 1196 1199 } … … 1283 1286 struct twitter_filter *tf; 1284 1287 GList *users = NULL; 1285 json_value *parsed; 1286 json_value *id; 1287 const char *name; 1288 JSON_Value *parsed; 1288 1289 GString *fstr; 1289 1290 GSList *l; … … 1310 1311 } 1311 1312 1312 if ( parsed->type != json_array) {1313 if (json_type(parsed) != JSONArray) { 1313 1314 goto finish; 1314 1315 } 1315 1316 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) { 1321 1323 continue; 1322 1324 } … … 1326 1328 1327 1329 if (g_strcasecmp(tf->text, name) == 0) { 1328 tf->uid = id ->u.integer;1330 tf->uid = id; 1329 1331 users = g_list_delete_link(users, u); 1330 1332 break; … … 1571 1573 struct im_connection *ic = req->data; 1572 1574 struct twitter_data *td; 1573 json_value *parsed;1575 JSON_Value *parsed; 1574 1576 struct twitter_xml_list *txl; 1575 1577 … … 1611 1613 struct im_connection *ic = req->data; 1612 1614 struct twitter_data *td; 1613 json_value *parsed;1615 JSON_Value *parsed; 1614 1616 struct twitter_xml_list *txl; 1615 1617 … … 1652 1654 struct im_connection *ic = req->data; 1653 1655 struct twitter_data *td; 1654 json_value *parsed, *id; 1656 JSON_Value *parsed; 1657 jint id; 1655 1658 1656 1659 // Check if the connection is still active. … … 1666 1669 } 1667 1670 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; 1670 1673 } 1671 1674 … … 1788 1791 { 1789 1792 struct im_connection *ic = req->data; 1790 json_value *parsed, *id; 1793 JSON_Value *parsed; 1794 uint64_t id; 1791 1795 const char *name; 1792 1796 … … 1800 1804 } 1801 1805 1802 /* for the parson branch:1803 1806 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1804 1807 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); 1812 1811 } else { 1813 1812 twitter_log(ic, "Error: could not fetch tweet url."); -
root_commands.c
r9f03c47 r537d9b9 499 499 500 500 for (a = irc->b->accounts; a; a = a->next) { 501 char *con ;501 char *con = NULL, *protocol = NULL; 502 502 503 503 if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { … … 510 510 con = ""; 511 511 } 512 513 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); 512 if (a->prpl == &protocol_missing) { 513 protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name")); 514 } else { 515 protocol = g_strdup(a->prpl->name); 516 } 517 518 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con); 519 g_free(protocol); 514 520 515 521 i++; … … 525 531 526 532 for (a = irc->b->accounts; a; a = a->next) { 527 if (!a->ic && a->auto_connect ) {533 if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) { 528 534 if (strcmp(a->pass, PASSWORD_PENDING) == 0) { 529 535 irc_rootmsg(irc, "Enter password for account %s " … … 585 591 irc_rootmsg(irc, "Enter password for account %s " 586 592 "first (use /OPER)", a->tag); 593 } else if (a->prpl == &protocol_missing) { 594 irc_rootmsg(irc, "Protocol `%s' not recognised (plugin may be missing or not running?)", 595 set_getstr(&a->set, "_protocol_name")); 587 596 } else { 588 597 account_on(irc->b, a); … … 689 698 irc_rootmsg(irc, "That account is not on-line"); 690 699 return; 700 } else if (add_on_server && !a->prpl->add_buddy) { 701 irc_rootmsg(irc, "IM protocol does not support contact list modification"); 702 return; 703 } 704 705 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' && 706 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) { 707 /* If there's no @ or it's the last char, append the user's 708 domain name now. Exclude handles starting with a _ so 709 adding _xmlconsole will keep working. */ 710 if (s) { 711 *s = '\0'; 712 } 713 if ((s = strchr(a->user, '@'))) { 714 cmd[2] = handle = g_strconcat(cmd[2], s, NULL); 715 } 691 716 } 692 717 … … 703 728 } 704 729 705 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' &&706 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) {707 /* If there's no @ or it's the last char, append the user's708 domain name now. Exclude handles starting with a _ so709 adding _xmlconsole will keep working. */710 if (s) {711 *s = '\0';712 }713 if ((s = strchr(a->user, '@'))) {714 cmd[2] = handle = g_strconcat(cmd[2], s, NULL);715 }716 }717 718 730 if (add_on_server) { 719 731 irc_channel_t *ic; … … 759 771 s = g_strdup(bu->handle); 760 772 761 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 773 if (bu->ic->acc->prpl->remove_buddy) { 774 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 775 } else { 776 irc_rootmsg(irc, "IM protocol does not support contact list modification, " 777 "removal will likely not be permanent"); 778 } 779 762 780 nick_del(bu); 763 781 if (g_slist_find(irc->users, iu)) { -
storage.c
r9f03c47 r537d9b9 32 32 33 33 static GList *storage_backends = NULL; 34 35 const struct prpl protocol_missing = { 36 .name = "_unknown", 37 }; 34 38 35 39 void register_storage_backend(storage_t *backend) -
storage.h
r9f03c47 r537d9b9 63 63 G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); 64 64 65 extern const struct prpl protocol_missing; 66 65 67 #endif /* __STORAGE_H__ */ -
storage_xml.c
r9f03c47 r537d9b9 89 89 } 90 90 91 /* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */ 92 static void handle_settings_raw(struct xt_node *node, set_t **head) 93 { 94 struct xt_node *c; 95 96 for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { 97 char *name = xt_find_attr(c, "name"); 98 99 if (!name) { 100 continue; 101 } 102 103 set_t *s = set_add(head, name, NULL, NULL, NULL); 104 set_setstr(head, name, c->text); 105 s->flags |= SET_HIDDEN | 106 ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; 107 } 108 } 109 91 110 static xt_status handle_account(struct xt_node *node, gpointer data) 92 111 { … … 95 114 char *pass_b64 = NULL; 96 115 unsigned char *pass_cr = NULL; 97 int pass_len , local = 0;116 int pass_len; 98 117 struct prpl *prpl = NULL; 99 118 account_t *acc; … … 111 130 prpl = find_protocol(protocol); 112 131 if (!prpl) { 113 irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol); 114 return XT_ABORT; 115 } 116 local = protocol_account_islocal(protocol); 132 irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol); 133 prpl = (struct prpl*) &protocol_missing; 134 } 117 135 } 118 136 … … 143 161 set_setstr(&acc->set, "tag", tag); 144 162 } 145 if (local) {146 acc->flags |= ACC_FLAG_LOCAL;147 }148 163 if (locked && !g_strcasecmp(locked, "true")) { 149 164 acc->flags |= ACC_FLAG_LOCKED; 150 165 } 166 if (prpl == &protocol_missing) { 167 set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL); 168 s->flags |= SET_HIDDEN | SET_NOSAVE | 169 ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; 170 } 151 171 152 172 g_free(pass_cr); 153 173 g_free(password); 154 174 155 handle_settings(node, &acc->set); 175 if (prpl == &protocol_missing) { 176 handle_settings_raw(node, &acc->set); 177 } else { 178 handle_settings(node, &acc->set); 179 } 156 180 157 181 for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { … … 342 366 343 367 cur = xt_new_node("account", NULL, NULL); 344 xt_add_attr(cur, "protocol", acc->prpl->name); 368 if (acc->prpl == &protocol_missing) { 369 xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name")); 370 } else { 371 xt_add_attr(cur, "protocol", acc->prpl->name); 372 } 345 373 xt_add_attr(cur, "handle", acc->user); 346 374 xt_add_attr(cur, "password", pass_b64);
Note: See TracChangeset
for help on using the changeset viewer.