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