Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/jabglue.c @ 447:03bb57383cea
Initial Multi-User Chat support
This patch adds basic MUC support. We now can:
- join an existing room;
- create and unlock a room using the /rawxml command;
- set our nickname;
- send/receive chatgroup messages;
- see the members of the room;
- leave the room.
Chatroom logging is currently disabled, as it could do some unexpected things.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 25 Sep 2005 01:01:44 +0200 |
parents | 5927c3bfba13 |
children | e08b0c2d0e54 |
comparison
equal
deleted
inserted
replaced
446:9f4e9e9aaf08 | 447:03bb57383cea |
---|---|
331 | 331 |
332 hk_mystatuschange(0, mystatus, st, msg); | 332 hk_mystatuschange(0, mystatus, st, msg); |
333 mystatus = st; | 333 mystatus = st; |
334 } | 334 } |
335 | 335 |
336 void jb_send_msg(const char *jid, const char *text) | 336 void jb_send_msg(const char *jid, const char *text, int type) |
337 { | 337 { |
338 gchar *strtype; | |
338 gchar *buffer = to_utf8(text); | 339 gchar *buffer = to_utf8(text); |
339 xmlnode x = jutil_msgnew(TMSG_CHAT, (char*)jid, 0, (char*)buffer); | 340 |
341 if (type == ROSTER_TYPE_ROOM) | |
342 strtype = TMSG_GROUPCHAT; | |
343 else | |
344 strtype = TMSG_CHAT; | |
345 | |
346 xmlnode x = jutil_msgnew(strtype, (char*)jid, 0, (char*)buffer); | |
340 jab_send(jc, x); | 347 jab_send(jc, x); |
341 xmlnode_free(x); | 348 xmlnode_free(x); |
342 g_free(buffer); | 349 g_free(buffer); |
343 jb_reset_keepalive(); | 350 jb_reset_keepalive(); |
344 } | 351 } |
460 xmlnode_free(x); | 467 xmlnode_free(x); |
461 g_free(name_utf8); | 468 g_free(name_utf8); |
462 g_free(cleanjid); | 469 g_free(cleanjid); |
463 } | 470 } |
464 | 471 |
472 // Join a MUC room | |
473 // room syntax: "room@server/nick" | |
474 void jb_room_join(const char *room) | |
475 { | |
476 xmlnode x, y; | |
477 | |
478 if (!online) return; | |
479 if (!room) return; | |
480 | |
481 x = jutil_presnew(JPACKET__UNKNOWN, 0, 0); | |
482 xmlnode_put_attrib(x, "from", jid_full(jc->user)); | |
483 xmlnode_put_attrib(x, "to", room); | |
484 y = xmlnode_insert_tag(x, "x"); | |
485 xmlnode_put_attrib(y, "xmlns", "http://jabber.org/protocol/muc"); | |
486 | |
487 jab_send(jc, x); | |
488 xmlnode_free(x); | |
489 jb_reset_keepalive(); | |
490 } | |
491 | |
465 void postlogin() | 492 void postlogin() |
466 { | 493 { |
467 //int i; | 494 //int i; |
468 | 495 |
469 //flogged = TRUE; | 496 //flogged = TRUE; |
569 | 596 |
570 void gotmessage(char *type, const char *from, const char *body, | 597 void gotmessage(char *type, const char *from, const char *body, |
571 const char *enc, time_t timestamp) | 598 const char *enc, time_t timestamp) |
572 { | 599 { |
573 char *jid; | 600 char *jid; |
601 const char *rname; | |
574 gchar *buffer = from_utf8(body); | 602 gchar *buffer = from_utf8(body); |
575 | 603 |
576 jid = jidtodisp(from); | 604 jid = jidtodisp(from); |
577 | 605 |
578 if (!buffer && body) { | 606 if (!buffer && body) { |
583 0, HBB_PREFIX_ERR | HBB_PREFIX_IN); | 611 0, HBB_PREFIX_ERR | HBB_PREFIX_IN); |
584 g_free(jid); | 612 g_free(jid); |
585 return; | 613 return; |
586 } | 614 } |
587 | 615 |
588 /* | 616 rname = strchr(from, '/'); |
589 //char *u, *h, *r; | 617 if (rname) rname++; |
590 //jidsplit(from, &u, &h, &r); | 618 hk_message_in(jid, rname, timestamp, buffer, type); |
591 // Maybe we should remember the resource? | |
592 if (r) | |
593 scr_LogPrint(LPRINT_NORMAL, | |
594 "There is an extra part in message (resource?): %s", r); | |
595 //scr_LogPrint(LPRINT_NORMAL, "Msg from <%s>, type=%s", | |
596 // jidtodisp(from), type); | |
597 */ | |
598 | |
599 hk_message_in(jid, timestamp, buffer, type); | |
600 g_free(jid); | 619 g_free(jid); |
601 g_free(buffer); | 620 g_free(buffer); |
602 } | 621 } |
603 | 622 |
604 const char *defaulterrormsg(int code) | 623 const char *defaulterrormsg(int code) |
725 previous_state = state; | 744 previous_state = state; |
726 } | 745 } |
727 | 746 |
728 void packethandler(jconn conn, jpacket packet) | 747 void packethandler(jconn conn, jpacket packet) |
729 { | 748 { |
730 char *p, *r; | 749 char *p, *r, *s; |
731 const char *m, *rname; | 750 const char *m, *rname; |
732 xmlnode x, y; | 751 xmlnode x, y; |
733 char *from=NULL, *type=NULL, *body=NULL, *enc=NULL; | 752 char *from=NULL, *type=NULL, *body=NULL, *enc=NULL; |
734 char *ns=NULL; | 753 char *ns=NULL; |
735 char *id=NULL; | 754 char *id=NULL; |
904 xmlnode_free(x); | 923 xmlnode_free(x); |
905 } | 924 } |
906 | 925 |
907 } | 926 } |
908 } | 927 } |
928 } else if (!strcmp(type, "get")) { | |
929 p = xmlnode_get_attrib(packet->x, "id"); | |
930 if (p) { | |
931 xmlnode z; | |
932 | |
933 id = p; | |
934 x = xmlnode_new_tag("iq"); | |
935 xmlnode_put_attrib(x, "type", "result"); | |
936 xmlnode_put_attrib(x, "to", from); | |
937 xmlnode_put_attrib(x, "id", id); | |
938 xmlnode_put_attrib(x, "type", "error"); | |
939 y = xmlnode_insert_tag(x, "error"); | |
940 xmlnode_put_attrib(y, "code", "503"); | |
941 xmlnode_put_attrib(y, "type", "cancel"); | |
942 z = xmlnode_insert_tag(y, "feature-not-implemented"); | |
943 xmlnode_put_attrib(z, "xmlns", | |
944 "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
945 jab_send(conn, x); | |
946 xmlnode_free(x); | |
947 } | |
909 } else if (!strcmp(type, "set")) { | 948 } else if (!strcmp(type, "set")) { |
949 /* FIXME: send error */ | |
910 } else if (!strcmp(type, "error")) { | 950 } else if (!strcmp(type, "error")) { |
911 if ((x = xmlnode_get_tag(packet->x, "error")) != NULL) | 951 if ((x = xmlnode_get_tag(packet->x, "error")) != NULL) |
912 display_server_error(x); | 952 display_server_error(x); |
913 } | 953 } |
914 break; | 954 break; |
938 | 978 |
939 if (type && !strcmp(type, "unavailable")) | 979 if (type && !strcmp(type, "unavailable")) |
940 ust = offline; | 980 ust = offline; |
941 | 981 |
942 if ((x = xmlnode_get_tag(packet->x, "status")) != NULL) | 982 if ((x = xmlnode_get_tag(packet->x, "status")) != NULL) |
943 p = from_utf8(xmlnode_get_data(x)); | 983 s = from_utf8(xmlnode_get_data(x)); |
944 else | 984 else |
945 p = NULL; | 985 s = NULL; |
946 | 986 |
947 // Call hk_statuschange() if status has changed or if the | 987 // Call hk_statuschange() if status has changed or if the |
948 // status message is different | 988 // status message is different |
949 rname = strchr(from, '/'); | 989 rname = strchr(from, '/'); |
950 if (rname) rname++; | 990 if (rname) rname++; |
991 | |
992 // Check for MUC presence packet | |
993 // There can be multiple <x> tags!! | |
994 x = xmlnode_get_firstchild(packet->x); | |
995 for ( ; x; x = xmlnode_get_nextsibling(x)) { | |
996 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) | |
997 if ((p = xmlnode_get_attrib(x, "xmlns")) && | |
998 !strncasecmp(p, "http://jabber.org/protocol/muc", 30)) | |
999 break; | |
1000 } | |
1001 if (x) { // This is a MUC presence message | |
1002 roster_add_user(r, NULL, NULL, ROSTER_TYPE_ROOM); | |
1003 | |
1004 if (rname) | |
1005 roster_setstatus(r, rname, bpprio, ust, NULL); | |
1006 else | |
1007 scr_LogPrint(LPRINT_LOGNORM, "MUC DBG: no rname!"); /* DBG */ | |
1008 | |
1009 buddylist_build(); | |
1010 scr_DrawRoster(); | |
1011 break; | |
1012 } | |
1013 | |
1014 // Not a MUC message, so this is a regular buddy... | |
951 m = roster_getstatusmsg(r, rname); | 1015 m = roster_getstatusmsg(r, rname); |
952 if ((ust != roster_getstatus(r, rname)) || (p && (!m || strcmp(p, m)))) | 1016 if ((ust != roster_getstatus(r, rname)) || (s && (!m || strcmp(s, m)))) |
953 hk_statuschange(r, rname, bpprio, 0, ust, p); | 1017 hk_statuschange(r, rname, bpprio, 0, ust, s); |
954 g_free(r); | 1018 g_free(r); |
955 if (p) g_free(p); | 1019 if (s) g_free(s); |
956 break; | 1020 break; |
957 | 1021 |
958 case JPACKET_S10N: | 1022 case JPACKET_S10N: |
959 scr_LogPrint(LPRINT_LOGNORM, "Received (un)subscription packet " | 1023 scr_LogPrint(LPRINT_LOGNORM, "Received (un)subscription packet " |
960 "(type=%s)", ((type) ? type : "")); | 1024 "(type=%s)", ((type) ? type : "")); |