/* Massjoin support - really useful when trying to do things (like op/deop) to people after netjoins. It sends "massjoin #channel nick!user@host nick2!user@host ..." signals */ static void event_join(IRC_SERVER_REC *server, const char *data, const char *nick, const char *address) { char *params, *channel, *ptr; IRC_CHANNEL_REC *chanrec; NICK_REC *nickrec; GSList *nicks, *tmp; g_return_if_fail(data != NULL); if (g_strcasecmp(nick, server->nick) == 0) { /* You joined, no need to do anything here */ return; } params = event_get_params(data, 1, &channel); ptr = strchr(channel, 7); /* ^G does something weird.. */ if (ptr != NULL) *ptr = '\0'; /* find channel */ chanrec = irc_channel_find(server, channel); g_free(params); if (chanrec == NULL) return; /* check that the nick isn't already in nicklist. seems to happen sometimes (server desyncs or something?) */ nickrec = nicklist_find(CHANNEL(chanrec), nick); if (nickrec != NULL) { /* destroy the old record */ nicklist_remove(CHANNEL(chanrec), nickrec); } /* add user to nicklist */ nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, TRUE); nicklist_set_host(CHANNEL(chanrec), nickrec, address); if (chanrec->massjoins == 0) { /* no nicks waiting in massjoin queue */ chanrec->massjoin_start = time(NULL); chanrec->last_massjoins = 0; } if (nickrec->realname == NULL) { /* Check if user is already in some other channel, get the realname and other stuff from there */ nicks = nicklist_get_same(SERVER(server), nick); for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { NICK_REC *rec = tmp->next->data; if (rec->realname != NULL) { nickrec->last_check = rec->last_check; nickrec->realname = g_strdup(rec->realname); nickrec->gone = rec->gone; break; } } g_slist_free(nicks); } chanrec->massjoins++; }
static void event_names_list(IRC_SERVER_REC *server, const char *data) { IRC_CHANNEL_REC *chanrec; NICK_REC *rec; char *params, *type, *channel, *names, *ptr, *host; int op, halfop, voice; char prefixes[MAX_USER_PREFIXES+1]; g_return_if_fail(data != NULL); params = event_get_params(data, 4, NULL, &type, &channel, &names); chanrec = irc_channel_find(server, channel); if (chanrec == NULL || chanrec->names_got) { /* unknown channel / names list already read */ g_free(params); return; } /* type = '=' = public, '*' = private, '@' = secret. This is actually pretty useless to check here, but at least we get to know if the channel is +p or +s a few seconds before we receive the MODE reply... If the channel key is set, assume the channel is +k also until we know better, so parse_channel_modes() won't clear the key */ if (*type == '*') { parse_channel_modes(chanrec, NULL, chanrec->key ? "+kp" : "+p", FALSE); } else if (*type == '@') { parse_channel_modes(chanrec, NULL, chanrec->key ? "+ks" : "+s", FALSE); } while (*names != '\0') { while (*names == ' ') names++; ptr = names; while (*names != '\0' && *names != ' ') names++; if (*names != '\0') *names++ = '\0'; /* some servers show ".@nick", there's also been talk about showing "@+nick" and since none of these chars are valid nick chars, just check them until a non-nickflag char is found. */ op = halfop = voice = FALSE; prefixes[0] = '\0'; while (isnickflag(server, *ptr)) { prefix_add(prefixes, *ptr, (SERVER_REC *) server); switch (*ptr) { case '@': op = TRUE; break; case '%': halfop = TRUE; break; case '+': voice = TRUE; break; } ptr++; } host = strchr(ptr, '!'); if (host != NULL) *host++ = '\0'; if (nicklist_find((CHANNEL_REC *) chanrec, ptr) == NULL) { rec = irc_nicklist_insert(chanrec, ptr, op, halfop, voice, FALSE, prefixes); if (host != NULL) nicklist_set_host(CHANNEL(chanrec), rec, host); } } g_free(params); }