libpurple/protocols/jabber/jabber.c

branch
soc.2007.xmpp
changeset 19895
158490a51f8b
parent 19341
2a00e275b66b
parent 19894
b273d0db2bdd
child 19897
8b5abbdebc87
equal deleted inserted replaced
19831:0853a065e5c3 19895:158490a51f8b
8 * the Free Software Foundation; either version 2 of the License, or 8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version. 9 * (at your option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * 19 *
20 */ 20 */
21 #include "internal.h" 21 #include "internal.h"
22 22
23 #include "account.h" 23 #include "account.h"
49 #include "message.h" 49 #include "message.h"
50 #include "parser.h" 50 #include "parser.h"
51 #include "presence.h" 51 #include "presence.h"
52 #include "jabber.h" 52 #include "jabber.h"
53 #include "roster.h" 53 #include "roster.h"
54 #include "ping.h"
54 #include "si.h" 55 #include "si.h"
55 #include "xdata.h" 56 #include "xdata.h"
56 57 #include "pep.h"
57 #define JABBER_CONNECT_STEPS (js->gsc ? 8 : 5) 58 #include "adhoccommands.h"
59
60 #include <assert.h>
61
62 #define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5)
58 63
59 static PurplePlugin *my_protocol = NULL; 64 static PurplePlugin *my_protocol = NULL;
65 GList *jabber_features;
66
67 static void jabber_unregister_account_cb(JabberStream *js);
60 68
61 static void jabber_stream_init(JabberStream *js) 69 static void jabber_stream_init(JabberStream *js)
62 { 70 {
63 char *open_stream; 71 char *open_stream;
64 72
65 open_stream = g_strdup_printf("<stream:stream to='%s' " 73 open_stream = g_strdup_printf("<stream:stream to='%s' "
66 "xmlns='jabber:client' " 74 "xmlns='jabber:client' "
67 "xmlns:stream='http://etherx.jabber.org/streams' " 75 "xmlns:stream='http://etherx.jabber.org/streams' "
68 "version='1.0'>", 76 "version='1.0'>",
69 js->user->domain); 77 js->user->domain);
70 /* setup the parser fresh for each stream */ 78 /* setup the parser fresh for each stream */
71 jabber_parser_setup(js); 79 jabber_parser_setup(js);
78 jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data) 86 jabber_session_initialized_cb(JabberStream *js, xmlnode *packet, gpointer data)
79 { 87 {
80 const char *type = xmlnode_get_attrib(packet, "type"); 88 const char *type = xmlnode_get_attrib(packet, "type");
81 if(type && !strcmp(type, "result")) { 89 if(type && !strcmp(type, "result")) {
82 jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); 90 jabber_stream_set_state(js, JABBER_STREAM_CONNECTED);
91 if(js->unregistration)
92 jabber_unregister_account_cb(js);
83 } else { 93 } else {
84 purple_connection_error(js->gc, _("Error initializing session")); 94 purple_connection_error(js->gc, _("Error initializing session"));
85 } 95 }
86 } 96 }
87 97
130 static void jabber_stream_features_parse(JabberStream *js, xmlnode *packet) 140 static void jabber_stream_features_parse(JabberStream *js, xmlnode *packet)
131 { 141 {
132 if(xmlnode_get_child(packet, "starttls")) { 142 if(xmlnode_get_child(packet, "starttls")) {
133 if(jabber_process_starttls(js, packet)) 143 if(jabber_process_starttls(js, packet))
134 return; 144 return;
145 } else if(purple_account_get_bool(js->gc->account, "require_tls", FALSE) && !js->gsc) {
146 purple_connection_error(js->gc, _("You require encryption, but it is not available on this server."));
147 return;
135 } 148 }
136 149
137 if(js->registration) { 150 if(js->registration) {
138 jabber_register_start(js); 151 jabber_register_start(js);
139 } else if(xmlnode_get_child(packet, "mechanisms")) { 152 } else if(xmlnode_get_child(packet, "mechanisms")) {
167 g_free(msg); 180 g_free(msg);
168 } 181 }
169 182
170 static void tls_init(JabberStream *js); 183 static void tls_init(JabberStream *js);
171 184
172 void jabber_process_packet(JabberStream *js, xmlnode *packet) 185 void jabber_process_packet(JabberStream *js, xmlnode **packet)
173 { 186 {
174 const char *xmlns; 187 const char *xmlns;
175 188
176 purple_signal_emit(my_protocol, "jabber-receiving-xmlnode", js->gc, &packet); 189 purple_signal_emit(my_protocol, "jabber-receiving-xmlnode", js->gc, packet);
177 190
178 /* if the signal leaves us with a null packet, we're done */ 191 /* if the signal leaves us with a null packet, we're done */
179 if(NULL == packet) 192 if(NULL == *packet)
180 return; 193 return;
181 194
182 xmlns = xmlnode_get_namespace(packet); 195 xmlns = xmlnode_get_namespace(*packet);
183 196
184 if(!strcmp(packet->name, "iq")) { 197 if(!strcmp((*packet)->name, "iq")) {
185 jabber_iq_parse(js, packet); 198 jabber_iq_parse(js, *packet);
186 } else if(!strcmp(packet->name, "presence")) { 199 } else if(!strcmp((*packet)->name, "presence")) {
187 jabber_presence_parse(js, packet); 200 jabber_presence_parse(js, *packet);
188 } else if(!strcmp(packet->name, "message")) { 201 } else if(!strcmp((*packet)->name, "message")) {
189 jabber_message_parse(js, packet); 202 jabber_message_parse(js, *packet);
190 } else if(!strcmp(packet->name, "stream:features")) { 203 } else if(!strcmp((*packet)->name, "stream:features")) {
191 jabber_stream_features_parse(js, packet); 204 jabber_stream_features_parse(js, *packet);
192 } else if (!strcmp(packet->name, "features") && 205 } else if (!strcmp((*packet)->name, "features") &&
193 !strcmp(xmlns, "http://etherx.jabber.org/streams")) { 206 !strcmp(xmlns, "http://etherx.jabber.org/streams")) {
194 jabber_stream_features_parse(js, packet); 207 jabber_stream_features_parse(js, *packet);
195 } else if(!strcmp(packet->name, "stream:error") || 208 } else if(!strcmp((*packet)->name, "stream:error") ||
196 (!strcmp(packet->name, "error") && 209 (!strcmp((*packet)->name, "error") &&
197 !strcmp(xmlns, "http://etherx.jabber.org/streams"))) 210 !strcmp(xmlns, "http://etherx.jabber.org/streams")))
198 { 211 {
199 jabber_stream_handle_error(js, packet); 212 jabber_stream_handle_error(js, *packet);
200 } else if(!strcmp(packet->name, "challenge")) { 213 } else if(!strcmp((*packet)->name, "challenge")) {
201 if(js->state == JABBER_STREAM_AUTHENTICATING) 214 if(js->state == JABBER_STREAM_AUTHENTICATING)
202 jabber_auth_handle_challenge(js, packet); 215 jabber_auth_handle_challenge(js, *packet);
203 } else if(!strcmp(packet->name, "success")) { 216 } else if(!strcmp((*packet)->name, "success")) {
204 if(js->state == JABBER_STREAM_AUTHENTICATING) 217 if(js->state == JABBER_STREAM_AUTHENTICATING)
205 jabber_auth_handle_success(js, packet); 218 jabber_auth_handle_success(js, *packet);
206 } else if(!strcmp(packet->name, "failure")) { 219 } else if(!strcmp((*packet)->name, "failure")) {
207 if(js->state == JABBER_STREAM_AUTHENTICATING) 220 if(js->state == JABBER_STREAM_AUTHENTICATING)
208 jabber_auth_handle_failure(js, packet); 221 jabber_auth_handle_failure(js, *packet);
209 } else if(!strcmp(packet->name, "proceed")) { 222 } else if(!strcmp((*packet)->name, "proceed")) {
210 if(js->state == JABBER_STREAM_AUTHENTICATING && !js->gsc) 223 if(js->state == JABBER_STREAM_AUTHENTICATING && !js->gsc)
211 tls_init(js); 224 tls_init(js);
212 } else { 225 } else {
213 purple_debug(PURPLE_DEBUG_WARNING, "jabber", "Unknown packet: %s\n", 226 purple_debug(PURPLE_DEBUG_WARNING, "jabber", "Unknown packet: %s\n",
214 packet->name); 227 (*packet)->name);
215 } 228 }
216 } 229 }
217 230
218 static int jabber_do_send(JabberStream *js, const char *data, int len) 231 static int jabber_do_send(JabberStream *js, const char *data, int len)
219 { 232 {
446 purple_ssl_close(gsc); 459 purple_ssl_close(gsc);
447 return; 460 return;
448 } 461 }
449 462
450 js = gc->proto_data; 463 js = gc->proto_data;
451 464
452 if(js->state == JABBER_STREAM_CONNECTING) 465 if(js->state == JABBER_STREAM_CONNECTING)
453 jabber_send_raw(js, "<?xml version='1.0' ?>", -1); 466 jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
454 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING); 467 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
455 purple_ssl_input_add(gsc, jabber_recv_cb_ssl, gc); 468 purple_ssl_input_add(gsc, jabber_recv_cb_ssl, gc);
469
470 /* Tell the app that we're doing encryption */
471 jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING_ENCRYPTION);
456 } 472 }
457 473
458 474
459 static void 475 static void
460 jabber_login_callback(gpointer data, gint source, const gchar *error) 476 jabber_login_callback(gpointer data, gint source, const gchar *error)
552 js->chats = g_hash_table_new_full(g_str_hash, g_str_equal, 568 js->chats = g_hash_table_new_full(g_str_hash, g_str_equal,
553 g_free, (GDestroyNotify)jabber_chat_free); 569 g_free, (GDestroyNotify)jabber_chat_free);
554 js->user = jabber_id_new(purple_account_get_username(account)); 570 js->user = jabber_id_new(purple_account_get_username(account));
555 js->next_id = g_random_int(); 571 js->next_id = g_random_int();
556 js->write_buffer = purple_circ_buffer_new(512); 572 js->write_buffer = purple_circ_buffer_new(512);
573 js->old_length = -1;
557 574
558 if(!js->user) { 575 if(!js->user) {
559 purple_connection_error(gc, _("Invalid XMPP ID")); 576 purple_connection_error(gc, _("Invalid XMPP ID"));
560 return; 577 return;
561 } 578 }
611 static gboolean 628 static gboolean
612 conn_close_cb(gpointer data) 629 conn_close_cb(gpointer data)
613 { 630 {
614 JabberStream *js = data; 631 JabberStream *js = data;
615 PurpleAccount *account = purple_connection_get_account(js->gc); 632 PurpleAccount *account = purple_connection_get_account(js->gc);
633
634 jabber_parser_free(js);
616 635
617 purple_account_disconnect(account); 636 purple_account_disconnect(account);
618 637
619 return FALSE; 638 return FALSE;
620 } 639 }
626 } 645 }
627 646
628 static void 647 static void
629 jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data) 648 jabber_registration_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
630 { 649 {
650 PurpleAccount *account = purple_connection_get_account(js->gc);
631 const char *type = xmlnode_get_attrib(packet, "type"); 651 const char *type = xmlnode_get_attrib(packet, "type");
632 char *buf; 652 char *buf;
653 char *to = data;
633 654
634 if(!strcmp(type, "result")) { 655 if(!strcmp(type, "result")) {
635 buf = g_strdup_printf(_("Registration of %s@%s successful"), 656 if(js->registration) {
657 buf = g_strdup_printf(_("Registration of %s@%s successful"),
636 js->user->node, js->user->domain); 658 js->user->node, js->user->domain);
659 if(account->registration_cb)
660 (account->registration_cb)(account, TRUE, account->registration_cb_user_data);
661 }
662 else
663 buf = g_strdup_printf(_("Registration to %s successful"),
664 to);
637 purple_notify_info(NULL, _("Registration Successful"), 665 purple_notify_info(NULL, _("Registration Successful"),
638 _("Registration Successful"), buf); 666 _("Registration Successful"), buf);
639 g_free(buf); 667 g_free(buf);
640 } else { 668 } else {
641 char *msg = jabber_parse_error(js, packet); 669 char *msg = jabber_parse_error(js, packet);
644 msg = g_strdup(_("Unknown Error")); 672 msg = g_strdup(_("Unknown Error"));
645 673
646 purple_notify_error(NULL, _("Registration Failed"), 674 purple_notify_error(NULL, _("Registration Failed"),
647 _("Registration Failed"), msg); 675 _("Registration Failed"), msg);
648 g_free(msg); 676 g_free(msg);
649 } 677 if(account->registration_cb)
650 jabber_connection_schedule_close(js); 678 (account->registration_cb)(account, FALSE, account->registration_cb_user_data);
679 }
680 g_free(to);
681 if(js->registration)
682 jabber_connection_schedule_close(js);
651 } 683 }
652 684
653 static void 685 static void
654 jabber_register_cb(JabberStream *js, PurpleRequestFields *fields) 686 jabber_unregistration_result_cb(JabberStream *js, xmlnode *packet, gpointer data)
687 {
688 const char *type = xmlnode_get_attrib(packet, "type");
689 char *buf;
690 char *to = data;
691
692 if(!strcmp(type, "result")) {
693 buf = g_strdup_printf(_("Registration from %s successfully removed"),
694 to);
695 purple_notify_info(NULL, _("Unregistration Successful"),
696 _("Unregistration Successful"), buf);
697 g_free(buf);
698 } else {
699 char *msg = jabber_parse_error(js, packet);
700
701 if(!msg)
702 msg = g_strdup(_("Unknown Error"));
703
704 purple_notify_error(NULL, _("Unregistration Failed"),
705 _("Unregistration Failed"), msg);
706 g_free(msg);
707 }
708 g_free(to);
709 }
710
711 typedef struct _JabberRegisterCBData {
712 JabberStream *js;
713 char *who;
714 } JabberRegisterCBData;
715
716 static void
717 jabber_register_cb(JabberRegisterCBData *cbdata, PurpleRequestFields *fields)
655 { 718 {
656 GList *groups, *flds; 719 GList *groups, *flds;
657 xmlnode *query, *y; 720 xmlnode *query, *y;
658 JabberIq *iq; 721 JabberIq *iq;
659 char *username; 722 char *username;
660 723
661 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); 724 iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register");
662 query = xmlnode_get_child(iq->node, "query"); 725 query = xmlnode_get_child(iq->node, "query");
726 xmlnode_set_attrib(iq->node,"to",cbdata->who);
663 727
664 for(groups = purple_request_fields_get_groups(fields); groups; 728 for(groups = purple_request_fields_get_groups(fields); groups;
665 groups = groups->next) { 729 groups = groups->next) {
666 for(flds = purple_request_field_group_get_fields(groups->data); 730 for(flds = purple_request_field_group_get_fields(groups->data);
667 flds; flds = flds->next) { 731 flds; flds = flds->next) {
668 PurpleRequestField *field = flds->data; 732 PurpleRequestField *field = flds->data;
669 const char *id = purple_request_field_get_id(field); 733 const char *id = purple_request_field_get_id(field);
670 const char *value = purple_request_field_string_get_value(field); 734 if(!strcmp(id,"unregister")) {
671 735 gboolean value = purple_request_field_bool_get_value(field);
672 if(!strcmp(id, "username")) { 736 if(value) {
673 y = xmlnode_new_child(query, "username"); 737 /* unregister from service. this doesn't include any of the fields, so remove them from the stanza by recreating it
674 } else if(!strcmp(id, "password")) { 738 (there's no "remove child" function for xmlnode) */
675 y = xmlnode_new_child(query, "password"); 739 jabber_iq_free(iq);
676 } else if(!strcmp(id, "name")) { 740 iq = jabber_iq_new_query(cbdata->js, JABBER_IQ_SET, "jabber:iq:register");
677 y = xmlnode_new_child(query, "name"); 741 query = xmlnode_get_child(iq->node, "query");
678 } else if(!strcmp(id, "email")) { 742 xmlnode_set_attrib(iq->node,"to",cbdata->who);
679 y = xmlnode_new_child(query, "email"); 743 xmlnode_new_child(query, "remove");
680 } else if(!strcmp(id, "nick")) { 744
681 y = xmlnode_new_child(query, "nick"); 745 jabber_iq_set_callback(iq, jabber_unregistration_result_cb, cbdata->who);
682 } else if(!strcmp(id, "first")) { 746
683 y = xmlnode_new_child(query, "first"); 747 jabber_iq_send(iq);
684 } else if(!strcmp(id, "last")) { 748 g_free(cbdata);
685 y = xmlnode_new_child(query, "last"); 749 return;
686 } else if(!strcmp(id, "address")) { 750 }
687 y = xmlnode_new_child(query, "address");
688 } else if(!strcmp(id, "city")) {
689 y = xmlnode_new_child(query, "city");
690 } else if(!strcmp(id, "state")) {
691 y = xmlnode_new_child(query, "state");
692 } else if(!strcmp(id, "zip")) {
693 y = xmlnode_new_child(query, "zip");
694 } else if(!strcmp(id, "phone")) {
695 y = xmlnode_new_child(query, "phone");
696 } else if(!strcmp(id, "url")) {
697 y = xmlnode_new_child(query, "url");
698 } else if(!strcmp(id, "date")) {
699 y = xmlnode_new_child(query, "date");
700 } else { 751 } else {
701 continue; 752 const char *value = purple_request_field_string_get_value(field);
753
754 if(!strcmp(id, "username")) {
755 y = xmlnode_new_child(query, "username");
756 } else if(!strcmp(id, "password")) {
757 y = xmlnode_new_child(query, "password");
758 } else if(!strcmp(id, "name")) {
759 y = xmlnode_new_child(query, "name");
760 } else if(!strcmp(id, "email")) {
761 y = xmlnode_new_child(query, "email");
762 } else if(!strcmp(id, "nick")) {
763 y = xmlnode_new_child(query, "nick");
764 } else if(!strcmp(id, "first")) {
765 y = xmlnode_new_child(query, "first");
766 } else if(!strcmp(id, "last")) {
767 y = xmlnode_new_child(query, "last");
768 } else if(!strcmp(id, "address")) {
769 y = xmlnode_new_child(query, "address");
770 } else if(!strcmp(id, "city")) {
771 y = xmlnode_new_child(query, "city");
772 } else if(!strcmp(id, "state")) {
773 y = xmlnode_new_child(query, "state");
774 } else if(!strcmp(id, "zip")) {
775 y = xmlnode_new_child(query, "zip");
776 } else if(!strcmp(id, "phone")) {
777 y = xmlnode_new_child(query, "phone");
778 } else if(!strcmp(id, "url")) {
779 y = xmlnode_new_child(query, "url");
780 } else if(!strcmp(id, "date")) {
781 y = xmlnode_new_child(query, "date");
782 } else {
783 continue;
784 }
785 xmlnode_insert_data(y, value, -1);
786 if(cbdata->js->registration && !strcmp(id, "username")) {
787 if(cbdata->js->user->node)
788 g_free(cbdata->js->user->node);
789 cbdata->js->user->node = g_strdup(value);
790 }
791 if(cbdata->js->registration && !strcmp(id, "password"))
792 purple_account_set_password(cbdata->js->gc->account, value);
702 } 793 }
703 xmlnode_insert_data(y, value, -1); 794 }
704 if(!strcmp(id, "username")) { 795 }
705 if(js->user->node) 796
706 g_free(js->user->node); 797 if(cbdata->js->registration) {
707 js->user->node = g_strdup(value); 798 username = g_strdup_printf("%s@%s/%s", cbdata->js->user->node, cbdata->js->user->domain,
708 } 799 cbdata->js->user->resource);
709 } 800 purple_account_set_username(cbdata->js->gc->account, username);
710 } 801 g_free(username);
711 802 }
712 username = g_strdup_printf("%s@%s/%s", js->user->node, js->user->domain, 803
713 js->user->resource); 804 jabber_iq_set_callback(iq, jabber_registration_result_cb, cbdata->who);
714 purple_account_set_username(js->gc->account, username);
715 g_free(username);
716
717 jabber_iq_set_callback(iq, jabber_registration_result_cb, NULL);
718 805
719 jabber_iq_send(iq); 806 jabber_iq_send(iq);
720 807 g_free(cbdata);
721 } 808 }
722 809
723 static void 810 static void
724 jabber_register_cancel_cb(JabberStream *js, PurpleRequestFields *fields) 811 jabber_register_cancel_cb(JabberRegisterCBData *cbdata, PurpleRequestFields *fields)
725 { 812 {
726 jabber_connection_schedule_close(js); 813 PurpleAccount *account = purple_connection_get_account(cbdata->js->gc);
814 if(account && cbdata->js->registration) {
815 if(account->registration_cb)
816 (account->registration_cb)(account, FALSE, account->registration_cb_user_data);
817 jabber_connection_schedule_close(cbdata->js);
818 }
819 g_free(cbdata->who);
820 g_free(cbdata);
727 } 821 }
728 822
729 static void jabber_register_x_data_cb(JabberStream *js, xmlnode *result, gpointer data) 823 static void jabber_register_x_data_cb(JabberStream *js, xmlnode *result, gpointer data)
730 { 824 {
731 xmlnode *query; 825 xmlnode *query;
732 JabberIq *iq; 826 JabberIq *iq;
827 char *to = data;
733 828
734 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register"); 829 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register");
735 query = xmlnode_get_child(iq->node, "query"); 830 query = xmlnode_get_child(iq->node, "query");
831 xmlnode_set_attrib(iq->node,"to",to);
736 832
737 xmlnode_insert_child(query, result); 833 xmlnode_insert_child(query, result);
738 834
739 jabber_iq_set_callback(iq, jabber_registration_result_cb, NULL); 835 jabber_iq_set_callback(iq, jabber_registration_result_cb, to);
740 jabber_iq_send(iq); 836 jabber_iq_send(iq);
741 } 837 }
742 838
743 void jabber_register_parse(JabberStream *js, xmlnode *packet) 839 void jabber_register_parse(JabberStream *js, xmlnode *packet)
744 { 840 {
841 PurpleAccount *account = purple_connection_get_account(js->gc);
745 const char *type; 842 const char *type;
843 const char *from = xmlnode_get_attrib(packet, "from");
844 PurpleRequestFields *fields;
845 PurpleRequestFieldGroup *group;
846 PurpleRequestField *field;
847 xmlnode *query, *x, *y;
848 char *instructions;
849 JabberRegisterCBData *cbdata;
850 gboolean registered = FALSE;
851
746 if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result")) 852 if(!(type = xmlnode_get_attrib(packet, "type")) || strcmp(type, "result"))
747 return; 853 return;
748 854
749 if(js->registration) { 855 if(js->registration)
750 PurpleRequestFields *fields;
751 PurpleRequestFieldGroup *group;
752 PurpleRequestField *field;
753 xmlnode *query, *x, *y;
754 char *instructions;
755
756 /* get rid of the login thingy */ 856 /* get rid of the login thingy */
757 purple_connection_set_state(js->gc, PURPLE_CONNECTED); 857 purple_connection_set_state(js->gc, PURPLE_CONNECTED);
758 858
759 query = xmlnode_get_child(packet, "query"); 859 query = xmlnode_get_child(packet, "query");
760 860
761 if(xmlnode_get_child(query, "registered")) { 861 if(xmlnode_get_child(query, "registered")) {
862 registered = TRUE;
863
864 if(js->registration) {
762 purple_notify_error(NULL, _("Already Registered"), 865 purple_notify_error(NULL, _("Already Registered"),
763 _("Already Registered"), NULL); 866 _("Already Registered"), NULL);
867 if(account->registration_cb)
868 (account->registration_cb)(account, FALSE, account->registration_cb_user_data);
764 jabber_connection_schedule_close(js); 869 jabber_connection_schedule_close(js);
765 return; 870 return;
766 } 871 }
767 872 }
768 if((x = xmlnode_get_child_with_namespace(packet, "x", 873
769 "jabber:x:data"))) { 874 if((x = xmlnode_get_child_with_namespace(packet, "x",
770 jabber_x_data_request(js, x, jabber_register_x_data_cb, NULL); 875 "jabber:x:data"))) {
771 return; 876 jabber_x_data_request(js, x, jabber_register_x_data_cb, g_strdup(from));
772 } else if((x = xmlnode_get_child_with_namespace(packet, "x", 877 return;
773 "jabber:x:oob"))) { 878 } else if((x = xmlnode_get_child_with_namespace(packet, "x",
774 xmlnode *url; 879 "jabber:x:oob"))) {
775 880 xmlnode *url;
776 if((url = xmlnode_get_child(x, "url"))) { 881
777 char *href; 882 if((url = xmlnode_get_child(x, "url"))) {
778 if((href = xmlnode_get_data(url))) { 883 char *href;
779 purple_notify_uri(NULL, href); 884 if((href = xmlnode_get_data(url))) {
780 g_free(href); 885 purple_notify_uri(NULL, href);
886 g_free(href);
887 if(js->registration) {
781 js->gc->wants_to_die = TRUE; 888 js->gc->wants_to_die = TRUE;
889 if(account->registration_cb) /* succeeded, but we have no login info */
890 (account->registration_cb)(account, TRUE, account->registration_cb_user_data);
782 jabber_connection_schedule_close(js); 891 jabber_connection_schedule_close(js);
783 return;
784 } 892 }
893 return;
785 } 894 }
786 } 895 }
787 896 }
788 /* as a last resort, use the old jabber:iq:register syntax */ 897
789 898 /* as a last resort, use the old jabber:iq:register syntax */
790 fields = purple_request_fields_new(); 899
791 group = purple_request_field_group_new(NULL); 900 fields = purple_request_fields_new();
792 purple_request_fields_add_group(fields, group); 901 group = purple_request_field_group_new(NULL);
793 902 purple_request_fields_add_group(fields, group);
903
904 if(js->registration)
794 field = purple_request_field_string_new("username", _("Username"), 905 field = purple_request_field_string_new("username", _("Username"),
795 js->user->node, FALSE); 906 js->user->node, FALSE);
796 purple_request_field_group_add_field(group, field); 907 else
797 908 field = purple_request_field_string_new("username", _("Username"),
909 NULL, FALSE);
910
911 purple_request_field_group_add_field(group, field);
912
913 if(js->registration)
798 field = purple_request_field_string_new("password", _("Password"), 914 field = purple_request_field_string_new("password", _("Password"),
799 purple_connection_get_password(js->gc), FALSE); 915 purple_connection_get_password(js->gc), FALSE);
800 purple_request_field_string_set_masked(field, TRUE); 916 else
801 purple_request_field_group_add_field(group, field); 917 field = purple_request_field_string_new("password", _("Password"),
802 918 NULL, FALSE);
803 if(xmlnode_get_child(query, "name")) { 919
920 purple_request_field_string_set_masked(field, TRUE);
921 purple_request_field_group_add_field(group, field);
922
923 if(xmlnode_get_child(query, "name")) {
924 if(js->registration)
804 field = purple_request_field_string_new("name", _("Name"), 925 field = purple_request_field_string_new("name", _("Name"),
805 purple_account_get_alias(js->gc->account), FALSE); 926 purple_account_get_alias(js->gc->account), FALSE);
806 purple_request_field_group_add_field(group, field); 927 else
807 } 928 field = purple_request_field_string_new("name", _("Name"),
808 if(xmlnode_get_child(query, "email")) {
809 field = purple_request_field_string_new("email", _("E-mail"),
810 NULL, FALSE); 929 NULL, FALSE);
811 purple_request_field_group_add_field(group, field); 930 purple_request_field_group_add_field(group, field);
812 } 931 }
813 if(xmlnode_get_child(query, "nick")) { 932 if(xmlnode_get_child(query, "email")) {
814 field = purple_request_field_string_new("nick", _("Nickname"), 933 field = purple_request_field_string_new("email", _("E-mail"),
815 NULL, FALSE); 934 NULL, FALSE);
816 purple_request_field_group_add_field(group, field); 935 purple_request_field_group_add_field(group, field);
817 } 936 }
818 if(xmlnode_get_child(query, "first")) { 937 if(xmlnode_get_child(query, "nick")) {
819 field = purple_request_field_string_new("first", _("First name"), 938 field = purple_request_field_string_new("nick", _("Nickname"),
820 NULL, FALSE); 939 NULL, FALSE);
821 purple_request_field_group_add_field(group, field); 940 purple_request_field_group_add_field(group, field);
822 } 941 }
823 if(xmlnode_get_child(query, "last")) { 942 if(xmlnode_get_child(query, "first")) {
824 field = purple_request_field_string_new("last", _("Last name"), 943 field = purple_request_field_string_new("first", _("First name"),
825 NULL, FALSE); 944 NULL, FALSE);
826 purple_request_field_group_add_field(group, field); 945 purple_request_field_group_add_field(group, field);
827 } 946 }
828 if(xmlnode_get_child(query, "address")) { 947 if(xmlnode_get_child(query, "last")) {
829 field = purple_request_field_string_new("address", _("Address"), 948 field = purple_request_field_string_new("last", _("Last name"),
830 NULL, FALSE); 949 NULL, FALSE);
831 purple_request_field_group_add_field(group, field); 950 purple_request_field_group_add_field(group, field);
832 } 951 }
833 if(xmlnode_get_child(query, "city")) { 952 if(xmlnode_get_child(query, "address")) {
834 field = purple_request_field_string_new("city", _("City"), 953 field = purple_request_field_string_new("address", _("Address"),
835 NULL, FALSE); 954 NULL, FALSE);
836 purple_request_field_group_add_field(group, field); 955 purple_request_field_group_add_field(group, field);
837 } 956 }
838 if(xmlnode_get_child(query, "state")) { 957 if(xmlnode_get_child(query, "city")) {
839 field = purple_request_field_string_new("state", _("State"), 958 field = purple_request_field_string_new("city", _("City"),
840 NULL, FALSE); 959 NULL, FALSE);
841 purple_request_field_group_add_field(group, field); 960 purple_request_field_group_add_field(group, field);
842 } 961 }
843 if(xmlnode_get_child(query, "zip")) { 962 if(xmlnode_get_child(query, "state")) {
844 field = purple_request_field_string_new("zip", _("Postal code"), 963 field = purple_request_field_string_new("state", _("State"),
845 NULL, FALSE); 964 NULL, FALSE);
846 purple_request_field_group_add_field(group, field); 965 purple_request_field_group_add_field(group, field);
847 } 966 }
848 if(xmlnode_get_child(query, "phone")) { 967 if(xmlnode_get_child(query, "zip")) {
849 field = purple_request_field_string_new("phone", _("Phone"), 968 field = purple_request_field_string_new("zip", _("Postal code"),
850 NULL, FALSE); 969 NULL, FALSE);
851 purple_request_field_group_add_field(group, field); 970 purple_request_field_group_add_field(group, field);
852 } 971 }
853 if(xmlnode_get_child(query, "url")) { 972 if(xmlnode_get_child(query, "phone")) {
854 field = purple_request_field_string_new("url", _("URL"), 973 field = purple_request_field_string_new("phone", _("Phone"),
855 NULL, FALSE); 974 NULL, FALSE);
856 purple_request_field_group_add_field(group, field); 975 purple_request_field_group_add_field(group, field);
857 } 976 }
858 if(xmlnode_get_child(query, "date")) { 977 if(xmlnode_get_child(query, "url")) {
859 field = purple_request_field_string_new("date", _("Date"), 978 field = purple_request_field_string_new("url", _("URL"),
860 NULL, FALSE); 979 NULL, FALSE);
861 purple_request_field_group_add_field(group, field); 980 purple_request_field_group_add_field(group, field);
862 } 981 }
863 982 if(xmlnode_get_child(query, "date")) {
864 if((y = xmlnode_get_child(query, "instructions"))) 983 field = purple_request_field_string_new("date", _("Date"),
865 instructions = xmlnode_get_data(y); 984 NULL, FALSE);
866 else 985 purple_request_field_group_add_field(group, field);
867 instructions = g_strdup(_("Please fill out the information below " 986 }
868 "to register your new account.")); 987 if(registered) {
869 988 field = purple_request_field_bool_new("unregister", _("Unregister"), FALSE);
989 purple_request_field_group_add_field(group, field);
990 }
991
992 if((y = xmlnode_get_child(query, "instructions")))
993 instructions = xmlnode_get_data(y);
994 else if(registered)
995 instructions = g_strdup(_("Please fill out the information below "
996 "to change your account registration."));
997 else
998 instructions = g_strdup(_("Please fill out the information below "
999 "to register your new account."));
1000
1001 cbdata = g_new0(JabberRegisterCBData, 1);
1002 cbdata->js = js;
1003 cbdata->who = g_strdup(from);
1004
1005 if(js->registration)
870 purple_request_fields(js->gc, _("Register New XMPP Account"), 1006 purple_request_fields(js->gc, _("Register New XMPP Account"),
871 _("Register New XMPP Account"), instructions, fields, 1007 _("Register New XMPP Account"), instructions, fields,
872 _("Register"), G_CALLBACK(jabber_register_cb), 1008 _("Register"), G_CALLBACK(jabber_register_cb),
873 _("Cancel"), G_CALLBACK(jabber_register_cancel_cb), 1009 _("Cancel"), G_CALLBACK(jabber_register_cancel_cb),
874 purple_connection_get_account(js->gc), NULL, NULL, 1010 purple_connection_get_account(js->gc), NULL, NULL,
875 js); 1011 cbdata);
876 1012 else {
877 g_free(instructions); 1013 char *title = registered?g_strdup_printf(_("Change Account Registration at %s"), from)
878 } 1014 :g_strdup_printf(_("Register New Account at %s"), from);
1015 purple_request_fields(js->gc, title,
1016 title, instructions, fields,
1017 registered?_("Change Registration"):_("Register"), G_CALLBACK(jabber_register_cb),
1018 _("Cancel"), G_CALLBACK(jabber_register_cancel_cb),
1019 purple_connection_get_account(js->gc), NULL, NULL,
1020 cbdata);
1021 g_free(title);
1022 }
1023
1024 g_free(instructions);
879 } 1025 }
880 1026
881 void jabber_register_start(JabberStream *js) 1027 void jabber_register_start(JabberStream *js)
882 { 1028 {
883 JabberIq *iq; 1029 JabberIq *iq;
884 1030
885 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:register"); 1031 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:register");
1032 jabber_iq_send(iq);
1033 }
1034
1035 void jabber_register_gateway(JabberStream *js, const char *gateway) {
1036 JabberIq *iq;
1037
1038 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:register");
1039 xmlnode_set_attrib(iq->node, "to", gateway);
886 jabber_iq_send(iq); 1040 jabber_iq_send(iq);
887 } 1041 }
888 1042
889 void jabber_register_account(PurpleAccount *account) 1043 void jabber_register_account(PurpleAccount *account)
890 { 1044 {
902 g_free, g_free); 1056 g_free, g_free);
903 js->disco_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, 1057 js->disco_callbacks = g_hash_table_new_full(g_str_hash, g_str_equal,
904 g_free, g_free); 1058 g_free, g_free);
905 js->user = jabber_id_new(purple_account_get_username(account)); 1059 js->user = jabber_id_new(purple_account_get_username(account));
906 js->next_id = g_random_int(); 1060 js->next_id = g_random_int();
1061 js->old_length = -1;
907 1062
908 if(!js->user) { 1063 if(!js->user) {
909 purple_connection_error(gc, _("Invalid XMPP ID")); 1064 purple_connection_error(gc, _("Invalid XMPP ID"));
910 return; 1065 return;
911 } 1066 }
943 } 1098 }
944 1099
945 if(!js->gsc) { 1100 if(!js->gsc) {
946 if (connect_server[0]) { 1101 if (connect_server[0]) {
947 jabber_login_connect(js, js->user->domain, server, 1102 jabber_login_connect(js, js->user->domain, server,
948 purple_account_get_int(account, 1103 purple_account_get_int(account,
949 "port", 5222)); 1104 "port", 5222));
950 } else { 1105 } else {
951 js->srv_query_data = purple_srv_resolve("xmpp-client", 1106 js->srv_query_data = purple_srv_resolve("xmpp-client",
952 "tcp", 1107 "tcp",
953 js->user->domain, 1108 js->user->domain,
954 srv_resolved_cb, 1109 srv_resolved_cb,
955 js); 1110 js);
956 } 1111 }
957 } 1112 }
1113 }
1114
1115 static void jabber_unregister_account_iq_cb(JabberStream *js, xmlnode *packet, gpointer data) {
1116 PurpleAccount *account = purple_connection_get_account(js->gc);
1117 const char *type = xmlnode_get_attrib(packet,"type");
1118 if(!strcmp(type,"error")) {
1119 char *msg = jabber_parse_error(js, packet);
1120
1121 purple_notify_error(js->gc, _("Error unregistering account"),
1122 _("Error unregistering account"), msg);
1123 g_free(msg);
1124 if(js->unregistration_cb)
1125 js->unregistration_cb(account, FALSE, js->unregistration_user_data);
1126 } else if(!strcmp(type,"result")) {
1127 purple_notify_info(js->gc, _("Account successfully unregistered"),
1128 _("Account successfully unregistered"), NULL);
1129 if(js->unregistration_cb)
1130 js->unregistration_cb(account, TRUE, js->unregistration_user_data);
1131 }
1132 }
1133
1134 static void jabber_unregister_account_cb(JabberStream *js) {
1135 JabberIq *iq;
1136 xmlnode *query;
1137 assert(js->unregistration);
1138
1139 iq = jabber_iq_new_query(js,JABBER_IQ_SET,"jabber:iq:register");
1140 assert(iq);
1141 query = xmlnode_get_child_with_namespace(iq->node,"query","jabber:iq:register");
1142 assert(query);
1143 xmlnode_new_child(query,"remove");
1144
1145 xmlnode_set_attrib(iq->node,"to",js->user->domain);
1146 jabber_iq_set_callback(iq,jabber_unregister_account_iq_cb,NULL);
1147
1148 jabber_iq_send(iq);
1149 }
1150
1151 void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) {
1152 PurpleConnection *gc = purple_account_get_connection(account);
1153 JabberStream *js;
1154
1155 if(gc->state != PURPLE_CONNECTED) {
1156 if(gc->state != PURPLE_CONNECTING)
1157 jabber_login(account);
1158 js = gc->proto_data;
1159 js->unregistration = TRUE;
1160 js->unregistration_cb = cb;
1161 js->unregistration_user_data = user_data;
1162 return;
1163 }
1164
1165 js = gc->proto_data;
1166 assert(!js->unregistration); /* don't allow multiple calls */
1167 js->unregistration = TRUE;
1168 js->unregistration_cb = cb;
1169 js->unregistration_user_data = user_data;
1170
1171 jabber_unregister_account_cb(js);
958 } 1172 }
959 1173
960 void jabber_close(PurpleConnection *gc) 1174 void jabber_close(PurpleConnection *gc)
961 { 1175 {
962 JabberStream *js = gc->proto_data; 1176 JabberStream *js = gc->proto_data;
981 purple_input_remove(js->gc->inpa); 1195 purple_input_remove(js->gc->inpa);
982 close(js->fd); 1196 close(js->fd);
983 } 1197 }
984 1198
985 jabber_buddy_remove_all_pending_buddy_info_requests(js); 1199 jabber_buddy_remove_all_pending_buddy_info_requests(js);
1200
1201 jabber_parser_free(js);
986 1202
987 if(js->iq_callbacks) 1203 if(js->iq_callbacks)
988 g_hash_table_destroy(js->iq_callbacks); 1204 g_hash_table_destroy(js->iq_callbacks);
989 if(js->disco_callbacks) 1205 if(js->disco_callbacks)
990 g_hash_table_destroy(js->disco_callbacks); 1206 g_hash_table_destroy(js->disco_callbacks);
1017 if(js->sasl_cb) 1233 if(js->sasl_cb)
1018 g_free(js->sasl_cb); 1234 g_free(js->sasl_cb);
1019 #endif 1235 #endif
1020 if(js->serverFQDN) 1236 if(js->serverFQDN)
1021 g_free(js->serverFQDN); 1237 g_free(js->serverFQDN);
1238 while(js->commands) {
1239 JabberAdHocCommands *cmd = js->commands->data;
1240 g_free(cmd->jid);
1241 g_free(cmd->node);
1242 g_free(cmd->name);
1243 g_free(cmd);
1244 js->commands = g_list_delete_link(js->commands, js->commands);
1245 }
1022 g_free(js->server_name); 1246 g_free(js->server_name);
1023 g_free(js->gmail_last_time); 1247 g_free(js->gmail_last_time);
1024 g_free(js->gmail_last_tid); 1248 g_free(js->gmail_last_tid);
1249 if(js->old_msg)
1250 g_free(js->old_msg);
1251 if(js->old_avatarhash)
1252 g_free(js->old_avatarhash);
1253 if(js->old_artist)
1254 g_free(js->old_artist);
1255 if(js->old_title)
1256 g_free(js->old_title);
1257 if(js->old_source)
1258 g_free(js->old_source);
1259 if(js->old_uri)
1260 g_free(js->old_uri);
1261 if(js->old_track)
1262 g_free(js->old_track);
1263
1025 g_free(js); 1264 g_free(js);
1026 1265
1027 gc->proto_data = NULL; 1266 gc->proto_data = NULL;
1028 } 1267 }
1029 1268
1040 case JABBER_STREAM_INITIALIZING: 1279 case JABBER_STREAM_INITIALIZING:
1041 purple_connection_update_progress(js->gc, _("Initializing Stream"), 1280 purple_connection_update_progress(js->gc, _("Initializing Stream"),
1042 js->gsc ? 5 : 2, JABBER_CONNECT_STEPS); 1281 js->gsc ? 5 : 2, JABBER_CONNECT_STEPS);
1043 jabber_stream_init(js); 1282 jabber_stream_init(js);
1044 break; 1283 break;
1284 case JABBER_STREAM_INITIALIZING_ENCRYPTION:
1285 purple_connection_update_progress(js->gc, _("Initializing SSL/TLS"),
1286 6, JABBER_CONNECT_STEPS);
1287 break;
1045 case JABBER_STREAM_AUTHENTICATING: 1288 case JABBER_STREAM_AUTHENTICATING:
1046 purple_connection_update_progress(js->gc, _("Authenticating"), 1289 purple_connection_update_progress(js->gc, _("Authenticating"),
1047 js->gsc ? 6 : 3, JABBER_CONNECT_STEPS); 1290 js->gsc ? 7 : 3, JABBER_CONNECT_STEPS);
1048 if(js->protocol_version == JABBER_PROTO_0_9 && js->registration) { 1291 if(js->protocol_version == JABBER_PROTO_0_9 && js->registration) {
1049 jabber_register_start(js); 1292 jabber_register_start(js);
1050 } else if(js->auth_type == JABBER_AUTH_IQ_AUTH) { 1293 } else if(js->auth_type == JABBER_AUTH_IQ_AUTH) {
1051 jabber_auth_start_old(js); 1294 jabber_auth_start_old(js);
1052 } 1295 }
1053 break; 1296 break;
1054 case JABBER_STREAM_REINITIALIZING: 1297 case JABBER_STREAM_REINITIALIZING:
1055 purple_connection_update_progress(js->gc, _("Re-initializing Stream"), 1298 purple_connection_update_progress(js->gc, _("Re-initializing Stream"),
1056 (js->gsc ? 7 : 4), JABBER_CONNECT_STEPS); 1299 (js->gsc ? 8 : 4), JABBER_CONNECT_STEPS);
1057 1300
1058 /* The stream will be reinitialized later, in jabber_recv_cb_ssl() */ 1301 /* The stream will be reinitialized later, in jabber_recv_cb_ssl() */
1059 js->reinit = TRUE; 1302 js->reinit = TRUE;
1060 1303
1061 break; 1304 break;
1078 JabberStream *js = gc->proto_data; 1321 JabberStream *js = gc->proto_data;
1079 1322
1080 js->idle = idle ? time(NULL) - idle : idle; 1323 js->idle = idle ? time(NULL) - idle : idle;
1081 } 1324 }
1082 1325
1326 void jabber_add_feature(const char *shortname, const char *namespace, JabberFeatureEnabled cb) {
1327 JabberFeature *feat;
1328
1329 assert(shortname != NULL);
1330 assert(namespace != NULL);
1331
1332 feat = g_new0(JabberFeature,1);
1333 feat->shortname = g_strdup(shortname);
1334 feat->namespace = g_strdup(namespace);
1335 feat->is_enabled = cb;
1336
1337 /* try to remove just in case it already exists in the list */
1338 jabber_remove_feature(shortname);
1339
1340 jabber_features = g_list_append(jabber_features, feat);
1341 }
1342
1343 void jabber_remove_feature(const char *shortname) {
1344 GList *feature;
1345 for(feature = jabber_features; feature; feature = feature->next) {
1346 JabberFeature *feat = (JabberFeature*)feature->data;
1347 if(!strcmp(feat->shortname, shortname)) {
1348 g_free(feat->shortname);
1349 g_free(feat->namespace);
1350
1351 g_free(feature->data);
1352 feature = g_list_delete_link(feature, feature);
1353 break;
1354 }
1355 }
1356 }
1357
1083 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b) 1358 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b)
1084 { 1359 {
1085 return "jabber"; 1360 return "jabber";
1086 } 1361 }
1087 1362
1152 JabberBuddyResource *jbr = NULL; 1427 JabberBuddyResource *jbr = NULL;
1153 const char *sub; 1428 const char *sub;
1154 GList *l; 1429 GList *l;
1155 1430
1156 if (full) { 1431 if (full) {
1432 PurpleStatus *status;
1433 PurpleValue *value;
1434
1157 if(jb->subscription & JABBER_SUB_FROM) { 1435 if(jb->subscription & JABBER_SUB_FROM) {
1158 if(jb->subscription & JABBER_SUB_TO) 1436 if(jb->subscription & JABBER_SUB_TO)
1159 sub = _("Both"); 1437 sub = _("Both");
1160 else if(jb->subscription & JABBER_SUB_PENDING) 1438 else if(jb->subscription & JABBER_SUB_PENDING)
1161 sub = _("From (To pending)"); 1439 sub = _("From (To pending)");
1169 else 1447 else
1170 sub = _("None"); 1448 sub = _("None");
1171 } 1449 }
1172 1450
1173 purple_notify_user_info_add_pair(user_info, _("Subscription"), sub); 1451 purple_notify_user_info_add_pair(user_info, _("Subscription"), sub);
1452
1453 status = purple_presence_get_active_status(purple_buddy_get_presence(b));
1454 value = purple_status_get_attr_value(status, "mood");
1455 if(value && purple_value_get_type(value) == PURPLE_TYPE_STRING) {
1456 const char *mood = purple_value_get_string(value);
1457
1458 value = purple_status_get_attr_value(status, "moodtext");
1459 if(value && purple_value_get_type(value) == PURPLE_TYPE_STRING) {
1460 char *moodplustext = g_strdup_printf("%s (%s)",mood,purple_value_get_string(value));
1461
1462 purple_notify_user_info_add_pair(user_info, _("Mood"), moodplustext);
1463 g_free(moodplustext);
1464 } else
1465 purple_notify_user_info_add_pair(user_info, _("Mood"), mood);
1466 }
1174 } 1467 }
1175 1468
1176 for(l=jb->resources; l; l = l->next) { 1469 for(l=jb->resources; l; l = l->next) {
1177 char *text = NULL; 1470 char *text = NULL;
1178 char *res = NULL; 1471 char *res = NULL;
1231 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, 1524 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
1232 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE), 1525 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_ONLINE),
1233 NULL, TRUE, TRUE, FALSE, 1526 NULL, TRUE, TRUE, FALSE,
1234 "priority", _("Priority"), priority_value, 1527 "priority", _("Priority"), priority_value,
1235 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), 1528 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
1529 "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
1530 "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
1531 "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
1532 "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
1533 "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
1534 "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
1535 "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
1536 "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
1537 "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
1538 "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
1539 "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
1540 "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
1541 "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
1236 NULL); 1542 NULL);
1237 types = g_list_append(types, type); 1543 types = g_list_append(types, type);
1238 1544
1239 priority_value = purple_value_new(PURPLE_TYPE_INT); 1545 priority_value = purple_value_new(PURPLE_TYPE_INT);
1240 purple_value_set_int(priority_value, 1); 1546 purple_value_set_int(priority_value, 1);
1241 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, 1547 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
1242 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT), 1548 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_CHAT),
1243 _("Chatty"), TRUE, TRUE, FALSE, 1549 _("Chatty"), TRUE, TRUE, FALSE,
1244 "priority", _("Priority"), priority_value, 1550 "priority", _("Priority"), priority_value,
1245 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), 1551 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
1552 "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
1553 "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
1554 "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
1555 "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
1556 "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
1557 "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
1558 "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
1559 "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
1560 "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
1561 "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
1562 "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
1563 "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
1564 "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
1246 NULL); 1565 NULL);
1247 types = g_list_append(types, type); 1566 types = g_list_append(types, type);
1248 1567
1249 priority_value = purple_value_new(PURPLE_TYPE_INT); 1568 priority_value = purple_value_new(PURPLE_TYPE_INT);
1250 purple_value_set_int(priority_value, 0); 1569 purple_value_set_int(priority_value, 0);
1251 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, 1570 type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
1252 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY), 1571 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_AWAY),
1253 NULL, TRUE, TRUE, FALSE, 1572 NULL, TRUE, TRUE, FALSE,
1254 "priority", _("Priority"), priority_value, 1573 "priority", _("Priority"), priority_value,
1255 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), 1574 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
1575 "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
1576 "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
1577 "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
1578 "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
1579 "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
1580 "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
1581 "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
1582 "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
1583 "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
1584 "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
1585 "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
1586 "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
1587 "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
1256 NULL); 1588 NULL);
1257 types = g_list_append(types, type); 1589 types = g_list_append(types, type);
1258 1590
1259 priority_value = purple_value_new(PURPLE_TYPE_INT); 1591 priority_value = purple_value_new(PURPLE_TYPE_INT);
1260 purple_value_set_int(priority_value, 0); 1592 purple_value_set_int(priority_value, 0);
1261 type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY, 1593 type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY,
1262 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA), 1594 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_XA),
1263 NULL, TRUE, TRUE, FALSE, 1595 NULL, TRUE, TRUE, FALSE,
1264 "priority", _("Priority"), priority_value, 1596 "priority", _("Priority"), priority_value,
1265 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), 1597 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
1598 "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
1599 "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
1600 "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
1601 "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
1602 "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
1603 "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
1604 "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
1605 "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
1606 "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
1607 "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
1608 "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
1609 "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
1610 "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
1266 NULL); 1611 NULL);
1267 types = g_list_append(types, type); 1612 types = g_list_append(types, type);
1268 1613
1269 priority_value = purple_value_new(PURPLE_TYPE_INT); 1614 priority_value = purple_value_new(PURPLE_TYPE_INT);
1270 purple_value_set_int(priority_value, 0); 1615 purple_value_set_int(priority_value, 0);
1271 type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, 1616 type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
1272 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_DND), 1617 jabber_buddy_state_get_status_id(JABBER_BUDDY_STATE_DND),
1273 _("Do Not Disturb"), TRUE, TRUE, FALSE, 1618 _("Do Not Disturb"), TRUE, TRUE, FALSE,
1274 "priority", _("Priority"), priority_value, 1619 "priority", _("Priority"), priority_value,
1275 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), 1620 "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
1621 "mood", _("Mood"), purple_value_new(PURPLE_TYPE_STRING),
1622 "moodtext", _("Mood Text"), purple_value_new(PURPLE_TYPE_STRING),
1623 "tune_artist", _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
1624 "tune_title", _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
1625 "tune_album", _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
1626 "tune_genre", _("Tune Genre"), purple_value_new(PURPLE_TYPE_STRING),
1627 "tune_comment", _("Tune Comment"), purple_value_new(PURPLE_TYPE_STRING),
1628 "tune_track", _("Tune Track"), purple_value_new(PURPLE_TYPE_STRING),
1629 "tune_time", _("Tune Time"), purple_value_new(PURPLE_TYPE_INT),
1630 "tune_year", _("Tune Year"), purple_value_new(PURPLE_TYPE_INT),
1631 "tune_url", _("Tune URL"), purple_value_new(PURPLE_TYPE_STRING),
1632 "nick", _("Nickname"), purple_value_new(PURPLE_TYPE_STRING),
1633 "buzz", _("Allow Buzz"), purple_value_new(PURPLE_TYPE_BOOLEAN),
1276 NULL); 1634 NULL);
1277 types = g_list_append(types, type); 1635 types = g_list_append(types, type);
1278 1636
1279 /* 1637 /*
1280 if(js->protocol_version == JABBER_PROTO_0_9) 1638 if(js->protocol_version == JABBER_PROTO_0_9)
1377 js); 1735 js);
1378 } 1736 }
1379 1737
1380 GList *jabber_actions(PurplePlugin *plugin, gpointer context) 1738 GList *jabber_actions(PurplePlugin *plugin, gpointer context)
1381 { 1739 {
1740 PurpleConnection *gc = (PurpleConnection *) context;
1741 JabberStream *js = gc->proto_data;
1382 GList *m = NULL; 1742 GList *m = NULL;
1383 PurplePluginAction *act; 1743 PurplePluginAction *act;
1384 1744
1385 act = purple_plugin_action_new(_("Set User Info..."), 1745 act = purple_plugin_action_new(_("Set User Info..."),
1386 jabber_setup_set_info); 1746 jabber_setup_set_info);
1387 m = g_list_append(m, act); 1747 m = g_list_append(m, act);
1388 1748
1389 /* if (js->protocol_options & CHANGE_PASSWORD) { */ 1749 /* if (js->protocol_options & CHANGE_PASSWORD) { */
1390 act = purple_plugin_action_new(_("Change Password..."), 1750 act = purple_plugin_action_new(_("Change Password..."),
1391 jabber_password_change); 1751 jabber_password_change);
1392 m = g_list_append(m, act); 1752 m = g_list_append(m, act);
1393 /* } */ 1753 /* } */
1394 1754
1395 act = purple_plugin_action_new(_("Search for Users..."), 1755 act = purple_plugin_action_new(_("Search for Users..."),
1396 jabber_user_search_begin); 1756 jabber_user_search_begin);
1397 m = g_list_append(m, act); 1757 m = g_list_append(m, act);
1758
1759 purple_debug_info("jabber", "jabber_actions: have pep: %s\n", js->pep?"YES":"NO");
1760
1761 if(js->pep)
1762 jabber_pep_init_actions(&m);
1763
1764 if(js->commands)
1765 jabber_adhoc_init_server_commands(js, &m);
1398 1766
1399 return m; 1767 return m;
1400 } 1768 }
1401 1769
1402 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name) 1770 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name)
1688 2056
1689 if (!chat || !args || !args[0] || !args[1]) 2057 if (!chat || !args || !args[0] || !args[1])
1690 return PURPLE_CMD_RET_FAILED; 2058 return PURPLE_CMD_RET_FAILED;
1691 2059
1692 if (strcmp(args[1], "owner") != 0 && 2060 if (strcmp(args[1], "owner") != 0 &&
1693 strcmp(args[1], "admin") != 0 && 2061 strcmp(args[1], "admin") != 0 &&
1694 strcmp(args[1], "member") != 0 && 2062 strcmp(args[1], "member") != 0 &&
1695 strcmp(args[1], "outcast") != 0 && 2063 strcmp(args[1], "outcast") != 0 &&
1696 strcmp(args[1], "none") != 0) { 2064 strcmp(args[1], "none") != 0) {
1697 *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[1]); 2065 *error = g_strdup_printf(_("Unknown affiliation: \"%s\""), args[1]);
1698 return PURPLE_CMD_RET_FAILED; 2066 return PURPLE_CMD_RET_FAILED;
1699 } 2067 }
1700 2068
1701 if (!jabber_chat_affiliate_user(chat, args[0], args[1])) { 2069 if (!jabber_chat_affiliate_user(chat, args[0], args[1])) {
1713 2081
1714 if (!chat || !args || !args[0] || !args[1]) 2082 if (!chat || !args || !args[0] || !args[1])
1715 return PURPLE_CMD_RET_FAILED; 2083 return PURPLE_CMD_RET_FAILED;
1716 2084
1717 if (strcmp(args[1], "moderator") != 0 && 2085 if (strcmp(args[1], "moderator") != 0 &&
1718 strcmp(args[1], "participant") != 0 && 2086 strcmp(args[1], "participant") != 0 &&
1719 strcmp(args[1], "visitor") != 0 && 2087 strcmp(args[1], "visitor") != 0 &&
1720 strcmp(args[1], "none") != 0) { 2088 strcmp(args[1], "none") != 0) {
1721 *error = g_strdup_printf(_("Unknown role: \"%s\""), args[1]); 2089 *error = g_strdup_printf(_("Unknown role: \"%s\""), args[1]);
1722 return PURPLE_CMD_RET_FAILED; 2090 return PURPLE_CMD_RET_FAILED;
1723 } 2091 }
1724 2092
1725 if (!jabber_chat_role_user(chat, args[0], args[1])) { 2093 if (!jabber_chat_role_user(chat, args[0], args[1])) {
1726 *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"), 2094 *error = g_strdup_printf(_("Unable to set role \"%s\" for user: %s"),
1727 args[1], args[0]); 2095 args[1], args[0]);
1728 return PURPLE_CMD_RET_FAILED; 2096 return PURPLE_CMD_RET_FAILED;
1729 } 2097 }
1730 2098
1731 return PURPLE_CMD_RET_OK; 2099 return PURPLE_CMD_RET_OK;
1732 } 2100 }
1798 2166
1799 g_free(who); 2167 g_free(who);
1800 return PURPLE_CMD_RET_OK; 2168 return PURPLE_CMD_RET_OK;
1801 } 2169 }
1802 2170
2171 static PurpleCmdRet jabber_cmd_ping(PurpleConversation *conv,
2172 const char *cmd, char **args, char **error, void *data)
2173 {
2174 if(!args || !args[0])
2175 return PURPLE_CMD_RET_FAILED;
2176
2177 if(!jabber_ping_jid(conv, args[0])) {
2178 *error = g_strdup_printf(_("Unable to ping user %s"), args[0]);
2179 return PURPLE_CMD_RET_FAILED;
2180 }
2181
2182 return PURPLE_CMD_RET_OK;
2183 }
2184
2185 static PurpleCmdRet jabber_cmd_buzz(PurpleConversation *conv,
2186 const char *cmd, char **args, char **error, void *data)
2187 {
2188 JabberStream *js = conv->account->gc->proto_data;
2189 xmlnode *msg, *buzz;
2190 JabberBuddy *jb;
2191 JabberBuddyResource *jbr;
2192 char *to;
2193 GList *iter;
2194
2195 if(!args || !args[0])
2196 return PURPLE_CMD_RET_FAILED;
2197
2198 jb = jabber_buddy_find(js, args[0], FALSE);
2199 if(!jb) {
2200 *error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), args[0]);
2201 return PURPLE_CMD_RET_FAILED;
2202 }
2203
2204 jbr = jabber_buddy_find_resource(jb, NULL);
2205 if(!jbr) {
2206 *error = g_strdup_printf(_("Unable to buzz, because user %s might be offline."), args[0]);
2207 return PURPLE_CMD_RET_FAILED;
2208 }
2209 if(!jbr->caps) {
2210 *error = g_strdup_printf(_("Unable to buzz, because there is nothing known about user %s."), args[0]);
2211 return PURPLE_CMD_RET_FAILED;
2212 }
2213 for(iter = jbr->caps->features; iter; iter = g_list_next(iter)) {
2214 if(!strcmp(iter->data, "http://www.xmpp.org/extensions/xep-0224.html#ns")) {
2215 msg = xmlnode_new("message");
2216 to = g_strdup_printf("%s/%s", args[0], jbr->name);
2217 xmlnode_set_attrib(msg,"to",to);
2218 g_free(to);
2219
2220 /* avoid offline storage */
2221 xmlnode_set_attrib(msg,"type","headline");
2222
2223 buzz = xmlnode_new_child(msg,"attention");
2224 xmlnode_set_namespace(buzz,"http://www.xmpp.org/extensions/xep-0224.html#ns");
2225
2226 jabber_send(js,msg);
2227 xmlnode_free(msg);
2228
2229 return PURPLE_CMD_RET_OK;
2230 }
2231 }
2232 *error = g_strdup_printf(_("Unable to buzz, because the user %s does not support it."), args[0]);
2233 return PURPLE_CMD_RET_FAILED;
2234 }
2235
1803 gboolean jabber_offline_message(const PurpleBuddy *buddy) 2236 gboolean jabber_offline_message(const PurpleBuddy *buddy)
1804 { 2237 {
1805 return TRUE; 2238 return TRUE;
1806 } 2239 }
1807 2240
1808 void jabber_register_commands(void) 2241 void jabber_register_commands(void)
1809 { 2242 {
1810 purple_cmd_register("config", "", PURPLE_CMD_P_PRPL, 2243 purple_cmd_register("config", "", PURPLE_CMD_P_PRPL,
1811 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, 2244 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
1812 "prpl-jabber", jabber_cmd_chat_config, 2245 "prpl-jabber", jabber_cmd_chat_config,
1813 _("config: Configure a chat room."), NULL); 2246 _("config: Configure a chat room."), NULL);
1814 purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL, 2247 purple_cmd_register("configure", "", PURPLE_CMD_P_PRPL,
1815 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, 2248 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
1816 "prpl-jabber", jabber_cmd_chat_config, 2249 "prpl-jabber", jabber_cmd_chat_config,
1817 _("configure: Configure a chat room."), NULL); 2250 _("configure: Configure a chat room."), NULL);
1818 purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL, 2251 purple_cmd_register("nick", "s", PURPLE_CMD_P_PRPL,
1819 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, 2252 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
1820 "prpl-jabber", jabber_cmd_chat_nick, 2253 "prpl-jabber", jabber_cmd_chat_nick,
1821 _("nick &lt;new nickname&gt;: Change your nickname."), 2254 _("nick &lt;new nickname&gt;: Change your nickname."),
1822 NULL); 2255 NULL);
1823 purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL, 2256 purple_cmd_register("part", "s", PURPLE_CMD_P_PRPL,
1824 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2257 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1825 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2258 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1826 jabber_cmd_chat_part, _("part [room]: Leave the room."), 2259 jabber_cmd_chat_part, _("part [room]: Leave the room."),
1827 NULL); 2260 NULL);
1828 purple_cmd_register("register", "", PURPLE_CMD_P_PRPL, 2261 purple_cmd_register("register", "", PURPLE_CMD_P_PRPL,
1829 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, 2262 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
1830 "prpl-jabber", jabber_cmd_chat_register, 2263 "prpl-jabber", jabber_cmd_chat_register,
1831 _("register: Register with a chat room."), NULL); 2264 _("register: Register with a chat room."), NULL);
1832 /* XXX: there needs to be a core /topic cmd, methinks */ 2265 /* XXX: there needs to be a core /topic cmd, methinks */
1833 purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL, 2266 purple_cmd_register("topic", "s", PURPLE_CMD_P_PRPL,
1834 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2267 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1835 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2268 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1836 jabber_cmd_chat_topic, 2269 jabber_cmd_chat_topic,
1837 _("topic [new topic]: View or change the topic."), 2270 _("topic [new topic]: View or change the topic."),
1838 NULL); 2271 NULL);
1839 purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL, 2272 purple_cmd_register("ban", "ws", PURPLE_CMD_P_PRPL,
1840 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2273 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1841 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2274 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1842 jabber_cmd_chat_ban, 2275 jabber_cmd_chat_ban,
1843 _("ban &lt;user&gt; [room]: Ban a user from the room."), 2276 _("ban &lt;user&gt; [room]: Ban a user from the room."),
1844 NULL); 2277 NULL);
1845 purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL, 2278 purple_cmd_register("affiliate", "ws", PURPLE_CMD_P_PRPL,
1846 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2279 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1847 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2280 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1848 jabber_cmd_chat_affiliate, 2281 jabber_cmd_chat_affiliate,
1849 _("affiliate &lt;user&gt; &lt;owner|admin|member|outcast|none&gt;: Set a user's affiliation with the room."), 2282 _("affiliate &lt;user&gt; &lt;owner|admin|member|outcast|none&gt;: Set a user's affiliation with the room."),
1850 NULL); 2283 NULL);
1851 purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL, 2284 purple_cmd_register("role", "ws", PURPLE_CMD_P_PRPL,
1852 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2285 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1853 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2286 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1854 jabber_cmd_chat_role, 2287 jabber_cmd_chat_role,
1855 _("role &lt;user&gt; &lt;moderator|participant|visitor|none&gt;: Set a user's role in the room."), 2288 _("role &lt;user&gt; &lt;moderator|participant|visitor|none&gt;: Set a user's role in the room."),
1856 NULL); 2289 NULL);
1857 purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL, 2290 purple_cmd_register("invite", "ws", PURPLE_CMD_P_PRPL,
1858 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2291 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1859 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2292 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1860 jabber_cmd_chat_invite, 2293 jabber_cmd_chat_invite,
1861 _("invite &lt;user&gt; [message]: Invite a user to the room."), 2294 _("invite &lt;user&gt; [message]: Invite a user to the room."),
1862 NULL); 2295 NULL);
1863 purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL, 2296 purple_cmd_register("join", "ws", PURPLE_CMD_P_PRPL,
1864 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2297 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1865 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2298 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1866 jabber_cmd_chat_join, 2299 jabber_cmd_chat_join,
1867 _("join: &lt;room&gt; [server]: Join a chat on this server."), 2300 _("join: &lt;room&gt; [server]: Join a chat on this server."),
1868 NULL); 2301 NULL);
1869 purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL, 2302 purple_cmd_register("kick", "ws", PURPLE_CMD_P_PRPL,
1870 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY | 2303 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY |
1871 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber", 2304 PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS, "prpl-jabber",
1872 jabber_cmd_chat_kick, 2305 jabber_cmd_chat_kick,
1873 _("kick &lt;user&gt; [room]: Kick a user from the room."), 2306 _("kick &lt;user&gt; [room]: Kick a user from the room."),
1874 NULL); 2307 NULL);
1875 purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL, 2308 purple_cmd_register("msg", "ws", PURPLE_CMD_P_PRPL,
1876 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY, 2309 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_PRPL_ONLY,
1877 "prpl-jabber", jabber_cmd_chat_msg, 2310 "prpl-jabber", jabber_cmd_chat_msg,
1878 _("msg &lt;user&gt; &lt;message&gt;: Send a private message to another user."), 2311 _("msg &lt;user&gt; &lt;message&gt;: Send a private message to another user."),
1879 NULL); 2312 NULL);
2313 purple_cmd_register("ping", "w", PURPLE_CMD_P_PRPL,
2314 PURPLE_CMD_FLAG_CHAT | PURPLE_CMD_FLAG_IM |
2315 PURPLE_CMD_FLAG_PRPL_ONLY,
2316 "prpl-jabber", jabber_cmd_ping,
2317 _("ping &lt;jid&gt;: Ping a user/component/server."),
2318 NULL);
2319 purple_cmd_register("buzz", "s", PURPLE_CMD_P_PRPL,
2320 PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
2321 "prpl-jabber", jabber_cmd_buzz,
2322 _("buzz: Buzz a user to get their attention"), NULL);
1880 } 2323 }
1881 2324
1882 void 2325 void
1883 jabber_init_plugin(PurplePlugin *plugin) 2326 jabber_init_plugin(PurplePlugin *plugin)
1884 { 2327 {
1885 my_protocol = plugin; 2328 my_protocol = plugin;
1886 } 2329 }

mercurial