/* proto-common.c - common IRC protocol parsing/sending support
* Copyright 2000-2004 srvx Development Team
*
- * This file is part of srvx.
+ * This file is part of x3.
*
* srvx is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
log_module(MAIN_LOG, LOG_ERROR, "Could not find VERSION origin user %s", origin);
return 0;
}
- irc_numeric(user, 351, "%s.%s %s :%s", PACKAGE_TARNAME, PACKAGE_VERSION, self->name, CODENAME);
+ irc_numeric(user, 351, "%s %s %s", PACKAGE_TARNAME, PACKAGE_VERSION, self->name);
return 1;
}
mn->idle_since = now;
/* Never send a NOTICE to a channel to one of the services */
- if (!pd->is_notice && cf->func && GetUserMode(cn, cf->service))
- cf->func(pd->user, cn, pd->text+1, cf->service);
+ if (!pd->is_notice && cf->func
+ && ((cn->modes & MODE_REGISTERED) || GetUserMode(cn, cf->service)))
+ cf->func(pd->user, cn, pd->text+1, cf->service);
/* This catches *all* text sent to the channel that the services server sees */
for (x = 0; x < ALLCHANMSG_FUNCS_MAX; x++) {
if (!cf->func)
break; /* end of list */
else
- cf->func(pd->user, cn, pd->text, cf->service);
+ cf->func(pd->user, cn, pd->text, cf->service);
}
}
mod_chanmode_apply(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change)
{
struct banNode *bn;
+ struct exemptNode *en;
unsigned int ii, jj;
assert(change->argc <= change->alloc_argc);
* to be more specific than an existing ban.
*/
for (jj=0; jj<channel->banlist.used; ++jj) {
- if (match_ircglobs(change->args[ii].hostmask, channel->banlist.list[jj]->ban)) {
- banList_remove(&channel->banlist, channel->banlist.list[jj]);
- free(channel->banlist.list[jj]);
+ bn = channel->banlist.list[jj];
+ if (match_ircglobs(change->args[ii].u.hostmask, bn->ban)) {
+ banList_remove(&channel->banlist, bn);
+ free(bn);
jj--;
}
}
bn = calloc(1, sizeof(*bn));
- safestrncpy(bn->ban, change->args[ii].hostmask, sizeof(bn->ban));
+ safestrncpy(bn->ban, change->args[ii].u.hostmask, sizeof(bn->ban));
if (who)
safestrncpy(bn->who, who->nick, sizeof(bn->who));
else
break;
case MODE_REMOVE|MODE_BAN:
for (jj=0; jj<channel->banlist.used; ++jj) {
- if (strcmp(channel->banlist.list[jj]->ban, change->args[ii].hostmask))
+ bn = channel->banlist.list[jj];
+ if (strcmp(bn->ban, change->args[ii].u.hostmask))
continue;
- free(channel->banlist.list[jj]);
- banList_remove(&channel->banlist, channel->banlist.list[jj]);
+ free(bn);
+ banList_remove(&channel->banlist, bn);
+ break;
+ }
+ break;
+ case MODE_EXEMPT:
+ /* If any existing exempt is a subset of the new exempt,
+ * silently remove it. The new exempt is not allowed
+ * to be more specific than an existing exempt.
+ */
+ for (jj=0; jj<channel->exemptlist.used; ++jj) {
+ if (match_ircglobs(change->args[ii].u.hostmask, channel->exemptlist.list[jj]->exempt)) {
+ exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]);
+ free(channel->exemptlist.list[jj]);
+ jj--;
+ }
+ }
+ en = calloc(1, sizeof(*en));
+ safestrncpy(en->exempt, change->args[ii].u.hostmask, sizeof(en->exempt));
+ if (who)
+ safestrncpy(en->who, who->nick, sizeof(en->who));
+ else
+ safestrncpy(en->who, "<unknown>", sizeof(en->who));
+ en->set = now;
+ exemptList_append(&channel->exemptlist, en);
+ break;
+ case MODE_REMOVE|MODE_EXEMPT:
+ for (jj=0; jj<channel->exemptlist.used; ++jj) {
+ if (strcmp(channel->exemptlist.list[jj]->exempt, change->args[ii].u.hostmask))
+ continue;
+ free(channel->exemptlist.list[jj]);
+ exemptList_remove(&channel->exemptlist, channel->exemptlist.list[jj]);
break;
}
break;
case MODE_REMOVE|MODE_VOICE:
case MODE_REMOVE|MODE_VOICE|MODE_CHANOP|MODE_HALFOP:
if (change->args[ii].mode & MODE_REMOVE)
- change->args[ii].member->modes &= ~change->args[ii].mode;
+ change->args[ii].u.member->modes &= ~change->args[ii].mode;
else
- change->args[ii].member->modes |= change->args[ii].mode;
+ change->args[ii].u.member->modes |= change->args[ii].mode;
break;
default:
assert(0 && "Invalid mode argument");
}
int
-irc_make_chanmode(struct chanNode *chan, char *out) {
+irc_make_chanmode(struct chanNode *chan, char *out)
+{
struct mod_chanmode change;
mod_chanmode_init(&change);
change.modes_set = chan->modes;
mask = ~0 << masklen;
masked_ip = ntohl(user->ip.s_addr) & mask;
hostname = alloca(32);
- if (options & GENMASK_SRVXMASK) {
+ if (options & GENMASK_X3MASK) {
sprintf(hostname, "%d.%d.%d.%d/%d", (masked_ip>>24)&0xFF, (masked_ip>>16)&0xFF, (masked_ip>>8)&0xFF, masked_ip&0xFF, masklen);
} else {
int ofs = 0;