📄 m_tkl.c
字号:
"no reason" /*8 reason */ }; struct tm *t; if (parc == 1) { tkl_stats(sptr, 0, NULL); sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'g'); return 0; } mask = parv[1]; if (*mask == '-') { whattodo = 1; mask++; } else if (*mask == '+') { whattodo = 0; mask++; } if (strchr(mask, '!')) { sendto_one(sptr, ":%s NOTICE %s :[error] Cannot have '!' in masks.", me.name, sptr->name); return 0; } if (*mask == ':') { sendto_one(sptr, ":%s NOTICE %s :[error] Mask cannot start with a ':'.", me.name, sptr->name); return 0; } if (strchr(mask, ' ')) return 0; /* Check if its a hostmask and legal .. */ p = strchr(mask, '@'); if (p) { if ((p == mask) || !p[1]) { sendnotice(sptr, "Error: no user@host specified"); return 0; } usermask = strtok(mask, "@"); hostmask = strtok(NULL, ""); if (BadPtr(hostmask)) { if (BadPtr(usermask)) { return 0; } hostmask = usermask; usermask = "*"; } if (*hostmask == ':') { sendnotice(sptr, "[error] For (weird) technical reasons you cannot start the host with a ':', sorry"); return 0; } if (((*type == 'z') || (*type == 'Z')) && !whattodo) { /* It's a (G)ZLINE, make sure the user isn't specyfing a HOST. * Just a warning in 3.2.3, but an error in 3.2.4. */ if (strcmp(usermask, "*")) { sendnotice(sptr, "ERROR: (g)zlines must be placed at \037*\037@ipmask, not \037user\037@ipmask. This is " "because (g)zlines are processed BEFORE dns and ident lookups are done. " "If you want to use usermasks, use a KLINE/GLINE instead."); return -1; } for (p=hostmask; *p; p++) if (isalpha(*p)) { sendnotice(sptr, "ERROR: (g)zlines must be placed at *@\037IPMASK\037, not *@\037HOSTMASK\037 " "(so for example *@192.168.* is ok, but *@*.aol.com is not). " "This is because (g)zlines are processed BEFORE dns and ident lookups are done. " "If you want to use hostmasks instead of ipmasks, use a KLINE/GLINE instead."); return -1; } } /* set 'p' right for later... */ p = hostmask-1; } else { /* It's seemingly a nick .. let's see if we can find the user */ if ((acptr = find_person(mask, NULL))) { usermask = "*"; if ((*type == 'z') || (*type == 'Z')) { /* Fill in IP */ hostmask = GetIP(acptr); if (!hostmask) { sendnotice(sptr, "Could not get IP for user '%s'", acptr->name); return 0; } } else { /* Fill in host */ hostmask = acptr->user->realhost; } p = hostmask - 1; } else { sendto_one(sptr, rpl_str(ERR_NOSUCHNICK), me.name, sptr->name, mask); return 0; } } if (!whattodo) { char c; if (!strchr(usermask, '*') && !strchr(usermask, '?')) { /* Allow things like clone@*, dsfsf@*, etc.. */ } else { /* Check hostmask. */ /* STEP 1: Must at least contain 4 non-wildcard/non-dot characters */ p++; i = 0; while (*p) { if (*p != '*' && *p != '.' && *p != '?') i++; p++; } if (i < 4) { sendto_one(sptr, ":%s NOTICE %s :*** [error] Too broad mask", me.name, sptr->name); return 0; } /* STEP 2: Check CIDR.. allow x.x/16, but not /15, /14, etc... */ c = tolower(*type); if (c == 'k' || c == 'z' || *type == 'G' || *type == 's') { struct irc_netmask tmp; if ((tmp.type = parse_netmask(hostmask, &tmp)) != HM_HOST) { if (tmp.bits < 16) { sendto_one(sptr, ":%s NOTICE %s :*** [error] Too broad mask", me.name, sptr->name); return 0; } } } } } tkl_check_expire(NULL); secs = 0; if (whattodo == 0 && (parc > 3)) { secs = atime(parv[2]); if (secs < 0) { sendto_one(sptr, ":%s NOTICE %s :*** [error] The time you specified is out of range!", me.name, sptr->name); return 0; } } tkllayer[1] = whattodo == 0 ? "+" : "-"; tkllayer[2] = type; tkllayer[3] = usermask; tkllayer[4] = hostmask; tkllayer[5] = make_nick_user_host(sptr->name, sptr->user->username, GetHost(sptr)); if (whattodo == 0) { if (secs == 0) { if (DEFAULT_BANTIME && (parc <= 3)) ircsprintf(mo, "%li", DEFAULT_BANTIME + TStime()); else ircsprintf(mo, "%li", secs); /* "0" */ } else ircsprintf(mo, "%li", secs + TStime()); ircsprintf(mo2, "%li", TStime()); tkllayer[6] = mo; tkllayer[7] = mo2; if (parc > 3) { tkllayer[8] = parv[3]; } else if (parc > 2) { tkllayer[8] = parv[2]; } /* Blerghhh... */ i = atol(mo); t = gmtime(&i); if (!t) { sendto_one(sptr, ":%s NOTICE %s :*** [error] The time you specified is out of range", me.name, sptr->name); return 0; } /* call the tkl layer .. */ m_tkl(&me, &me, 9, tkllayer); } else { /* call the tkl layer .. */ m_tkl(&me, &me, 6, tkllayer); } return 0;}int spamfilter_usage(aClient *sptr){ sendnotice(sptr, "Use: /spamfilter [add|del|remove|+|-] [type] [action] [tkltime] [tklreason] [regex]"); sendnotice(sptr, "See '/helpop ?spamfilter' for more information."); return 0;}DLLFUNC int m_spamfilter(aClient *cptr, aClient *sptr, int parc, char *parv[]){int whattodo = 0; /* 0 = add 1 = del */char mo[32], mo2[32];char *p;char *tkllayer[11] = { me.name, /* 0 server.name */ NULL, /* 1 +|- */ "F", /* 2 F */ NULL, /* 3 usermask (targets) */ NULL, /* 4 hostmask (action) */ NULL, /* 5 setby */ "0", /* 6 expire_at */ "0", /* 7 set_at */ "", /* 8 tkl time */ "", /* 9 tkl reason */ "" /* 10 regex */};int targets = 0, action = 0;char targetbuf[64], actionbuf[2];char reason[512];int n; if (IsServer(sptr)) return 0; if (!OPCanTKL(sptr) || !IsOper(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name); return 0; } if (parc == 1) { tkl_stats(sptr, TKL_SPAMF, NULL); tkl_stats(sptr, TKL_SPAMF|TKL_GLOBAL, NULL); sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, sptr->name, 'F'); return 0; } if ((parc < 7) || BadPtr(parv[4])) return spamfilter_usage(sptr); /* parv[1]: [add|del|+|-] * parv[2]: type * parv[3]: action * parv[4]: tkl time * parv[5]: tkl reason (or block reason..) * parv[6]: regex */ if (!strcasecmp(parv[1], "add") || !strcmp(parv[1], "+")) whattodo = 0; else if (!strcasecmp(parv[1], "del") || !strcmp(parv[1], "-") || !strcasecmp(parv[1], "remove")) whattodo = 1; else { sendto_one(sptr, ":%s NOTICE %s :1st parameter invalid", me.name, sptr->name); return spamfilter_usage(sptr); } targets = spamfilter_gettargets(parv[2], sptr); if (!targets) return spamfilter_usage(sptr); strncpyzt(targetbuf, spamfilter_target_inttostring(targets), sizeof(targetbuf)); action = banact_stringtoval(parv[3]); if (!action) { sendto_one(sptr, ":%s NOTICE %s :Invalid 'action' field (%s)", me.name, sptr->name, parv[3]); return spamfilter_usage(sptr); } actionbuf[0] = banact_valtochar(action); actionbuf[1] = '\0'; /* now check the regex... */ p = unreal_checkregex(parv[6],0,1); if (p) { sendto_one(sptr, ":%s NOTICE %s :Error in regex '%s': %s", me.name, sptr->name, parv[6], p); return 0; } tkllayer[1] = whattodo ? "-" : "+"; tkllayer[3] = targetbuf; tkllayer[4] = actionbuf; tkllayer[5] = make_nick_user_host(sptr->name, sptr->user->username, GetHost(sptr)); if (parv[4][0] == '-') { ircsprintf(mo, "%li", SPAMFILTER_BAN_TIME); tkllayer[8] = mo; } else tkllayer[8] = parv[4]; if (parv[5][0] == '-') strlcpy(reason, unreal_encodespace(SPAMFILTER_BAN_REASON), sizeof(reason)); else strlcpy(reason, parv[5], sizeof(reason)); tkllayer[9] = reason; tkllayer[10] = parv[6]; /* SPAMFILTER LENGTH CHECK. * We try to limit it here so '/stats f' output shows ok, output of that is: * :servername 229 destname F <target> <action> <num> <num> <num> <reason> <setby> :<regex> * : ^NICKLEN ^ NICKLEN ^check ^check ^check * And for the other fields (and spacing/etc) we count on max 40 characters. * We also do >500 instead of >510, since that looks cleaner ;).. so actually we count * on 50 characters for the rest... -- Syzop */ n = strlen(reason) + strlen(parv[6]) + strlen(tkllayer[5]) + (NICKLEN * 2) + 40; if ((n > 500) && (whattodo == 0)) { sendnotice(sptr, "Sorry, spamfilter too long. You'll either have to trim down the " "reason or the regex (exceeded by %d bytes)", n - 500); return 0; } if (whattodo == 0) { ircsprintf(mo2, "%li", TStime()); tkllayer[7] = mo2; } m_tkl(&me, &me, 11, tkllayer); return 0;}/** tkl hash method. * NOTE1: the input value 'c' is assumed to be in range a-z or A-Z! * NOTE2: don't blindly change the hashmethod, some things depend on * 'z'/'Z' getting the same bucket. */int _tkl_hash(unsigned int c){#ifdef DEBUGMODE if ((c >= 'a') && (c <= 'z')) return c-'a'; else if ((c >= 'A') && (c <= 'Z')) return c-'A'; else { sendto_realops("[BUG] tkl_hash() called with out of range parameter (c = '%c') !!!", c); ircd_log(LOG_ERROR, "[BUG] tkl_hash() called with out of range parameter (c = '%c') !!!", c); return 0; }#else return (isupper(c) ? c-'A' : c-'a');#endif}/** tkl type to tkl character. * NOTE: type is assumed to be valid. */char _tkl_typetochar(int type){ if (type & TKL_GLOBAL) { if (type & TKL_KILL) return 'G'; if (type & TKL_ZAP) return 'Z'; if (type & TKL_SHUN) return 's'; if (type & TKL_KILL) return 'G'; if (type & TKL_SPAMF) return 'F'; if (type & TKL_NICK) return 'Q'; } else { if (type & TKL_ZAP) return 'z'; if (type & TKL_KILL) return 'k'; if (type & TKL_SPAMF) return 'f'; if (type & TKL_NICK) return 'q'; } sendto_realops("[BUG]: tkl_typetochar(): unknown type 0x%x !!!", type); ircd_log(LOG_ERROR, "[BUG] tkl_typetochar(): unknown type 0x%x !!!", type); return 0;}/* * type = TKL_* * usermask@hostmask * reason * setby = whom set it * expire_at = when to expire - 0 if not to expire * set_at = was set at * spamf_tkl_duration = duration of *line placed by spamfilter [1] * spamf_tkl_reason = escaped reason field for *lines placed by spamfilter [1] * * [1]: only relevant for spamfilters, else ignored (eg 0, NULL).*/aTKline *_tkl_add_line(int type, char *usermask, char *hostmask, char *reason, char *setby, TS expire_at, TS set_at, TS spamf_tkl_duration, char *spamf_tkl_reason){ aTKline *nl; int index; /* Pre-allocate etc check for spamfilters that fail to compile. * This could happen if for example TRE supports a feature on server X, but not * on server Y! */ if (type & TKL_SPAMF) { char *myerr = unreal_checkregex(reason, 0, 0); if (myerr) { sendto_realops("[TKL ERROR] ERROR: Spamfilter was added but did not compile. ERROR='%s', Spamfilter='%s'", myerr, reason); return NULL; } } nl = (aTKline *) MyMallocEx(sizeof(aTKline)); if (!nl) return NULL; nl->type = type; nl->expire_at = expire_at; nl->set_at = set_at; strncpyzt(nl->usermask, usermask, sizeof(nl->usermask)); nl->hostmask = strdup(hostmask); nl->reason = strdup(reason); nl->setby = strdup(setby); if (type & TKL_SPAMF) { /* Need to set some additional flags like 'targets' and 'action'.. */ nl->subtype = spamfilter_gettargets(usermask, NULL); nl->ptr.spamf = unreal_buildspamfilter(reason); nl->ptr.spamf->action = banact_chartoval(*hostmask); nl->expire_at = 0; /* temporary spamfilters are NOT supported! (makes no sense) */ if (!spamf_tkl_reason) { /* no exttkl support, use default values... */ nl->ptr.spamf->tkl_duration = SPAMFILTER_BAN_TIME; nl->ptr.spamf->tkl_reason = strdup(unreal_encodespace(SPAMFILTER_BAN_REASON)); } else { nl->ptr.spamf->tkl_duration = spamf_tkl_duration; nl->ptr.spamf->tkl_reason = strdup(spamf_tkl_reason); /* already encoded */ } if (nl->subtype & SPAMF_USER) loop.do_bancheck_spamf_user = 1; if (nl->subtype & SPAMF_AWAY) loop.do_bancheck_spamf_away = 1; } else if (type & TKL_KILL || type & TKL_ZAP || type & TKL_SHUN)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -