Changes in / [24de9fa:69b94c3]
- Files:
-
- 7 added
- 4 deleted
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
r24de9fa r69b94c3 32 32 bitlbee.service 33 33 bitlbee@.service 34 *.pyc -
configure
r24de9fa r69b94c3 32 32 jabber="default-on" 33 33 oscar="default-on" 34 rpc="rpc-on" 34 35 yahoo="default-on" 35 36 … … 130 131 --purple=0/1 Disable/enable libpurple support $purple 131 132 (automatically disables other protocol modules) 133 --rpc=0/1 Disable/enable RPC interface $rpc 132 134 133 135 --doc=0/1 Disable/enable help.txt generation $doc … … 820 822 protocols=$protocols'twitter ' 821 823 protoobjs=$protoobjs'twitter_mod.o ' 824 fi 825 826 if [ "$rpc" = 0 ]; then 827 echo '#undef WITH_RPC' >> config.h 828 else 829 echo '#define WITH_RPC' >> config.h 830 protocols=$protocols'rpc ' 831 protoobjs=$protoobjs'rpc_mod.o ' 822 832 fi 823 833 -
doc/user-guide/commands.xml
r24de9fa r69b94c3 1186 1186 </bitlbee-setting> 1187 1187 1188 <bitlbee-setting name="anonymous" type="boolean" scope="account"> 1189 <default>false</default> 1190 1191 <description> 1192 <para> 1193 This enables SASL ANONYMOUS login for jabber accounts, as specified by XEP-0175. 1194 </para> 1195 1196 <para> 1197 With this setting enabled, if the server allows this method, a password isn't required and the username part of the JID is ignored (you can use anonymous@jabber.example.com). Servers will usually assign you a random numeric username instead. 1198 </para> 1199 </description> 1200 1201 </bitlbee-setting> 1202 1188 1203 <bitlbee-setting name="ops" type="string" scope="global"> 1189 1204 <default>both</default> -
irc_channel.c
r24de9fa r69b94c3 724 724 } 725 725 726 if (!bu->ic->acc->prpl->add_buddy) { 727 irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name); 728 return FALSE; 729 } 730 726 731 bu->ic->acc->prpl->add_buddy(bu->ic, bu->handle, 727 732 icc->group ? icc->group->name : NULL); … … 741 746 if (icc->type != IRC_CC_TYPE_GROUP) { 742 747 irc_send_num(ic->irc, 482, "%s :Kicks are only possible to fill_by=group channels", ic->name); 748 return; 749 } 750 751 if (!bu->ic->acc->prpl->remove_buddy) { 752 irc_send_num(ic->irc, 482, "%s :IM protocol does not support contact list modification", ic->name); 743 753 return; 744 754 } -
irc_commands.c
r24de9fa r69b94c3 166 166 showed an error message, or is doing some work 167 167 before the join should be confirmed. (In the 168 latter case, the calle rshould take care of that168 latter case, the callee should take care of that 169 169 confirmation.) TRUE means all's good, let the 170 170 user join the channel right away. */ -
lib/Makefile
r24de9fa r69b94c3 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
r24de9fa r69b94c3 427 427 } 428 428 429 int is_bool(c har *value)429 int is_bool(const char *value) 430 430 { 431 431 if (*value == 0) { … … 453 453 } 454 454 455 int bool2int(c har *value)455 int bool2int(const char *value) 456 456 { 457 457 int i; -
lib/misc.h
r24de9fa r69b94c3 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
r24de9fa r69b94c3 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
r24de9fa r69b94c3 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); … … 463 459 return a->auto_reconnect_delay; 464 460 } 465 466 int protocol_account_islocal(const char* protocol)467 {468 const char** p = account_protocols_local;469 470 do {471 if (strcmp(*p, protocol) == 0) {472 return 1;473 }474 } while (*(++p));475 return 0;476 } -
protocols/account.h
r24de9fa r69b94c3 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/jabber/jabber.c
r24de9fa r69b94c3 85 85 set_setstr(&acc->set, "server", "chat.hipchat.com"); 86 86 } else { 87 s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc); 87 set_add(&acc->set, "oauth", "false", set_eval_oauth, acc); 88 89 /* this reuses set_eval_oauth, which clears the password */ 90 set_add(&acc->set, "anonymous", "false", set_eval_oauth, acc); 88 91 } 89 92 -
protocols/jabber/s5bytestream.c
r24de9fa r69b94c3 85 85 return jabber_bs_abort(bt, msg ": %s", strerror(errno)); } 86 86 87 gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...) ;87 gboolean jabber_bs_abort(struct bs_transfer *bt, char *format, ...) G_GNUC_PRINTF(2, 3); 88 88 void jabber_bs_canceled(file_transfer_t *ft, char *reason); 89 89 void jabber_bs_free_transfer(file_transfer_t *ft); -
protocols/jabber/sasl.c
r24de9fa r69b94c3 54 54 struct xt_node *c, *reply; 55 55 char *s; 56 int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0 ;57 int want_oauth = FALSE, want_hipchat = FALSE ;56 int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0, sup_anonymous = 0; 57 int want_oauth = FALSE, want_hipchat = FALSE, want_anonymous = FALSE; 58 58 GString *mechs; 59 59 … … 74 74 } 75 75 76 want_anonymous = set_getbool(&ic->acc->set, "anonymous"); 76 77 want_oauth = set_getbool(&ic->acc->set, "oauth"); 77 78 want_hipchat = (jd->flags & JFLAG_HIPCHAT); … … 84 85 } else if (c->text && g_strcasecmp(c->text, "DIGEST-MD5") == 0) { 85 86 sup_digest = 1; 87 } else if (c->text && g_strcasecmp(c->text, "ANONYMOUS") == 0) { 88 sup_anonymous = 1; 86 89 } else if (c->text && g_strcasecmp(c->text, "X-OAUTH2") == 0) { 87 90 sup_gtalk = 1; … … 139 142 } else if (want_oauth) { 140 143 imcb_error(ic, "OAuth requested, but not supported by server"); 144 imc_logout(ic, FALSE); 145 xt_free_node(reply); 146 return XT_ABORT; 147 } else if (want_anonymous && sup_anonymous) { 148 xt_add_attr(reply, "mechanism", "ANONYMOUS"); 149 150 /* Well, that was easy. */ 151 } else if (want_anonymous) { 152 imcb_error(ic, "Anonymous login requested, but not supported by server"); 141 153 imc_logout(ic, FALSE); 142 154 xt_free_node(reply); -
protocols/nogaim.c
r24de9fa r69b94c3 132 132 extern void twitter_initmodule(); 133 133 extern void purple_initmodule(); 134 extern void rpc_initmodule(); 134 135 135 136 #ifdef WITH_MSN … … 155 156 #ifdef WITH_PURPLE 156 157 purple_initmodule(); 158 #endif 159 160 #ifdef WITH_RPC 161 rpc_initmodule(); 157 162 #endif 158 163 … … 307 312 } 308 313 309 if (ic->acc->flags & ACC_FLAG_LOCAL) { 314 if ((ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS) && 315 !(ic->flags & OPT_LOCAL_CONTACTS_SENT) && 316 ic->acc->prpl->add_buddy) { 310 317 GHashTableIter nicks; 311 gpointer k, v;318 gpointer handle; 312 319 g_hash_table_iter_init(&nicks, ic->acc->nicks); 313 while (g_hash_table_iter_next(&nicks, & k, &v)) {314 ic->acc->prpl->add_buddy(ic, (char *) k, NULL);320 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 321 ic->acc->prpl->add_buddy(ic, (char *) handle, NULL); 315 322 } 316 323 } … … 407 414 query_del_by_conn((irc_t *) ic->bee->ui_data, ic); 408 415 416 /* Throw away groupchats owned by this account. Historically this was only 417 ever done by IM modules which is a bug. But it gives them opportunity 418 to clean up protocol-specific bits as well so keep it that way, just 419 do another cleanup here as a fallback. Don't want to leave any dangling 420 pointers! */ 421 while (ic->groupchats) { 422 imcb_chat_free(ic->groupchats->data); 423 } 424 409 425 if (!a) { 410 426 /* Uhm... This is very sick. */ … … 492 508 } 493 509 510 /* Returns the local contacts for an IM account (based on assigned nicks). 511 Linked list should be freed, the strings themselves not! So look at it 512 like a GSList<const char*> I guess? Empty list means NULL retval (as 513 always with GSList). */ 514 GSList *imcb_get_local_contacts(struct im_connection *ic) 515 { 516 GHashTableIter nicks; 517 GSList *ret = NULL; 518 519 if (!(ic->acc->flags & ACC_FLAG_LOCAL_CONTACTS)) { 520 /* Only allow protocols that indicate local contact list 521 support to use this function. */ 522 return ret; 523 } 524 525 g_hash_table_iter_init(&nicks, ic->acc->nicks); 526 gpointer handle; 527 while (g_hash_table_iter_next(&nicks, &handle, NULL)) { 528 ret = g_slist_prepend(ret, (char *) handle); 529 } 530 531 /* If the protocol asked for the list, assume we won't have to send it 532 anymore in imcb_connected(). */ 533 ic->flags |= OPT_LOCAL_CONTACTS_SENT; 534 535 return ret; 536 } 537 494 538 495 539 struct imcb_ask_cb_data { … … 550 594 struct imcb_ask_cb_data *cbd = data; 551 595 552 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 596 if (cbd->ic->acc->prpl->add_buddy) { 597 cbd->ic->acc->prpl->add_buddy(cbd->ic, cbd->handle, NULL); 598 } 553 599 554 600 imcb_ask_cb_free(data); -
protocols/nogaim.h
r24de9fa r69b94c3 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 73 79 /* ok. now the fun begins. first we create a connection structure */ … … 324 330 G_MODULE_EXPORT void imcb_buddy_nick_hint(struct im_connection *ic, const char *handle, const char *nick); 325 331 G_MODULE_EXPORT void imcb_buddy_action_response(bee_user_t *bu, const char *action, char * const args[], void *data); 332 G_MODULE_EXPORT GSList *imcb_get_local_contacts(struct im_connection *ic); 326 333 327 334 G_MODULE_EXPORT void imcb_buddy_typing(struct im_connection *ic, const char *handle, uint32_t flags); -
protocols/purple/purple.c
r24de9fa r69b94c3 264 264 } 265 265 purple_accounts_remove(pa); 266 267 /* Last, some protocols want their contact lists locally. */ 268 if (strcmp(acc->prpl->name, "whatsapp") == 0 || strcmp(acc->prpl->name, "gg") == 0) { 269 acc->flags |= ACC_FLAG_LOCAL_CONTACTS; 270 } 266 271 } 267 272 -
protocols/twitter/twitter_lib.c
r24de9fa r69b94c3 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; … … 410 412 } 411 413 412 struct twitter_xml_user *twitter_xt_get_user(const json_value*node)414 struct twitter_xml_user *twitter_xt_get_user(const JSON_Object *node) 413 415 { 414 416 struct twitter_xml_user *txu; 415 json_value *jv; 417 418 if (!node) 419 return NULL; 416 420 417 421 txu = g_new0(struct twitter_xml_user, 1); 418 txu->name = g_strdup(json_o_str(node, "name")); 419 txu->screen_name = g_strdup(json_o_str(node, "screen_name")); 420 421 jv = json_o_get(node, "id"); 422 txu->uid = jv->u.integer; 422 txu->name = g_strdup(json_object_get_string(node, "name")); 423 txu->screen_name = g_strdup(json_object_get_string(node, "screen_name")); 424 txu->uid = json_object_get_integer(node, "id"); 423 425 424 426 return txu; … … 430 432 * - all <user>s from the <users> element. 431 433 */ 432 static gboolean twitter_xt_get_users( json_value *node, struct twitter_xml_list *txl)434 static gboolean twitter_xt_get_users(JSON_Value *node, struct twitter_xml_list *txl) 433 435 { 434 436 struct twitter_xml_user *txu; … … 438 440 txl->type = TXL_USER; 439 441 440 if ( !node || node->type != json_array) {442 if (json_type(node) != JSONArray) { 441 443 return FALSE; 442 444 } 443 445 444 446 // The root <users> node should hold the list of users <user> 445 447 // Walk over the nodes children. 446 for (i = 0; i < node->u.array.length; i++) { 447 txu = twitter_xt_get_user(node->u.array.values[i]); 448 JSON_Array *arr = json_array(node); 449 for (i = 0; i < json_array_get_count(arr); i++) { 450 JSON_Object *o = json_array_get_object(arr, i); 451 if (!o) 452 continue; 453 txu = twitter_xt_get_user(o); 448 454 if (txu) { 449 455 txl->list = g_slist_prepend(txl->list, txu); … … 460 466 #endif 461 467 462 static void expand_entities(char **text, const json_value*node);468 static void expand_entities(char **text, const JSON_Object *node); 463 469 464 470 /** … … 470 476 * - the user in a twitter_xml_user struct. 471 477 */ 472 static struct twitter_xml_status *twitter_xt_get_status(const json_value*node)478 static struct twitter_xml_status *twitter_xt_get_status(const JSON_Object *node) 473 479 { 474 480 struct twitter_xml_status *txs; 475 const json_value*rt = NULL;476 477 if ( node->type != json_object) {481 const JSON_Object *rt = NULL; 482 483 if (!node) { 478 484 return FALSE; 479 485 } … … 481 487 482 488 JSON_O_FOREACH(node, k, v) { 483 if (strcmp("text", k) == 0 && v->type == json_string) {484 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1);489 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 490 // TODO: Huh strip html? In json? Not sure whether I have to.. 485 491 strip_html(txs->text); 486 } else if (strcmp("retweeted_status", k) == 0 && v->type == json_object) {487 rt = v;488 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {492 } else if (strcmp("retweeted_status", k) == 0 && (rt = json_object(v))) { 493 // Handling below. 494 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 489 495 struct tm parsed; 490 496 … … 492 498 this field. :-( Also assumes the timezone used 493 499 is UTC since C time handling functions suck. */ 494 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {500 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 495 501 txs->created_at = mktime_utc(&parsed); 496 502 } 497 } else if (strcmp("user", k) == 0 && v->type == json_object) {498 txs->user = twitter_xt_get_user( v);499 } else if (strcmp("id", k) == 0 && v->type == json_integer) {500 txs->rt_id = txs->id = v->u.integer;501 } else if (strcmp("in_reply_to_status_id", k) == 0 && v->type == json_integer) {502 txs->reply_to = v->u.integer;503 } else if (strcmp("user", k) == 0 && json_type(v) == JSONObject) { 504 txs->user = twitter_xt_get_user(json_object(v)); 505 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 506 txs->rt_id = txs->id = json_integer(v); 507 } else if (strcmp("in_reply_to_status_id", k) == 0 && json_type(v) == JSONInteger) { 508 txs->reply_to = json_integer(v); 503 509 } 504 510 } … … 529 535 * Function to fill a twitter_xml_status struct (DM variant). 530 536 */ 531 static struct twitter_xml_status *twitter_xt_get_dm(const json_value*node)537 static struct twitter_xml_status *twitter_xt_get_dm(const JSON_Object *node) 532 538 { 533 539 struct twitter_xml_status *txs; 534 540 535 if ( node->type != json_object) {541 if (!node) { 536 542 return FALSE; 537 543 } … … 539 545 540 546 JSON_O_FOREACH(node, k, v) { 541 if (strcmp("text", k) == 0 && v->type == json_string) { 542 txs->text = g_memdup(v->u.string.ptr, v->u.string.length + 1); 547 if (strcmp("text", k) == 0 && (txs->text = g_strdup(json_string(v)))) { 543 548 strip_html(txs->text); 544 } else if (strcmp("created_at", k) == 0 && v->type == json_string) {549 } else if (strcmp("created_at", k) == 0 && json_type(v) == JSONString) { 545 550 struct tm parsed; 546 551 … … 548 553 this field. :-( Also assumes the timezone used 549 554 is UTC since C time handling functions suck. */ 550 if (strptime( v->u.string.ptr, TWITTER_TIME_FORMAT, &parsed) != NULL) {555 if (strptime(json_string(v), TWITTER_TIME_FORMAT, &parsed) != NULL) { 551 556 txs->created_at = mktime_utc(&parsed); 552 557 } 553 } else if (strcmp("sender", k) == 0 && v->type == json_object) {554 txs->user = twitter_xt_get_user( v);555 } else if (strcmp("id", k) == 0 && v->type == json_integer) {556 txs->id = v->u.integer;558 } else if (strcmp("sender", k) == 0 && json_type(v) == JSONObject) { 559 txs->user = twitter_xt_get_user(json_object(v)); 560 } else if (strcmp("id", k) == 0 && json_type(v) == JSONInteger) { 561 txs->id = json_integer(v); 557 562 } 558 563 } … … 568 573 } 569 574 570 static void expand_entities(char **text, const json_value*node)571 { 572 json_value*entities, *quoted;575 static void expand_entities(char **text, const JSON_Object *node) 576 { 577 JSON_Object *entities, *quoted; 573 578 char *quote_url = NULL, *quote_text = NULL; 574 579 575 if (!( (entities = json_o_get(node, "entities")) && entities->type == json_object))576 return; 577 if ((quoted = json_o _get(node, "quoted_status")) && quoted->type == json_object) {580 if (!(entities = json_object_get_object(node, "entities"))) 581 return; 582 if ((quoted = json_object_get_object(node, "quoted_status"))) { 578 583 /* New "retweets with comments" feature. Note that this info 579 584 * seems to be included in the streaming API only! Grab the … … 591 596 int i; 592 597 593 if ( v->type != json_array) {598 if (json_type(v) != JSONArray) { 594 599 continue; 595 600 } … … 598 603 } 599 604 600 for (i = 0; i < v->u.array.length; i++) {605 for (i = 0; i < json_array_get_count(json_array(v)); i++) { 601 606 const char *format = "%s%s <%s>%s"; 602 603 if (v->u.array.values[i]->type != json_object) { 607 JSON_Object *r = json_array_get_object(json_array(v), i); 608 609 if (!r) { 604 610 continue; 605 611 } 606 612 607 const char *kort = json_o _str(v->u.array.values[i], "url");608 const char *disp = json_o _str(v->u.array.values[i], "display_url");609 const char *full = json_o _str(v->u.array.values[i], "expanded_url");613 const char *kort = json_object_get_string(r, "url"); 614 const char *disp = json_object_get_string(r, "display_url"); 615 const char *full = json_object_get_string(r, "expanded_url"); 610 616 char *pos, *new; 611 617 … … 636 642 * - the next_cursor. 637 643 */ 638 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const json_value *node,644 static gboolean twitter_xt_get_status_list(struct im_connection *ic, const JSON_Value *node, 639 645 struct twitter_xml_list *txl) 640 646 { … … 645 651 txl->type = TXL_STATUS; 646 652 647 if ( node->type != json_array) {653 if (json_type(node) != JSONArray) { 648 654 return FALSE; 649 655 } … … 651 657 // The root <statuses> node should hold the list of statuses <status> 652 658 // Walk over the nodes children. 653 for (i = 0; i < node->u.array.length; i++) {654 txs = twitter_xt_get_status( node->u.array.values[i]);659 for (i = 0; i < json_array_get_count(json_array(node)); i++) { 660 txs = twitter_xt_get_status(json_array_get_object(json_array(node), i)); 655 661 if (!txs) { 656 662 continue; … … 858 864 } 859 865 860 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter);866 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter); 861 867 862 868 static void twitter_http_stream(struct http_request *req) … … 864 870 struct im_connection *ic = req->data; 865 871 struct twitter_data *td; 866 json_value *parsed;872 JSON_Value *parsed; 867 873 int len = 0; 868 874 char c, *nl; … … 902 908 req->reply_body[len] = '\0'; 903 909 904 if ((parsed = json_parse (req->reply_body, req->body_size))) {910 if ((parsed = json_parse_string(req->reply_body))) { 905 911 from_filter = (req == td->filter_stream); 906 twitter_stream_handle_object(ic, parsed, from_filter);912 twitter_stream_handle_object(ic, json_object(parsed), from_filter); 907 913 } 908 914 json_value_free(parsed); … … 918 924 } 919 925 920 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value*o);926 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o); 921 927 static gboolean twitter_stream_handle_status(struct im_connection *ic, struct twitter_xml_status *txs); 922 928 923 static gboolean twitter_stream_handle_object(struct im_connection *ic, json_value*o, gboolean from_filter)929 static gboolean twitter_stream_handle_object(struct im_connection *ic, JSON_Object *o, gboolean from_filter) 924 930 { 925 931 struct twitter_data *td = ic->proto_data; 926 932 struct twitter_xml_status *txs; 927 json_value*c;933 JSON_Object *c; 928 934 929 935 if ((txs = twitter_xt_get_status(o))) { … … 932 938 txs_free(txs); 933 939 return ret; 934 } else if ((c = json_o _get(o, "direct_message")) &&940 } else if ((c = json_object_get_object(o, "direct_message")) && 935 941 (txs = twitter_xt_get_dm(c))) { 936 942 if (g_strcasecmp(txs->user->screen_name, td->user) != 0) { … … 940 946 txs_free(txs); 941 947 return TRUE; 942 } else if ( (c = json_o_get(o, "event")) && c->type == json_string) {948 } else if (json_object_get_string(o, "event")) { 943 949 twitter_stream_handle_event(ic, o); 944 950 return TRUE; 945 } else if ((c = json_o _get(o, "disconnect")) && c->type == json_object) {951 } else if ((c = json_object_get_object(o, "disconnect"))) { 946 952 /* HACK: Because we're inside an event handler, we can't just 947 953 disconnect here. Instead, just change the HTTP status string 948 954 into a Twitter status string. */ 949 char *reason = json_o_strdup(c, "reason");955 char *reason = g_strdup(json_object_get_string(c, "reason")); 950 956 if (reason) { 951 957 g_free(td->stream->status_string); … … 986 992 } 987 993 988 static gboolean twitter_stream_handle_event(struct im_connection *ic, json_value *o) 989 { 990 struct twitter_data *td = ic->proto_data; 991 json_value *source = json_o_get(o, "source"); 992 json_value *target = json_o_get(o, "target"); 993 const char *type = json_o_str(o, "event"); 994 995 if (!type || !source || source->type != json_object 996 || !target || target->type != json_object) { 994 static gboolean twitter_stream_handle_event(struct im_connection *ic, JSON_Object *o) 995 { 996 struct twitter_data *td = ic->proto_data; 997 JSON_Object *source = json_object_get_object(o, "source"); 998 JSON_Object *target = json_object_get_object(o, "target"); 999 const char *type = json_object_get_string(o, "event"); 1000 1001 if (!type || !source || !target) { 997 1002 return FALSE; 998 1003 } … … 1091 1096 struct twitter_filter *tf; 1092 1097 GList *users = NULL; 1093 json_value *parsed; 1094 json_value *id; 1095 const char *name; 1098 JSON_Value *parsed; 1096 1099 GString *fstr; 1097 1100 GSList *l; … … 1118 1121 } 1119 1122 1120 if ( parsed->type != json_array) {1123 if (json_type(parsed) != JSONArray) { 1121 1124 goto finish; 1122 1125 } 1123 1126 1124 for (i = 0; i < parsed->u.array.length; i++) { 1125 id = json_o_get(parsed->u.array.values[i], "id"); 1126 name = json_o_str(parsed->u.array.values[i], "screen_name"); 1127 1128 if (!name || !id || id->type != json_integer) { 1127 for (i = 0; i < json_array_get_count(json_array(parsed)); i++) { 1128 JSON_Object *o = json_array_get_object(json_array(parsed), i); 1129 jint id = json_object_get_integer(o, "id"); 1130 const char *name = json_object_get_string(o, "screen_name"); 1131 1132 if (!name || !id) { 1129 1133 continue; 1130 1134 } … … 1134 1138 1135 1139 if (g_strcasecmp(tf->text, name) == 0) { 1136 tf->uid = id ->u.integer;1140 tf->uid = id; 1137 1141 users = g_list_delete_link(users, u); 1138 1142 break; … … 1375 1379 struct im_connection *ic = req->data; 1376 1380 struct twitter_data *td; 1377 json_value *parsed;1381 JSON_Value *parsed; 1378 1382 struct twitter_xml_list *txl; 1379 1383 … … 1414 1418 struct im_connection *ic = req->data; 1415 1419 struct twitter_data *td; 1416 json_value *parsed;1420 JSON_Value *parsed; 1417 1421 struct twitter_xml_list *txl; 1418 1422 … … 1454 1458 struct im_connection *ic = req->data; 1455 1459 struct twitter_data *td; 1456 json_value *parsed, *id; 1460 JSON_Value *parsed; 1461 jint id; 1457 1462 1458 1463 // Check if the connection is still active. … … 1468 1473 } 1469 1474 1470 if ((id = json_o _get(parsed, "id")) && id->type == json_integer) {1471 td->last_status_id = id ->u.integer;1475 if ((id = json_object_get_integer(json_object(parsed), "id"))) { 1476 td->last_status_id = id; 1472 1477 } 1473 1478 … … 1577 1582 { 1578 1583 struct im_connection *ic = req->data; 1579 json_value *parsed, *id; 1584 JSON_Value *parsed; 1585 uint64_t id; 1580 1586 const char *name; 1581 1587 … … 1589 1595 } 1590 1596 1591 /* for the parson branch:1592 1597 name = json_object_dotget_string(json_object(parsed), "user.screen_name"); 1593 1598 id = json_object_get_integer(json_object(parsed), "id"); 1594 */ 1595 1596 name = json_o_str(json_o_get(parsed, "user"), "screen_name"); 1597 id = json_o_get(parsed, "id"); 1598 1599 if (name && id && id->type == json_integer) { 1600 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id->u.integer); 1599 1600 if (name && id) { 1601 twitter_log(ic, "https://twitter.com/%s/status/%" G_GUINT64_FORMAT, name, id); 1601 1602 } else { 1602 1603 twitter_log(ic, "Error: could not fetch tweet url."); -
root_commands.c
r24de9fa r69b94c3 460 460 461 461 for (a = irc->b->accounts; a; a = a->next) { 462 char *con ;462 char *con = NULL, *protocol = NULL; 463 463 464 464 if (a->ic && (a->ic->flags & OPT_LOGGED_IN)) { … … 471 471 con = ""; 472 472 } 473 474 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, a->prpl->name, a->user, con); 473 if (a->prpl == &protocol_missing) { 474 protocol = g_strdup_printf("%s (missing!)", set_getstr(&a->set, "_protocol_name")); 475 } else { 476 protocol = g_strdup(a->prpl->name); 477 } 478 479 irc_rootmsg(irc, "%2d (%s): %s, %s%s", i, a->tag, protocol, a->user, con); 480 g_free(protocol); 475 481 476 482 i++; … … 486 492 487 493 for (a = irc->b->accounts; a; a = a->next) { 488 if (!a->ic && a->auto_connect ) {494 if (!a->ic && a->auto_connect && a->prpl != &protocol_missing) { 489 495 if (strcmp(a->pass, PASSWORD_PENDING) == 0) { 490 496 irc_rootmsg(irc, "Enter password for account %s " … … 543 549 irc_rootmsg(irc, "Enter password for account %s " 544 550 "first (use /OPER)", a->tag); 551 } else if (a->prpl == &protocol_missing) { 552 irc_rootmsg(irc, "Protocol `%s' not recognised (plugin may be missing or not running?)", 553 set_getstr(&a->set, "_protocol_name")); 545 554 } else { 546 555 account_on(irc->b, a); … … 647 656 irc_rootmsg(irc, "That account is not on-line"); 648 657 return; 658 } else if (add_on_server && !a->prpl->add_buddy) { 659 irc_rootmsg(irc, "IM protocol does not support contact list modification"); 660 return; 661 } 662 663 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' && 664 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) { 665 /* If there's no @ or it's the last char, append the user's 666 domain name now. Exclude handles starting with a _ so 667 adding _xmlconsole will keep working. */ 668 if (s) { 669 *s = '\0'; 670 } 671 if ((s = strchr(a->user, '@'))) { 672 cmd[2] = handle = g_strconcat(cmd[2], s, NULL); 673 } 649 674 } 650 675 … … 661 686 } 662 687 663 if ((a->flags & ACC_FLAG_HANDLE_DOMAINS) && cmd[2][0] != '_' &&664 (!(s = strchr(cmd[2], '@')) || s[1] == '\0')) {665 /* If there's no @ or it's the last char, append the user's666 domain name now. Exclude handles starting with a _ so667 adding _xmlconsole will keep working. */668 if (s) {669 *s = '\0';670 }671 if ((s = strchr(a->user, '@'))) {672 cmd[2] = handle = g_strconcat(cmd[2], s, NULL);673 }674 }675 676 688 if (add_on_server) { 677 689 irc_channel_t *ic; … … 717 729 s = g_strdup(bu->handle); 718 730 719 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 731 if (bu->ic->acc->prpl->remove_buddy) { 732 bu->ic->acc->prpl->remove_buddy(bu->ic, bu->handle, NULL); 733 } else { 734 irc_rootmsg(irc, "IM protocol does not support contact list modification, " 735 "removal will likely not be permanent"); 736 } 737 720 738 nick_del(bu); 721 739 if (g_slist_find(irc->users, iu)) { -
storage.c
r24de9fa r69b94c3 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
r24de9fa r69b94c3 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
r24de9fa r69b94c3 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.