#define CMD_VERSION "VERSION"
#define CMD_WALLCHOPS "WALLCHOPS"
#define CMD_WALLOPS "WALLOPS"
+#define CMD_WALLHOPS "WALLHOPS"
#define CMD_WALLUSERS "WALLUSERS"
#define CMD_WALLVOICES "WALLVOICES"
+#define CMD_WALLHOPS "WALLHOPS"
#define CMD_WHO "WHO"
#define CMD_WHOIS "WHOIS"
#define CMD_WHOWAS "WHOWAS"
#define TOK_VERSION "V"
#define TOK_WALLCHOPS "WC"
#define TOK_WALLOPS "WA"
+#define TOK_WALLHOPS "WH"
#define TOK_WALLUSERS "WU"
#define TOK_WALLVOICES "WV"
+#define TOK_WALLHOPS "WH"
#define TOK_WHO "H"
#define TOK_WHOIS "W"
#define TOK_WHOWAS "X"
#define P10_VERSION TYPE(VERSION)
#define P10_WALLCHOPS TYPE(WALLCHOPS)
#define P10_WALLOPS TYPE(WALLOPS)
+#define P10_WALLHOPS TYPE(WALLHOPS)
#define P10_WALLUSERS TYPE(WALLUSERS)
#define P10_WALLVOICES TYPE(WALLVOICES)
#define P10_WHO TYPE(WHO)
void
irc_gline(struct server *srv, struct gline *gline)
{
- putsock("%s " P10_GLINE " %s +%s %ld :%s",
- self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->reason);
+ putsock("%s " P10_GLINE " %s +%s %ld :<%s> %s",
+ self->numeric, (srv ? srv->numeric : "*"), gline->target, gline->expires-now, gline->issuer, gline->reason);
}
void
int pos, base_len, len;
struct modeNode *mn;
struct banNode *bn;
+ struct exemptNode *en;
long last_mode=-1;
unsigned int n;
burst_line[pos++] = ':';
if (last_mode & MODE_CHANOP)
burst_line[pos++] = 'o';
+ if (last_mode & MODE_HALFOP)
+ burst_line[pos++] = 'h';
if (last_mode & MODE_VOICE)
burst_line[pos++] = 'v';
}
burst_line[pos++] = ' ';
}
}
+ if (chan->exemptlist.used) {
+ /* dump the exempt */
+ if (pos+2+strlen(chan->exemptlist.list[0]->exempt) > 505) {
+ burst_line[pos-1] = 0;
+ putsock("%s", burst_line);
+ pos = base_len;
+ } else {
+ burst_line[pos++] = ' ';
+ }
+
+ burst_line[pos++] = ' ';
+ burst_line[pos++] = '~';
+ burst_line[pos++] = ' ';
+ base_len = pos;
+ for (n=0; n<chan->exemptlist.used; n++) {
+ en = chan->exemptlist.list[n];
+ len = strlen(en->exempt);
+ if (pos+len+1 > 510) {
+ burst_line[pos-1] = 0; /* -1 to back up over the space or comma */
+ putsock("%s", burst_line);
+ pos = base_len;
+ }
+ memcpy(burst_line+pos, en->exempt, len);
+ pos += len;
+ burst_line[pos++] = ' ';
+ }
+ }
/* print the last line */
burst_line[pos] = 0;
putsock("%s", burst_line);
return;
}
- AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL));
+ AddChannelUser(cd->user, AddChannel(name, cd->when, NULL, NULL, NULL));
}
static CMD_FUNC(cmd_create)
static CMD_FUNC(cmd_burst)
{
extern int rel_age;
- char modes[MAXLEN], *members = "", *banlist = NULL;
- unsigned int next = 3, res = 1;
+ char modes[MAXLEN], *members = "";
+ static char exemptlist[MAXLEN], banlist[MAXLEN];
+ unsigned int next = 3;
+ unsigned int res = 1;
+ int ctype = 0, echeck = 0, bcheck = 0;
struct chanNode *cNode;
struct userNode *un;
struct modeNode *mNode;
long mode;
char *user, *end, sep;
time_t in_timestamp;
+ char* parm = NULL;
if (argc < 3)
return 0;
modes[0] = 0;
+
+ exemptlist[0] = 0;
+ banlist[0] = 0;
+
while (next < argc) {
switch (argv[next][0]) {
case '+': {
const char *pos;
int n_modes;
- for (pos=argv[next], n_modes = 1; *pos; pos++)
+ for (pos=argv[next], n_modes = 1; *pos; pos++) {
if ((*pos == 'k') || (*pos == 'l'))
n_modes++;
+ }
unsplit_string(argv+next, n_modes, modes);
next += n_modes;
break;
}
- case '%': banlist = argv[next++]+1; break;
- default: members = argv[next++]; break;
+ case '%': {
+ for(parm = mysep(&argv[next], " "); /* parm = first param */
+ parm; /* While param is not null */
+ parm = mysep(&argv[next], " ") /* parm = next param */
+ )
+ {
+ switch (parm[0]) {
+ case '%': {
+ ctype = 1;
+ break;
+ }
+ case '~': {
+ ctype = 2;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ if (ctype == 1) {
+ if (bcheck == 0) {
+ /* strip % char off start of very first ban */
+ strncat(banlist, strtok(parm, "%"), sizeof(banlist) - 1 - strlen(banlist));
+ strncat(banlist, " ", sizeof(banlist) - 1 - strlen(banlist));
+ bcheck = 1;
+ } else {
+ strncat(banlist, parm, sizeof(banlist) - 1 - strlen(banlist));
+ strncat(banlist, " ", sizeof(banlist) - 1 - strlen(banlist));
+ }
+ } else if (ctype == 2) {
+ if (echeck == 0) {
+ echeck = 1;
+ } else {
+ strncat(exemptlist, parm, sizeof(exemptlist) - 1 - strlen(exemptlist));
+ strncat(exemptlist, " ", sizeof(exemptlist) - 1 - strlen(exemptlist));
+ }
+ }
+ }
+ next++;
+ break;
+ }
+ default: {
+ members = argv[next++];
+ break;
}
+ }
}
+
in_timestamp = atoi(argv[2]);
if ((cNode = dict_find(unbursted_channels, argv[1], NULL))) {
cNode->timestamp = in_timestamp;
dict_remove(unbursted_channels, cNode->name);
irc_burst(cNode);
}
- cNode = AddChannel(argv[1], in_timestamp, modes, banlist);
/* Burst channel members in now. */
+ cNode = AddChannel(argv[1], in_timestamp, modes, banlist, exemptlist);
+
for (user = members, sep = *members, mode = 0; sep; user = end) {
for (end = user + 3; isalnum(*end) || *end == '[' || *end == ']'; end++) ;
sep = *end++; end[-1] = 0;
while ((sep = *end++)) {
if (sep == 'o')
mode |= MODE_CHANOP;
+ else if (sep == 'h')
+ mode |= MODE_HALFOP;
else if (sep == 'v')
mode |= MODE_VOICE;
else
dict_insert(irc_func_dict, TOK_WALLCHOPS, cmd_dummy);
dict_insert(irc_func_dict, CMD_WALLVOICES, cmd_dummy);
dict_insert(irc_func_dict, TOK_WALLVOICES, cmd_dummy);
+ dict_insert(irc_func_dict, CMD_WALLHOPS, cmd_dummy);
+ dict_insert(irc_func_dict, TOK_WALLHOPS, cmd_dummy);
/* Ignore opers being silly. */
dict_insert(irc_func_dict, CMD_WALLOPS, cmd_dummy);
dict_insert(irc_func_dict, TOK_WALLOPS, cmd_dummy);
+ dict_insert(irc_func_dict, CMD_WALLHOPS, cmd_dummy);
+ dict_insert(irc_func_dict, TOK_WALLHOPS, cmd_dummy);
/* We have reliable clock! Always! Wraaa! */
dict_insert(irc_func_dict, CMD_SETTIME, cmd_dummy);
dict_insert(irc_func_dict, TOK_SETTIME, cmd_dummy);
case 'r': do_chan_mode(MODE_REGONLY); break;
case 's': do_chan_mode(MODE_SECRET); break;
case 't': do_chan_mode(MODE_TOPICLIMIT); break;
+ case 'S': do_chan_mode(MODE_STRIPCOLOR); break;
+ case 'M': do_chan_mode(MODE_MODUNREG); break;
+ case 'N': do_chan_mode(MODE_NONOTICE); break;
+ case 'Q': do_chan_mode(MODE_NOQUITMSGS); break;
+ case 'T': do_chan_mode(MODE_NOAMSG); break;
+ case 'O': do_chan_mode(MODE_OPERSONLY); break;
+// uncomment this when ssl is enabled on the network.
+// case 'z': do_chan_mode(MODE_SSLONLY); break;
#undef do_chan_mode
case 'l':
if (add) {
change->args[ch_arg].mode |= MODE_REMOVE;
change->args[ch_arg++].hostmask = modes[in_arg++];
break;
- case 'o': case 'v':
+ case 'e':
+ if (!(flags & MCP_ALLOW_OVB))
+ goto error;
+ if (in_arg >= argc)
+ goto error;
+ change->args[ch_arg].mode = MODE_EXEMPT;
+ if (!add)
+ change->args[ch_arg].mode |= MODE_REMOVE;
+ change->args[ch_arg++].hostmask = modes[in_arg++];
+ break;
+ case 'o': case 'h': case 'v':
{
struct userNode *victim;
if (!(flags & MCP_ALLOW_OVB))
goto error;
if (in_arg >= argc)
goto error;
- change->args[ch_arg].mode = (modes[0][ii] == 'o') ? MODE_CHANOP : MODE_VOICE;
+
+ if (modes[0][ii] == 'o')
+ change->args[ch_arg].mode = MODE_CHANOP;
+ else if (modes[0][ii] == 'h')
+ change->args[ch_arg].mode = MODE_HALFOP;
+ else if (modes[0][ii] == 'v')
+ change->args[ch_arg].mode = MODE_VOICE;
+
if (!add)
change->args[ch_arg].mode |= MODE_REMOVE;
if (flags & MCP_FROM_SERVER)
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(STRIPCOLOR, 'S');
+ DO_MODE_CHAR(MODUNREG, 'M');
+ DO_MODE_CHAR(NONOTICE, 'N');
+ DO_MODE_CHAR(NOQUITMSGS, 'Q');
+ DO_MODE_CHAR(NOAMSG, 'T');
+ DO_MODE_CHAR(OPERSONLY, 'O');
+ // uncomment this for ssl support
+ //DO_MODE_CHAR(SSLONLY, 'z');
#undef DO_MODE_CHAR
if (change->modes_clear & channel->modes & MODE_KEY)
mod_chanmode_append(&chbuf, 'k', channel->key);
case MODE_BAN:
mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask);
break;
+ case MODE_EXEMPT:
+ mod_chanmode_append(&chbuf, 'e', change->args[arg].hostmask);
+ break;
default:
if (change->args[arg].mode & MODE_CHANOP)
mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->numeric);
+ if (change->args[arg].mode & MODE_HALFOP)
+ mod_chanmode_append(&chbuf, 'h', change->args[arg].member->user->numeric);
if (change->args[arg].mode & MODE_VOICE)
mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->numeric);
break;
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(STRIPCOLOR, 'S');
+ DO_MODE_CHAR(MODUNREG, 'M');
+ DO_MODE_CHAR(NONOTICE, 'N');
+ DO_MODE_CHAR(NOQUITMSGS, 'Q');
+ DO_MODE_CHAR(NOAMSG, 'T');
+ DO_MODE_CHAR(OPERSONLY, 'O');
+ // uncomment this for ssl support
+ //DO_MODE_CHAR(SSLONLY, 'z');
#undef DO_MODE_CHAR
if(change->modes_set & MODE_KEY)
mod_chanmode_append(&chbuf, 'k', change->new_key);
case MODE_BAN:
mod_chanmode_append(&chbuf, 'b', change->args[arg].hostmask);
break;
+ case MODE_EXEMPT:
+ mod_chanmode_append(&chbuf, 'e', change->args[arg].hostmask);
+ break;
default:
if (change->args[arg].mode & MODE_CHANOP)
mod_chanmode_append(&chbuf, 'o', change->args[arg].member->user->numeric);
+ if (change->args[arg].mode & MODE_HALFOP)
+ mod_chanmode_append(&chbuf, 'h', change->args[arg].member->user->numeric);
if (change->args[arg].mode & MODE_VOICE)
mod_chanmode_append(&chbuf, 'v', change->args[arg].member->user->numeric);
break;
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(STRIPCOLOR, 'S');
+ DO_MODE_CHAR(MODUNREG, 'M');
+ DO_MODE_CHAR(NONOTICE, 'N');
+ DO_MODE_CHAR(NOQUITMSGS, 'Q');
+ DO_MODE_CHAR(NOAMSG, 'T');
+ DO_MODE_CHAR(OPERSONLY, 'O');
+ // uncomment this for ssl support
+ //DO_MODE_CHAR(SSLONLY, 'z');
#undef DO_MODE_CHAR
}
if (change->modes_set) {
DO_MODE_CHAR(REGONLY, 'r');
DO_MODE_CHAR(NOCOLORS, 'c');
DO_MODE_CHAR(NOCTCPS, 'C');
+ DO_MODE_CHAR(STRIPCOLOR, 'S');
+ DO_MODE_CHAR(MODUNREG, 'M');
+ DO_MODE_CHAR(NONOTICE, 'N');
+ DO_MODE_CHAR(NOQUITMSGS, 'Q');
+ DO_MODE_CHAR(NOAMSG, 'T');
+ DO_MODE_CHAR(OPERSONLY, 'O');
+ // uncomment this for ssl support
+ //DO_MODE_CHAR(SSLONLY, 'z');
#undef DO_MODE_CHAR
switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
case MODE_KEY|MODE_LIMIT:
for (remove = 0; *modes; modes++) {
switch (*modes) {
case 'o': remove |= MODE_CHANOP; break;
+ case 'h': remove |= MODE_HALFOP; break;
case 'v': remove |= MODE_VOICE; break;
case 'p': remove |= MODE_PRIVATE; break;
case 's': remove |= MODE_SECRET; break;
channel->limit = 0;
break;
case 'b': remove |= MODE_BAN; break;
+ case 'e': remove |= MODE_EXEMPT; break;
case 'D': remove |= MODE_DELAYJOINS; break;
case 'r': remove |= MODE_REGONLY; break;
case 'c': remove |= MODE_NOCOLORS;
case 'C': remove |= MODE_NOCTCPS; break;
+ case 'S': remove |= MODE_STRIPCOLOR; break;
+ case 'M': remove |= MODE_MODUNREG; break;
+ case 'N': remove |= MODE_NONOTICE; break;
+ case 'Q': remove |= MODE_NOQUITMSGS; break;
+ case 'T': remove |= MODE_NOAMSG; break;
+ case 'O': remove |= MODE_OPERSONLY; break;
}
}
channel->banlist.used = 0;
}
+ /* If removing exempts, kill 'em all. */
+ if ((remove & MODE_EXEMPT) && channel->exemptlist.used) {
+ unsigned int i;
+ for (i=0; i<channel->exemptlist.used; i++)
+ free(channel->exemptlist.list[i]);
+ channel->exemptlist.used = 0;
+ }
+
/* Remove member modes. */
- if ((remove & (MODE_CHANOP | MODE_VOICE)) && channel->members.used) {
- int mask = ~(remove & (MODE_CHANOP | MODE_VOICE));
+ if ((remove & (MODE_CHANOP | MODE_HALFOP | MODE_VOICE)) && channel->members.used) {
+ int mask = ~(remove & (MODE_CHANOP | MODE_HALFOP | MODE_VOICE));
unsigned int i;
for (i = 0; i < channel->members.used; i++)