|
|
@@ -41,414 +41,6 @@ static int do_op(char *nick, struct chanset_t *chan, int force)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-/* #define NEW_ADDMODE 1 */
|
|
|
-#undef NEW_ADDMODE
|
|
|
-
|
|
|
-#ifdef NEW_ADDMODE
|
|
|
-void dequeue_op_deop(struct chanset_t * chan);
|
|
|
-
|
|
|
-static void flush_mode(struct chanset_t *chan, int pri)
|
|
|
-{
|
|
|
- char *p = NULL, out[512] = "", post[512] = "";
|
|
|
- size_t postsize = sizeof(post);
|
|
|
- int i, plus = 2; /* 0 = '-', 1 = '+', 2 = none */
|
|
|
-
|
|
|
- dequeue_op_deop(chan);
|
|
|
- p = out;
|
|
|
- post[0] = 0, postsize--;
|
|
|
-
|
|
|
- if (chan->pls[0]) {
|
|
|
- *p++ = '+', plus = 1;
|
|
|
- for (i = 0; i < strlen(chan->pls); i++)
|
|
|
- *p++ = chan->pls[i];
|
|
|
- chan->pls[0] = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (chan->mns[0]) {
|
|
|
- *p++ = '-', plus = 0;
|
|
|
- for (i = 0; i < strlen(chan->mns); i++)
|
|
|
- *p++ = chan->mns[i];
|
|
|
- chan->mns[0] = 0;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- chan->bytes = 0;
|
|
|
- chan->compat = 0;
|
|
|
-
|
|
|
- /* +k or +l ? */
|
|
|
- if (chan->key && !chan->rmkey) {
|
|
|
- if (plus != 1) {
|
|
|
- *p++ = '+', plus = 1;
|
|
|
- }
|
|
|
- *p++ = 'k';
|
|
|
-
|
|
|
- postsize -= egg_strcatn(post, chan->key, sizeof(post));
|
|
|
- postsize -= egg_strcatn(post, " ", sizeof(post));
|
|
|
-
|
|
|
- free(chan->key), chan->key = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- /* max +l is signed 2^32 on ircnet at least... so makesure we've got at least
|
|
|
- * a 13 char buffer for '-2147483647 \0'. We'll be overwriting the existing
|
|
|
- * terminating null in 'post', so makesure postsize >= 12.
|
|
|
- */
|
|
|
- if (chan->limit != 0 && postsize >= 12) {
|
|
|
- if (plus != 1) {
|
|
|
- *p++ = '+', plus = 1;
|
|
|
- }
|
|
|
- *p++ = 'l';
|
|
|
-
|
|
|
- /* 'sizeof(post) - 1' is used because we want to overwrite the old null */
|
|
|
- postsize -= sprintf(&post[(sizeof(post) - 1) - postsize], "%d ", chan->limit);
|
|
|
-
|
|
|
- chan->limit = 0;
|
|
|
- }
|
|
|
-
|
|
|
- /* -k ? */
|
|
|
- if (chan->rmkey) {
|
|
|
- if (plus) {
|
|
|
- *p++ = '-', plus = 0;
|
|
|
- }
|
|
|
- *p++ = 'k';
|
|
|
-
|
|
|
- postsize -= egg_strcatn(post, chan->rmkey, sizeof(post));
|
|
|
- postsize -= egg_strcatn(post, " ", sizeof(post));
|
|
|
-
|
|
|
- free(chan->rmkey), chan->rmkey = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- /* Do -{b,e,I} before +{b,e,I} to avoid the server ignoring overlaps */
|
|
|
- for (i = 0; i < modesperline; i++) {
|
|
|
- if ((chan->cmode[i].type & MINUS) &&
|
|
|
- postsize > strlen(chan->cmode[i].op)) {
|
|
|
- if (plus) {
|
|
|
- *p++ = '-', plus = 0;
|
|
|
- }
|
|
|
-
|
|
|
- *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
|
|
|
- ((chan->cmode[i].type & CHOP) ? 'o' :
|
|
|
- ((chan->cmode[i].type & EXEMPT) ? 'e' :
|
|
|
- ((chan->cmode[i].type & INVITE) ? 'I' : 'v'))));
|
|
|
-
|
|
|
- postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
|
|
|
- postsize -= egg_strcatn(post, " ", sizeof(post));
|
|
|
-
|
|
|
- free(chan->cmode[i].op), chan->cmode[i].op = NULL;
|
|
|
- chan->cmode[i].type = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* now do all the + modes... */
|
|
|
- for (i = 0; i < modesperline; i++) {
|
|
|
- if ((chan->cmode[i].type & PLUS) &&
|
|
|
- postsize > strlen(chan->cmode[i].op)) {
|
|
|
- if (plus != 1) {
|
|
|
- *p++ = '+', plus = 1;
|
|
|
- }
|
|
|
-
|
|
|
- *p++ = ((chan->cmode[i].type & BAN) ? 'b' :
|
|
|
- ((chan->cmode[i].type & CHOP) ? 'o' :
|
|
|
- ((chan->cmode[i].type & EXEMPT) ? 'e' :
|
|
|
- ((chan->cmode[i].type & INVITE) ? 'I' : 'v'))));
|
|
|
-
|
|
|
- postsize -= egg_strcatn(post, chan->cmode[i].op, sizeof(post));
|
|
|
- postsize -= egg_strcatn(post, " ", sizeof(post));
|
|
|
-
|
|
|
- free(chan->cmode[i].op), chan->cmode[i].op = NULL;
|
|
|
- chan->cmode[i].type = 0;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* remember to terminate the buffer ('out')... */
|
|
|
- *p = 0;
|
|
|
-
|
|
|
- if (post[0]) {
|
|
|
- /* remove the trailing space... */
|
|
|
- size_t index = (sizeof(post) - 1) - postsize;
|
|
|
- if (index > 0 && post[index - 1] == ' ')
|
|
|
- post[index - 1] = 0;
|
|
|
-
|
|
|
- egg_strcatn(out, " ", sizeof(out));
|
|
|
- egg_strcatn(out, post, sizeof(out));
|
|
|
- }
|
|
|
- if (out[0]) {
|
|
|
- if (pri == QUICK) {
|
|
|
- char outbuf[201] = "";
|
|
|
-
|
|
|
- sprintf(outbuf, "MODE %s %s\n", chan->name, out);
|
|
|
- tputs(serv, outbuf, strlen(outbuf));
|
|
|
- /* dprintf(DP_MODE, "MODE %s %s\n", chan->name, out); */
|
|
|
- }
|
|
|
- else
|
|
|
- dprintf(DP_SERVER, "MODE %s %s\n", chan->name, out);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void dequeue_op_deop(struct chanset_t * chan) {
|
|
|
- char lines[4096], modechars[10] = "", nicks[128] = "";
|
|
|
- int i = 0, cnt = 0;
|
|
|
-
|
|
|
- lines[0] = 0;
|
|
|
- while ((i < 20) && (chan->opqueue[i].target)) {
|
|
|
- strcat(nicks, " ");
|
|
|
- strcat(nicks, chan->opqueue[i].target);
|
|
|
- if (!modechars[0])
|
|
|
- strcat(modechars, " +");
|
|
|
- strcat(modechars, "o");
|
|
|
- cnt++;
|
|
|
- if (!(cnt % 4)) {
|
|
|
- strcat(lines, "MODE ");
|
|
|
- strcat(lines, chan->name);
|
|
|
- strcat(lines, modechars);
|
|
|
- strcat(lines, nicks);
|
|
|
- strcat(lines, "\n");
|
|
|
- modechars[0] = 0;
|
|
|
- nicks[0] = 0;
|
|
|
- }
|
|
|
- free(chan->opqueue[i].target);
|
|
|
- chan->opqueue[i].target = NULL;
|
|
|
- i++;
|
|
|
- }
|
|
|
- if (modechars[0] && chan->deopqueue[0].target)
|
|
|
- strcat(modechars, "-");
|
|
|
- i = 0;
|
|
|
- while ((i < 20) && (chan->deopqueue[i].target)) {
|
|
|
- strcat(nicks, " ");
|
|
|
- strcat(nicks, chan->deopqueue[i].target);
|
|
|
- if (!modechars[0])
|
|
|
- strcat(modechars, " -");
|
|
|
- strcat(modechars, "o");
|
|
|
- cnt++;
|
|
|
- if (!(cnt % 4)) {
|
|
|
- strcat(lines, "MODE ");
|
|
|
- strcat(lines, chan->name);
|
|
|
- strcat(lines, modechars);
|
|
|
- strcat(lines, nicks);
|
|
|
- strcat(lines, "\n");
|
|
|
- modechars[0] = 0;
|
|
|
- nicks[0] = 0;
|
|
|
- if (cnt >= 24) {
|
|
|
- dprintf(DP_SERVER, lines);
|
|
|
- lines[0]=0;
|
|
|
- }
|
|
|
- }
|
|
|
- free(chan->deopqueue[i].target);
|
|
|
- chan->deopqueue[i].target = NULL;
|
|
|
- i++;
|
|
|
- }
|
|
|
- if (cnt % 4) {
|
|
|
- strcat(lines, "MODE ");
|
|
|
- strcat(lines, chan->name);
|
|
|
- strcat(lines, modechars);
|
|
|
- strcat(lines, nicks);
|
|
|
- strcat(lines, "\n");
|
|
|
- }
|
|
|
- if (lines[0])
|
|
|
- dprintf(DP_SERVER, lines);
|
|
|
-}
|
|
|
-
|
|
|
-void queue_op(struct chanset_t *chan, char *op) {
|
|
|
- int n;
|
|
|
- memberlist *m = NULL;
|
|
|
-
|
|
|
- for (n = 0; n < 20; n++) {
|
|
|
- if (!chan->opqueue[n].target) {
|
|
|
- chan->opqueue[n].target = strdup(op);
|
|
|
- m = ismember(chan, op);
|
|
|
- if (m)
|
|
|
- m->flags |= SENTOP;
|
|
|
- if (n == 19)
|
|
|
- dequeue_op_deop(chan);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void queue_deop(struct chanset_t *chan, char *op) {
|
|
|
- int n;
|
|
|
- memberlist *m = NULL;
|
|
|
-
|
|
|
- for (n = 0; n < 20; n++) {
|
|
|
- if (!chan->deopqueue[n].target) {
|
|
|
- chan->deopqueue[n].target = strdup(op);
|
|
|
- m = ismember(chan, op);
|
|
|
- if (m)
|
|
|
- m->flags |= SENTDEOP;
|
|
|
- if (n == 19)
|
|
|
- dequeue_op_deop(chan);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/* Queue a channel mode change
|
|
|
- */
|
|
|
-void add_mode(struct chanset_t *chan, char plus, char mode, char *op)
|
|
|
-{
|
|
|
- int i, type, modes, l;
|
|
|
- masklist *m = NULL;
|
|
|
- memberlist *mx = NULL;
|
|
|
- char s[21] = "";
|
|
|
-
|
|
|
- if (!me_op(chan))
|
|
|
- return; /* No point in queueing the mode */
|
|
|
-
|
|
|
- if (mode == 'o') {
|
|
|
- if (plus=='+')
|
|
|
- queue_op(chan, op);
|
|
|
- else
|
|
|
- queue_deop(chan, op);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (mode == 'v') {
|
|
|
- mx = ismember(chan, op);
|
|
|
- if (!mx)
|
|
|
- return;
|
|
|
-
|
|
|
- if (plus == '-' && mode == 'v') {
|
|
|
- if (chan_sentdevoice(mx) || !chan_hasvoice(mx))
|
|
|
- return;
|
|
|
- mx->flags |= SENTDEVOICE;
|
|
|
- }
|
|
|
- if (plus == '+' && mode == 'v') {
|
|
|
- if (chan_sentvoice(mx) || chan_hasvoice(mx))
|
|
|
- return;
|
|
|
- mx->flags |= SENTVOICE;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (chan->compat == 0) {
|
|
|
- if (mode == 'e' || mode == 'I')
|
|
|
- chan->compat = 2;
|
|
|
- else
|
|
|
- chan->compat = 1;
|
|
|
- } else if (mode == 'e' || mode == 'I') {
|
|
|
- if (prevent_mixing && chan->compat == 1)
|
|
|
- flush_mode(chan, NORMAL);
|
|
|
- } else if (prevent_mixing && chan->compat == 2)
|
|
|
- flush_mode(chan, NORMAL);
|
|
|
-
|
|
|
- if (mode == 'o' || mode == 'b' || mode == 'v' || mode == 'e' || mode == 'I') {
|
|
|
- type = (plus == '+' ? PLUS : MINUS) |
|
|
|
- (mode == 'o' ? CHOP :
|
|
|
- (mode == 'b' ? BAN :
|
|
|
- (mode == 'v' ? VOICE :
|
|
|
- (mode == 'e' ? EXEMPT : INVITE))));
|
|
|
-
|
|
|
- /*
|
|
|
- * FIXME: Some networks remove overlapped bans, IrcNet does not
|
|
|
- * (poptix/drummer)
|
|
|
- *
|
|
|
- * Note: On ircnet ischanXXX() should be used, otherwise isXXXed().
|
|
|
- */
|
|
|
- /* If removing a non-existant mask... */
|
|
|
- if ((plus == '-' &&
|
|
|
- ((mode == 'b' && !ischanban(chan, op)) ||
|
|
|
- (mode == 'e' && !ischanexempt(chan, op)) ||
|
|
|
- (mode == 'I' && !ischaninvite(chan, op)))) ||
|
|
|
- /* or adding an existant mask... */
|
|
|
- (plus == '+' &&
|
|
|
- ((mode == 'b' && ischanban(chan, op)) ||
|
|
|
- (mode == 'e' && ischanexempt(chan, op)) ||
|
|
|
- (mode == 'I' && ischaninvite(chan, op)))))
|
|
|
- return; /* ...nuke it */
|
|
|
-
|
|
|
- /* If there are already max_bans bans, max_exempts exemptions,
|
|
|
- * max_invites invitations or max_modes +b/+e/+I modes on the
|
|
|
- * channel, don't try to add one more.
|
|
|
- */
|
|
|
- if (plus == '+' && (mode == 'b' || mode == 'e' || mode == 'I')) {
|
|
|
- int bans = 0, exempts = 0, invites = 0;
|
|
|
-
|
|
|
- for (m = chan->channel.ban; m && m->mask[0]; m = m->next)
|
|
|
- bans++;
|
|
|
- if (mode == 'b')
|
|
|
- if (bans >= max_bans)
|
|
|
- return;
|
|
|
-
|
|
|
- for (m = chan->channel.exempt; m && m->mask[0]; m = m->next)
|
|
|
- exempts++;
|
|
|
- if (mode == 'e')
|
|
|
- if (exempts >= max_exempts)
|
|
|
- return;
|
|
|
-
|
|
|
- for (m = chan->channel.invite; m && m->mask[0]; m = m->next)
|
|
|
- invites++;
|
|
|
- if (mode == 'I')
|
|
|
- if (invites >= max_invites)
|
|
|
- return;
|
|
|
-
|
|
|
- if (bans + exempts + invites >= max_modes)
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- /* op-type mode change */
|
|
|
- for (i = 0; i < modesperline; i++)
|
|
|
- if (chan->cmode[i].type == type && chan->cmode[i].op != NULL &&
|
|
|
- !rfc_casecmp(chan->cmode[i].op, op))
|
|
|
- return; /* Already in there :- duplicate */
|
|
|
- l = strlen(op) + 1;
|
|
|
- if (chan->bytes + l > mode_buf_len)
|
|
|
- flush_mode(chan, NORMAL);
|
|
|
- for (i = 0; i < modesperline; i++)
|
|
|
- if (chan->cmode[i].type == 0) {
|
|
|
- chan->cmode[i].type = type;
|
|
|
- chan->cmode[i].op = (char *) calloc(1, l);
|
|
|
- chan->bytes += l; /* Add 1 for safety */
|
|
|
- strcpy(chan->cmode[i].op, op);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /* +k ? store key */
|
|
|
- else if (plus == '+' && mode == 'k') {
|
|
|
- if (chan->key)
|
|
|
- free(chan->key);
|
|
|
- chan->key = (char *) calloc(1, strlen(op) + 1);
|
|
|
- strcpy(chan->key, op);
|
|
|
- }
|
|
|
- /* -k ? store removed key */
|
|
|
- else if (plus == '-' && mode == 'k') {
|
|
|
- if (chan->rmkey)
|
|
|
- free(chan->rmkey);
|
|
|
- chan->rmkey = (char *) calloc(1, strlen(op) + 1);
|
|
|
- strcpy(chan->rmkey, op);
|
|
|
- }
|
|
|
- /* +l ? store limit */
|
|
|
- else if (plus == '+' && mode == 'l')
|
|
|
- chan->limit = atoi(op);
|
|
|
- else {
|
|
|
- /* Typical mode changes */
|
|
|
- if (plus == '+')
|
|
|
- strcpy(s, chan->pls);
|
|
|
- else
|
|
|
- strcpy(s, chan->mns);
|
|
|
- if (!strchr(s, mode)) {
|
|
|
- if (plus == '+') {
|
|
|
- chan->pls[strlen(chan->pls) + 1] = 0;
|
|
|
- chan->pls[strlen(chan->pls)] = mode;
|
|
|
- } else {
|
|
|
- chan->mns[strlen(chan->mns) + 1] = 0;
|
|
|
- chan->mns[strlen(chan->mns)] = mode;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- modes = modesperline; /* Check for full buffer. */
|
|
|
- for (i = 0; i < modesperline; i++)
|
|
|
- if (chan->cmode[i].type)
|
|
|
- modes--;
|
|
|
- if (include_lk && chan->limit)
|
|
|
- modes--;
|
|
|
- if (include_lk && chan->rmkey)
|
|
|
- modes--;
|
|
|
- if (include_lk && chan->key)
|
|
|
- modes--;
|
|
|
- if (modes < 1)
|
|
|
- flush_mode(chan, NORMAL); /* Full buffer! Flush modes. */
|
|
|
-}
|
|
|
-#else /* OLD SHIT */
|
|
|
-
|
|
|
static void flush_mode(struct chanset_t *chan, int pri)
|
|
|
{
|
|
|
char *p = NULL, out[512] = "", post[512] = "";
|
|
|
@@ -749,7 +341,6 @@ void add_mode(struct chanset_t *chan, char plus, char mode, char *op)
|
|
|
if (modes < 1)
|
|
|
flush_mode(chan, NORMAL); /* Full buffer! Flush modes. */
|
|
|
}
|
|
|
-#endif /* NEW_ADDMODE */
|
|
|
|
|
|
/*
|
|
|
* Mode parsing functions
|