comparison mcabber/src/jabglue.c @ 644:68fb0c1dfb15

MUC: better nickname check when entering a room
author Mikael Berthe <mikael@lilotux.net>
date Thu, 05 Jan 2006 20:20:57 +0100
parents dd73c3dad815
children d26a1c9611db
comparison
equal deleted inserted replaced
643:dd73c3dad815 644:68fb0c1dfb15
574 // Join a MUC room 574 // Join a MUC room
575 void jb_room_join(const char *room, const char *nickname) 575 void jb_room_join(const char *room, const char *nickname)
576 { 576 {
577 xmlnode x, y; 577 xmlnode x, y;
578 gchar *roomid; 578 gchar *roomid;
579 GSList *room_elt;
579 580
580 if (!online || !room) return; 581 if (!online || !room) return;
581 if (!nickname) return; 582 if (!nickname) return;
582 583
583 roomid = g_strdup_printf("%s/%s", room, nickname); 584 roomid = g_strdup_printf("%s/%s", room, nickname);
584 if (check_jid_syntax(roomid)) { 585 if (check_jid_syntax(roomid)) {
585 scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room, 586 scr_LogPrint(LPRINT_NORMAL, "<%s/%s> is not a valid Jabber room", room,
586 nickname); 587 nickname);
587 g_free(roomid); 588 g_free(roomid);
588 return; 589 return;
590 }
591
592 room_elt = roster_find(room, jidsearch, ROSTER_TYPE_USER|ROSTER_TYPE_ROOM);
593 // Add room if it doesn't already exist
594 if (!room_elt)
595 room_elt = roster_add_user(room, NULL, NULL, ROSTER_TYPE_ROOM, sub_none);
596 // If insideroom is TRUE, this is a nickname change and we don't care here
597 if (!buddy_getinsideroom(room_elt->data)) {
598 // We're trying to enter a room
599 buddy_setnickname(room_elt->data, nickname);
589 } 600 }
590 601
591 // Send the XML request 602 // Send the XML request
592 x = presnew(mystatus, roomid, mystatusmsg); 603 x = presnew(mystatus, roomid, mystatusmsg);
593 y = xmlnode_insert_tag(x, "x"); 604 y = xmlnode_insert_tag(x, "x");
900 break; 911 break;
901 } 912 }
902 previous_state = state; 913 previous_state = state;
903 } 914 }
904 915
905 static time_t xml_get_timestamp(xmlnode xmldata) 916 inline static xmlnode xml_get_xmlns(xmlnode xmldata, const char *xmlns)
906 { 917 {
907 xmlnode x; 918 xmlnode x;
908 char *p; 919 char *p;
909 920
910 x = xmlnode_get_firstchild(xmldata); 921 x = xmlnode_get_firstchild(xmldata);
911 for ( ; x; x = xmlnode_get_nextsibling(x)) { 922 for ( ; x; x = xmlnode_get_nextsibling(x)) {
912 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x")) 923 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x"))
913 if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, NS_DELAY)) { 924 if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, xmlns)) {
914 break; 925 break;
915 } 926 }
916 } 927 }
928 return x;
929 }
930
931 static time_t xml_get_timestamp(xmlnode xmldata)
932 {
933 xmlnode x;
934 char *p;
935
936 x = xml_get_xmlns(xmldata, NS_DELAY);
917 if ((p = xmlnode_get_attrib(x, "stamp")) != NULL) 937 if ((p = xmlnode_get_attrib(x, "stamp")) != NULL)
918 return from_iso8601(p, 1); 938 return from_iso8601(p, 1);
919 return 0; 939 return 0;
920 } 940 }
921 941
937 957
938 log_muc_conf = settings_opt_get_int("log_muc_conf"); 958 log_muc_conf = settings_opt_get_int("log_muc_conf");
939 959
940 room_elt = roster_find(roomjid, jidsearch, 0); 960 room_elt = roster_find(roomjid, jidsearch, 0);
941 if (!room_elt) { 961 if (!room_elt) {
942 // Add room if it doesn't already exist 962 // Add room if it doesn't already exist FIXME shouldn't happen!
943 room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM, sub_none); 963 room_elt = roster_add_user(roomjid, NULL, NULL, ROSTER_TYPE_ROOM, sub_none);
944 } else { 964 } else {
945 // Make sure this is a room (it can be a conversion user->room) 965 // Make sure this is a room (it can be a conversion user->room)
946 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM); 966 buddy_settype(room_elt->data, ROSTER_TYPE_ROOM);
947 } 967 }
1027 // If this is a leave, check if it is ourself 1047 // If this is a leave, check if it is ourself
1028 m = buddy_getnickname(room_elt->data); 1048 m = buddy_getnickname(room_elt->data);
1029 1049
1030 if (m && !strcmp(rname, m)) { 1050 if (m && !strcmp(rname, m)) {
1031 we_left = TRUE; // _We_ have left! (kicked, banned, etc.) 1051 we_left = TRUE; // _We_ have left! (kicked, banned, etc.)
1052 buddy_setinsideroom(room_elt->data, FALSE);
1032 buddy_setnickname(room_elt->data, NULL); 1053 buddy_setnickname(room_elt->data, NULL);
1033 buddy_del_all_resources(room_elt->data); 1054 buddy_del_all_resources(room_elt->data);
1034 buddy_settopic(room_elt->data, NULL); 1055 buddy_settopic(room_elt->data, NULL);
1035 update_roster = TRUE; 1056 update_roster = TRUE;
1036 } 1057 }
1103 } 1124 }
1104 g_free(mbuf); 1125 g_free(mbuf);
1105 } else if (buddy_getstatus(room_elt->data, rname) == offline && 1126 } else if (buddy_getstatus(room_elt->data, rname) == offline &&
1106 ust != offline) { 1127 ust != offline) {
1107 gchar *mbuf; 1128 gchar *mbuf;
1108 if (buddy_getnickname(room_elt->data) == NULL) { 1129 if (!buddy_getinsideroom(room_elt->data)) {
1109 buddy_setnickname(room_elt->data, rname); 1130 const char *ournick = buddy_getnickname(room_elt->data);
1131 // We weren't inside the room yet. Now we are.
1132 // However, this could be a presence packet from another room member
1133
1134 if (!ournick) {
1135 // I think it shouldn't happen, but let's put a warning for a while...
1136 scr_LogPrint(LPRINT_LOGNORM, "MUC ERR: you have no nickname, "
1137 "please send a bug report!");
1138 ournick = "";
1139 buddylist_build();
1140 scr_DrawRoster();
1141 return;
1142 }
1143
1144 buddy_setinsideroom(room_elt->data, TRUE);
1110 // Add a message to the tracelog file 1145 // Add a message to the tracelog file
1111 mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, rname); 1146 mbuf = g_strdup_printf("You have joined %s as \"%s\"", roomjid, ournick);
1112 scr_LogPrint(LPRINT_LOG, "%s", mbuf); 1147 scr_LogPrint(LPRINT_LOG, "%s", mbuf);
1113 g_free(mbuf); 1148 g_free(mbuf);
1114 mbuf = g_strdup_printf("You have joined as \"%s\"", rname); 1149 mbuf = g_strdup_printf("You have joined as \"%s\"", ournick);
1150
1151 // The 1st presence message could be for another room member
1152 if (strcmp(ournick, rname)) {
1153 // Display current mbuf and create a new message for the member
1154 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
1155 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG);
1156 if (log_muc_conf) hlog_write_message(roomjid, 0, FALSE, mbuf);
1157 g_free(mbuf);
1158 mbuf = g_strdup_printf("%s has joined", rname);
1159 }
1115 } else { 1160 } else {
1116 mbuf = g_strdup_printf("%s has joined", rname); 1161 mbuf = g_strdup_printf("%s has joined", rname);
1117 } 1162 }
1118 scr_WriteIncomingMessage(roomjid, mbuf, usttime, 1163 scr_WriteIncomingMessage(roomjid, mbuf, usttime,
1119 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG); 1164 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG);
1138 static void handle_packet_presence(jconn conn, char *type, char *from, 1183 static void handle_packet_presence(jconn conn, char *type, char *from,
1139 xmlnode xmldata) 1184 xmlnode xmldata)
1140 { 1185 {
1141 char *p, *r; 1186 char *p, *r;
1142 char *ustmsg; 1187 char *ustmsg;
1143 xmlnode x;
1144 const char *rname; 1188 const char *rname;
1145 enum imstatus ust; 1189 enum imstatus ust;
1146 char bpprio; 1190 char bpprio;
1147 time_t timestamp = 0; 1191 time_t timestamp = 0;
1192 xmlnode muc_packet;
1193
1194 rname = strchr(from, '/');
1195 if (rname) rname++;
1148 1196
1149 r = jidtodisp(from); 1197 r = jidtodisp(from);
1198
1199 // Check for MUC presence packet
1200 muc_packet = xml_get_xmlns(xmldata, "http://jabber.org/protocol/muc#user");
1201
1150 if (type && !strcmp(type, TMSG_ERROR)) { 1202 if (type && !strcmp(type, TMSG_ERROR)) {
1203 xmlnode x;
1151 scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r); 1204 scr_LogPrint(LPRINT_LOGNORM, "Error presence packet from <%s>", r);
1152 if ((x = xmlnode_get_tag(xmldata, TMSG_ERROR)) != NULL) 1205 if ((x = xmlnode_get_tag(xmldata, TMSG_ERROR)) != NULL)
1153 display_server_error(x); 1206 display_server_error(x);
1207
1208 // Let's check it isn't a nickname conflict.
1209 // XXX Note: We should handle the <conflict/> string condition.
1210 if ((p = xmlnode_get_attrib(x, "code")) != NULL) {
1211 if (atoi(p) == 409) {
1212 // 409 = conlict (nickname is in use or registered by another user)
1213 // If we are not inside this room, we should reset the nickname
1214 GSList *room_elt = roster_find(r, jidsearch, 0);
1215 if (room_elt && !buddy_getinsideroom(room_elt->data))
1216 buddy_setnickname(room_elt->data, NULL);
1217 }
1218 }
1219
1154 g_free(r); 1220 g_free(r);
1155 return; 1221 return;
1156 } 1222 }
1157 1223
1158 p = xmlnode_get_tag_data(xmldata, "priority"); 1224 p = xmlnode_get_tag_data(xmldata, "priority");
1179 scr_LogPrint(LPRINT_LOG, 1245 scr_LogPrint(LPRINT_LOG,
1180 "Decoding of status message of <%s> has failed: %s", 1246 "Decoding of status message of <%s> has failed: %s",
1181 from, p); 1247 from, p);
1182 } 1248 }
1183 1249
1184 rname = strchr(from, '/');
1185 if (rname) rname++;
1186
1187 // Timestamp? 1250 // Timestamp?
1188 timestamp = xml_get_timestamp(xmldata); 1251 timestamp = xml_get_timestamp(xmldata);
1189 1252
1190 // Check for MUC presence packet 1253 if (muc_packet) {
1191 // There can be multiple <x> tags!!
1192 x = xmlnode_get_firstchild(xmldata);
1193 for ( ; x; x = xmlnode_get_nextsibling(x)) {
1194 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x"))
1195 if ((p = xmlnode_get_attrib(x, "xmlns")) &&
1196 !strcmp(p, "http://jabber.org/protocol/muc#user"))
1197 break;
1198 }
1199 if (x) {
1200 // This is a MUC presence message 1254 // This is a MUC presence message
1201 handle_presence_muc(from, x, r, rname, ust, ustmsg, timestamp, bpprio); 1255 handle_presence_muc(from, muc_packet, r, rname,
1256 ust, ustmsg, timestamp, bpprio);
1202 } else { 1257 } else {
1203 // Not a MUC message, so this is a regular buddy... 1258 // Not a MUC message, so this is a regular buddy...
1204 // Call hk_statuschange() if status has changed or if the 1259 // Call hk_statuschange() if status has changed or if the
1205 // status message is different 1260 // status message is different
1206 const char *m = roster_getstatusmsg(r, rname); 1261 const char *m = roster_getstatusmsg(r, rname);
1267 if (body) strcat(tmp, body); 1322 if (body) strcat(tmp, body);
1268 body = tmp; 1323 body = tmp;
1269 } 1324 }
1270 } 1325 }
1271 1326
1272 /* there can be multiple <x> tags. we're looking for one with 1327 // Not used yet...
1273 xmlns = jabber:x:encrypted */ 1328 x = xml_get_xmlns(xmldata, NS_ENCRYPTED);
1274 1329 if (x && (p = xmlnode_get_data(x)) != NULL) {
1275 x = xmlnode_get_firstchild(xmldata); 1330 enc = p;
1276 for ( ; x; x = xmlnode_get_nextsibling(x)) {
1277 if ((p = xmlnode_get_name(x)) && !strcmp(p, "x"))
1278 if ((p = xmlnode_get_attrib(x, "xmlns")) && !strcmp(p, NS_ENCRYPTED))
1279 if ((p = xmlnode_get_data(x)) != NULL) {
1280 enc = p;
1281 break;
1282 }
1283 } 1331 }
1284 1332
1285 // Timestamp? 1333 // Timestamp?
1286 timestamp = xml_get_timestamp(xmldata); 1334 timestamp = xml_get_timestamp(xmldata);
1287 1335