// TODO: +s
channel_sendtopic(client, chan, 0);
} else {
- // TODO: +t check, membership check
+ // TODO: membership check, maybe?
+ if (chan->dmode & DMODE_TOPICPROT && !trie_get(&chan->o, client->key))
+ return 0; // error 482
free(chan->topic);
free(chan->topic_who);
if (!*args[1]) {
return err_notregistered(client), sendbuf(client), 0;
if (argc < 2) // FIXME: error message
return 0;
+ client->lastactivity = time(NULL);
(command[0] == 'P' ? msg_privmsg : msg_notice)(client, args[0], args[1]);
// TODO: extra target forms such as nick@server #hostmask $servermask
int is_modmsg = !!strchr("@+", args[0][0]);
char *nick = args[1] ? args[1] : args[0];
struct client_data *cl = findClient(nick);
if (cl) {
- copy_strf(&databuf, ":%s 311 %s %s %s %s * :%s\n", hostname, client->nick, cl->nick, cl->username, cl->hostname, cl->realname);
+ copy_strf(&databuf, ":%s 311 %s %s %s %s * :%s\r\n", hostname, client->nick, cl->nick, cl->username, cl->hostname, cl->realname);
sendbuf(client);
- copy_strf(&databuf, ":%s 312 %s %s %s :Patchy server\n", hostname, client->nick, cl->nick, hostname);
+ copy_strf(&databuf, ":%s 312 %s %s %s :Patchy server\r\n", hostname, client->nick, cl->nick, hostname);
sendbuf(client);
if (cl->umode & UMODE_OPER) {
- copy_strf(&databuf, ":%s 313 %s %s :is an IRC operator\n", hostname, client->nick, cl->nick);
+ copy_strf(&databuf, ":%s 313 %s %s :is an IRC operator\r\n", hostname, client->nick, cl->nick);
sendbuf(client);
}
+ // FIXME: 64-bit time_t
+ copy_strf(&databuf, ":%s 317 %s %s %u %u :seconds idle, signon time\r\n",
+ hostname, client->nick, cl->nick, (unsigned)(time(NULL)-cl->lastactivity), (unsigned)cl->signon);
+ sendbuf(client);
if (cl->away) {
- copy_strf(&databuf, ":%s 301 %s %s :%s\n", hostname, client->nick, cl->nick, cl->away);
+ copy_strf(&databuf, ":%s 301 %s %s :%s\r\n", hostname, client->nick, cl->nick, cl->away);
sendbuf(client);
}
- copy_strf(&databuf, ":%s 318 %s %s :End of /WHOIS list\n", hostname, client->nick, cl->nick);
+ struct trie_find *f = NULL;
+ if (trie_findfirst(&f, &cl->channels) == 1)
+ do {
+ struct channel *chan = f->n->value;
+ if ((cl->umode & UMODE_INVISIBLE || chan->dmode & DMODE_SECRET) && !trie_get(&chan->members, client->key))
+ continue;
+ char prefix[2] = {0,0};
+ if (trie_get(&chan->o, cl->key))
+ prefix[0] = '@';
+ else if (trie_get(&chan->v, cl->key))
+ prefix[0] = '+';
+ copy_strf(&databuf, ":%s 319 %s %s :%s%s\r\n", hostname, client->nick, cl->nick, prefix, chan->name);
+ sendbuf(client);
+ } while (trie_findnext(&f) == 1);
+ copy_strf(&databuf, ":%s 318 %s %s :End of /WHOIS list\r\n", hostname, client->nick, cl->nick);
sendbuf(client);
} else {
err_nosuchnick(client, nick);
setNick(client, client->nick_reg);
free(client->nick_reg);
client->nick_reg = NULL;
+ client->signon = client->lastactivity = time(NULL);
if (!client->nick)
return;
client->regstate = REG_REGISTERED;