Mercurial > ~mikael > mcabber > hg
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 |