mirror of
https://github.com/pissnet/pissircd.git
synced 2025-04-26 08:35:05 +01:00
Preparations for #4356 (experimental / on-going):
* add general matching framework (aMatch type, unreal_match_xxx functions) * change spamfilter { } block syntax * add support for simple wildcard matching (non-regex, just '?' and '*') This is the initial commit so the new lib is not in yet, 'regex' is not functional (but 'posix' and 'simple' are working), linking has not been fully tested and no warnings are printed yet. IOTW: work in progress!
This commit is contained in:
parent
39c3a03d14
commit
58bd3cf60b
13 changed files with 403 additions and 138 deletions
|
@ -98,6 +98,10 @@ SJ3 Notifies the server that the SJOIN command with SJ3 syntax is
|
|||
TKLEXT This allows 10 instead of 8 parameters in TKL's for spamfilter, see s_kline.c
|
||||
function m_tkl for more info on this (added in 3.2RC2).
|
||||
|
||||
TKLEXT2 This allows 11 instead of 8 or 10 parameters in TKL's for spamfilter,
|
||||
see s_kline.c function m_tkl for more info on this (added in 3.4-alpha3).
|
||||
Note that TKLEXT2 implies TKLEXT support as well.
|
||||
|
||||
NICKIP This token indicates that a (standard) base64 encoded IP address is included
|
||||
in the NICK command. The IP is in binary network byte order formated and
|
||||
encoded using the standard base64 algorithm. '*' is used if no IP is available.
|
||||
|
|
26
help.conf
26
help.conf
|
@ -1349,7 +1349,11 @@ help Spamfilter {
|
|||
" This command adds/removes global spam filters.";
|
||||
" Spamfilters can be used to get rid of spam, advertising, bots, etc.";
|
||||
" -";
|
||||
" Use: /spamfilter [add|del|remove|+|-] [type] [action] [tkltime] [reason] [regex]";
|
||||
" Use: /spamfilter [add|del|remove|+|-] [method] [type] [action] [tkltime] [reason] [string]";
|
||||
" [method] Matching method, must be one of:";
|
||||
" -regex (PCRE fast regex),";
|
||||
" -posix (old 3.2.x POSIX regex), or";
|
||||
" -simple (fastest but only supports ? and * wildcards)";
|
||||
" [type] specifies the target type, you can specify multiple targets:";
|
||||
" 'c' channel msg, 'p' private msg, 'n' private notice,";
|
||||
" 'N' channel notice, 'P' part msg, 'q' quit msg, 'd' dcc,";
|
||||
|
@ -1359,22 +1363,22 @@ help Spamfilter {
|
|||
" 'kline', 'gline', 'zline', 'gzline', 'block' (blocks the msg),";
|
||||
" 'dccblock' (unable to send any dccs), 'viruschan' (part all channels";
|
||||
" and join the virus help chan), 'warn' (warn for IRC Operators).";
|
||||
" [regex] this is the actual regex where we should block on";
|
||||
" [string] this is the actual string that should be blocked (regex or simple pattern)";
|
||||
" [tkltime] the duration of the *LINEs placed by action (use '-' to use the default";
|
||||
" set::spamfilter::ban-time, this value is ignored for block/tempshun');";
|
||||
" [reason] the reason for the *LINE or blockmsg, CANNOT CONTAIN SPACES,";
|
||||
" '_' will be translated to spaces. Again, if you use '-' for this";
|
||||
" the default (set::spamfilter::ban-reason) is used.";
|
||||
" - ";
|
||||
" A few examples (note they will probably linewrap!):";
|
||||
" /spamfilter add p block - - Come watch me on my webcam";
|
||||
" /spamfilter add p block - Possible_virus_detected,_join_#help Come watch me on my webcam";
|
||||
" /spamfilter add p tempshun - - You_are_infected me\.mpg";
|
||||
" /spamfilter add p gline - - Come watch me on my webcam";
|
||||
" /spamfilter add p gline 3h Please_go_to_www.viruscan.xx/nicepage/virus=blah Come watch me on my webcam";
|
||||
" /spamfilter add p kill - Please_go_to_www.viruscan.xx/nicepage/virus=blah Come watch me on my webcam";
|
||||
" /spamfilter del p block - - Come watch me on my webcam*";
|
||||
" /spamfilter add cN gzline 1d No_advertising_please come to irc\..+\..+";
|
||||
" A few examples (note they will probably line-wrap!):";
|
||||
" /spamfilter add -simple p block - - Come watch me on my webcam";
|
||||
" /spamfilter add -simple p block - Possible_virus_detected,_join_#help Come watch me on my webcam";
|
||||
" /spamfilter add -simple p tempshun - - You_are_infected me.mpg";
|
||||
" /spamfilter add -simple p gline - - Come watch me on my webcam";
|
||||
" /spamfilter add -simple p gline 3h Please_go_to_www.viruscan.xx/nicepage/virus=blah Come watch me on my webcam";
|
||||
" /spamfilter add -simple p kill - Please_go_to_www.viruscan.xx/nicepage/virus=blah Come watch me on my webcam";
|
||||
" /spamfilter del -simple p block - - Come watch me on my webcam*";
|
||||
" /spamfilter add -regex cN gzline 1d No_advertising_please /come to irc\..+\..+/";
|
||||
};
|
||||
|
||||
help Tempshun {
|
||||
|
|
|
@ -239,6 +239,8 @@ static char *StsMalloc(size_t size, char *file, long line)
|
|||
|
||||
#define ircstrdup(x,y) do { if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y); } while(0)
|
||||
#define ircfree(x) do { if (x) MyFree(x); x = NULL; } while(0)
|
||||
#define safefree ircfree
|
||||
#define safestrdup ircstrdup
|
||||
|
||||
extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ );
|
||||
|
||||
|
@ -279,6 +281,7 @@ extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ );
|
|||
" VL" \
|
||||
" SJ3" \
|
||||
" TKLEXT" \
|
||||
" TKLEXT2" \
|
||||
" NICKIP" \
|
||||
" ESVID"
|
||||
|
||||
|
|
|
@ -467,6 +467,9 @@
|
|||
#define SPAMFILTER_DETECTSLOW
|
||||
#endif
|
||||
|
||||
/* Use TRE Regex Library (as well) ? */
|
||||
#define USE_TRE
|
||||
|
||||
/* The 3.4-alpha* series, especially the first few, are highly experimental.
|
||||
* If EXPERIMENTAL is #define'd then all users will receive a notice about
|
||||
* this when they connect, along with a pointer to bugs.unrealircd.org where
|
||||
|
|
|
@ -517,7 +517,7 @@ extern void count_memory(aClient *cptr, char *nick);
|
|||
extern void list_scache(aClient *sptr);
|
||||
extern char *oflagstr(long oflag);
|
||||
extern int rehash(aClient *cptr, aClient *sptr, int sig);
|
||||
extern int _match(char *mask, char *name);
|
||||
extern int _match(const char *mask, const char *name);
|
||||
extern void outofmemory(void);
|
||||
extern int add_listener2(ConfigItem_listen *conf);
|
||||
extern void link_cleanup(ConfigItem_link *link_ptr);
|
||||
|
@ -659,7 +659,7 @@ extern MODVAR int (*register_user)(aClient *cptr, aClient *sptr, char *nick, cha
|
|||
extern MODVAR int (*tkl_hash)(unsigned int c);
|
||||
extern MODVAR char (*tkl_typetochar)(int type);
|
||||
extern MODVAR 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);
|
||||
TS expire_at, TS set_at, TS spamf_tkl_duration, char *spamf_tkl_reason, MatchType match_type);
|
||||
extern MODVAR aTKline *(*tkl_del_line)(aTKline *tkl);
|
||||
extern MODVAR void (*tkl_check_local_remove_shun)(aTKline *tmp);
|
||||
extern MODVAR aTKline *(*tkl_expire)(aTKline * tmp);
|
||||
|
@ -751,3 +751,8 @@ extern void send_moddata_members(aClient *srv);
|
|||
extern int ssl_used_in_config_but_unavail(void);
|
||||
extern void config_report_ssl_error(void);
|
||||
extern int dead_link(aClient *to, char *notice);
|
||||
extern aMatch *unreal_create_match(MatchType type, char *str, char **error);
|
||||
extern void unreal_delete_match(aMatch *m);
|
||||
extern int unreal_match(aMatch *m, char *str);
|
||||
extern int unreal_match_method_strtoval(char *str);
|
||||
extern char *unreal_match_method_valtostr(int val);
|
||||
|
|
|
@ -316,6 +316,7 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
|||
#define PROTO_NICKv2 0x0008 /* Negotiated NICKv2 protocol */
|
||||
#define PROTO_SJOIN2 0x0010 /* Negotiated SJOIN2 protocol */
|
||||
#define PROTO_UMODE2 0x0020 /* Negotiated UMODE2 protocol */
|
||||
#define PROTO_TKLEXT2 0x0040 /* TKL extension 2: 11 parameters instead of 8 or 10 */
|
||||
#define PROTO_INVITENOTIFY 0x0080 /* client supports invite-notify */
|
||||
#define PROTO_VL 0x0100 /* Negotiated VL protocol */
|
||||
#define PROTO_SJ3 0x0200 /* Negotiated SJ3 protocol */
|
||||
|
@ -465,6 +466,7 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
|||
#define SupportSJ3(x) (CHECKPROTO(x, PROTO_SJ3))
|
||||
#define SupportVHP(x) (CHECKPROTO(x, PROTO_VHP))
|
||||
#define SupportTKLEXT(x) (CHECKPROTO(x, PROTO_TKLEXT))
|
||||
#define SupportTKLEXT2(x) (CHECKPROTO(x, PROTO_TKLEXT2))
|
||||
#define SupportNAMESX(x) (CHECKPROTO(x, PROTO_NAMESX))
|
||||
#define SupportCLK(x) (CHECKPROTO(x, PROTO_CLK))
|
||||
#define SupportUHNAMES(x) (CHECKPROTO(x, PROTO_UHNAMES))
|
||||
|
@ -479,6 +481,7 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
|||
#define SetSJ3(x) ((x)->proto |= PROTO_SJ3)
|
||||
#define SetVHP(x) ((x)->proto |= PROTO_VHP)
|
||||
#define SetTKLEXT(x) ((x)->proto |= PROTO_TKLEXT)
|
||||
#define SetTKLEXT2(x) ((x)->proto |= PROTO_TKLEXT2)
|
||||
#define SetNAMESX(x) ((x)->proto |= PROTO_NAMESX)
|
||||
#define SetCLK(x) ((x)->proto |= PROTO_CLK)
|
||||
#define SetUHNAMES(x) ((x)->proto |= PROTO_UHNAMES)
|
||||
|
@ -491,6 +494,8 @@ typedef unsigned int u_int32_t; /* XXX Hope this works! */
|
|||
#define ClearVL(x) ((x)->proto &= ~PROTO_VL)
|
||||
#define ClearVHP(x) ((x)->proto &= ~PROTO_VHP)
|
||||
#define ClearSJ3(x) ((x)->proto &= ~PROTO_SJ3)
|
||||
#define ClearTKLEXT(x) ((x)->proto &= ~PROTO_TKLEXT)
|
||||
#define ClearTKLEXT2(x) ((x)->proto &= ~PROTO_TKLEXT2)
|
||||
|
||||
/*
|
||||
* defined operator access levels
|
||||
|
@ -724,6 +729,27 @@ struct aloopStruct {
|
|||
int rehash_save_sig;
|
||||
};
|
||||
|
||||
/** Matching types for aMatch.type */
|
||||
typedef enum {
|
||||
MATCH_SIMPLE=1, /**< Simple pattern with * and ? */
|
||||
MATCH_PCRE_REGEX=2, /**< PCRE2 Perl-like regex (new) */
|
||||
#ifdef USE_TRE
|
||||
MATCH_TRE_REGEX=3, /**< TRE POSIX regex (old, unreal3.2.x) */
|
||||
#endif
|
||||
} MatchType;
|
||||
|
||||
/** Match struct, which allows various matching styles, see MATCH_* */
|
||||
typedef struct _match {
|
||||
char *str; /**< Text of the glob/regex/whatever. Always set. */
|
||||
MatchType type;
|
||||
union {
|
||||
// pcre2_code *pcre_expr; /**< PCRE2 Perl-like Regex (New) */
|
||||
#ifdef USE_TRE
|
||||
regex_t *tre_expr; /**< TRE POSIX Regex (Old) */
|
||||
#endif
|
||||
} ext;
|
||||
} aMatch;
|
||||
|
||||
typedef struct Whowas {
|
||||
int hashv;
|
||||
char *name;
|
||||
|
@ -845,7 +871,7 @@ struct Server {
|
|||
|
||||
struct _spamfilter {
|
||||
unsigned short action; /* see BAN_ACT* */
|
||||
regex_t expr;
|
||||
aMatch *expr;
|
||||
char *tkl_reason; /* spamfilter reason field [escaped by unreal_encodespace()!] */
|
||||
TS tkl_duration;
|
||||
};
|
||||
|
@ -1359,7 +1385,7 @@ struct _configitem_alias_format {
|
|||
char *nick;
|
||||
AliasType type;
|
||||
char *format, *parameters;
|
||||
regex_t expr;
|
||||
aMatch *expr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
117
src/match.c
117
src/match.c
|
@ -21,6 +21,7 @@
|
|||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
|
||||
ID_Copyright("(C) 1990 Jarkko Oikarinen");
|
||||
|
||||
|
@ -427,3 +428,119 @@ int match(const char *mask, const char *name) {
|
|||
}
|
||||
return match2(mask,name);
|
||||
}
|
||||
|
||||
/** Free up all resources of an aMatch entry (including the struct itself).
|
||||
* NOTE: this function may (also) be called for aMatch structs that have only been
|
||||
* setup half-way, so use special care when accessing members (NULL checks!)
|
||||
*/
|
||||
void unreal_delete_match(aMatch *m)
|
||||
{
|
||||
safefree(m->str);
|
||||
#ifdef USE_TRE
|
||||
if (m->type == MATCH_TRE_REGEX)
|
||||
{
|
||||
if (m->ext.tre_expr)
|
||||
regfree(m->ext.tre_expr);
|
||||
}
|
||||
#endif
|
||||
// TODO: PCRE2 !!
|
||||
MyFree(m);
|
||||
}
|
||||
|
||||
aMatch *unreal_create_match(MatchType type, char *str, char **error)
|
||||
{
|
||||
aMatch *m = MyMallocEx(sizeof(aMatch));
|
||||
static char errorbuf[512];
|
||||
|
||||
m->str = strdup(str);
|
||||
m->type = type;
|
||||
|
||||
if (m->type == MATCH_SIMPLE)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
else if (m->type == MATCH_PCRE_REGEX)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
#ifdef USE_TRE
|
||||
else if (m->type == MATCH_TRE_REGEX)
|
||||
{
|
||||
int errorcode;
|
||||
|
||||
m->ext.tre_expr = MyMallocEx(sizeof(regex_t));
|
||||
errorcode = regcomp(m->ext.tre_expr, str, REG_ICASE|REG_EXTENDED|REG_NOSUB);
|
||||
if (errorcode > 0)
|
||||
{
|
||||
int errorbufsize = 512;
|
||||
char *errtmp = MyMallocEx(errorbufsize);
|
||||
regerror(errorcode, m->ext.tre_expr, errtmp, errorbufsize);
|
||||
strlcpy(errorbuf, errtmp, sizeof(errorbuf));
|
||||
MyFree(errtmp);
|
||||
if (error)
|
||||
*error = errorbuf;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
abort(); /* unknown type, how did that happen ? */
|
||||
}
|
||||
return m;
|
||||
|
||||
fail:
|
||||
unreal_delete_match(m);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Try to match an aMatch entry ('m') against a string ('str').
|
||||
* @returns 1 if matched, 0 if not.
|
||||
* @notes These (more logical) return values are opposite to the match() function.
|
||||
*/
|
||||
int unreal_match(aMatch *m, char *str)
|
||||
{
|
||||
if (m->type == MATCH_SIMPLE)
|
||||
{
|
||||
if (_match(m->str, str) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->type == MATCH_PCRE_REGEX)
|
||||
{
|
||||
// todo
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_TRE
|
||||
if (m->type == MATCH_TRE_REGEX)
|
||||
{
|
||||
if (regexec(m->ext.tre_expr, str, 0, NULL, 0) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int unreal_match_method_strtoval(char *str)
|
||||
{
|
||||
if (!strcmp(str, "regex") || !strcmp(str, "pcre"))
|
||||
return MATCH_PCRE_REGEX;
|
||||
if (!strcmp(str, "posix") || !strcmp(str, "tre"))
|
||||
return MATCH_TRE_REGEX;
|
||||
if (!strcmp(str, "simple") || !strcmp(str, "glob"))
|
||||
return MATCH_SIMPLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *unreal_match_method_valtostr(int val)
|
||||
{
|
||||
if (val == MATCH_PCRE_REGEX)
|
||||
return "regex";
|
||||
if (val == MATCH_TRE_REGEX)
|
||||
return "posix";
|
||||
if (val == MATCH_SIMPLE)
|
||||
return "simple";
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ int (*register_user)(aClient *cptr, aClient *sptr, char *nick, char *username, c
|
|||
int (*tkl_hash)(unsigned int c);
|
||||
char (*tkl_typetochar)(int type);
|
||||
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);
|
||||
TS expire_at, TS set_at, TS spamf_tkl_duration, char *spamf_tkl_reason, MatchType match_type);
|
||||
aTKline *(*tkl_del_line)(aTKline *tkl);
|
||||
void (*tkl_check_local_remove_shun)(aTKline *tmp);
|
||||
aTKline *(*tkl_expire)(aTKline * tmp);
|
||||
|
|
|
@ -267,6 +267,12 @@ CMD_FUNC(m_protoctl)
|
|||
Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
|
||||
SetTKLEXT(cptr);
|
||||
}
|
||||
else if (strcmp(s, "TKLEXT2") == 0)
|
||||
{
|
||||
Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
|
||||
SetTKLEXT2(cptr);
|
||||
SetTKLEXT(cptr); /* TKLEXT is implied as well. always. */
|
||||
}
|
||||
else if (strcmp(s, "NICKIP") == 0)
|
||||
{
|
||||
Debug((DEBUG_ERROR, "Chose protocol %s for link %s", proto, cptr->name));
|
||||
|
|
|
@ -76,7 +76,7 @@ DLLFUNC int m_spamfilter(aClient *cptr, aClient *sptr, int parc, char *parv[]);
|
|||
int _tkl_hash(unsigned int c);
|
||||
char _tkl_typetochar(int type);
|
||||
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);
|
||||
TS expire_at, TS set_at, TS spamf_tkl_duration, char *spamf_tkl_reason, MatchType match_type);
|
||||
aTKline *_tkl_del_line(aTKline *tkl);
|
||||
static void _tkl_check_local_remove_shun(aTKline *tmp);
|
||||
aTKline *_tkl_expire(aTKline * tmp);
|
||||
|
@ -160,7 +160,7 @@ DLLFUNC int MOD_INIT(m_tkl)(ModuleInfo *modinfo)
|
|||
CommandAdd(modinfo->handle, MSG_ZLINE, m_tzline, 3, M_OPER);
|
||||
CommandAdd(modinfo->handle, MSG_KLINE, m_tkline, 3, M_OPER);
|
||||
CommandAdd(modinfo->handle, MSG_GZLINE, m_gzline, 3, M_OPER);
|
||||
CommandAdd(modinfo->handle, MSG_SPAMFILTER, m_spamfilter, 6, M_OPER);
|
||||
CommandAdd(modinfo->handle, MSG_SPAMFILTER, m_spamfilter, 7, M_OPER);
|
||||
CommandAdd(modinfo->handle, MSG_TKL, _m_tkl, MAXPARA, M_OPER|M_SERVER);
|
||||
MARK_AS_OFFICIAL_MODULE(modinfo);
|
||||
return MOD_SUCCESS;
|
||||
|
@ -480,16 +480,17 @@ DLLFUNC int m_tkl_line(aClient *cptr, aClient *sptr, int parc, char *parv[], ch
|
|||
char *mask = NULL;
|
||||
char mo[1024], mo2[1024];
|
||||
char *p, *usermask, *hostmask;
|
||||
char *tkllayer[9] = {
|
||||
me.name, /*0 server.name */
|
||||
NULL, /*1 +|- */
|
||||
NULL, /*2 G */
|
||||
NULL, /*3 user */
|
||||
NULL, /*4 host */
|
||||
NULL, /*5 setby */
|
||||
"0", /*6 expire_at */
|
||||
NULL, /*7 set_at */
|
||||
"no reason" /*8 reason */
|
||||
char *tkllayer[10] = {
|
||||
me.name, /*0 server.name */
|
||||
NULL, /*1 +|- */
|
||||
NULL, /*2 G */
|
||||
NULL, /*3 user */
|
||||
NULL, /*4 host */
|
||||
NULL, /*5 setby */
|
||||
"0", /*6 expire_at */
|
||||
NULL, /*7 set_at */
|
||||
"no reason", /*8 reason */
|
||||
NULL
|
||||
};
|
||||
struct tm *t;
|
||||
|
||||
|
@ -713,17 +714,19 @@ DLLFUNC int m_tkl_line(aClient *cptr, aClient *sptr, int parc, char *parv[], ch
|
|||
|
||||
int spamfilter_usage(aClient *sptr)
|
||||
{
|
||||
sendnotice(sptr, "Use: /spamfilter [add|del|remove|+|-] [type] [action] [tkltime] [tklreason] [regex]");
|
||||
sendnotice(sptr, "Use: /spamfilter [add|del|remove|+|-] [-simple|-regex|-posix] [type] [action] [tkltime] [tklreason] [regex]");
|
||||
sendnotice(sptr, "See '/helpop ?spamfilter' for more information.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** /spamfilter [add|del|remove|+|-] [match-type] [type] [action] [tkltime] [reason] [regex]
|
||||
* 1 2 3 4 5 6 7
|
||||
*/
|
||||
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] = {
|
||||
char *tkllayer[13] = {
|
||||
me.name, /* 0 server.name */
|
||||
NULL, /* 1 +|- */
|
||||
"F", /* 2 F */
|
||||
|
@ -734,12 +737,17 @@ char *tkllayer[11] = {
|
|||
"0", /* 7 set_at */
|
||||
"", /* 8 tkl time */
|
||||
"", /* 9 tkl reason */
|
||||
"" /* 10 regex */
|
||||
"", /* 10 match method */
|
||||
"", /* 11 regex */
|
||||
NULL
|
||||
};
|
||||
int targets = 0, action = 0;
|
||||
char targetbuf[64], actionbuf[2];
|
||||
char reason[512];
|
||||
int n;
|
||||
aMatch *m;
|
||||
int match_type = 0;
|
||||
char *err = NULL;
|
||||
|
||||
if (IsServer(sptr))
|
||||
return 0;
|
||||
|
@ -759,15 +767,20 @@ int n;
|
|||
sptr->name, sptr->user->username, GetHost(sptr));
|
||||
return 0;
|
||||
}
|
||||
if ((parc < 7) || BadPtr(parv[4]))
|
||||
|
||||
if ((parc == 7) && (*parv[2] != '-'))
|
||||
goto new_spamfilter_syntax;
|
||||
|
||||
if ((parc < 8) || BadPtr(parv[7]))
|
||||
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
|
||||
* parv[2]: match-type
|
||||
* parv[3]: type
|
||||
* parv[4]: action
|
||||
* parv[5]: tkl time
|
||||
* parv[6]: tkl reason (or block reason..)
|
||||
* parv[7]: regex
|
||||
*/
|
||||
if (!strcasecmp(parv[1], "add") || !strcmp(parv[1], "+"))
|
||||
whattodo = 0;
|
||||
|
@ -779,50 +792,66 @@ int n;
|
|||
return spamfilter_usage(sptr);
|
||||
}
|
||||
|
||||
targets = spamfilter_gettargets(parv[2], sptr);
|
||||
match_type = unreal_match_method_strtoval(parv[2]+1);
|
||||
if (!match_type)
|
||||
{
|
||||
new_spamfilter_syntax:
|
||||
sendnotice(sptr, "Unknown match-type '%s'. Must be one of: -regex (new fast PCRE regexes), "
|
||||
"-posix (old unreal 3.2.x posix regexes) or "
|
||||
"-simple (simple text with ? and * wildcards)",
|
||||
parv[2]);
|
||||
if (*parv[2] != '-')
|
||||
sendnotice(sptr, "Using the old 3.2.x /SPAMFILTER syntax? Note the new -regex/-posix/-simple field!!");
|
||||
|
||||
return spamfilter_usage(cptr);
|
||||
}
|
||||
|
||||
targets = spamfilter_gettargets(parv[3], sptr);
|
||||
if (!targets)
|
||||
return spamfilter_usage(sptr);
|
||||
|
||||
strlcpy(targetbuf, spamfilter_target_inttostring(targets), sizeof(targetbuf));
|
||||
|
||||
action = banact_stringtoval(parv[3]);
|
||||
action = banact_stringtoval(parv[4]);
|
||||
if (!action)
|
||||
{
|
||||
sendto_one(sptr, ":%s NOTICE %s :Invalid 'action' field (%s)", me.name, sptr->name, parv[3]);
|
||||
sendto_one(sptr, ":%s NOTICE %s :Invalid 'action' field (%s)", me.name, sptr->name, parv[4]);
|
||||
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)
|
||||
/* now check the regex / match field... */
|
||||
m = unreal_create_match(match_type, reason, &err);
|
||||
if (!m)
|
||||
{
|
||||
sendto_one(sptr, ":%s NOTICE %s :Error in regex '%s': %s",
|
||||
me.name, sptr->name, parv[6], p);
|
||||
me.name, sptr->name, parv[7], err);
|
||||
return 0;
|
||||
}
|
||||
unreal_delete_match(m);
|
||||
|
||||
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] == '-')
|
||||
if (parv[5][0] == '-')
|
||||
{
|
||||
ircsnprintf(mo, sizeof(mo), "%li", SPAMFILTER_BAN_TIME);
|
||||
tkllayer[8] = mo;
|
||||
}
|
||||
else
|
||||
tkllayer[8] = parv[4];
|
||||
tkllayer[8] = parv[5];
|
||||
|
||||
if (parv[5][0] == '-')
|
||||
if (parv[6][0] == '-')
|
||||
strlcpy(reason, unreal_encodespace(SPAMFILTER_BAN_REASON), sizeof(reason));
|
||||
else
|
||||
strlcpy(reason, parv[5], sizeof(reason));
|
||||
strlcpy(reason, parv[6], sizeof(reason));
|
||||
|
||||
tkllayer[9] = reason;
|
||||
tkllayer[10] = parv[6];
|
||||
tkllayer[10] = parv[2]+1; /* +1 to skip the '-' */
|
||||
tkllayer[11] = parv[7];
|
||||
|
||||
/* SPAMFILTER LENGTH CHECK.
|
||||
* We try to limit it here so '/stats f' output shows ok, output of that is:
|
||||
|
@ -832,7 +861,7 @@ int n;
|
|||
* 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;
|
||||
n = strlen(reason) + strlen(parv[7]) + strlen(tkllayer[6]) + (NICKLEN * 2) + 40;
|
||||
if ((n > 500) && (whattodo == 0))
|
||||
{
|
||||
sendnotice(sptr, "Sorry, spamfilter too long. You'll either have to trim down the "
|
||||
|
@ -846,7 +875,7 @@ int n;
|
|||
tkllayer[7] = mo2;
|
||||
}
|
||||
|
||||
m_tkl(&me, &me, 11, tkllayer);
|
||||
m_tkl(&me, &me, 12, tkllayer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -921,10 +950,11 @@ char _tkl_typetochar(int type)
|
|||
*/
|
||||
|
||||
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)
|
||||
TS expire_at, TS set_at, TS spamf_tkl_duration, char *spamf_tkl_reason, MatchType match_type)
|
||||
{
|
||||
aTKline *nl;
|
||||
int index;
|
||||
aMatch *m;
|
||||
|
||||
/* 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
|
||||
|
@ -932,11 +962,12 @@ aTKline *_tkl_add_line(int type, char *usermask, char *hostmask, char *reason, c
|
|||
*/
|
||||
if (type & TKL_SPAMF)
|
||||
{
|
||||
char *myerr = unreal_checkregex(reason, 0, 0);
|
||||
if (myerr)
|
||||
char *err = NULL;
|
||||
m = unreal_create_match(match_type, reason, &err);
|
||||
if (!m)
|
||||
{
|
||||
sendto_realops("[TKL ERROR] ERROR: Spamfilter was added but did not compile. ERROR='%s', Spamfilter='%s'",
|
||||
myerr, reason);
|
||||
err, reason);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -957,7 +988,8 @@ aTKline *_tkl_add_line(int type, char *usermask, char *hostmask, char *reason, c
|
|||
{
|
||||
/* 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 = MyMallocEx(sizeof(Spamfilter));
|
||||
nl->ptr.spamf->expr = m;
|
||||
nl->ptr.spamf->action = banact_chartoval(*hostmask);
|
||||
nl->expire_at = 0; /* temporary spamfilters are NOT supported! (makes no sense) */
|
||||
if (!spamf_tkl_reason)
|
||||
|
@ -1005,7 +1037,7 @@ aTKline *_tkl_del_line(aTKline *tkl)
|
|||
MyFree(p->setby);
|
||||
if (p->type & TKL_SPAMF && p->ptr.spamf)
|
||||
{
|
||||
regfree(&p->ptr.spamf->expr);
|
||||
unreal_delete_match(p->ptr.spamf->expr);
|
||||
if (p->ptr.spamf->tkl_reason)
|
||||
MyFree(p->ptr.spamf->tkl_reason);
|
||||
MyFree(p->ptr.spamf);
|
||||
|
@ -1435,7 +1467,7 @@ aClient *acptr;
|
|||
if (MyClient(acptr))
|
||||
{
|
||||
spamfilter_build_user_string(spamfilter_user, acptr->name, acptr);
|
||||
if (regexec(&tk->ptr.spamf->expr, spamfilter_user, 0, NULL, 0))
|
||||
if (!unreal_match(tk->ptr.spamf->expr, spamfilter_user))
|
||||
continue; /* No match */
|
||||
|
||||
/* matched! */
|
||||
|
@ -1465,7 +1497,7 @@ aClient *acptr;
|
|||
if (IsPerson(acptr))
|
||||
{
|
||||
spamfilter_build_user_string(spamfilter_user, acptr->name, acptr);
|
||||
if (regexec(&tk->ptr.spamf->expr, spamfilter_user, 0, NULL, 0))
|
||||
if (!unreal_match(tk->ptr.spamf->expr, spamfilter_user))
|
||||
continue; /* No match */
|
||||
|
||||
/* matched! */
|
||||
|
@ -1783,6 +1815,7 @@ void _tkl_stats(aClient *cptr, int type, char *para)
|
|||
sendto_one(cptr, rpl_str(RPL_STATSSPAMF), me.name,
|
||||
cptr->name,
|
||||
(tk->type & TKL_GLOBAL) ? 'F' : 'f',
|
||||
unreal_match_method_valtostr(tk->ptr.spamf->expr->type),
|
||||
spamfilter_target_inttostring(tk->subtype),
|
||||
banact_valtostring(tk->ptr.spamf->action),
|
||||
(tk->expire_at != 0) ? (tk->expire_at - curtime) : 0,
|
||||
|
@ -1850,21 +1883,23 @@ void _tkl_synch(aClient *sptr)
|
|||
* This routine is used both internally by the ircd (to
|
||||
* for example add local klines, zlines, etc) and over the
|
||||
* network (glines, gzlines, spamfilter, etc).
|
||||
* add: remove: spamfilter: spamfilter+TKLEXT sqline:
|
||||
* parv[ 1]: + - +/- + +/-
|
||||
* parv[ 2]: type type type type type
|
||||
* parv[ 3]: user user target target hold
|
||||
* parv[ 4]: host host action action host
|
||||
* parv[ 5]: setby removedby (un)setby setby setby
|
||||
* parv[ 6]: expire_at expire_at (0) expire_at (0) expire_at
|
||||
* parv[ 7]: set_at set_at set_at set_at
|
||||
* parv[ 8]: reason regex tkl duration reason
|
||||
* parv[ 9]: tkl reason [A]
|
||||
* parv[10]: regex
|
||||
* add: remove: spamfilter: spamfilter+TKLEXT spamfilter+TKLEXT2 sqline:
|
||||
* parv[ 1]: + - +/- + + +/-
|
||||
* parv[ 2]: type type type type type type
|
||||
* parv[ 3]: user user target target target hold
|
||||
* parv[ 4]: host host action action action host
|
||||
* parv[ 5]: setby removedby (un)setby setby setby setby
|
||||
* parv[ 6]: expire_at expire_at (0) expire_at (0) expire_at (0) expire_at
|
||||
* parv[ 7]: set_at set_at set_at set_at set_at
|
||||
* parv[ 8]: reason regex tkl duration tkl duration reason
|
||||
* parv[ 9]: tkl reason [A] tkl reason [A]
|
||||
* parv[10]: regex match-type [B]
|
||||
* parv[11]: match-string [C]
|
||||
*
|
||||
* [A] tkl reason field must be escaped by caller [eg: use unreal_encodespace()
|
||||
* if m_tkl is called internally].
|
||||
*
|
||||
* [B] match-type must be one of: regex, simple, posix.
|
||||
* [C] Could be a regex or a regular string with wildcards, depending on [B]
|
||||
*/
|
||||
int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
||||
{
|
||||
|
@ -1874,6 +1909,7 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
char gmt[256], gmt2[256];
|
||||
char txt[256];
|
||||
TS expiry_1, setat_1, spamf_tklduration = 0;
|
||||
MatchType spamf_match_method = MATCH_TRE_REGEX; /* (if unspecified, default to this) */
|
||||
char *reason = NULL, *timeret;
|
||||
|
||||
if (!IsServer(sptr) && !IsOper(sptr) && !IsMe(sptr))
|
||||
|
@ -1935,7 +1971,27 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
found = 0;
|
||||
if ((type & TKL_SPAMF) && (parc >= 11))
|
||||
{
|
||||
reason = parv[10];
|
||||
if (parc >= 12)
|
||||
{
|
||||
reason = parv[11];
|
||||
spamf_match_method = unreal_match_method_strtoval(parv[10]);
|
||||
if (spamf_match_method == 0)
|
||||
{
|
||||
sendto_realops("Ignoring spamfilter from %s with unknown match type '%s'",
|
||||
sptr->name, parv[10]);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
reason = parv[10];
|
||||
#ifdef USE_TRE
|
||||
spamf_match_method = MATCH_TRE_REGEX;
|
||||
#else
|
||||
sendto_realops("Ignoring spamfilter from %s. Spamfilter is of type 'posix' (TRE) and this "
|
||||
"build was compiled without TRE support. Suggestion: upgrade the other server",
|
||||
sptr->name);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
spamf_tklduration = config_checkval(parv[8], CFG_TIME); /* was: atol(parv[8]); */
|
||||
}
|
||||
for (tk = tklines[tkl_hash(parv[2][0])]; tk; tk = tk->next)
|
||||
|
@ -2030,10 +2086,10 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
/* there is something fucked here? */
|
||||
if ((type & TKL_SPAMF) && (parc >= 11))
|
||||
tk = tkl_add_line(type, parv[3], parv[4], reason, parv[5],
|
||||
expiry_1, setat_1, spamf_tklduration, parv[9]);
|
||||
expiry_1, setat_1, spamf_tklduration, parv[9], spamf_match_method);
|
||||
else
|
||||
tk = tkl_add_line(type, parv[3], parv[4], reason, parv[5],
|
||||
expiry_1, setat_1, 0, NULL);
|
||||
expiry_1, setat_1, 0, NULL, 0);
|
||||
|
||||
if (!tk)
|
||||
return 0; /* ERROR on allocate or something else... */
|
||||
|
@ -2137,6 +2193,22 @@ int _m_tkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
|
||||
if (type & TKL_GLOBAL)
|
||||
{
|
||||
if ((parc == 12) && (type & TKL_SPAMF))
|
||||
{
|
||||
/* Oooooh.. so many flavours ! */
|
||||
sendto_server(cptr, PROTO_TKLEXT2, 0,
|
||||
":%s TKL %s %s %s %s %s %s %s %s %s %s :%s", sptr->name,
|
||||
parv[1], parv[2], parv[3], parv[4], parv[5],
|
||||
parv[6], parv[7], parv[8], parv[9], parv[10], parv[11]);
|
||||
sendto_server(cptr, PROTO_TKLEXT, PROTO_TKLEXT2,
|
||||
":%s TKL %s %s %s %s %s %s %s %s %s :%s", sptr->name,
|
||||
parv[1], parv[2], parv[3], parv[4], parv[5],
|
||||
parv[6], parv[7], parv[8], parv[9], parv[11]); /* parv[11] = regex */
|
||||
sendto_server(cptr, 0, PROTO_TKLEXT,
|
||||
":%s TKL %s %s %s %s %s %s %s :%s", sptr->name,
|
||||
parv[1], parv[2], parv[3], parv[4], parv[5],
|
||||
parv[6], parv[7], parv[10]);
|
||||
} else
|
||||
if ((parc == 11) && (type & TKL_SPAMF))
|
||||
{
|
||||
sendto_server(cptr, PROTO_TKLEXT, 0,
|
||||
|
@ -2542,7 +2614,7 @@ long ms_past;
|
|||
getrusage(RUSAGE_SELF, &rprev);
|
||||
#endif
|
||||
|
||||
ret = regexec(&tk->ptr.spamf->expr, str, 0, NULL, 0);
|
||||
ret = unreal_match(tk->ptr.spamf->expr, str);
|
||||
|
||||
#ifdef SPAMFILTER_DETECTSLOW
|
||||
getrusage(RUSAGE_SELF, &rnow);
|
||||
|
@ -2564,7 +2636,7 @@ long ms_past;
|
|||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
if (ret)
|
||||
{
|
||||
/* We have a match! */
|
||||
char buf[1024];
|
||||
|
|
127
src/s_conf.c
127
src/s_conf.c
|
@ -2140,7 +2140,7 @@ void config_rehash()
|
|||
ircfree(fmt->format);
|
||||
ircfree(fmt->nick);
|
||||
ircfree(fmt->parameters);
|
||||
regfree(&fmt->expr);
|
||||
unreal_delete_match(fmt->expr);
|
||||
DelListItem(fmt, alias_ptr->format);
|
||||
MyFree(fmt);
|
||||
}
|
||||
|
@ -5634,10 +5634,11 @@ int _conf_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
char *word = NULL, *reason = NULL, *bantime = NULL;
|
||||
int action = 0, target = 0;
|
||||
char has_reason = 0, has_bantime = 0;
|
||||
int match_type = 0;
|
||||
|
||||
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
|
||||
{
|
||||
if (!strcmp(cep->ce_varname, "regex"))
|
||||
if (!strcmp(cep->ce_varname, "match"))
|
||||
{
|
||||
nl->reason = strdup(cep->ce_vardata);
|
||||
|
||||
|
@ -5668,6 +5669,10 @@ int _conf_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
has_bantime = 1;
|
||||
bantime = cep->ce_vardata;
|
||||
}
|
||||
else if (!strcmp(cep->ce_varname, "match-type"))
|
||||
{
|
||||
match_type = unreal_match_method_strtoval(cep->ce_vardata);
|
||||
}
|
||||
}
|
||||
nl->type = TKL_SPAMF;
|
||||
nl->expire_at = 0;
|
||||
|
@ -5677,7 +5682,8 @@ int _conf_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
nl->subtype = target;
|
||||
|
||||
nl->setby = BadPtr(me.name) ? NULL : strdup(me.name); /* Hmm! */
|
||||
nl->ptr.spamf = unreal_buildspamfilter(word);
|
||||
nl->ptr.spamf = MyMallocEx(sizeof(Spamfilter));
|
||||
nl->ptr.spamf->expr = unreal_create_match(match_type, word, NULL);
|
||||
nl->ptr.spamf->action = action;
|
||||
|
||||
if (has_reason && reason)
|
||||
|
@ -5698,8 +5704,9 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
{
|
||||
ConfigEntry *cep, *cepp;
|
||||
int errors = 0;
|
||||
char *regex = NULL, *reason = NULL;
|
||||
char has_target = 0, has_regex = 0, has_action = 0, has_reason = 0, has_bantime = 0;
|
||||
char *match = NULL, *reason = NULL;
|
||||
char has_target = 0, has_match = 0, has_action = 0, has_reason = 0, has_bantime = 0, has_match_type = 0;
|
||||
int match_type = 0;
|
||||
|
||||
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
|
||||
{
|
||||
|
@ -5775,26 +5782,16 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
has_reason = 1;
|
||||
reason = cep->ce_vardata;
|
||||
}
|
||||
else if (!strcmp(cep->ce_varname, "regex"))
|
||||
else if (!strcmp(cep->ce_varname, "match"))
|
||||
{
|
||||
char *errbuf;
|
||||
if (has_regex)
|
||||
if (has_match)
|
||||
{
|
||||
config_warn_duplicate(cep->ce_fileptr->cf_filename,
|
||||
cep->ce_varlinenum, "spamfilter::regex");
|
||||
cep->ce_varlinenum, "spamfilter::match");
|
||||
continue;
|
||||
}
|
||||
has_regex = 1;
|
||||
if ((errbuf = unreal_checkregex(cep->ce_vardata,0,0)))
|
||||
{
|
||||
config_error("%s:%i: spamfilter::regex contains an invalid regex: %s",
|
||||
cep->ce_fileptr->cf_filename,
|
||||
cep->ce_varlinenum,
|
||||
errbuf);
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
regex = cep->ce_vardata;
|
||||
has_match = 1;
|
||||
match = cep->ce_vardata;
|
||||
}
|
||||
else if (!strcmp(cep->ce_varname, "action"))
|
||||
{
|
||||
|
@ -5822,6 +5819,26 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
}
|
||||
has_bantime = 1;
|
||||
}
|
||||
else if (!strcmp(cep->ce_varname, "match-type"))
|
||||
{
|
||||
if (has_match_type)
|
||||
{
|
||||
config_warn_duplicate(cep->ce_fileptr->cf_filename,
|
||||
cep->ce_varlinenum, "spamfilter::match-type");
|
||||
continue;
|
||||
}
|
||||
match_type = unreal_match_method_strtoval(cep->ce_vardata);
|
||||
if (match_type == 0)
|
||||
{
|
||||
config_error("%s:%i: spamfilter::match-type: unknown match type '%s', "
|
||||
"should be one of: 'simple', 'regex' or 'posix'",
|
||||
cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
|
||||
cep->ce_vardata);
|
||||
errors++;
|
||||
continue;
|
||||
}
|
||||
has_match_type = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
config_error_unknown(cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
|
||||
|
@ -5831,10 +5848,26 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
}
|
||||
}
|
||||
|
||||
if (!has_regex)
|
||||
if (match && match_type)
|
||||
{
|
||||
aMatch *m;
|
||||
char *err;
|
||||
|
||||
m = unreal_create_match(match_type, match, &err);
|
||||
if (!m)
|
||||
{
|
||||
config_error("%s:%i: spamfilter::match contains an invalid regex: %s",
|
||||
cep->ce_fileptr->cf_filename,
|
||||
cep->ce_varlinenum,
|
||||
err);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_match)
|
||||
{
|
||||
config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
|
||||
"spamfilter::regex");
|
||||
"spamfilter::match");
|
||||
errors++;
|
||||
}
|
||||
if (!has_target)
|
||||
|
@ -5849,13 +5882,25 @@ int _test_spamfilter(ConfigFile *conf, ConfigEntry *ce)
|
|||
"spamfilter::action");
|
||||
errors++;
|
||||
}
|
||||
if (regex && reason && (strlen(regex) + strlen(reason) > 505))
|
||||
if (match && reason && (strlen(match) + strlen(reason) > 505))
|
||||
{
|
||||
config_error("%s:%i: spamfilter block problem: regex + reason field are together over 505 bytes, "
|
||||
config_error("%s:%i: spamfilter block problem: match + reason field are together over 505 bytes, "
|
||||
"please choose a shorter regex or reason",
|
||||
ce->ce_fileptr->cf_filename, ce->ce_varlinenum);
|
||||
errors++;
|
||||
}
|
||||
if (!has_match_type)
|
||||
{
|
||||
config_error_missing(ce->ce_fileptr->cf_filename, ce->ce_varlinenum,
|
||||
"spamfilter::match-type");
|
||||
errors++;
|
||||
}
|
||||
|
||||
if (!has_match_type && !has_match && has_action && has_target)
|
||||
{
|
||||
config_error("Upgrading from 3.2.x to 3.4.x? Your spamfilter { } blocks need to be converted. "
|
||||
"See https://www.unrealircd.org/docs/Upgrading_from_3.2.x#Spamfilter");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
@ -8392,7 +8437,9 @@ int _conf_alias(ConfigFile *conf, ConfigEntry *ce)
|
|||
if (!strcmp(cep->ce_varname, "format")) {
|
||||
format = MyMallocEx(sizeof(ConfigItem_alias_format));
|
||||
ircstrdup(format->format, cep->ce_vardata);
|
||||
regcomp(&format->expr, cep->ce_vardata, REG_ICASE|REG_EXTENDED);
|
||||
format->expr = unreal_create_match(MATCH_PCRE_REGEX, cep->ce_vardata, NULL);
|
||||
if (!format->expr)
|
||||
abort(); /* Impossible due to _test_alias earlier */
|
||||
for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
|
||||
if (!strcmp(cepp->ce_varname, "nick") ||
|
||||
!strcmp(cepp->ce_varname, "target") ||
|
||||
|
@ -8477,26 +8524,22 @@ int _test_alias(ConfigFile *conf, ConfigEntry *ce) {
|
|||
continue;
|
||||
}
|
||||
if (!strcmp(cep->ce_varname, "format")) {
|
||||
int errorcode, errorbufsize;
|
||||
char *errorbuf;
|
||||
regex_t expr;
|
||||
char *err = NULL;
|
||||
aMatch *expr;
|
||||
char has_type = 0, has_target = 0, has_parameters = 0;
|
||||
|
||||
has_format = 1;
|
||||
errorcode = regcomp(&expr, cep->ce_vardata, REG_ICASE|REG_EXTENDED);
|
||||
if (errorcode > 0)
|
||||
{
|
||||
errorbufsize = regerror(errorcode, &expr, NULL, 0)+1;
|
||||
errorbuf = MyMalloc(errorbufsize);
|
||||
regerror(errorcode, &expr, errorbuf, errorbufsize);
|
||||
config_error("%s:%i: alias::format contains an invalid regex: %s",
|
||||
cep->ce_fileptr->cf_filename,
|
||||
cep->ce_varlinenum,
|
||||
errorbuf);
|
||||
errors++;
|
||||
free(errorbuf);
|
||||
}
|
||||
regfree(&expr);
|
||||
expr = unreal_create_match(MATCH_PCRE_REGEX, cep->ce_vardata, &err);
|
||||
if (!expr)
|
||||
{
|
||||
config_error("%s:%i: alias::format contains an invalid regex: %s",
|
||||
cep->ce_fileptr->cf_filename, cep->ce_varlinenum, err);
|
||||
config_error("Upgrading from 3.2.x to 3.4.x? Note that regex changed from POSIX Regex "
|
||||
"to PCRE Regex!"); /* TODO: refer to some url ? */
|
||||
} else {
|
||||
unreal_delete_match(expr);
|
||||
}
|
||||
|
||||
for (cepp = cep->ce_entries; cepp; cepp = cepp->ce_next) {
|
||||
if (config_is_blankorempty(cepp, "alias::format"))
|
||||
{
|
||||
|
|
|
@ -262,7 +262,7 @@ static char *replies[] = {
|
|||
/* 226 RPL_STATSNLINE */ ":%s 226 %s n %s %s",
|
||||
/* 227 RPL_STATSVLINE */ ":%s 227 %s v %s %s %s",
|
||||
/* 228 RPL_STATSBANVER */ ":%s 228 %s %s %s",
|
||||
/* 229 RPL_STATSSPAMF */ ":%s 229 %s %c %s %s %li %li %li %s %s :%s",
|
||||
/* 229 RPL_STATSSPAMF */ ":%s 229 %s %c %s %s %s %li %li %li %s %s :%s",
|
||||
/* 230 RPL_STATSEXCEPTTKL */ ":%s 230 %s %c %s",
|
||||
/* 231 */ NULL, /* rfc1459 */
|
||||
/* 232 RPL_RULES */ ":%s 232 %s :- %s",
|
||||
|
|
18
src/s_misc.c
18
src/s_misc.c
|
@ -847,26 +847,8 @@ Ilovegotos:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SPF_REGEX_FLAGS (REG_ICASE|REG_EXTENDED|REG_NOSUB)
|
||||
|
||||
/** Allocates a new Spamfilter entry and compiles/fills in the info.
|
||||
* NOTE: originally I wanted to integrate both badwords and spamfilter
|
||||
* into one function, but that was quickly getting ugly :(.
|
||||
*/
|
||||
Spamfilter *unreal_buildspamfilter(char *s)
|
||||
{
|
||||
Spamfilter *e = MyMallocEx(sizeof(Spamfilter));
|
||||
|
||||
regcomp(&e->expr, s, SPF_REGEX_FLAGS);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/*|| BAN ACTION ROUTINES FOLLOW ||*/
|
||||
|
||||
|
||||
/** Converts a banaction string (eg: "kill") to an integer value (eg: BAN_ACT_KILL) */
|
||||
int banact_stringtoval(char *s)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue