Changes in / [2dd23da:fc650a8]
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
irc_im.c
r2dd23da rfc650a8 573 573 ic->data = c; 574 574 575 topic = g_strdup_printf( 576 "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", 577 c->title); 578 irc_channel_set_topic(ic, topic, irc->root); 579 g_free(topic); 575 if (ic->topic == NULL) { 576 /* New channel with no preset topic - make up a generic one */ 577 topic = g_strdup_printf( 578 "BitlBee groupchat: \"%s\". Please keep in mind that root-commands won't work here. Have fun!", 579 c->title); 580 irc_channel_set_topic(ic, topic, irc->root); 581 } else { 582 /* Preset topic from the channel we picked */ 583 topic = g_strdup(ic->topic); 584 } 585 586 g_free(c->topic); 587 c->topic = topic; /* Let groupchat borrow this pointer */ 580 588 581 589 return TRUE; -
protocols/account.c
r2dd23da rfc650a8 83 83 } else { 84 84 strcpy(tag, "aim"); 85 }86 } else if (strcmp(prpl->name, "jabber") == 0) {87 if (strstr(a->user, "@gmail.com") ||88 strstr(a->user, "@googlemail.com")) {89 strcpy(tag, "gtalk");90 } else if (strstr(a->user, "@chat.facebook.com")) {91 strcpy(tag, "fb");92 85 } 93 86 } -
protocols/jabber/Makefile
r2dd23da rfc650a8 13 13 14 14 # [SH] Program variables 15 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o 15 objects = conference.o io.o iq.o jabber.o jabber_util.o message.o presence.o s5bytestream.o sasl.o si.o hipchat.o 16 16 17 17 LFLAGS += -r -
protocols/jabber/conference.c
r2dd23da rfc650a8 354 354 struct xt_node *subject = xt_find_node(node->children, "subject"); 355 355 struct xt_node *body = xt_find_node(node->children, "body"); 356 struct groupchat *chat = bud ? jabber_chat_by_jid(ic, bud->bare_jid) : NULL; 357 struct jabber_chat *jc = chat ? chat->data : NULL; 358 char *s; 356 struct groupchat *chat = NULL; 357 struct jabber_chat *jc = NULL; 358 char *from = NULL; 359 char *nick = NULL; 360 char *final_from = NULL; 361 char *bare_jid = NULL; 362 363 from = (bud) ? bud->full_jid : xt_find_attr(node, "from"); 364 365 if (from) { 366 nick = strchr(from, '/'); 367 if (nick) { 368 *nick = 0; 369 } 370 chat = jabber_chat_by_jid(ic, from); 371 if (nick) { 372 *nick = '/'; 373 nick++; 374 } 375 } 376 377 jc = (chat) ? chat->data : NULL; 378 379 if (!bud) { 380 struct xt_node *c; 381 char *s; 382 383 /* Try some clever stuff to find out the real JID here */ 384 c = xt_find_node_by_attr(node->children, "delay", "xmlns", XMLNS_DELAY); 385 386 if (c && ((s = xt_find_attr(c, "from")) || 387 (s = xt_find_attr(c, "from_jid")))) { 388 /* This won't be useful if it's the MUC JID */ 389 if (!(jc && jabber_compare_jid(s, jc->name))) { 390 /* Hopefully this one makes more sense! */ 391 bud = jabber_buddy_by_jid(ic, s, GET_BUDDY_FIRST | GET_BUDDY_CREAT); 392 } 393 } 394 395 } 359 396 360 397 if (subject && chat) { 361 s = bud ? strchr(bud->ext_jid, '/') : NULL; 362 if (s) { 363 *s = 0; 364 } 365 imcb_chat_topic(chat, bud ? bud->ext_jid : NULL, subject->text_len > 0 ? 366 subject->text : NULL, jabber_get_timestamp(node)); 367 if (s) { 368 *s = '/'; 369 } 370 } 371 372 if (bud == NULL || (jc && ~jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me)) { 373 char *nick; 374 375 if (body == NULL || body->text_len == 0) { 376 /* Meh. Empty messages aren't very interesting, no matter 377 how much some servers love to send them. */ 378 return; 379 } 380 381 s = xt_find_attr(node, "from"); /* pkt_message() already NULL-checked this one. */ 382 nick = strchr(s, '/'); 383 if (nick) { 384 /* If this message included a resource/nick we don't know, 385 we might still know the groupchat itself. */ 386 *nick = 0; 387 chat = jabber_chat_by_jid(ic, s); 388 *nick = '/'; 389 390 nick++; 398 char *subject_text = subject->text_len > 0 ? subject->text : NULL; 399 if (g_strcmp0(chat->topic, subject_text) != 0) { 400 bare_jid = (bud) ? jabber_get_bare_jid(bud->ext_jid) : NULL; 401 imcb_chat_topic(chat, bare_jid, subject_text, 402 jabber_get_timestamp(node)); 403 g_free(bare_jid); 404 } 405 } 406 407 if (body == NULL || body->text_len == 0) { 408 /* Meh. Empty messages aren't very interesting, no matter 409 how much some servers love to send them. */ 410 return; 411 } 412 413 if (chat == NULL) { 414 if (nick == NULL) { 415 imcb_log(ic, "System message from unknown groupchat %s: %s", from, body->text); 391 416 } else { 392 /* message.c uses the EXACT_JID option, so bud should 393 always be NULL here for bare JIDs. */ 394 chat = jabber_chat_by_jid(ic, s); 395 } 396 397 if (nick == NULL) { 398 /* This is fine, the groupchat itself isn't in jd->buddies. */ 399 if (chat) { 400 imcb_chat_log(chat, "From conference server: %s", body->text); 401 } else { 402 imcb_log(ic, "System message from unknown groupchat %s: %s", s, body->text); 403 } 404 } else { 405 /* This can happen too, at least when receiving a backlog when 406 just joining a channel. */ 407 if (chat) { 408 imcb_chat_log(chat, "Message from unknown participant %s: %s", nick, body->text); 409 } else { 410 imcb_log(ic, "Groupchat message from unknown JID %s: %s", s, body->text); 411 } 417 imcb_log(ic, "Groupchat message from unknown JID %s: %s", from, body->text); 412 418 } 413 419 414 420 return; 415 } else if (chat == NULL) { 416 /* How could this happen?? We could do kill( self, 11 ) 417 now or just wait for the OS to do it. :-) */ 421 } else if (chat != NULL && bud == NULL && nick == NULL) { 422 imcb_chat_log(chat, "From conference server: %s", body->text); 418 423 return; 419 } 420 if (body && body->text_len > 0) { 421 s = strchr(bud->ext_jid, '/'); 422 if (s) { 423 *s = 0; 424 } 425 imcb_chat_msg(chat, bud->ext_jid, body->text, 0, jabber_get_timestamp(node)); 426 if (s) { 427 *s = '/'; 428 } 429 } 430 } 424 } else if (jc && jc->flags & JCFLAG_MESSAGE_SENT && bud == jc->me) { 425 /* exclude self-messages since they would get filtered out 426 * but not the ones in the backlog */ 427 return; 428 } 429 430 if (bud && jc && bud != jc->me) { 431 bare_jid = jabber_get_bare_jid(bud->ext_jid ? bud->ext_jid : bud->full_jid); 432 final_from = bare_jid; 433 } else { 434 final_from = nick; 435 } 436 437 imcb_chat_msg(chat, final_from, body->text, 0, jabber_get_timestamp(node)); 438 439 g_free(bare_jid); 440 } -
protocols/jabber/iq.c
r2dd23da rfc650a8 27 27 static xt_status jabber_parse_roster(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); 28 28 static xt_status jabber_iq_display_vcard(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); 29 static int jabber_iq_disco_server(struct im_connection *ic);30 29 31 30 xt_status jabber_pkt_iq(struct xt_node *node, gpointer data) … … 388 387 char *name = xt_find_attr(c, "name"); 389 388 char *sub = xt_find_attr(c, "subscription"); 389 char *mention_name = xt_find_attr(c, "mention_name"); 390 char *nick = mention_name ? : name; 390 391 391 392 if (jid && sub) { … … 396 397 if (name) { 397 398 imcb_rename_buddy(ic, jid, name); 399 } 400 401 if (nick) { 402 imcb_buddy_nick_hint(ic, jid, nick); 398 403 } 399 404 } else if (strcmp(sub, "remove") == 0) { … … 855 860 struct xt_node *node, struct xt_node *orig); 856 861 857 staticint jabber_iq_disco_server(struct im_connection *ic)862 int jabber_iq_disco_server(struct im_connection *ic) 858 863 { 859 864 struct xt_node *node, *iq; -
protocols/jabber/jabber.c
r2dd23da rfc650a8 54 54 }; 55 55 56 static jabber_subproto_desc_t jabber_subproto_list[] = { 57 { "jabber", JSUB_NONE, NULL, NULL }, 58 { "gtalk", JSUB_GTALK, &oauth2_service_google, "talk.google.com" }, 59 { "fb", JSUB_FACEBOOK, &oauth2_service_facebook, "chat.facebook.com" }, 60 { "hipchat", JSUB_HIPCHAT, NULL, "chat.hipchat.com" }, 61 { NULL }, 62 }; 63 56 64 static void jabber_init(account_t *acc) 57 65 { 58 66 set_t *s; 59 67 char str[16]; 68 jabber_subproto_desc_t *subproto = acc->prpl->data; 60 69 61 70 s = set_add(&acc->set, "activity_timeout", "600", set_eval_int, acc); 62 71 63 s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc);64 65 72 s = set_add(&acc->set, "display_name", NULL, NULL, acc); 73 74 if (subproto->oauth2_service) { 75 s = set_add(&acc->set, "oauth", "false", set_eval_oauth, acc); 76 } 66 77 67 78 g_snprintf(str, sizeof(str), "%d", jabber_port_list[0]); … … 100 111 acc->flags |= ACC_FLAG_AWAY_MESSAGE | ACC_FLAG_STATUS_MESSAGE | 101 112 ACC_FLAG_HANDLE_DOMAINS; 113 114 if (subproto->server) { 115 set_setstr(&acc->set, "server", (char *) subproto->server); 116 } 102 117 } 103 118 … … 108 123 struct im_connection *ic = imcb_new(acc); 109 124 struct jabber_data *jd = g_new0(struct jabber_data, 1); 125 jabber_subproto_desc_t *subproto = acc->prpl->data; 110 126 char *s; 111 127 … … 117 133 jd->ic = ic; 118 134 ic->proto_data = jd; 135 jd->subproto = subproto->id; 119 136 120 137 jabber_set_me(ic, acc->user); … … 141 158 jd->buddies = g_hash_table_new(g_str_hash, g_str_equal); 142 159 143 if (s et_getbool(&acc->set, "oauth")) {160 if (subproto->oauth2_service && set_getbool(&acc->set, "oauth")) { 144 161 GSList *p_in = NULL; 145 162 const char *tok; … … 147 164 jd->fd = jd->r_inpa = jd->w_inpa = -1; 148 165 149 if (strstr(jd->server, ".facebook.com")) { 150 jd->oauth2_service = &oauth2_service_facebook; 151 } else { 152 jd->oauth2_service = &oauth2_service_google; 153 } 166 jd->oauth2_service = subproto->oauth2_service; 154 167 155 168 oauth_params_parse(&p_in, ic->acc->pass); … … 655 668 void jabber_initmodule() 656 669 { 657 struct prpl *ret = g_new0(struct prpl, 1); 658 659 ret->name = "jabber"; 660 ret->mms = 0; /* no limit */ 661 ret->login = jabber_login; 662 ret->init = jabber_init; 663 ret->logout = jabber_logout; 664 ret->buddy_msg = jabber_buddy_msg; 665 ret->away_states = jabber_away_states; 666 ret->set_away = jabber_set_away; 667 // ret->set_info = jabber_set_info; 668 ret->get_info = jabber_get_info; 669 ret->add_buddy = jabber_add_buddy; 670 ret->remove_buddy = jabber_remove_buddy; 671 ret->chat_msg = jabber_chat_msg_; 672 ret->chat_topic = jabber_chat_topic_; 673 ret->chat_invite = jabber_chat_invite_; 674 ret->chat_leave = jabber_chat_leave_; 675 ret->chat_join = jabber_chat_join_; 676 ret->chat_with = jabber_chat_with_; 677 ret->chat_add_settings = jabber_chat_add_settings; 678 ret->chat_free_settings = jabber_chat_free_settings; 679 ret->keepalive = jabber_keepalive; 680 ret->send_typing = jabber_send_typing; 681 ret->handle_cmp = g_strcasecmp; 682 ret->handle_is_self = jabber_handle_is_self; 683 ret->transfer_request = jabber_si_transfer_request; 684 ret->buddy_action_list = jabber_buddy_action_list; 685 ret->buddy_action = jabber_buddy_action; 686 687 register_protocol(ret); 688 } 670 int i; 671 struct prpl funcs; 672 673 memset(&funcs, 0, sizeof(funcs)); 674 675 funcs.mms = 0; /* no limit */ 676 funcs.login = jabber_login; 677 funcs.init = jabber_init; 678 funcs.logout = jabber_logout; 679 funcs.buddy_msg = jabber_buddy_msg; 680 funcs.away_states = jabber_away_states; 681 funcs.set_away = jabber_set_away; 682 funcs.get_info = jabber_get_info; 683 funcs.add_buddy = jabber_add_buddy; 684 funcs.remove_buddy = jabber_remove_buddy; 685 funcs.chat_msg = jabber_chat_msg_; 686 funcs.chat_topic = jabber_chat_topic_; 687 funcs.chat_invite = jabber_chat_invite_; 688 funcs.chat_leave = jabber_chat_leave_; 689 funcs.chat_join = jabber_chat_join_; 690 funcs.chat_with = jabber_chat_with_; 691 funcs.chat_add_settings = jabber_chat_add_settings; 692 funcs.chat_free_settings = jabber_chat_free_settings; 693 funcs.keepalive = jabber_keepalive; 694 funcs.send_typing = jabber_send_typing; 695 funcs.handle_cmp = g_strcasecmp; 696 funcs.handle_is_self = jabber_handle_is_self; 697 funcs.transfer_request = jabber_si_transfer_request; 698 funcs.buddy_action_list = jabber_buddy_action_list; 699 funcs.buddy_action = jabber_buddy_action; 700 701 for (i = 0; jabber_subproto_list[i].name; i++) { 702 struct prpl *subproto = g_memdup(&funcs, sizeof(funcs)); 703 subproto->name = jabber_subproto_list[i].name; 704 subproto->data = &jabber_subproto_list[i]; 705 register_protocol(subproto); 706 } 707 } -
protocols/jabber/jabber.h
r2dd23da rfc650a8 77 77 } jabber_chat_flags_t; 78 78 79 typedef enum { 80 JSUB_NONE = 0, 81 JSUB_GTALK, 82 JSUB_FACEBOOK, 83 JSUB_HIPCHAT, 84 } jabber_subproto_t; 85 86 typedef struct { 87 const char *name; 88 jabber_subproto_t id; 89 const struct oauth2_service *oauth2_service; 90 const char *server; 91 } jabber_subproto_desc_t; 92 79 93 struct jabber_data { 80 94 struct im_connection *ic; … … 88 102 struct xt_parser *xt; 89 103 jabber_flags_t flags; 104 jabber_subproto_t subproto; 90 105 91 106 char *username; /* USERNAME@server */ … … 235 250 #define XMLNS_IBB "http://jabber.org/protocol/ibb" /* XEP-0047 */ 236 251 252 /* Hipchat protocol extensions*/ 253 #define XMLNS_HIPCHAT "http://hipchat.com" 254 #define XMLNS_HIPCHAT_PROFILE "http://hipchat.com/protocol/profile" 255 #define XMLNS_HIPCHAT_MUC "http://hipchat.com/protocol/muc#room" 256 237 257 /* jabber.c */ 238 258 void jabber_connect(struct im_connection *ic); … … 244 264 int jabber_get_roster(struct im_connection *ic); 245 265 int jabber_get_vcard(struct im_connection *ic, char *bare_jid); 266 int jabber_iq_disco_muc(struct im_connection *ic, char *muc_server); 246 267 int jabber_add_to_roster(struct im_connection *ic, const char *handle, const char *name, const char *group); 247 268 int jabber_remove_from_roster(struct im_connection *ic, char *handle); … … 249 270 xt_status jabber_iq_query_server(struct im_connection *ic, char *jid, char *xmlns); 250 271 void jabber_iq_version_send(struct im_connection *ic, struct jabber_buddy *bud, void *data); 272 int jabber_iq_disco_server(struct im_connection *ic); 251 273 252 274 /* si.c */ … … 306 328 void jabber_error_free(struct jabber_error *err); 307 329 gboolean jabber_set_me(struct im_connection *ic, const char *me); 330 char *jabber_get_bare_jid(char *jid); 308 331 309 332 extern const struct jabber_away_state jabber_away_state_list[]; … … 341 364 void jabber_chat_invite(struct groupchat *c, char *who, char *message); 342 365 366 /* hipchat.c */ 367 int jabber_get_hipchat_profile(struct im_connection *ic); 368 xt_status jabber_parse_hipchat_profile(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); 369 xt_status hipchat_handle_success(struct im_connection *ic, struct xt_node *node); 370 xt_status jabber_parse_muc_list(struct im_connection *ic, struct xt_node *node, struct xt_node *orig); 371 343 372 #endif -
protocols/jabber/jabber_util.c
r2dd23da rfc650a8 819 819 return TRUE; 820 820 } 821 822 /* Returns new reference! g_free() afterwards. */ 823 char *jabber_get_bare_jid(char *jid) 824 { 825 char *s = NULL; 826 827 if (jid == NULL) { 828 return NULL; 829 } 830 831 if ((s = strchr(jid, '/'))) { 832 return g_strndup(jid, s - jid); 833 } else { 834 return g_strdup(jid); 835 } 836 } -
protocols/jabber/sasl.c
r2dd23da rfc650a8 55 55 char *s; 56 56 int sup_plain = 0, sup_digest = 0, sup_gtalk = 0, sup_fb = 0; 57 int want_oauth = FALSE ;57 int want_oauth = FALSE, want_hipchat = FALSE; 58 58 GString *mechs; 59 59 … … 75 75 76 76 want_oauth = set_getbool(&ic->acc->set, "oauth"); 77 want_hipchat = (jd->subproto == JSUB_HIPCHAT); 77 78 78 79 mechs = g_string_new(""); … … 111 112 112 113 reply = xt_new_node("auth", NULL, NULL); 113 xt_add_attr(reply, "xmlns", XMLNS_SASL); 114 if (!want_hipchat) { 115 xt_add_attr(reply, "xmlns", XMLNS_SASL); 116 } else { 117 xt_add_attr(reply, "xmlns", XMLNS_HIPCHAT); 118 } 114 119 115 120 if (sup_gtalk && want_oauth) { … … 143 148 } else if (sup_plain) { 144 149 int len; 145 146 xt_add_attr(reply, "mechanism", "PLAIN"); 150 GString *gs; 151 char *username; 152 153 if (!want_hipchat) { 154 xt_add_attr(reply, "mechanism", "PLAIN"); 155 username = jd->username; 156 } else { 157 username = jd->me; 158 } 159 160 /* set an arbitrary initial size to avoid reallocations */ 161 gs = g_string_sized_new(128); 147 162 148 163 /* With SASL PLAIN in XMPP, the text should be b64(\0user\0pass) */ 149 len = strlen(jd->username) + strlen(ic->acc->pass) + 2; 150 s = g_malloc(len + 1); 151 s[0] = 0; 152 strcpy(s + 1, jd->username); 153 strcpy(s + 2 + strlen(jd->username), ic->acc->pass); 164 g_string_append_c(gs, '\0'); 165 g_string_append(gs, username); 166 g_string_append_c(gs, '\0'); 167 g_string_append(gs, ic->acc->pass); 168 if (want_hipchat) { 169 /* Hipchat's variation adds \0resource at the end */ 170 g_string_append_c(gs, '\0'); 171 g_string_append(gs, set_getstr(&ic->acc->set, "resource")); 172 } 173 174 len = gs->len; 175 s = g_string_free(gs, FALSE); 176 154 177 reply->text = base64_encode((unsigned char *) s, len); 155 178 reply->text_len = strlen(reply->text); … … 397 420 imcb_log(ic, "Authentication finished"); 398 421 jd->flags |= JFLAG_AUTHENTICATED | JFLAG_STREAM_RESTART; 422 423 if (jd->subproto == JSUB_HIPCHAT) { 424 return hipchat_handle_success(ic, node); 425 } 399 426 } else if (strcmp(node->name, "failure") == 0) { 400 427 imcb_error(ic, "Authentication failure"); -
root_commands.c
r2dd23da rfc650a8 395 395 if (len >= 1 && g_strncasecmp(cmd[1], "add", len) == 0) { 396 396 struct prpl *prpl; 397 char *protocol_name = cmd[2]; 397 398 398 399 MIN_ARGS(3); … … 410 411 } 411 412 412 prpl = find_protocol(cmd[2]); 413 /* These used to be just hardcoded account tag guesses, 414 * now they are promoted to hardecoded subprotocol guesses */ 415 if (strcmp(protocol_name, "jabber") == 0) { 416 if (strstr(cmd[3], "@gmail.com") || strstr(cmd[3], "@googlemail.com")) { 417 protocol_name = "gtalk"; 418 } else if (strstr(cmd[3], "@chat.facebook.com")) { 419 protocol_name = "fb"; 420 } 421 } 422 423 prpl = find_protocol(protocol_name); 413 424 414 425 if (prpl == NULL) {
Note: See TracChangeset
for help on using the changeset viewer.