Mercurial > pidgin.yaz
comparison libpurple/protocols/jabber/presence.c @ 27577:6d26258e9f1d
propagate from branch 'im.pidgin.pidgin' (head ac87c285c7056f86005dc157b9870745de471f74)
to branch 'im.pidgin.cpw.darkrain42.roster' (head 976d874853ac9745edb77d3cf107b92ebc037c10)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Mon, 06 Jul 2009 04:37:41 +0000 |
parents | 9a5a9a4e7626 b41b69e8b341 |
children | 3bb1085235d0 |
comparison
equal
deleted
inserted
replaced
27576:b9da56683499 | 27577:6d26258e9f1d |
---|---|
249 | 249 |
250 xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority) | 250 xmlnode *jabber_presence_create_js(JabberStream *js, JabberBuddyState state, const char *msg, int priority) |
251 { | 251 { |
252 xmlnode *show, *status, *presence, *pri, *c; | 252 xmlnode *show, *status, *presence, *pri, *c; |
253 const char *show_string = NULL; | 253 const char *show_string = NULL; |
254 #ifdef USE_VV | |
254 gboolean audio_enabled, video_enabled; | 255 gboolean audio_enabled, video_enabled; |
256 #endif | |
255 | 257 |
256 presence = xmlnode_new("presence"); | 258 presence = xmlnode_new("presence"); |
257 | 259 |
258 if(state == JABBER_BUDDY_STATE_UNAVAILABLE) | 260 if(state == JABBER_BUDDY_STATE_UNAVAILABLE) |
259 xmlnode_set_attrib(presence, "type", "unavailable"); | 261 xmlnode_set_attrib(presence, "type", "unavailable"); |
462 | 464 |
463 void jabber_presence_parse(JabberStream *js, xmlnode *packet) | 465 void jabber_presence_parse(JabberStream *js, xmlnode *packet) |
464 { | 466 { |
465 const char *from; | 467 const char *from; |
466 const char *type; | 468 const char *type; |
467 const char *real_jid = NULL; | |
468 const char *affiliation = NULL; | |
469 const char *role = NULL; | |
470 char *status = NULL; | 469 char *status = NULL; |
471 int priority = 0; | 470 int priority = 0; |
472 JabberID *jid; | 471 JabberID *jid; |
473 JabberChat *chat; | 472 JabberChat *chat; |
474 JabberBuddy *jb; | 473 JabberBuddy *jb; |
478 const gchar *stamp = NULL; /* from <delayed/> element */ | 477 const gchar *stamp = NULL; /* from <delayed/> element */ |
479 PurpleBuddy *b = NULL; | 478 PurpleBuddy *b = NULL; |
480 char *buddy_name; | 479 char *buddy_name; |
481 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; | 480 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; |
482 xmlnode *y; | 481 xmlnode *y; |
483 gboolean muc = FALSE; | |
484 char *avatar_hash = NULL; | 482 char *avatar_hash = NULL; |
485 xmlnode *caps = NULL; | 483 xmlnode *caps = NULL; |
486 int idle = 0; | 484 int idle = 0; |
487 gchar *nickname = NULL; | 485 gchar *nickname = NULL; |
488 gboolean signal_return; | 486 gboolean signal_return; |
489 | 487 |
490 from = xmlnode_get_attrib(packet, "from"); | 488 from = xmlnode_get_attrib(packet, "from"); |
491 type = xmlnode_get_attrib(packet, "type"); | 489 type = xmlnode_get_attrib(packet, "type"); |
492 | 490 |
493 if(!(jb = jabber_buddy_find(js, from, TRUE))) | 491 jb = jabber_buddy_find(js, from, TRUE); |
494 return; | 492 g_return_if_fail(jb != NULL); |
495 | 493 |
496 signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, | 494 signal_return = GPOINTER_TO_INT(purple_signal_emit_return_1(jabber_plugin, |
497 "jabber-receiving-presence", js->gc, type, from, packet)); | 495 "jabber-receiving-presence", js->gc, type, from, packet)); |
498 if (signal_return) | 496 if (signal_return) |
499 return; | 497 return; |
500 | 498 |
501 if(!(jid = jabber_id_new(from))) | 499 jid = jabber_id_new(from); |
502 return; | 500 if (jid == NULL) { |
501 purple_debug_error("jabber", "Ignoring presence with malformed 'from' " | |
502 "JID: %s\n", from); | |
503 return; | |
504 } | |
503 | 505 |
504 if(jb->error_msg) { | 506 if(jb->error_msg) { |
505 g_free(jb->error_msg); | 507 g_free(jb->error_msg); |
506 jb->error_msg = NULL; | 508 jb->error_msg = NULL; |
507 } | 509 } |
508 | 510 |
509 if(type && !strcmp(type, "error")) { | 511 if (type == NULL) { |
512 xmlnode *show; | |
513 char *show_data = NULL; | |
514 | |
515 state = JABBER_BUDDY_STATE_ONLINE; | |
516 | |
517 show = xmlnode_get_child(packet, "show"); | |
518 if (show) { | |
519 show_data = xmlnode_get_data(show); | |
520 if (show_data) { | |
521 state = jabber_buddy_show_get_state(show_data); | |
522 g_free(show_data); | |
523 } else | |
524 purple_debug_warning("jabber", "<show/> present on presence, " | |
525 "but no contents!\n"); | |
526 } | |
527 } else if (g_str_equal(type, "error")) { | |
510 char *msg = jabber_parse_error(js, packet, NULL); | 528 char *msg = jabber_parse_error(js, packet, NULL); |
511 | 529 |
512 state = JABBER_BUDDY_STATE_ERROR; | 530 state = JABBER_BUDDY_STATE_ERROR; |
513 jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); | 531 jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); |
514 } else if(type && !strcmp(type, "subscribe")) { | 532 } else if (g_str_equal(type, "subscribe")) { |
515 struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); | 533 struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); |
516 gboolean onlist = FALSE; | 534 gboolean onlist = FALSE; |
517 PurpleBuddy *buddy = purple_find_buddy(purple_connection_get_account(js->gc), from); | 535 PurpleAccount *account; |
536 PurpleBuddy *buddy; | |
518 JabberBuddy *jb = NULL; | 537 JabberBuddy *jb = NULL; |
519 xmlnode *nick; | 538 xmlnode *nick; |
520 | 539 |
540 account = purple_connection_get_account(js->gc); | |
541 buddy = purple_find_buddy(account, from); | |
521 nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick"); | 542 nick = xmlnode_get_child_with_namespace(packet, "nick", "http://jabber.org/protocol/nick"); |
522 if (nick) | 543 if (nick) |
523 nickname = xmlnode_get_data(nick); | 544 nickname = xmlnode_get_data(nick); |
524 | 545 |
525 if (buddy) { | 546 if (buddy) { |
530 | 551 |
531 jap->gc = js->gc; | 552 jap->gc = js->gc; |
532 jap->who = g_strdup(from); | 553 jap->who = g_strdup(from); |
533 jap->js = js; | 554 jap->js = js; |
534 | 555 |
535 purple_account_request_authorization(purple_connection_get_account(js->gc), from, NULL, nickname, NULL, onlist, | 556 purple_account_request_authorization(account, from, NULL, nickname, |
536 authorize_add_cb, deny_add_cb, jap); | 557 NULL, onlist, authorize_add_cb, deny_add_cb, jap); |
558 | |
537 g_free(nickname); | 559 g_free(nickname); |
538 jabber_id_free(jid); | 560 jabber_id_free(jid); |
539 return; | 561 return; |
540 } else if(type && !strcmp(type, "subscribed")) { | 562 } else if (g_str_equal(type, "subscribed")) { |
541 /* we've been allowed to see their presence, but we don't care */ | 563 /* we've been allowed to see their presence, but we don't care */ |
542 jabber_id_free(jid); | 564 jabber_id_free(jid); |
543 return; | 565 return; |
544 } else if(type && !strcmp(type, "unsubscribe")) { | 566 } else if (g_str_equal(type, "unsubscribe")) { |
545 /* XXX I'm not sure this is the right way to handle this, it | 567 /* XXX I'm not sure this is the right way to handle this, it |
546 * might be better to add "unsubscribe" to the presence status | 568 * might be better to add "unsubscribe" to the presence status |
547 * if lower down, but I'm not sure. */ | 569 * if lower down, but I'm not sure. */ |
548 /* they are unsubscribing from our presence, we don't care */ | 570 /* they are unsubscribing from our presence, we don't care */ |
549 /* Well, maybe just a little, we might want/need to start | 571 /* Well, maybe just a little, we might want/need to start |
550 * acknowledging this (and the others) at some point. */ | 572 * acknowledging this (and the others) at some point. */ |
551 jabber_id_free(jid); | 573 jabber_id_free(jid); |
552 return; | 574 return; |
575 } else if (g_str_equal(type, "probe")) { | |
576 purple_debug_warning("jabber", "Ignoring presence probe\n"); | |
577 jabber_id_free(jid); | |
578 return; | |
579 } else if (g_str_equal(type, "unavailable")) { | |
580 state = JABBER_BUDDY_STATE_UNAVAILABLE; | |
581 } else if (g_str_equal(type, "unsubscribed")) { | |
582 state = JABBER_BUDDY_STATE_UNKNOWN; | |
553 } else { | 583 } else { |
554 if((y = xmlnode_get_child(packet, "show"))) { | 584 purple_debug_warning("jabber", "Ignoring presence with invalid type " |
555 char *show = xmlnode_get_data(y); | 585 "'%s'\n", type); |
556 state = jabber_buddy_show_get_state(show); | 586 jabber_id_free(jid); |
557 g_free(show); | 587 return; |
558 } else { | |
559 state = JABBER_BUDDY_STATE_ONLINE; | |
560 } | |
561 } | 588 } |
562 | 589 |
563 | 590 |
564 for(y = packet->child; y; y = y->next) { | 591 for(y = packet->child; y; y = y->next) { |
565 const char *xmlns; | 592 const char *xmlns; |
590 } else if(!strcmp(y->name, "x")) { | 617 } else if(!strcmp(y->name, "x")) { |
591 if(!strcmp(xmlns, "jabber:x:delay")) { | 618 if(!strcmp(xmlns, "jabber:x:delay")) { |
592 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ | 619 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ |
593 delayed = TRUE; | 620 delayed = TRUE; |
594 stamp = xmlnode_get_attrib(y, "stamp"); | 621 stamp = xmlnode_get_attrib(y, "stamp"); |
595 } else if(!strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { | 622 } else if(!strcmp(xmlns, "vcard-temp:x:update")) { |
596 xmlnode *z; | 623 xmlnode *photo = xmlnode_get_child(y, "photo"); |
597 | 624 if(photo) { |
598 muc = TRUE; | 625 g_free(avatar_hash); |
599 if((z = xmlnode_get_child(y, "status"))) { | 626 avatar_hash = xmlnode_get_data(photo); |
600 const char *code = xmlnode_get_attrib(z, "code"); | 627 } |
601 if(code && !strcmp(code, "201")) { | 628 } |
602 if((chat = jabber_chat_find(js, jid->node, jid->domain))) { | 629 } else if (!strcmp(y->name, "query") && |
630 !strcmp(xmlnode_get_namespace(y), "jabber:iq:last")) { | |
631 /* resource has specified idle */ | |
632 const gchar *seconds = xmlnode_get_attrib(y, "seconds"); | |
633 if (seconds) { | |
634 /* we may need to take "delayed" into account here */ | |
635 idle = atoi(seconds); | |
636 } | |
637 } | |
638 } | |
639 | |
640 if (idle && delayed && stamp) { | |
641 /* if we have a delayed presence, we need to add the delay to the idle | |
642 value */ | |
643 time_t offset = time(NULL) - purple_str_to_time(stamp, TRUE, NULL, NULL, | |
644 NULL); | |
645 purple_debug_info("jabber", "got delay %s yielding %ld s offset\n", | |
646 stamp, offset); | |
647 idle += offset; | |
648 } | |
649 | |
650 if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { | |
651 static int i = 1; | |
652 | |
653 if(state == JABBER_BUDDY_STATE_ERROR) { | |
654 char *title, *msg = jabber_parse_error(js, packet, NULL); | |
655 | |
656 if (!chat->conv) { | |
657 title = g_strdup_printf(_("Error joining chat %s"), from); | |
658 purple_serv_got_join_chat_failed(js->gc, chat->components); | |
659 } else { | |
660 title = g_strdup_printf(_("Error in chat %s"), from); | |
661 if (g_hash_table_size(chat->members) == 0) | |
662 serv_got_chat_left(js->gc, chat->id); | |
663 } | |
664 purple_notify_error(js->gc, title, title, msg); | |
665 g_free(title); | |
666 g_free(msg); | |
667 | |
668 if (g_hash_table_size(chat->members) == 0) | |
669 /* Only destroy the chat if the error happened while joining */ | |
670 jabber_chat_destroy(chat); | |
671 jabber_id_free(jid); | |
672 g_free(status); | |
673 g_free(avatar_hash); | |
674 g_free(nickname); | |
675 return; | |
676 } | |
677 | |
678 if (type == NULL) { | |
679 xmlnode *x; | |
680 const char *real_jid = NULL; | |
681 const char *affiliation = NULL; | |
682 const char *role = NULL; | |
683 | |
684 /* | |
685 * XEP-0045 mandates the presence to include a resource (which is | |
686 * treated as the chat nick). Some non-compliant servers allow | |
687 * joining without a nick. | |
688 */ | |
689 if (!jid->resource) { | |
690 jabber_id_free(jid); | |
691 g_free(avatar_hash); | |
692 g_free(nickname); | |
693 g_free(status); | |
694 return; | |
695 } | |
696 | |
697 x = xmlnode_get_child_with_namespace(packet, "x", | |
698 "http://jabber.org/protocol/muc#user"); | |
699 if (x) { | |
700 xmlnode *status_node; | |
701 xmlnode *item_node; | |
702 | |
703 status_node = xmlnode_get_child(x, "status"); | |
704 if (status_node) { | |
705 const char *code = xmlnode_get_attrib(status_node, "code"); | |
706 if (purple_strequal(code, "201")) { | |
707 if ((chat = jabber_chat_find(js, jid->node, jid->domain))) { | |
603 chat->config_dialog_type = PURPLE_REQUEST_ACTION; | 708 chat->config_dialog_type = PURPLE_REQUEST_ACTION; |
604 chat->config_dialog_handle = | 709 chat->config_dialog_handle = |
605 purple_request_action(js->gc, | 710 purple_request_action(js->gc, |
606 _("Create New Room"), | 711 _("Create New Room"), |
607 _("Create New Room"), | 712 _("Create New Room"), |
612 purple_connection_get_account(js->gc), NULL, chat->conv, | 717 purple_connection_get_account(js->gc), NULL, chat->conv, |
613 chat, 2, | 718 chat, 2, |
614 _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), | 719 _("_Configure Room"), G_CALLBACK(jabber_chat_request_room_configure), |
615 _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); | 720 _("_Accept Defaults"), G_CALLBACK(jabber_chat_create_instant_room)); |
616 } | 721 } |
617 } else if(code && !strcmp(code, "210")) { | 722 } else if (purple_strequal(code, "210")) { |
618 /* server rewrote room-nick */ | 723 /* server rewrote room-nick */ |
619 if((chat = jabber_chat_find(js, jid->node, jid->domain))) { | 724 if((chat = jabber_chat_find(js, jid->node, jid->domain))) { |
620 g_free(chat->handle); | 725 g_free(chat->handle); |
621 chat->handle = g_strdup(jid->resource); | 726 chat->handle = g_strdup(jid->resource); |
622 } | 727 } |
623 } | 728 } |
624 } | 729 } |
625 if((z = xmlnode_get_child(y, "item"))) { | 730 |
626 real_jid = xmlnode_get_attrib(z, "jid"); | 731 item_node = xmlnode_get_child(x, "item"); |
627 affiliation = xmlnode_get_attrib(z, "affiliation"); | 732 if (item_node) { |
628 role = xmlnode_get_attrib(z, "role"); | 733 real_jid = xmlnode_get_attrib(item_node, "jid"); |
629 if(affiliation != NULL && !strcmp(affiliation, "owner")) | 734 affiliation = xmlnode_get_attrib(item_node, "affiliation"); |
735 role = xmlnode_get_attrib(item_node, "role"); | |
736 | |
737 if (purple_strequal(affiliation, "owner")) | |
630 flags |= PURPLE_CBFLAGS_FOUNDER; | 738 flags |= PURPLE_CBFLAGS_FOUNDER; |
631 if (role != NULL) { | 739 if (role) { |
632 if (!strcmp(role, "moderator")) | 740 if (g_str_equal(role, "moderator")) |
633 flags |= PURPLE_CBFLAGS_OP; | 741 flags |= PURPLE_CBFLAGS_OP; |
634 else if (!strcmp(role, "participant")) | 742 else if (g_str_equal(role, "participant")) |
635 flags |= PURPLE_CBFLAGS_VOICE; | 743 flags |= PURPLE_CBFLAGS_VOICE; |
636 } | 744 } |
637 } | 745 } |
638 } else if(!strcmp(xmlns, "vcard-temp:x:update")) { | 746 } |
639 xmlnode *photo = xmlnode_get_child(y, "photo"); | 747 |
640 if(photo) { | 748 if(!chat->conv) { |
641 g_free(avatar_hash); | 749 char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); |
642 avatar_hash = xmlnode_get_data(photo); | 750 chat->id = i++; |
643 } | 751 chat->muc = (x != NULL); |
644 } | 752 chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); |
645 } else if (!strcmp(y->name, "query") && | 753 purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle); |
646 !strcmp(xmlnode_get_namespace(y), "jabber:iq:last")) { | 754 |
647 /* resource has specified idle */ | 755 jabber_chat_disco_traffic(chat); |
648 const gchar *seconds = xmlnode_get_attrib(y, "seconds"); | 756 g_free(room_jid); |
649 if (seconds) { | 757 } |
650 /* we may need to take "delayed" into account here */ | 758 |
651 idle = atoi(seconds); | 759 jabber_buddy_track_resource(jb, jid->resource, priority, state, |
652 } | 760 status); |
653 } | 761 |
654 } | 762 jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); |
655 | 763 |
656 if (idle && delayed && stamp) { | 764 if(!jabber_chat_find_buddy(chat->conv, jid->resource)) |
657 /* if we have a delayed presence, we need to add the delay to the idle | 765 purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, |
658 value */ | 766 real_jid, flags, !delayed); |
659 time_t offset = time(NULL) - purple_str_to_time(stamp, TRUE, NULL, NULL, | 767 else |
660 NULL); | 768 purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), jid->resource, |
661 purple_debug_info("jabber", "got delay %s yielding %ld s offset\n", | 769 flags); |
662 stamp, offset); | 770 } else if (g_str_equal(type, "unavailable")) { |
663 idle += offset; | |
664 } | |
665 | |
666 if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { | |
667 static int i = 1; | |
668 | |
669 if(state == JABBER_BUDDY_STATE_ERROR) { | |
670 char *title, *msg = jabber_parse_error(js, packet, NULL); | |
671 | |
672 if (!chat->conv) { | |
673 title = g_strdup_printf(_("Error joining chat %s"), from); | |
674 purple_serv_got_join_chat_failed(js->gc, chat->components); | |
675 } else { | |
676 title = g_strdup_printf(_("Error in chat %s"), from); | |
677 if (g_hash_table_size(chat->members) == 0) | |
678 serv_got_chat_left(js->gc, chat->id); | |
679 } | |
680 purple_notify_error(js->gc, title, title, msg); | |
681 g_free(title); | |
682 g_free(msg); | |
683 | |
684 if (g_hash_table_size(chat->members) == 0) | |
685 /* Only destroy the chat if the error happened while joining */ | |
686 jabber_chat_destroy(chat); | |
687 jabber_id_free(jid); | |
688 g_free(status); | |
689 g_free(avatar_hash); | |
690 g_free(nickname); | |
691 return; | |
692 } | |
693 | |
694 | |
695 if(type && !strcmp(type, "unavailable")) { | |
696 gboolean nick_change = FALSE; | 771 gboolean nick_change = FALSE; |
772 gboolean kick = FALSE; | |
773 gboolean is_our_resource = FALSE; /* Is the presence about us? */ | |
697 | 774 |
698 /* If the chat nick is invalid, we haven't yet joined, or we've | 775 /* If the chat nick is invalid, we haven't yet joined, or we've |
699 * already left (it was probably us leaving after we closed the | 776 * already left (it was probably us leaving after we closed the |
700 * chat), we don't care. | 777 * chat), we don't care. |
701 */ | 778 */ |
708 g_free(avatar_hash); | 785 g_free(avatar_hash); |
709 g_free(nickname); | 786 g_free(nickname); |
710 return; | 787 return; |
711 } | 788 } |
712 | 789 |
790 is_our_resource = (0 == g_utf8_collate(jid->resource, chat->handle)); | |
791 | |
713 jabber_buddy_remove_resource(jb, jid->resource); | 792 jabber_buddy_remove_resource(jb, jid->resource); |
714 if(chat->muc) { | 793 if(chat->muc) { |
715 xmlnode *x; | 794 xmlnode *x; |
716 for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) { | 795 for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) { |
717 const char *xmlns, *nick, *code; | 796 const char *xmlns, *nick, *code; |
721 continue; | 800 continue; |
722 if(!(stat = xmlnode_get_child(x, "status"))) | 801 if(!(stat = xmlnode_get_child(x, "status"))) |
723 continue; | 802 continue; |
724 if(!(code = xmlnode_get_attrib(stat, "code"))) | 803 if(!(code = xmlnode_get_attrib(stat, "code"))) |
725 continue; | 804 continue; |
805 | |
806 item = xmlnode_get_child(x, "item"); | |
807 | |
726 if(!strcmp(code, "301")) { | 808 if(!strcmp(code, "301")) { |
727 /* XXX: we got banned */ | 809 /* XXX: we got banned */ |
728 } else if(!strcmp(code, "303")) { | 810 } else if(!strcmp(code, "303")) { |
729 if(!(item = xmlnode_get_child(x, "item"))) | 811 if (!item) |
730 continue; | 812 continue; |
731 if(!(nick = xmlnode_get_attrib(item, "nick"))) | 813 if(!(nick = xmlnode_get_attrib(item, "nick"))) |
732 continue; | 814 continue; |
733 nick_change = TRUE; | 815 nick_change = TRUE; |
734 if(!strcmp(jid->resource, chat->handle)) { | 816 if(!strcmp(jid->resource, chat->handle)) { |
737 } | 819 } |
738 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, nick); | 820 purple_conv_chat_rename_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, nick); |
739 jabber_chat_remove_handle(chat, jid->resource); | 821 jabber_chat_remove_handle(chat, jid->resource); |
740 break; | 822 break; |
741 } else if(!strcmp(code, "307")) { | 823 } else if(!strcmp(code, "307")) { |
742 /* XXX: we got kicked */ | 824 /* Someone was kicked from the room */ |
825 xmlnode *reason = NULL, *actor = NULL; | |
826 const char *actor_name = NULL; | |
827 char *reason_text = NULL; | |
828 char *tmp; | |
829 | |
830 kick = TRUE; | |
831 | |
832 if (item) { | |
833 reason = xmlnode_get_child(item, "reason"); | |
834 actor = xmlnode_get_child(item, "actor"); | |
835 | |
836 if (reason != NULL) | |
837 reason_text = xmlnode_get_data(reason); | |
838 if (actor != NULL) | |
839 actor_name = xmlnode_get_attrib(actor, "jid"); | |
840 } | |
841 | |
842 if (reason_text == NULL) | |
843 reason_text = g_strdup(_("No reason")); | |
844 | |
845 if (is_our_resource) { | |
846 if (actor_name != NULL) | |
847 tmp = g_strdup_printf(_("You have been kicked by %s: (%s)"), | |
848 actor_name, reason_text); | |
849 else | |
850 tmp = g_strdup_printf(_("You have been kicked: (%s)"), | |
851 reason_text); | |
852 } else { | |
853 if (actor_name != NULL) | |
854 tmp = g_strdup_printf(_("Kicked by %s (%s)"), | |
855 actor_name, reason_text); | |
856 else | |
857 tmp = g_strdup_printf(_("Kicked (%s)"), | |
858 reason_text); | |
859 } | |
860 | |
861 g_free(reason_text); | |
862 g_free(status); | |
863 status = tmp; | |
743 } else if(!strcmp(code, "321")) { | 864 } else if(!strcmp(code, "321")) { |
744 /* XXX: removed due to an affiliation change */ | 865 /* XXX: removed due to an affiliation change */ |
745 } else if(!strcmp(code, "322")) { | 866 } else if(!strcmp(code, "322")) { |
746 /* XXX: removed because room is now members-only */ | 867 /* XXX: removed because room is now members-only */ |
747 } else if(!strcmp(code, "332")) { | 868 } else if(!strcmp(code, "332")) { |
748 /* XXX: removed due to system shutdown */ | 869 /* XXX: removed due to system shutdown */ |
749 } | 870 } |
750 } | 871 } |
751 } | 872 } |
752 if(!nick_change) { | 873 if(!nick_change) { |
753 if(!g_utf8_collate(jid->resource, chat->handle)) { | 874 if (is_our_resource) { |
875 if (kick) | |
876 purple_conv_chat_write(PURPLE_CONV_CHAT(chat->conv), jid->resource, | |
877 status, PURPLE_MESSAGE_SYSTEM, time(NULL)); | |
878 | |
754 serv_got_chat_left(js->gc, chat->id); | 879 serv_got_chat_left(js->gc, chat->id); |
755 jabber_chat_destroy(chat); | 880 jabber_chat_destroy(chat); |
756 } else { | 881 } else { |
757 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, | 882 purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, |
758 status); | 883 status); |
759 jabber_chat_remove_handle(chat, jid->resource); | 884 jabber_chat_remove_handle(chat, jid->resource); |
760 } | 885 } |
761 } | 886 } |
762 } else { | 887 } else { |
763 /* | 888 /* A type that isn't available or unavailable */ |
764 * XEP-0045 mandates the presence to include a resource (which is | 889 purple_debug_error("jabber", "MUC presence with bad type: %s\n", |
765 * treated as the chat nick). Some non-compliant servers allow | 890 type); |
766 * joining without a nick. | 891 |
767 */ | 892 jabber_id_free(jid); |
768 if (!jid->resource) { | 893 g_free(avatar_hash); |
769 jabber_id_free(jid); | 894 g_free(status); |
770 g_free(avatar_hash); | 895 g_free(nickname); |
771 g_free(nickname); | 896 g_return_if_reached(); |
772 g_free(status); | |
773 return; | |
774 } | |
775 | |
776 if(!chat->conv) { | |
777 char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); | |
778 chat->id = i++; | |
779 chat->muc = muc; | |
780 chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); | |
781 purple_conv_chat_set_nick(PURPLE_CONV_CHAT(chat->conv), chat->handle); | |
782 | |
783 jabber_chat_disco_traffic(chat); | |
784 g_free(room_jid); | |
785 } | |
786 | |
787 jabber_buddy_track_resource(jb, jid->resource, priority, state, | |
788 status); | |
789 | |
790 jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); | |
791 | |
792 if(!jabber_chat_find_buddy(chat->conv, jid->resource)) | |
793 purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat->conv), jid->resource, | |
794 real_jid, flags, !delayed); | |
795 else | |
796 purple_conv_chat_user_set_flags(PURPLE_CONV_CHAT(chat->conv), jid->resource, | |
797 flags); | |
798 } | 897 } |
799 } else { | 898 } else { |
800 buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", | 899 buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", |
801 jid->node ? "@" : "", jid->domain); | 900 jid->node ? "@" : "", jid->domain); |
802 if((b = purple_find_buddy(js->gc->account, buddy_name)) == NULL) { | 901 if((b = purple_find_buddy(js->gc->account, buddy_name)) == NULL) { |
839 } | 938 } |
840 } | 939 } |
841 } | 940 } |
842 | 941 |
843 if(state == JABBER_BUDDY_STATE_ERROR || | 942 if(state == JABBER_BUDDY_STATE_ERROR || |
844 (type && (!strcmp(type, "unavailable") || | 943 (type && (g_str_equal(type, "unavailable") || |
845 !strcmp(type, "unsubscribed")))) { | 944 g_str_equal(type, "unsubscribed")))) { |
846 PurpleConversation *conv; | 945 PurpleConversation *conv; |
847 | 946 |
848 jabber_buddy_remove_resource(jb, jid->resource); | 947 jabber_buddy_remove_resource(jb, jid->resource); |
849 if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) | 948 if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) |
850 purple_conversation_set_name(conv, buddy_name); | 949 purple_conversation_set_name(conv, buddy_name); |
869 purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); | 968 purple_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); |
870 } | 969 } |
871 g_free(buddy_name); | 970 g_free(buddy_name); |
872 } | 971 } |
873 | 972 |
874 if (caps && (!type || g_str_equal(type, "available"))) { | 973 if (caps && !type) { |
875 /* handle Entity Capabilities (XEP-0115) */ | 974 /* handle Entity Capabilities (XEP-0115) */ |
876 const char *node = xmlnode_get_attrib(caps, "node"); | 975 const char *node = xmlnode_get_attrib(caps, "node"); |
877 const char *ver = xmlnode_get_attrib(caps, "ver"); | 976 const char *ver = xmlnode_get_attrib(caps, "ver"); |
878 const char *hash = xmlnode_get_attrib(caps, "hash"); | 977 const char *hash = xmlnode_get_attrib(caps, "hash"); |
879 const char *ext = xmlnode_get_attrib(caps, "ext"); | 978 const char *ext = xmlnode_get_attrib(caps, "ext"); |