| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044 |
- /*
- * Copyright (C) 1997 Robey Pointer
- * Copyright (C) 1999 - 2002 Eggheads Development Team
- * Copyright (C) 2002 - 2008 Bryan Drewery
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- /*
- * tclchan.c -- part of channels.mod
- *
- */
- static int FindElement(char *resultBuf, const char *list, size_t listLength,
- const char **elementPtr, const char **nextPtr,
- size_t *sizePtr, int *bracePtr)
- {
- const char *p = list;
- const char *elemStart = NULL; /* Points to first byte of first element. */
- const char *limit = (list + listLength); /* Points just after list's last byte. */
- int openBraces = 0; /* Brace nesting level during parse. */
- int inQuotes = 0;
- size_t size = 0; /* lint. */
- const char *p2 = NULL;
- /*
- * Skim off leading white space and check for an opening brace or
- * quote. We treat embedded NULLs in the list as bytes belonging to
- * a list element.
- */
- while ((p < limit) && egg_isspace(*p)) { /* INTL: ISO space. */
- p++;
- }
- if (p == limit) { /* no element found */
- elemStart = limit;
- goto done;
- }
- if (*p == '{') {
- openBraces = 1;
- p++;
- } else if (*p == '"') {
- inQuotes = 1;
- p++;
- }
- elemStart = p;
- if (bracePtr != 0) {
- *bracePtr = openBraces;
- }
- /*
- * Find element's end (a space, close brace, or the end of the string).
- */
- while (p < limit) {
- switch (*p) {
- /*
- * Open brace: don't treat specially unless the element is in
- * braces. In this case, keep a nesting count.
- */
- case '{':
- if (openBraces != 0) {
- openBraces++;
- }
- break;
- /*
- * Close brace: if element is in braces, keep nesting count and
- * quit when the last close brace is seen.
- */
- case '}':
- if (openBraces > 1) {
- openBraces--;
- } else if (openBraces == 1) {
- size = (p - elemStart);
- p++;
- if ((p >= limit) || egg_isspace(*p)) { /* INTL: ISO space. */
- goto done;
- }
- /*
- * Garbage after the closing brace; return an error.
- */
- if (resultBuf) {
- p2 = p;
- while ((p2 < limit)
- && (!egg_isspace(*p2)) /* INTL: ISO space. */
- && (p2 < p+20)) {
- p2++;
- }
- // snprintf(resultBuf, RESULT_LEN, "list element in braces followed by \"%.*s\" instead of space", (int) (p2-p), p);
- }
- return ERROR;
- }
- break;
- /*
- * Backslash: skip over everything up to the end of the
- * backslash sequence.
- */
- /* case '\\': {
- Tcl_UtfBackslash(p, &numChars, NULL);
- p += (numChars - 1);
- break;
- }
- */
- /*
- * Space: ignore if element is in braces or quotes; otherwise
- * terminate element.
- */
- case ' ':
- case '\f':
- case '\n':
- case '\r':
- case '\t':
- case '\v':
- if ((openBraces == 0) && !inQuotes) {
- size = (p - elemStart);
- goto done;
- }
- break;
- /*
- * Double-quote: if element is in quotes then terminate it.
- */
- case '"':
- if (inQuotes) {
- size = (p - elemStart);
- p++;
- if ((p >= limit) || egg_isspace(*p)) { /* INTL: ISO space */
- goto done;
- }
- /*
- * Garbage after the closing quote; return an error.
- */
- if (resultBuf) {
- p2 = p;
- while ((p2 < limit)
- && (!egg_isspace(*p2)) /* INTL: ISO space */
- && (p2 < p+20)) {
- p2++;
- }
- // sprintf(resultBuf, "list element in quotes followed by \"%.*s\" %s", (int) (p2-p), p, "instead of space");
- }
- return ERROR;
- }
- break;
- }
- p++;
- }
- /*
- * End of list: terminate element.
- */
- if (p == limit) {
- if (openBraces != 0) {
- if (resultBuf) {
- simple_snprintf(resultBuf, RESULT_LEN, "unmatched open brace in list");
- }
- return ERROR;
- } else if (inQuotes) {
- if (resultBuf) {
- simple_snprintf(resultBuf, RESULT_LEN, "unmatched open quote in list");
- }
- return ERROR;
- }
- size = (p - elemStart);
- }
- done:
- while ((p < limit) && (egg_isspace(*p))) { /* INTL: ISO space. */
- p++;
- }
- *elementPtr = elemStart;
- *nextPtr = p;
- if (sizePtr != 0) {
- *sizePtr = size;
- }
- return OK;
- }
- /* unneeded?
- int CopyAndCollapse(int count, const char *src, char *dst)
- {
- register char c;
- int numRead;
- int newCount = 0;
- int backslashCount;
- for (c = *src; count > 0; src++, c = *src, count--) {
- if (c == '\\') {
- backslashCount = Tcl_UtfBackslash(src, &numRead, dst);
- dst += backslashCount;
- newCount += backslashCount;
- src += numRead-1;
- count -= numRead-1;
- } else {
- *dst = c;
- dst++;
- newCount++;
- }
- }
- *dst = 0;
- return newCount;
- }
- */
- int SplitList(char *resultBuf, const char *list, int *argcPtr, const char ***argvPtr)
- {
- const char **argv = NULL;
- const char *l = NULL;
- const char *element = NULL;
- char *p = NULL;
- int result, brace = 0;
- size_t size = 2; /* initialized to 1 for NULL pointer */
- size_t length, elSize, i = 0;
- /*
- * Figure out how much space to allocate. There must be enough
- * space for both the array of pointers and also for a copy of
- * the list. To estimate the number of pointers needed, count
- * the number of space characters in the list.
- */
- for (l = list; *l != 0; l++) {
- if (egg_isspace(*l)) { /* INTL: ISO space. */
- size++;
- }
- }
- argv = (const char **) my_calloc(1, (unsigned) ((size * sizeof(char *)) + (l - list) + 1 + 15)); /* 15 cuz the tcl src is hard to follow */
- length = strlen(list);
- for (p = ((char *) argv) + size*sizeof(char *); *list != 0; i++) {
- const char *prevList = list;
- result = FindElement(resultBuf, list, length, &element, &list, &elSize, &brace);
- length -= (list - prevList);
- if (result != OK) {
- free((char *) argv);
- return result;
- }
- if (*element == 0) {
- break;
- }
- if (i >= size) {
- free((char *) argv);
- if (resultBuf)
- strlcpy(resultBuf, "internal error in SplitList", RESULT_LEN);
- return ERROR;
- }
- argv[i] = p;
- if (brace) {
- memcpy(p, element, elSize);
- p += elSize;
- *p = 0;
- p++;
- } else {
- /* CopyAndCollapse(elSize, element, p); */
- memcpy(p, element, elSize);
- p += elSize + 1;
- }
- }
- argv[i] = NULL;
- *argvPtr = argv;
- *argcPtr = i;
- return OK;
- }
- /* Parse options for a channel.
- */
- int channel_modify(char *result, struct chanset_t *chan, int items, char **item, bool cmd)
- {
- bool error = 0;
- int old_status = chan->status,
- old_mode_mns_prot = chan->mode_mns_prot,
- old_mode_pls_prot = chan->mode_pls_prot;
- char s[121] = "", result_extra[RESULT_LEN / 2] = "";
- if (result)
- result[0] = 0;
- for (register int i = 0; i < items; i++) {
- /* Chanchar template
- } else if (!strcmp(item[i], "temp")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel temp needs argument", RESULT_LEN);
- return ERROR;
- }
- strlcpy(chan->temp, item[i], sizeof(chan->temp));
- check_temp(chan);
- */
- if (!strcmp(item[i], "chanmode")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel chanmode needs argument", RESULT_LEN);
- return ERROR;
- }
- strlcpy(s, item[i], sizeof(s));
- set_mode_protect(chan, s);
- } else if (!strcmp(item[i], "topic")) {
- char *p = NULL;
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "topic needs argument", RESULT_LEN);
- return ERROR;
- }
- p = replace(item[i], "{", "[");
- p = replace(p, "}", "]");
- strlcpy(chan->topic, p, sizeof(chan->topic));
- } else if (!cmd && !strcmp(item[i], "addedby")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "addedby needs argument", RESULT_LEN);
- return ERROR;
- }
- strlcpy(chan->added_by, item[i], NICKLEN);
- } else if (!cmd && !strcmp(item[i], "addedts")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "addedts needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->added_ts = atoi(item[i]);
- } else if (!strcmp(item[i], "limit")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel limit needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->limitraise = atoi(item[i]);
- chan->limit_prot = 0;
- /*
- } else if (!strcmp(item[i], "revenge-mode")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel revenge-mode needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->revenge_mode = atoi(item[i]);
- */
- } else if (!strcmp(item[i], "ban-time")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel ban-time needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->ban_time = atoi(item[i]);
- } else if (!strcmp(item[i], "exempt-time")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel exempt-time needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->exempt_time = atoi(item[i]);
- } else if (!strcmp(item[i], "invite-time")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel invite-time needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->invite_time = atoi(item[i]);
- } else if (!strcmp(item[i], "closed-ban")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel closed-ban needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->closed_ban = atoi(item[i]);
- } else if (!strcmp(item[i], "closed-invite")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel closed-invite needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->closed_invite = atoi(item[i]);
- if (chan->mode_mns_prot & CHANINV && chan->closed_invite)
- chan->closed_invite = 0;
- } else if (!strcmp(item[i], "closed-private")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel closed-private needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->closed_private = atoi(item[i]);
- if (chan->mode_mns_prot & CHANPRIV && chan->closed_private)
- chan->closed_private = 0;
- } else if (!strcmp(item[i], "voice-non-ident")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel voice-ident needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->voice_non_ident = atoi(item[i]);
- } else if (!strcmp(item[i], "bad-cookie")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel bad-cookie needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->bad_cookie = deflag_translate(item[i]);
- } else if (!strcmp(item[i], "manop")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel manop needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->manop = deflag_translate(item[i]);
- } else if (!strcmp(item[i], "mdop")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel mdop needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->mdop = deflag_translate(item[i]);
- } else if (!strcmp(item[i], "mop")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel mop needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->mop = deflag_translate(item[i]);
- } else if (!strcmp(item[i], "knock")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel knock needs argument", RESULT_LEN);
- return ERROR;
- }
- if (!str_isdigit(item[i])) {
- if (!strcasecmp("Op", item[i]))
- chan->knock_flags = FLOOD_EXEMPT_OP;
- else if (!strcasecmp("Voice", item[i]))
- chan->knock_flags = FLOOD_EXEMPT_VOICE;
- else if (!strcasecmp("User", item[i]))
- chan->knock_flags = FLOOD_EXEMPT_USER;
- else if (!strcasecmp("None", item[i]))
- chan->knock_flags = 0;
- else {
- if (result)
- strlcpy(result, "channel knock only accepts Op|Voice|User|None", RESULT_LEN);
- return ERROR;
- }
- } else
- chan->knock_flags = atoi(item[i]);
- } else if (!strcmp(item[i], "flood-exempt")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel flood-exempt needs argument", RESULT_LEN);
- return ERROR;
- }
- if (!str_isdigit(item[i])) {
- if (!strcasecmp("Op", item[i]))
- chan->flood_exempt_mode = FLOOD_EXEMPT_OP;
- else if (!strcasecmp("Voice", item[i]))
- chan->flood_exempt_mode = FLOOD_EXEMPT_VOICE;
- else if (!strcasecmp("None", item[i]))
- chan->flood_exempt_mode = 0;
- else {
- if (result)
- strlcpy(result, "channel flood-exempt only accepts Op|Voice|None", RESULT_LEN);
- return ERROR;
- }
- } else
- chan->flood_exempt_mode = atoi(item[i]);
- } else if (!strcmp(item[i], "flood-lock-time")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel flood-lock-time needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->flood_lock_time = atoi(item[i]);
- } else if (!strcmp(item[i], "auto-delay")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel auto-delay needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->auto_delay = atoi(item[i]);
- } else if (!strcmp(item[i], "ban-type")) {
- i++;
- if (i >= items) {
- if (result)
- strlcpy(result, "channel ban-type needs argument", RESULT_LEN);
- return ERROR;
- }
- chan->ban_type = atoi(item[i]);
-
- /* Chanint template
- * } else if (!strcmp(item[i], "temp")) {
- * i++;
- * if (i >= items) {
- * if (result)
- * strlcpy(result, "channel temp needs argument", RESULT_LEN);
- * return ERROR;
- * }
- * chan->temp = atoi(item[i]);
- */
- }
- else if (!strcmp(item[i], "+enforcebans"))
- chan->status |= CHAN_ENFORCEBANS;
- else if (!strcmp(item[i], "-enforcebans"))
- chan->status &= ~CHAN_ENFORCEBANS;
- else if (!strcmp(item[i], "+dynamicbans"))
- chan->status |= CHAN_DYNAMICBANS;
- else if (!strcmp(item[i], "-dynamicbans"))
- chan->status &= ~CHAN_DYNAMICBANS;
- else if (!strcmp(item[i], "-userbans"))
- chan->status |= CHAN_NOUSERBANS;
- else if (!strcmp(item[i], "+userbans"))
- chan->status &= ~CHAN_NOUSERBANS;
- else if (!strcmp(item[i], "+bitch"))
- chan->status |= CHAN_BITCH;
- else if (!strcmp(item[i], "-bitch"))
- chan->status &= ~CHAN_BITCH;
- else if (!strcmp(item[i], "+nodesynch"))
- chan->status |= CHAN_NODESYNCH;
- else if (!strcmp(item[i], "-nodesynch"))
- chan->status &= ~CHAN_NODESYNCH;
- else if (!strcmp(item[i], "+inactive"))
- chan->status |= CHAN_INACTIVE;
- else if (!strcmp(item[i], "-inactive"))
- chan->status&= ~CHAN_INACTIVE;
- else if (!strcmp(item[i], "+secret"))
- chan->status |= CHAN_SECRET;
- else if (!strcmp(item[i], "-secret"))
- chan->status &= ~CHAN_SECRET;
- else if (!strcmp(item[i], "+cycle"))
- chan->status |= CHAN_CYCLE;
- else if (!strcmp(item[i], "-cycle"))
- chan->status &= ~CHAN_CYCLE;
- else if (!strcmp(item[i], "+dynamicexempts"))
- chan->status |= CHAN_DYNAMICEXEMPTS;
- else if (!strcmp(item[i], "-dynamicexempts"))
- chan->status &= ~CHAN_DYNAMICEXEMPTS;
- else if (!strcmp(item[i], "-userexempts"))
- chan->status |= CHAN_NOUSEREXEMPTS;
- else if (!strcmp(item[i], "+userexempts"))
- chan->status &= ~CHAN_NOUSEREXEMPTS;
- else if (!strcmp(item[i], "+dynamicinvites"))
- chan->status |= CHAN_DYNAMICINVITES;
- else if (!strcmp(item[i], "-dynamicinvites"))
- chan->status &= ~CHAN_DYNAMICINVITES;
- else if (!strcmp(item[i], "-userinvites"))
- chan->status |= CHAN_NOUSERINVITES;
- else if (!strcmp(item[i], "+userinvites"))
- chan->status &= ~CHAN_NOUSERINVITES;
- else if (!strcmp(item[i], "+closed"))
- chan->status |= CHAN_CLOSED;
- else if (!strcmp(item[i], "-closed"))
- chan->status &= ~CHAN_CLOSED;
- else if (HAVE_TAKE && !strcmp(item[i], "+take"))
- chan->status |= CHAN_TAKE;
- else if (HAVE_TAKE && !strcmp(item[i], "-take"))
- chan->status &= ~CHAN_TAKE;
- else if (!HAVE_TAKE && !strcmp(item[i], "+take"))
- chan->status |= CHAN_BITCH;
- else if (!HAVE_TAKE && !strcmp(item[i], "-take"))
- chan->status &= ~CHAN_BITCH;
- else if (!strcmp(item[i], "+voice"))
- chan->status |= CHAN_VOICE;
- else if (!strcmp(item[i], "-voice"))
- chan->status &= ~CHAN_VOICE;
- else if (!strcmp(item[i], "+autoop"))
- chan->status |= CHAN_AUTOOP;
- else if (!strcmp(item[i], "-autoop"))
- chan->status &= ~CHAN_AUTOOP;
- else if (!strcmp(item[i], "+botbitch"))
- chan->status |= CHAN_BOTBITCH;
- else if (!strcmp(item[i], "-botbitch"))
- chan->status &= ~CHAN_BOTBITCH;
- else if (!strcmp(item[i], "+nomassjoin"))
- chan->status |= CHAN_NOMASSJOIN;
- else if (!strcmp(item[i], "-nomassjoin"))
- chan->status &= ~CHAN_NOMASSJOIN;
- else if (!strcmp(item[i], "+meankicks"))
- chan->status |= CHAN_MEANKICKS;
- else if (!strcmp(item[i], "-meankicks"))
- chan->status &= ~CHAN_MEANKICKS;
- else if (!strcmp(item[i], "+rbl"))
- chan->status |= CHAN_RBL;
- else if (!strcmp(item[i], "-rbl"))
- chan->status &= ~CHAN_RBL;
- else if (!strcmp(item[i], "+voicebitch"))
- chan->status |= CHAN_VOICEBITCH;
- else if (!strcmp(item[i], "-voicebitch"))
- chan->status &= ~CHAN_VOICEBITCH;
- /* Chanflag template
- * else if (!strcmp(item[i], "+temp"))
- * chan->status |= CHAN_TEMP;
- * else if (!strcmp(item[i], "-temp"))
- * chan->status &= ~CHAN_TEMP;
- */
- else if (!strcmp(item[i], "+fastop"))
- chan->status |= CHAN_FASTOP;
- else if (!strcmp(item[i], "-fastop"))
- chan->status &= ~CHAN_FASTOP;
- else if (!strcmp(item[i], "+private"))
- chan->status |= CHAN_PRIVATE;
- else if (!strcmp(item[i], "-private"))
- chan->status &= ~CHAN_PRIVATE;
- else if (!strcmp(item[i], "+backup"))
- chan->status |= CHAN_BACKUP;
- else if (!strcmp(item[i], "-backup"))
- chan->status &= ~CHAN_BACKUP;
- /* ignore wasoptest, stopnethack and clearbans in chanfile, remove
- this later */
- else if (!cmd && !HAVE_TAKE && !strcmp(item[i], "+take")) ;
- else if (!cmd && !HAVE_TAKE && !strcmp(item[i], "-take")) ;
- else if (!cmd && !strcmp(item[i], "stopnethack-mode")) ;
- else if (!cmd && !strcmp(item[i], "revenge-mode")) ;
- else if (!cmd && !strcmp(item[i], "+revenge")) ;
- else if (!cmd && !strcmp(item[i], "-revenge")) ;
- else if (!cmd && !strcmp(item[i], "+revengebot")) ;
- else if (!cmd && !strcmp(item[i], "-revengebot")) ;
- else if (!cmd && !strcmp(item[i], "+manop")) ;
- else if (!cmd && !strcmp(item[i], "-manop")) ;
- else if (!cmd && !strcmp(item[i], "+dontkickops")) ;
- else if (!cmd && !strcmp(item[i], "-dontkickops")) ;
- else if (!cmd && !strcmp(item[i], "+nomdop")) ;
- else if (!cmd && !strcmp(item[i], "-nomdop")) ;
- else if (!cmd && !strcmp(item[i], "+protectfriends")) ;
- else if (!cmd && !strcmp(item[i], "-protectfriends")) ;
- else if (!cmd && !strcmp(item[i], "+protectops")) ;
- else if (!cmd && !strcmp(item[i], "-protectops")) ;
- else if (!cmd && !strcmp(item[i], "+punish")) ;
- else if (!cmd && !strcmp(item[i], "-punish")) ;
- else if (!cmd && !strcmp(item[i], "+seen")) ;
- else if (!cmd && !strcmp(item[i], "-seen")) ;
- else if (!cmd && !strcmp(item[i], "+secret")) ;
- else if (!cmd && !strcmp(item[i], "-secret")) ;
- else if (!cmd && !strcmp(item[i], "-stopnethack")) ;
- else if (!cmd && !strcmp(item[i], "+stopnethack")) ;
- else if (!cmd && !strcmp(item[i], "-wasoptest")) ;
- else if (!cmd && !strcmp(item[i], "+wasoptest")) ; /* Eule 01.2000 */
- else if (!cmd && !strcmp(item[i], "+clearbans")) ;
- else if (!cmd && !strcmp(item[i], "-clearbans")) ;
- else if (!cmd && !strncmp(item[i], "need-", 5)) ;
- else if (!strncmp(item[i], "flood-", 6)) {
- int *pthr = NULL;
- interval_t *ptime = NULL;
- char *p = NULL;
- if (!strcmp(item[i] + 6, "*")) {
- i++;
- if (i >= items) {
- if (result)
- simple_snprintf(result, RESULT_LEN, "%s needs argument", item[i - 1]);
- return ERROR;
- }
- p = strchr(item[i], ':');
- int thr = 0;
- interval_t time = 0;
- if (p) {
- *p++ = 0;
- thr = atoi(item[i]);
- time = atoi(p);
- *--p = ':';
- } else {
- thr = atoi(item[i]);
- time = 1;
- }
- chan->flood_pub_thr = thr;
- chan->flood_pub_time = time;
- chan->flood_join_thr = thr;
- chan->flood_join_time = time;
- chan->flood_ctcp_thr = thr;
- chan->flood_ctcp_time = time;
- chan->flood_kick_thr = thr;
- chan->flood_kick_time = time;
- chan->flood_deop_thr = thr;
- chan->flood_deop_time = time;
- chan->flood_nick_thr = thr;
- chan->flood_nick_time = time;
- chan->flood_mjoin_thr = thr;
- chan->flood_mjoin_time = time;
- } else if (!strcmp(item[i] + 6, "chan")) {
- pthr = &chan->flood_pub_thr;
- ptime = &chan->flood_pub_time;
- } else if (!strcmp(item[i] + 6, "join")) {
- pthr = &chan->flood_join_thr;
- ptime = &chan->flood_join_time;
- } else if (!strcmp(item[i] + 6, "ctcp")) {
- pthr = &chan->flood_ctcp_thr;
- ptime = &chan->flood_ctcp_time;
- } else if (!strcmp(item[i] + 6, "kick")) {
- pthr = &chan->flood_kick_thr;
- ptime = &chan->flood_kick_time;
- } else if (!strcmp(item[i] + 6, "deop")) {
- pthr = &chan->flood_deop_thr;
- ptime = &chan->flood_deop_time;
- } else if (!strcmp(item[i] + 6, "nick")) {
- pthr = &chan->flood_nick_thr;
- ptime = &chan->flood_nick_time;
- } else if (!strcmp(item[i] + 6, "mjoin")) {
- pthr = &chan->flood_mjoin_thr;
- ptime = &chan->flood_mjoin_time;
- } else { /* Ignore for optimal forward compatibility */
- i++;
- continue;
- }
- if (pthr && ptime) { //Ignore flood-*
- i++;
- if (i >= items) {
- if (result)
- simple_snprintf(result, RESULT_LEN, "%s needs argument", item[i - 1]);
- return ERROR;
- }
- p = strchr(item[i], ':');
- if (p) {
- *p++ = 0;
- *pthr = atoi(item[i]);
- *ptime = atoi(p);
- *--p = ':';
- } else {
- *pthr = atoi(item[i]);
- *ptime = 1;
- }
- }
- } else {
- if (result && item[i][0]) { /* ignore "" */
- if (!result[0])
- strlcpy(result, "illegal channel option: ", RESULT_LEN);
- if (result_extra[0])
- strlcat(result_extra, " ", sizeof(result_extra));
- strlcat(result_extra, item[i], sizeof(result_extra));
- }
- error = 1;
- }
- }
- if ((chan->status ^ old_status) & CHAN_TAKE)
- chan->status |= (CHAN_FASTOP|CHAN_BITCH); // to avoid bots still mass opping from +take from not using cookies
- if (!conf.bot->hub && (chan != chanset_default)) {
- if ((old_status ^ chan->status) & (CHAN_INACTIVE | CHAN_BACKUP)) {
- if (!shouldjoin(chan) && (chan->ircnet_status & (CHAN_ACTIVE | CHAN_PEND)))
- dprintf(DP_SERVER, "PART %s\n", chan->name);
- if (shouldjoin(chan) && !(chan->ircnet_status & (CHAN_ACTIVE | CHAN_PEND | CHAN_JOINING))) {
- dprintf(DP_SERVER, "JOIN %s %s\n", (chan->name[0]) ?
- chan->name : chan->dname,
- chan->channel.key[0] ?
- chan->channel.key : chan->key_prot);
- chan->ircnet_status |= CHAN_JOINING;
- }
- }
- if (me_op(chan)) {
- if ((old_status ^ chan->status) & (CHAN_ENFORCEBANS|CHAN_NOUSERBANS|CHAN_DYNAMICBANS|CHAN_NOUSEREXEMPTS|CHAN_NOUSERINVITES|CHAN_DYNAMICEXEMPTS|CHAN_DYNAMICINVITES)) {
- recheck_channel(chan, 1);
- /* if we -take, recheck the chan for modes and shit */
- /* also -[bot]bitch/-private might allow for auto-opping users */
- } else if ((chan->status ^ old_status) & (CHAN_BITCH | CHAN_BOTBITCH | CHAN_PRIVATE | CHAN_CLOSED)) {
- recheck_channel(chan, 0);
- } else if ((old_status & CHAN_TAKE) && !(chan->status & CHAN_TAKE)) {
- //Set -take, fetch bans/exempts/invites
- recheck_channel(chan, 2);
- } else if (old_mode_pls_prot != chan->mode_pls_prot || old_mode_mns_prot != chan->mode_mns_prot) {
- recheck_channel_modes(chan);
- }
- }
- }
- if (result && result[0] && result_extra[0])
- strlcat(result, result_extra, RESULT_LEN);
- if (error)
- return ERROR;
- return OK;
- }
- static void init_masklist(masklist *m)
- {
- m->mask = (char *) my_calloc(1, 1);
- m->who = NULL;
- m->next = NULL;
- }
- /* Initialize out the channel record.
- */
- static void init_channel(struct chanset_t *chan, bool reset)
- {
- chan->channel.maxmembers = 0;
- chan->channel.mode = 0;
- chan->channel.members = 0;
- if (!reset)
- chan->channel.key = (char *) my_calloc(1, 1);
- chan->channel.ban = (masklist *) my_calloc(1, sizeof(masklist));
- init_masklist(chan->channel.ban);
- chan->channel.exempt = (masklist *) my_calloc(1, sizeof(masklist));
- init_masklist(chan->channel.exempt);
- chan->channel.invite = (masklist *) my_calloc(1, sizeof(masklist));
- init_masklist(chan->channel.invite);
- chan->channel.member = (memberlist *) my_calloc(1, sizeof(memberlist));
- chan->channel.member->nick[0] = 0;
- chan->channel.member->next = NULL;
- chan->channel.topic = NULL;
- }
- static void clear_masklist(masklist *m)
- {
- masklist *temp = NULL;
- for (; m; m = temp) {
- temp = m->next;
- if (m->mask)
- free(m->mask);
- if (m->who)
- free(m->who);
- free(m);
- }
- }
- /* Clear out channel data from memory.
- */
- void clear_channel(struct chanset_t *chan, bool reset)
- {
- memberlist *m = NULL, *m1 = NULL;
- if (chan->channel.topic)
- free(chan->channel.topic);
- for (m = chan->channel.member; m; m = m1) {
- m1 = m->next;
- free(m);
- }
- clear_masklist(chan->channel.ban);
- chan->channel.ban = NULL;
- clear_masklist(chan->channel.exempt);
- chan->channel.exempt = NULL;
- clear_masklist(chan->channel.invite);
- chan->channel.invite = NULL;
- chan->channel.last_eI = 0;
- chan->ircnet_status &= ~CHAN_HAVEBANS;
- if (reset)
- init_channel(chan, 1);
- }
- /* Create new channel and parse commands.
- */
- int channel_add(char *result, char *newname, char *options, bool isdefault)
- {
- /* When loading userfile */
- if (newname && newname[0] && loading && !strcmp(newname, "default"))
- isdefault = 1;
- if (!newname || !newname[0] || (!isdefault && !strchr(CHANMETA, newname[0]))) {
- if (result)
- strlcpy(result, "invalid channel prefix", RESULT_LEN);
- return ERROR;
- }
- if (strchr(newname, ',') != NULL) {
- if (result)
- strlcpy(result, "invalid channel name", RESULT_LEN);
- return ERROR;
- }
- const char **item = NULL;
- int items = 0;
- char buf[3001] = "";
- simple_snprintf(buf, sizeof(buf), "chanmode { %s }", glob_chanmode);
- if (!isdefault) { // These are passed in in 'options'
- strlcat(buf, " ", sizeof(buf));
- strlcat(buf, def_chanset, sizeof(buf));
- }
- // Add in 'default' channel options
- if (!isdefault && chanset_default) {
- bd::String default_chan_options = channel_to_string(chanset_default);
- strlcat(buf, " ", sizeof(buf));
- strlcat(buf, default_chan_options.c_str(), sizeof(buf));
- }
- if (options && options[0]) {
- strlcat(buf, " ", sizeof(buf));
- strlcat(buf, options, sizeof(buf));
- }
- if (SplitList(result, buf, &items, &item) != OK)
- return ERROR;
- bool join = 0;
- struct chanset_t *chan = NULL;
- int ret = OK;
- if ((chan = findchan_by_dname(newname))) {
- /* Already existing channel, maybe a reload of the channel file */
- chan->status &= ~CHAN_FLAGGED; /* don't delete me! :) */
- } else {
- chan = (struct chanset_t *) my_calloc(1, sizeof(struct chanset_t));
- /* These are defaults, bzero already set them 0, but we set them for future reference */
- chan->limit_prot = 0;
- chan->limit = 0;
- chan->closed_ban = 0;
- chan->closed_private = 1;
- chan->closed_invite = 1;
- chan->voice_non_ident = 1;
- chan->auto_delay = 5;
- chan->ban_type = 3;
- /* Chanint template
- * chan->temp = 0;
- */
- chan->knock_flags = 0;
- chan->flood_lock_time = 120;
- chan->flood_exempt_mode = 0;
- chan->flood_pub_thr = gfld_chan_thr;
- chan->flood_pub_time = gfld_chan_time;
- chan->flood_ctcp_thr = gfld_ctcp_thr;
- chan->flood_ctcp_time = gfld_ctcp_time;
- chan->flood_join_thr = gfld_join_thr;
- chan->flood_join_time = gfld_join_time;
- chan->flood_deop_thr = gfld_deop_thr;
- chan->flood_deop_time = gfld_deop_time;
- chan->flood_kick_thr = gfld_kick_thr;
- chan->flood_kick_time = gfld_kick_time;
- chan->flood_nick_thr = gfld_nick_thr;
- chan->flood_nick_time = gfld_nick_time;
- chan->flood_mjoin_thr = 6;
- chan->flood_mjoin_time = 1;
- // chan->revenge_mode = global_revenge_mode;
- chan->limitraise = 20;
- chan->ban_time = global_ban_time;
- chan->exempt_time = global_exempt_time;
- chan->invite_time = global_invite_time;
- chan->channel.jointime = 0;
- chan->channel.parttime = 0;
- chan->channel.fighting = 0;
- chan->channel.drone_set_mode = 0;
- chan->channel.drone_jointime = 0;
- chan->channel.drone_joins = 0;
- chan->channel.last_eI = 0;
- /* We _only_ put the dname (display name) in here so as not to confuse
- * any code later on. chan->name gets updated with the channel name as
- * the server knows it, when we join the channel. <cybah>
- */
- strlcpy(chan->dname, newname, 81);
- /* Initialize chan->channel info */
- if (isdefault) {
- if (chanset_default)
- remove_channel(chanset_default);
- chanset_default = chan;
- } else {
- init_channel(chan, 0);
- list_append((struct list_type **) &chanset, (struct list_type *) chan);
- /* Channel name is stored in xtra field for sharebot stuff */
- if (!conf.bot->hub && !isdefault)
- join = 1;
- }
- }
- /* If loading is set, we're loading the userfile. Ignore errors while
- * reading userfile and just return OK. This is for compatability
- * if a user goes back to an eggdrop that no-longer supports certain
- * (channel) options.
- */
- if ((channel_modify(result, chan, items, (char **) item, 0) != OK)) {
- putlog(LOG_ERROR, "*", "Error parsing channel options for %s: %s", chan->dname, result);
- if (!loading)
- ret = ERROR;
- }
-
- free(item);
- if (join && shouldjoin(chan))
- dprintf(DP_SERVER, "JOIN %s %s\n", chan->dname, chan->key_prot);
- return ret;
- }
|