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