Changes in / [82cb190:3fbce97]
- Files:
-
- 7 added
- 4 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r82cb190 r3fbce97 32 32 bitlbee.service 33 33 bitlbee@.service 34 *.pyc -
configure
r82cb190 r3fbce97 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 … … 121 123 --datadir=... $datadir 122 124 --plugindir=... $plugindir 125 --rpcplugindir=... $rpcplugindir 123 126 --systemdsystemunitdir=... $systemdsystemunitdir 124 127 --pidfile=... $pidfile … … 133 136 --purple=0/1 Disable/enable libpurple support $purple 134 137 (automatically disables other protocol modules) 138 --rpc=0/1 Disable/enable RPC plugin interface $rpc 135 139 136 140 --doc=0/1 Disable/enable help.txt generation $doc … … 168 172 config=$(eval echo "$config/" | sed 's/\/\{1,\}/\//g') 169 173 plugindir=$(eval echo "$plugindir/" | sed 's/\/\{1,\}/\//g') 174 rpcplugindir=$(eval echo "$rpcplugindir/" | sed 's/\/\{1,\}/\//g') 170 175 includedir=$(eval echo "$includedir"/ | sed 's/\/\{1,\}/\//g') 171 176 libevent=$(eval echo "$libevent"/ | sed 's/\/\{1,\}/\//g') … … 189 194 DATADIR=$datadir 190 195 PLUGINDIR=$plugindir 196 RPCPLUGINDIR=$rpcplugindir 191 197 CONFIG=$config 192 198 INCLUDEDIR=$includedir … … 240 246 #define VARDIR "$datadir" 241 247 #define PLUGINDIR "$plugindir" 248 #define RPCPLUGINDIR "$rpcplugindir" 242 249 #define PIDFILE "$pidfile" 243 250 #define IPCSOCKET "$ipcsocket" … … 282 289 LDFLAGS="$LDFLAGS -fsanitize=address" 283 290 debug=1 291 fi 292 293 if [ "$tsan" = "1" ]; then 294 echo 295 echo "Threaded BitlBee? Have a nice tall glass of http://imgur.com/gallery/tX4qxzS" 296 echo "No need to sanitise threads in a single-threaded process!" 284 297 fi 285 298 … … 672 685 fi 673 686 687 if [ "$rpc" = 0 ]; then 688 # Somewhat pointless at this stage already but at least this keeps it 689 # out of bitlbee.pc which is probably a good thing. 690 rpcplugindir="" 691 fi 692 674 693 otrprefix="" 675 694 if [ "$otr" = "auto" ]; then … … 750 769 includedir=$includedir 751 770 plugindir=$plugindir 771 rpcplugindir=$rpcplugindir 752 772 753 773 Name: bitlbee … … 842 862 protocols=$protocols'twitter ' 843 863 protoobjs=$protoobjs'twitter_mod.o ' 864 fi 865 866 if [ "$rpc" = 0 ]; then 867 echo '#undef WITH_RPC' >> config.h 868 else 869 echo '#define WITH_RPC' >> config.h 870 protocols=$protocols'rpc ' 871 protoobjs=$protoobjs'rpc_mod.o ' 844 872 fi 845 873 … … 931 959 echo ' Using event handler: '$events 932 960 echo ' Using SSL library: '$ssl 933 #echo ' Building with these storage backends: '$STORAGES934 961 935 962 if [ -n "$protocols" ]; then -
irc_channel.c
r82cb190 r3fbce97 755 755 } 756 756 757 if (!bu->ic->acc->prpl->add_buddy) { 758 irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name); 759 return FALSE; 760 } 761 757 762 bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle, 758 763 icc->group ? icc->group->name : NULL); … … 772 777 if (icc->type != IRC_CC_TYPE_GROUP) { 773 778 irc_send_num(ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name); 779 return; 780 } 781 782 if (!bu->ic->acc->prpl->remove_buddy) { 783 irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name); 774 784 return; 775 785 } -
irc_commands.c
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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
r82cb190 r3fbce97 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. */ … … 69 67 ACC_FLAG_STATUS_MESSAGE = 0x02, /* Supports status messages (without being away). */ 70 68 ACC_FLAG_HANDLE_DOMAINS = 0x04, /* Contact handles need a domain portion. */ 71 ACC_FLAG_LOCAL = 0x08,/* Contact list is local. */69 ACC_FLAG_LOCAL_CONTACTS = 0x08, /* Contact list is local. */ 72 70 } account_flag_t; 73 71 -
protocols/nogaim.c
r82cb190 r3fbce97 135 135 extern void twitter_initmodule(); 136 136 extern void purple_initmodule(); 137 extern void rpc_initmodule(); 137 138 138 139 #ifdef WITH_MSN … … 158 159 #ifdef WITH_PURPLE 159 160 purple_initmodule(); 161 #endif 162 163 #ifdef WITH_RPC 164 rpc_initmodule(); 160 165 #endif 161 166 … … 313 318 } 314 319 315 if (ic->acc->flags & ACC_FLAG_LOCAL) { 320 if ((ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS) && 321 !(ic->flags & OPT_LOCAL_CONTACTS_SENT) && 322 ic->acc->prpl->add_buddy) { 316 323 GHashTableIter nicks; 317 gpointer k, v;324 gpointer handle; 318 325 g_hash_table_iter_init(&nicks, ic->acc->nicks); 319 while (g_hash_table_iter_next(&nicks, & k, &v)) {320 ic->acc->prpl->add_buddy(ic, (char *) k, NULL);326 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 327 ic->acc->prpl->add_buddy(ic, (char *) handle, NULL); 321 328 } 322 329 } … … 413 420 query_del_by_conn((irc_t *) ic->bee->ui_data, ic); 414 421 422 /* Throw away groupchats owned by this account. Historically this was only 423 ever done by IM modules which is a bug. But it gives them opportunity 424 to clean up protocol-specific bits as well so keep it that way, just 425 do another cleanup here as a fallback. Don't want to leave any dangling 426 pointers! */ 427 while (ic->groupchats) { 428 imcb_chat_free(ic->groupchats->data); 429 } 430 415 431 if (!a) { 416 432 /* Uhm... This is very sick. */ … … 498 514 } 499 515 516 /* Returns the local contacts for an IM account (based on assigned nicks). 517 Linked list should be freed, the strings themselves not! So look at it 518 like a GSList<const char*> I guess? Empty list means NULL retval (as 519 always with GSList). */ 520 GSList *imcb_get_local_contacts(struct im_connection *ic) 521 { 522 GHashTableIter nicks; 523 GSList *ret = NULL; 524 525 if (!(ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS)) { 526 /* Only allow protocols that indicate local contact list 527 support to use this function. */ 528 return ret; 529 } 530 531 g_hash_table_iter_init(&nicks, ic->acc->nicks); 532 gpointer handle; 533 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 534 ret = g_slist_prepend(ret, (char *) handle); 535 } 536 537 /* If the protocol asked for the list, assume we won't have to send it 538 anymore in imcb_connected(). */ 539 ic->flags |= OPT_LOCAL_CONTACTS_SENT; 540 541 return ret; 542 } 543 500 544 501 545 struct imcb_ask_cb_data { … … 556 600 struct imcb_ask_cb_data *cbd = data; 557 601 558 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 602 if (cbd->ic->acc->prpl->add_buddy) { 603 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 604 } 559 605 560 606 imcb_ask_cb_free(data); -
protocols/nogaim.h
r82cb190 r3fbce97 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 … … 325 331 G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick); 326 332 G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data); 333 G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic); 327 334 328 335 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, guint32 flags); -
protocols/purple/purple.c
r82cb190 r3fbce97 277 277 } 278 278 purple_accounts_remove(pa); 279 280 /* Last, some protocols want their contact lists locally. */ 281 if (strcmp(acc->prpl->name, "whatsapp") == 0 || strcmp(acc->prpl->name, "gg") == 0) { 282 acc->flags |= ACC_FLAG_LOCAL_CONTACTS; 283 } 279 284 } 280 285 -
protocols/twitter/twitter_lib.c
r82cb190 r3fbce97 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"); … … 259 264 * Fill a list of ids. 260 265 */ 261 static gboolean twitter_xt_get_friends_id_list( json_value *node, struct twitter_xml_list *txl)262 { 263 json_value*c;266 static gboolean twitter_xt_get_friends_id_list(JSON_Value *node, struct twitter_xml_list *txl) 267 { 268 JSON_Array *c; 264 269 int i; 265 270 … … 267 272 txl->type = TXL_ID; 268 273 269 c = json_o_get(node, "ids"); 270 if (!c || c->type != json_array) { 274 if (!(c = json_object_get_array(json_object(node), "ids"))) { 271 275 return FALSE; 272 276 } 273 277 274 for (i = 0; i < c->u.array.length; i++) { 275 if (c->u.array.values[i]->type != json_integer) { 276 continue; 277 } 278 for (i = 0; i < json_array_get_count(c); i++) { 279 jint id = json_array_get_integer(c, i); 278 280 279 281 txl->list = g_slist_prepend(txl->list, 280 g_strdup_printf("% " PRIu64, c->u.array.values[i]->u.integer));281 } 282 283 c = json_o_get(node, "next_cursor");284 if ( c && c->type == json_integer) {285 txl->next_cursor = c->u.integer;282 g_strdup_printf("%lld", id)); 283 } 284 285 JSON_Value *next = json_object_get_value(json_object(node), "next_cursor"); 286 if (next && json_type(next) == JSONInteger) { 287 txl->next_cursor = json_integer(next); 286 288 } else { 287 289 txl->next_cursor = -1; … … 299 301 { 300 302 struct im_connection *ic; 301 json_value *parsed;303 JSON_Value *parsed; 302 304 struct twitter_xml_list *txl; 303 305 struct twitter_data *td; … … 337 339 } 338 340 339 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl);341 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl); 340 342 static void twitter_http_get_users_lookup(struct http_request *req); 341 343 … … 378 380 { 379 381 struct im_connection *ic = req->data; 380 json_value *parsed;382 JSON_Value *parsed; 381 383 struct twitter_xml_list *txl; 382 384 GSList *l = NULL; … … 411 413 } 412 414 413 struct twitter_xml_user *twitter_xt_get_user(const json_value*node)415 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node) 414 416 { 415 417 struct twitter_xml_user *txu; 416 json_value *jv; 418 419 if (!node) 420 return NULL; 417 421 418 422 txu = g_new0(struct twitter_xml_user, 1); 419 txu->name = g_strdup(json_o_str(node, "name")); 420 txu->screen_name = g_strdup(json_o_str(node, "screen_name")); 421 422 jv = json_o_get(node, "id"); 423 txu->uid = jv->u.integer; 423 txu->name = g_strdup(json_object_get_string(node, "name")); 424 txu->screen_name = g_strdup(json_object_get_string(node, "screen_name")); 425 txu->uid = json_object_get_integer(node, "id"); 424 426 425 427 return txu; … … 431 433 * - all <user>s from the <users> element. 432 434 */ 433 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl)435 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl) 434 436 { 435 437 struct twitter_xml_user *txu; … … 439 441 txl->type = TXL_USER; 440 442 441 if ( !node || node->type != json_array) {443 if (json_type(node) != JSONArray) { 442 444 return FALSE; 443 445 } 444 446 445 447 // The root <users> node should hold the list of users <user> 446 448 // Walk over the nodes children. 447 for (i = 0; i < node->u.array.length; i++) { 448 txu = twitter_xt_get_user(node->u.array.values[i]); 449 JSON_Array *arr = json_array(node); 450 for (i = 0; i < json_array_get_count(arr); i++) { 451 JSON_Object *o = json_array_get_object(arr, i); 452 if (!o) 453 continue; 454 txu = twitter_xt_get_user(o); 449 455 if (txu) { 450 456 txl->list = g_slist_prepend(txl->list, txu); … … 461 467 #endif 462 468 463 static void expand_entities(char **text, const json_value*node);469 static void expand_entities(char **text, const JSON_Object *node); 464 470 465 471 /** … … 471 477 * - the user in a twitter_xml_user struct. 472 478 */ 473 static struct twitter_xml_status *twitter_xt_get_status(const json_value*node)479 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node) 474 480 { 475 481 struct twitter_xml_status *txs; 476 const json_value*rt = NULL;477 478 if ( node->type != json_object) {482 const JSON_Object *rt = NULL; 483 484 if (!node) { 479 485 return FALSE; 480 486 } … … 482 488 483 489 JSON_O_FOREACH(node, k, v) { 484 if (strcmp("text", k) == 0 && v->type == json_string) {485 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);490 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 491 // TODO: Huh strip html? In json? Not sure whether I have to.. 486 492 strip_html(txs->text); 487 } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {488 rt = v;489 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {493 } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) { 494 // Handling below. 495 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 490 496 struct tm parsed; 491 497 … … 493 499 this field. :-( Also assumes the timezone used 494 500 is UTC since C time handling functions suck. */ 495 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {501 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 496 502 txs->created_at = mktime_utc(&parsed); 497 503 } 498 } else if (strcmp("user", k) == 0 && v->type == json_object) {499 txs->user = twitter_xt_get_user( v);500 } else if (strcmp("id", k) == 0 && v->type == json_integer) {501 txs->rt_id = txs->id = v->u.integer;502 } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {503 txs->reply_to = v->u.integer;504 } else if (strcmp("user", k) == 0 && json_type(v) == JSONObject) { 505 txs->user = twitter_xt_get_user(json_object(v)); 506 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 507 txs->rt_id = txs->id = json_integer(v); 508 } else if (strcmp("in_reply_to_status_id", k) == 0 && json_type(v) == JSONInteger) { 509 txs->reply_to = json_integer(v); 504 510 } 505 511 } … … 530 536 * Function to fill a twitter_xml_status struct (DM variant). 531 537 */ 532 static struct twitter_xml_status *twitter_xt_get_dm(const json_value*node)538 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node) 533 539 { 534 540 struct twitter_xml_status *txs; 535 541 536 if ( node->type != json_object) {542 if (!node) { 537 543 return FALSE; 538 544 } … … 540 546 541 547 JSON_O_FOREACH(node, k, v) { 542 if (strcmp("text", k) == 0 && v->type == json_string) { 543 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); 548 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 544 549 strip_html(txs->text); 545 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {550 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 546 551 struct tm parsed; 547 552 … … 549 554 this field. :-( Also assumes the timezone used 550 555 is UTC since C time handling functions suck. */ 551 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {556 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 552 557 txs->created_at = mktime_utc(&parsed); 553 558 } 554 } else if (strcmp("sender", k) == 0 && v->type == json_object) {555 txs->user = twitter_xt_get_user( v);556 } else if (strcmp("id", k) == 0 && v->type == json_integer) {557 txs->id = v->u.integer;559 } else if (strcmp("sender", k) == 0 && json_type(v) == JSONObject) { 560 txs->user = twitter_xt_get_user(json_object(v)); 561 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 562 txs->id = json_integer(v); 558 563 } 559 564 } … … 569 574 } 570 575 571 static void expand_entities(char **text, const json_value*node)572 { 573 json_value*entities, *quoted;576 static void expand_entities(char **text, const JSON_Object *node) 577 { 578 JSON_Object *entities, *quoted; 574 579 char *quote_url = NULL, *quote_text = NULL; 575 580 576 if (!( (entities = json_o_get(node, "entities")) && entities->type == json_object))577 return; 578 if ((quoted = json_o _get(node, "quoted_status")) && quoted->type == json_object) {581 if (!(entities = json_object_get_object(node, "entities"))) 582 return; 583 if ((quoted = json_object_get_object(node, "quoted_status"))) { 579 584 /* New "retweets with comments" feature. Note that this info 580 585 * seems to be included in the streaming API only! Grab the … … 592 597 int i; 593 598 594 if ( v->type != json_array) {599 if (json_type(v) != JSONArray) { 595 600 continue; 596 601 } … … 599 604 } 600 605 601 for (i = 0; i < v->u.array.length; i++) {606 for (i = 0; i < json_array_get_count(json_array(v)); i++) { 602 607 const char *format = "%s%s <%s>%s"; 603 604 if (v->u.array.values[i]->type != json_object) { 608 JSON_Object *r = json_array_get_object(json_array(v), i); 609 610 if (!r) { 605 611 continue; 606 612 } 607 613 608 const char *kort = json_o _str(v->u.array.values[i], "url");609 const char *disp = json_o _str(v->u.array.values[i], "display_url");610 const char *full = json_o _str(v->u.array.values[i], "expanded_url");614 const char *kort = json_object_get_string(r, "url"); 615 const char *disp = json_object_get_string(r, "display_url"); 616 const char *full = json_object_get_string(r, "expanded_url"); 611 617 char *pos, *new; 612 618 … … 637 643 * - the next_cursor. 638 644 */ 639 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,645 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node, 640 646 struct twitter_xml_list *txl) 641 647 { … … 646 652 txl->type = TXL_STATUS; 647 653 648 if ( node->type != json_array) {654 if (json_type(node) != JSONArray) { 649 655 return FALSE; 650 656 } … … 652 658 // The root <statuses> node should hold the list of statuses <status> 653 659 // Walk over the nodes children. 654 for (i = 0; i < node->u.array.length; i++) {655 txs = twitter_xt_get_status( node->u.array.values[i]);660 for (i = 0; i < json_array_get_count(json_array(node)); i++) { 661 txs = twitter_xt_get_status(json_array_get_object(json_array(node), i)); 656 662 if (!txs) { 657 663 continue; … … 859 865 } 860 866 861 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter);867 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter); 862 868 863 869 static void twitter_http_stream(struct http_request *req) … … 865 871 struct im_connection *ic = req->data; 866 872 struct twitter_data *td; 867 json_value *parsed;873 JSON_Value *parsed; 868 874 int len = 0; 869 875 char c, *nl; … … 903 909 req->reply_body[len] = '\0'; 904 910 905 if ((parsed = json_parse (req->reply_body, req->body_size))) {911 if ((parsed = json_parse_string(req->reply_body))) { 906 912 from_filter = (req == td->filter_stream); 907 twitter_stream_handle_object(ic, parsed, from_filter);913 twitter_stream_handle_object(ic, json_object(parsed), from_filter); 908 914 } 909 915 json_value_free(parsed); … … 919 925 } 920 926 921 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value*o);927 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o); 922 928 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 923 929 924 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter)930 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter) 925 931 { 926 932 struct twitter_data *td = ic->proto_data; 927 933 struct twitter_xml_status *txs; 928 json_value*c;934 JSON_Object *c; 929 935 930 936 if ((txs = twitter_xt_get_status(o))) { … … 933 939 txs_free(txs); 934 940 return ret; 935 } else if ((c = json_o _get(o, "direct_message")) &&941 } else if ((c = json_object_get_object(o, "direct_message")) && 936 942 (txs = twitter_xt_get_dm(c))) { 937 943 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 941 947 txs_free(txs); 942 948 return TRUE; 943 } else if ( (c = json_o_get(o, "event")) && c->type == json_string) {949 } else if (json_object_get_string(o, "event")) { 944 950 twitter_stream_handle_event(ic, o); 945 951 return TRUE; 946 } else if ((c = json_o _get(o, "disconnect")) && c->type == json_object) {952 } else if ((c = json_object_get_object(o, "disconnect"))) { 947 953 /* HACK: Because we're inside an event handler, we can't just 948 954 disconnect here. Instead, just change the HTTP status string 949 955 into a Twitter status string. */ 950 char *reason = json_o_strdup(c, "reason");956 char *reason = g_strdup(json_object_get_string(c, "reason")); 951 957 if (reason) { 952 958 g_free(td->stream->status_string); … … 987 993 } 988 994 989 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o) 990 { 991 struct twitter_data *td = ic->proto_data; 992 json_value *source = json_o_get(o, "source"); 993 json_value *target = json_o_get(o, "target"); 994 const char *type = json_o_str(o, "event"); 995 996 if (!type || !source || source->type != json_object 997 || !target || target->type != json_object) { 995 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o) 996 { 997 struct twitter_data *td = ic->proto_data; 998 JSON_Object *source = json_object_get_object(o, "source"); 999 JSON_Object *target = json_object_get_object(o, "target"); 1000 const char *type = json_object_get_string(o, "event"); 1001 1002 if (!type || !source || !target) { 998 1003 return FALSE; 999 1004 } … … 1092 1097 struct twitter_filter *tf; 1093 1098 GList *users = NULL; 1094 json_value *parsed; 1095 json_value *id; 1096 const char *name; 1099 JSON_Value *parsed; 1097 1100 GString *fstr; 1098 1101 GSList *l; … … 1119 1122 } 1120 1123 1121 if ( parsed->type != json_array) {1124 if (json_type(parsed) != JSONArray) { 1122 1125 goto finish; 1123 1126 } 1124 1127 1125 for (i = 0; i < parsed->u.array.length; i++) { 1126 id = json_o_get(parsed->u.array.values[i], "id"); 1127 name = json_o_str(parsed->u.array.values[i], "screen_name"); 1128 1129 if (!name || !id || id->type != json_integer) { 1128 for (i = 0; i < json_array_get_count(json_array(parsed)); i++) { 1129 JSON_Object *o = json_array_get_object(json_array(parsed), i); 1130 jint id = json_object_get_integer(o, "id"); 1131 const char *name = json_object_get_string(o, "screen_name"); 1132 1133 if (!name || !id) { 1130 1134 continue; 1131 1135 } … … 1135 1139 1136 1140 if (g_strcasecmp(tf->text, name) == 0) { 1137 tf->uid = id ->u.integer;1141 tf->uid = id; 1138 1142 users = g_list_delete_link(users, u); 1139 1143 break; … … 1376 1380 struct im_connection *ic = req->data; 1377 1381 struct twitter_data *td; 1378 json_value *parsed;1382 JSON_Value *parsed; 1379 1383 struct twitter_xml_list *txl; 1380 1384 … … 1416 1420 struct im_connection *ic = req->data; 1417 1421 struct twitter_data *td; 1418 json_value *parsed;1422 JSON_Value *parsed; 1419 1423 struct twitter_xml_list *txl; 1420 1424 … … 1457 1461 struct im_connection *ic = req->data; 1458 1462 struct twitter_data *td; 1459 json_value *parsed, *id; 1463 JSON_Value *parsed; 1464 jint id; 1460 1465 1461 1466 // Check if the connection is still active. … … 1471 1476 } 1472 1477 1473 if ((id = json_o _get(parsed, "id")) && id->type == json_integer) {1474 td->last_status_id = id ->u.integer;1478 if ((id = json_object_get_integer(json_object(parsed), "id"))) { 1479 td->last_status_id = id; 1475 1480 } 1476 1481 … … 1580 1585 { 1581 1586 struct im_connection *ic = req->data; 1582 json_value *parsed, *id; 1587 JSON_Value *parsed; 1588 uint64_t id; 1583 1589 const char *name; 1584 1590 … … 1592 1598 } 1593 1599 1594 /* for the parson branch:1595 1600 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1596 1601 id = json_object_get_integer(json_object(parsed), "id"); 1597 */ 1598 1599 name = json_o_str(json_o_get(parsed, "user"), "screen_name"); 1600 id = json_o_get(parsed, "id"); 1601 1602 if (name && id && id->type == json_integer) { 1603 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer); 1602 1603 if (name && id) { 1604 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id); 1604 1605 } else { 1605 1606 twitter_log(ic, "Error: could not fetch tweet url."); -
root_commands.c
r82cb190 r3fbce97 476 476 477 477 for (a = irc->b->accounts; a; a = a->next) { 478 char *con ;478 char *con = NULL, *protocol = NULL; 479 479 480 480 if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { … … 487 487 con = ""; 488 488 } 489 490 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); 489 if (a->prpl == &protocol_missing) { 490 protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name")); 491 } else { 492 protocol = g_strdup(a->prpl->name); 493 } 494 495 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con); 496 g_free(protocol); 491 497 492 498 i++; … … 502 508 503 509 for (a = irc->b->accounts; a; a = a->next) { 504 if (!a->ic && a->auto_connect ) {510 if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) { 505 511 if (strcmp(a->pass, PASSWORD_PENDING) == 0) { 506 512 irc_rootmsg(irc, "Enter password for account %s " … … 559 565 irc_rootmsg(irc, "Enter password for account %s " 560 566 "first (use /OPER)", a->tag); 567 } else if (a->prpl == &protocol_missing) { 568 irc_rootmsg(irc, "Protocol `%s' not recognised (plugin may be missing or not running?)", 569 set_getstr(&a->set, "_protocol_name")); 561 570 } else { 562 571 account_on(irc->b, a); … … 663 672 irc_rootmsg(irc, "That account is not on-line"); 664 673 return; 674 } else if (add_on_server && !a->prpl->add_buddy) { 675 irc_rootmsg(irc, "IM protocol does not support contact list modification"); 676 return; 677 } 678 679 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' && 680 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) { 681 /* If there's no @ or it's the last char, append the user's 682 domain name now. Exclude handles starting with a _ so 683 adding _xmlconsole will keep working. */ 684 if (s) { 685 *s = '\0'; 686 } 687 if ((s = strchr(a->user, '@'))) { 688 cmd[2] = handle = g_strconcat(cmd[2], s, NULL); 689 } 665 690 } 666 691 … … 677 702 } 678 703 679 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' &&680 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) {681 /* If there's no @ or it's the last char, append the user's682 domain name now. Exclude handles starting with a _ so683 adding _xmlconsole will keep working. */684 if (s) {685 *s = '\0';686 }687 if ((s = strchr(a->user, '@'))) {688 cmd[2] = handle = g_strconcat(cmd[2], s, NULL);689 }690 }691 692 704 if (add_on_server) { 693 705 irc_channel_t *ic; … … 733 745 s = g_strdup(bu->handle); 734 746 735 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 747 if (bu->ic->acc->prpl->remove_buddy) { 748 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 749 } else { 750 irc_rootmsg(irc, "IM protocol does not support contact list modification, " 751 "removal will likely not be permanent"); 752 } 753 736 754 nick_del(bu); 737 755 if (g_slist_find(irc->users, iu)) { -
storage.c
r82cb190 r3fbce97 33 33 34 34 static GList *storage_backends = NULL; 35 36 const struct prpl protocol_missing = { 37 .name = "_unknown", 38 }; 35 39 36 40 void register_storage_backend(storage_t *backend) -
storage.h
r82cb190 r3fbce97 62 62 G_GNUC_MALLOC GList *storage_init(const char *primary, char **migrate); 63 63 64 extern const struct prpl protocol_missing; 65 64 66 #endif /* __STORAGE_H__ */ -
storage_xml.c
r82cb190 r3fbce97 83 83 } 84 84 85 /* Use for unsupported/not-found protocols. Save settings as-is but don't allow changes. */ 86 static void handle_settings_raw(struct xt_node *node, set_t **head) 87 { 88 struct xt_node *c; 89 90 for (c = node->children; (c = xt_find_node(c, "setting")); c = c->next) { 91 char *name = xt_find_attr(c, "name"); 92 93 if (!name) { 94 continue; 95 } 96 97 set_t *s = set_add(head, name, NULL, NULL, NULL); 98 set_setstr(head, name, c->text); 99 s->flags |= SET_HIDDEN | 100 ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; 101 } 102 } 103 85 104 static xt_status handle_account(struct xt_node *node, gpointer data) 86 105 { … … 89 108 char *pass_b64 = NULL; 90 109 unsigned char *pass_cr = NULL; 91 int pass_len , local = 0;110 int pass_len; 92 111 struct prpl *prpl = NULL; 93 112 account_t *acc; … … 104 123 prpl = find_protocol(protocol); 105 124 if (!prpl) { 106 irc_rootmsg(xd->irc, "Error loading user config: Protocol not found: `%s'", protocol); 107 return XT_ABORT; 108 } 109 local = protocol_account_islocal(protocol); 125 irc_rootmsg(xd->irc, "Warning: Protocol not found: `%s'", protocol); 126 prpl = (struct prpl*) &protocol_missing; 127 } 110 128 } 111 129 … … 124 142 set_setstr(&acc->set, "tag", tag); 125 143 } 126 if (local) { 127 acc->flags |= ACC_FLAG_LOCAL; 144 if (prpl == &protocol_missing) { 145 set_t *s = set_add(&acc->set, "_protocol_name", protocol, NULL, NULL); 146 s->flags |= SET_HIDDEN | SET_NOSAVE | 147 ACC_SET_OFFLINE_ONLY | ACC_SET_ONLINE_ONLY; 128 148 } 129 149 } else { … … 136 156 g_free(password); 137 157 138 handle_settings(node, &acc->set); 158 if (prpl == &protocol_missing) { 159 handle_settings_raw(node, &acc->set); 160 } else { 161 handle_settings(node, &acc->set); 162 } 139 163 140 164 for (c = node->children; (c = xt_find_node(c, "buddy")); c = c->next) { … … 312 336 313 337 cur = xt_new_node("account", NULL, NULL); 314 xt_add_attr(cur, "protocol", acc->prpl->name); 338 if (acc->prpl == &protocol_missing) { 339 xt_add_attr(cur, "protocol", set_getstr(&acc->set, "_protocol_name")); 340 } else { 341 xt_add_attr(cur, "protocol", acc->prpl->name); 342 } 315 343 xt_add_attr(cur, "handle", acc->user); 316 344 xt_add_attr(cur, "password", pass_b64);
Note: See TracChangeset
for help on using the changeset viewer.