mirror of
https://github.com/pissnet/pissircd.git
synced 2025-07-28 22:12:25 +01:00
Rewrite/cleanup huge portion of TKL handling (16 files updated, but
src/modules/tkl.c is the main one). Also move DB writing/reading functions to src/misc.c so they can be removed out of channeldb and tkldb. Important note to current tkldb users: Unfortunately due to the major cleanup I had to remove upgrading for previously saved tkl db files. That seemed not worth the effort for maybe <15 current users or so. It also makes the tkldb code a lot more cleaner. Otherwise it would be a huge mess. Currently a FIXME item: spamfilter support in RMTKL.
This commit is contained in:
parent
0116c4f0d6
commit
8a6c84876e
16 changed files with 1391 additions and 1200 deletions
24
include/h.h
24
include/h.h
|
@ -645,8 +645,20 @@ extern MODVAR int (*tkl_hash)(unsigned int c);
|
|||
extern MODVAR char (*tkl_typetochar)(int type);
|
||||
extern MODVAR int (*tkl_chartotype)(char c);
|
||||
extern MODVAR char *(*tkl_type_string)(aTKline *tk);
|
||||
extern MODVAR aTKline *(*tkl_add_line)(int type, char *usermask, char *hostmask, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, time_t spamf_tkl_duration, char *spamf_tkl_reason, MatchType spamf_match_type, int soft, int flags);
|
||||
extern MODVAR aTKline *(*tkl_add_serverban)(int type, char *usermask, char *hostmask, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, int soft, int flags);
|
||||
extern MODVAR aTKline *(*tkl_add_nameban)(int type, char *name, int hold, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, int flags);
|
||||
extern MODVAR aTKline *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, aMatch *match, char *setby,
|
||||
time_t expire_at, time_t set_at,
|
||||
time_t spamf_tkl_duration, char *spamf_tkl_reason,
|
||||
int flags);
|
||||
extern MODVAR aTKline *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
|
||||
extern MODVAR aTKline *(*find_tkl_nameban)(int type, char *name, int hold);
|
||||
extern MODVAR aTKline *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
|
||||
extern MODVAR void (*sendnotice_tkl_del)(char *removed_by, aTKline *tkl);
|
||||
extern MODVAR void (*sendnotice_tkl_add)(aTKline *tkl);
|
||||
extern MODVAR void (*free_tkl)(aTKline *tkl);
|
||||
extern MODVAR aTKline *(*tkl_del_line)(aTKline *tkl);
|
||||
extern MODVAR void (*tkl_check_local_remove_shun)(aTKline *tmp);
|
||||
extern MODVAR int (*find_tkline_match)(aClient *cptr, int skip_soft);
|
||||
|
@ -861,3 +873,11 @@ extern int history_request(aClient *acptr, char *object, HistoryFilter *filter);
|
|||
extern int history_del(char *object, int max_lines, long max_time);
|
||||
extern int history_destroy(char *object);
|
||||
extern void special_delayed_unloading(void);
|
||||
extern int write_int64(FILE *fd, uint64_t t);
|
||||
extern int write_int32(FILE *fd, uint32_t t);
|
||||
extern int read_int64(FILE *fd, uint64_t *t);
|
||||
extern int read_int32(FILE *fd, uint32_t *t);
|
||||
extern int read_data(FILE *fd, void *buf, size_t len);
|
||||
extern int write_data(FILE *fd, const void *buf, size_t len);
|
||||
extern int write_str(FILE *fd, char *x);
|
||||
extern int read_str(FILE *fd, char **x);
|
||||
|
|
|
@ -1170,7 +1170,7 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
|
|||
#define EFUNC_REGISTER_USER 7
|
||||
#define EFUNC_TKL_HASH 8
|
||||
#define EFUNC_TKL_TYPETOCHAR 9
|
||||
#define EFUNC_TKL_ADD_LINE 10
|
||||
#define EFUNC_TKL_ADD_SERVERBAN 10
|
||||
#define EFUNC_TKL_DEL_LINE 11
|
||||
#define EFUNC_TKL_CHECK_LOCAL_REMOVE_SHUN 12
|
||||
#define EFUNC_TKL_EXPIRE 13
|
||||
|
@ -1227,6 +1227,14 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
|
|||
#define EFUNC_BROADCAST_MD_GLOBALVAR_CMD 67
|
||||
#define EFUNC_TKL_IP_HASH 68
|
||||
#define EFUNC_TKL_IP_HASH_TYPE 69
|
||||
#define EFUNC_TKL_ADD_NAMEBAN 70
|
||||
#define EFUNC_TKL_ADD_SPAMFILTER 71
|
||||
#define EFUNC_SENDNOTICE_TKL_ADD 72
|
||||
#define EFUNC_SENDNOTICE_TKL_DEL 73
|
||||
#define EFUNC_FREE_TKL 74
|
||||
#define EFUNC_FIND_TKL_SERVERBAN 75
|
||||
#define EFUNC_FIND_TKL_NAMEBAN 76
|
||||
#define EFUNC_FIND_TKL_SPAMFILTER 77
|
||||
|
||||
/* Module flags */
|
||||
#define MODFLAG_NONE 0x0000
|
||||
|
|
|
@ -67,8 +67,9 @@ typedef struct aloopStruct LoopStruct;
|
|||
typedef struct ConfItem aConfItem;
|
||||
typedef struct t_kline aTKline;
|
||||
typedef struct _spamfilter Spamfilter;
|
||||
typedef struct _serverban ServerBan;
|
||||
typedef struct _nameban NameBan;
|
||||
typedef struct _spamexcept SpamExcept;
|
||||
/* New Config Stuff */
|
||||
typedef struct _conditionalconfig ConditionalConfig;
|
||||
typedef struct _configentry ConfigEntry;
|
||||
typedef struct _configfile ConfigFile;
|
||||
|
@ -711,11 +712,17 @@ struct Server {
|
|||
#define TKL_ZAP 0x0002
|
||||
#define TKL_GLOBAL 0x0004
|
||||
#define TKL_SHUN 0x0008
|
||||
#define TKL_QUIET 0x0010
|
||||
#define TKL_SPAMF 0x0020
|
||||
#define TKL_NICK 0x0040
|
||||
#define TKL_NAME 0x0040
|
||||
#define TKL_EXCEPT 0x0080
|
||||
|
||||
#define TKLIsServerBan(tkl) ((tkl)->type & (TKL_KILL|TKL_ZAP|TKL_SHUN))
|
||||
#define TKLIsServerBanType(tpe) ((tpe) & (TKL_KILL|TKL_ZAP|TKL_SHUN))
|
||||
#define TKLIsSpamfilter(tkl) ((tkl)->type & TKL_SPAMF)
|
||||
#define TKLIsSpamfilterType(tpe) ((tpe) & TKL_SPAMF)
|
||||
#define TKLIsNameBan(tkl) ((tkl)->type & TKL_NAME)
|
||||
#define TKLIsNameBanType(tpe) ((tpe) & TKL_NAME)
|
||||
|
||||
#define SPAMF_CHANMSG 0x0001 /* c */
|
||||
#define SPAMF_USERMSG 0x0002 /* p */
|
||||
#define SPAMF_USERNOTICE 0x0004 /* n */
|
||||
|
@ -730,14 +737,30 @@ struct Server {
|
|||
/* Other flags only for function calls: */
|
||||
#define SPAMFLAG_NOWARN 0x0001
|
||||
|
||||
/** Spamfilter sub-struct of TKL entry */
|
||||
/** Spamfilter sub-struct of TKL entry (Spamfilter) */
|
||||
struct _spamfilter {
|
||||
unsigned short target;
|
||||
unsigned short action; /**< Ban action, see BAN_ACT* */
|
||||
aMatch *expr; /**< Spamfilter matcher */
|
||||
aMatch *match; /**< Spamfilter matcher */
|
||||
char *tkl_reason; /**< Reason to use for bans placed by this spamfilter, escaped by unreal_encodespace(). */
|
||||
time_t tkl_duration; /**< Duration of bans placed by this spamfilter */
|
||||
};
|
||||
|
||||
/** Server ban sub-struct of TKL entry (KLINE/GLINE/ZLINE/GZLINE/SHUN) */
|
||||
struct _serverban {
|
||||
char *usermask; /**< User mask */
|
||||
char *hostmask; /**< Host mask */
|
||||
unsigned short subtype; /**< See TKL_SUBTYPE_* */
|
||||
char *reason; /**< Reason */
|
||||
};
|
||||
|
||||
/* Name ban sub-struct of TKL entry (QLINE) */
|
||||
struct _nameban {
|
||||
char hold; /**< nickname hold is used by services */
|
||||
char *name; /**< the nick or channel that is banned */
|
||||
char *reason; /**< Reason */
|
||||
};
|
||||
|
||||
#define TKL_SUBTYPE_NONE 0x0000
|
||||
#define TKL_SUBTYPE_SOFT 0x0001 /* (require SASL) */
|
||||
|
||||
|
@ -747,17 +770,15 @@ struct _spamfilter {
|
|||
struct t_kline {
|
||||
aTKline *prev, *next;
|
||||
unsigned int type; /**< TKL type. One of TKL_*, such as TKL_KILL|TKL_GLOBAL for gline */
|
||||
unsigned short subtype; /* TKL subtype. For spamfilter one of SPAMF_*, otherwise TKL_SUBTYPE_* */
|
||||
unsigned short flags; /**< One of TKL_FLAG_*, such as TKL_FLAG_CONFIG */
|
||||
union {
|
||||
Spamfilter *spamf;
|
||||
} ptr;
|
||||
char usermask[USERLEN + 3]; /**< User mask [different for spamfilter] */
|
||||
char *hostmask; /**< Host mask [different for spamfilter] */
|
||||
char *reason; /**< Reason [different for spamfilter] */
|
||||
char *setby; /**< By who was this entry added */
|
||||
time_t expire_at; /**< When this entry will expire */
|
||||
char *set_by; /**< By who was this entry added */
|
||||
time_t set_at; /**< When this entry was added */
|
||||
time_t expire_at; /**< When this entry will expire */
|
||||
union {
|
||||
Spamfilter *spamfilter;
|
||||
ServerBan *serverban;
|
||||
NameBan *nameban;
|
||||
} ptr;
|
||||
};
|
||||
|
||||
/** A spamfilter except entry */
|
||||
|
|
28
src/conf.c
28
src/conf.c
|
@ -174,9 +174,9 @@ static NameValue _LogFlags[] = {
|
|||
static NameValue ExceptTklFlags[] = {
|
||||
{ 0, "all" },
|
||||
{ TKL_GLOBAL|TKL_KILL, "gline" },
|
||||
{ TKL_GLOBAL|TKL_NICK, "gqline" },
|
||||
{ TKL_GLOBAL|TKL_NAME, "gqline" },
|
||||
{ TKL_GLOBAL|TKL_ZAP, "gzline" },
|
||||
{ TKL_NICK, "qline" },
|
||||
{ TKL_NAME, "qline" },
|
||||
{ TKL_GLOBAL|TKL_SHUN, "shun" }
|
||||
};
|
||||
|
||||
|
@ -1644,14 +1644,14 @@ void postconf_defaults(void)
|
|||
// which is more meaningful.
|
||||
for (tk = tklines[tkl_hash('q')]; tk; tk = tk->next)
|
||||
{
|
||||
if (tk->type != TKL_NICK)
|
||||
if (tk->type != TKL_NAME)
|
||||
continue;
|
||||
if (!tk->setby)
|
||||
if (!tk->set_by)
|
||||
{
|
||||
if (me.name[0] != '\0')
|
||||
tk->setby = strdup(me.name);
|
||||
tk->set_by = strdup(me.name);
|
||||
else
|
||||
tk->setby = strdup(conf_me->name ? conf_me->name : "~server~");
|
||||
tk->set_by = strdup(conf_me->name ? conf_me->name : "~server~");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1659,19 +1659,19 @@ void postconf_defaults(void)
|
|||
{
|
||||
if (tk->type != TKL_SPAMF)
|
||||
continue; /* global entry or something else.. */
|
||||
if (!strcmp(tk->ptr.spamf->tkl_reason, "<internally added by ircd>"))
|
||||
if (!strcmp(tk->ptr.spamfilter->tkl_reason, "<internally added by ircd>"))
|
||||
{
|
||||
MyFree(tk->ptr.spamf->tkl_reason);
|
||||
tk->ptr.spamf->tkl_reason = strdup(encoded);
|
||||
tk->ptr.spamf->tkl_duration = SPAMFILTER_BAN_TIME;
|
||||
MyFree(tk->ptr.spamfilter->tkl_reason);
|
||||
tk->ptr.spamfilter->tkl_reason = strdup(encoded);
|
||||
tk->ptr.spamfilter->tkl_duration = SPAMFILTER_BAN_TIME;
|
||||
}
|
||||
/* This one is even more ugly, but our config crap is VERY confusing :[ */
|
||||
if (!tk->setby)
|
||||
if (!tk->set_by)
|
||||
{
|
||||
if (me.name[0] != '\0')
|
||||
tk->setby = strdup(me.name);
|
||||
tk->set_by = strdup(me.name);
|
||||
else
|
||||
tk->setby = strdup(conf_me->name ? conf_me->name : "~server~");
|
||||
tk->set_by = strdup(conf_me->name ? conf_me->name : "~server~");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6882,7 +6882,7 @@ int _conf_require(ConfigFile *conf, ConfigEntry *ce)
|
|||
if (!reason)
|
||||
reason = strdup("-");
|
||||
|
||||
tkl_add_line(TKL_KILL, usermask, hostmask, reason, "-config-", 0, TStime(), 0, NULL, 0, 1, TKL_FLAG_CONFIG);
|
||||
tkl_add_serverban(TKL_KILL, usermask, hostmask, reason, "-config-", 0, TStime(), 1, TKL_FLAG_CONFIG);
|
||||
safefree(usermask);
|
||||
safefree(hostmask);
|
||||
safefree(reason);
|
||||
|
|
159
src/misc.c
159
src/misc.c
|
@ -1418,3 +1418,162 @@ time_t server_time_to_unix_time(const char *tbuf)
|
|||
ret = my_timegm(&tm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Write a 64 bit integer.
|
||||
* @param fd File descriptor
|
||||
* @param t The value to write
|
||||
* @example write_int64(fd, 1234);
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int write_int64(FILE *fd, uint64_t t)
|
||||
{
|
||||
if (fwrite(&t, 1, sizeof(t), fd) < sizeof(t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Write a 32 bit integer.
|
||||
* @param fd File descriptor
|
||||
* @param t The value to write
|
||||
* @example write_int32(fd, 1234);
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int write_int32(FILE *fd, uint32_t t)
|
||||
{
|
||||
if (fwrite(&t, 1, sizeof(t), fd) < sizeof(t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read a 64 bit integer.
|
||||
* @param fd File descriptor
|
||||
* @param t The value to write
|
||||
* @example read_int64(fd, &var);
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int read_int64(FILE *fd, uint64_t *t)
|
||||
{
|
||||
if (fread(t, 1, sizeof(uint64_t), fd) < sizeof(uint64_t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read a 64 bit integer.
|
||||
* @param fd File descriptor
|
||||
* @param t The value to write
|
||||
* @example read_int64(fd, &var);
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int read_int32(FILE *fd, uint32_t *t)
|
||||
{
|
||||
if (fread(t, 1, sizeof(uint32_t), fd) < sizeof(uint32_t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read binary data.
|
||||
* @param fd File descriptor
|
||||
* @param buf Pointer to buffer
|
||||
* @param len Size of buffer
|
||||
* @example read_data(fd, buf, sizeof(buf));
|
||||
* @notes This function is not used much, in most cases
|
||||
* you should use read_str(), read_int32() or
|
||||
* read_int64() instead.
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int read_data(FILE *fd, void *buf, size_t len)
|
||||
{
|
||||
if (fread(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Write binary data.
|
||||
* @param fd File descriptor
|
||||
* @param buf Pointer to buffer
|
||||
* @param len Size of buffer
|
||||
* @example write_data(fd, buf, sizeof(buf));
|
||||
* @notes This function is not used much, in most cases
|
||||
* you should use write_str(), write_int32() or
|
||||
* write_int64() instead.
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int write_data(FILE *fd, const void *buf, size_t len)
|
||||
{
|
||||
if (fwrite(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Write a string.
|
||||
* @param fd File descriptor
|
||||
* @param x Pointer to string
|
||||
* @example write_str(fd, "hello there!");
|
||||
* @notes This function can write a string up to 65534
|
||||
* characters, which should be plenty for usage
|
||||
* in UnrealIRCd.
|
||||
* Note that 'x' can safely be NULL.
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int write_str(FILE *fd, char *x)
|
||||
{
|
||||
uint16_t len;
|
||||
|
||||
len = x ? strlen(x) : 0xffff;
|
||||
if (!write_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
if ((len > 0) && (len < 0xffff))
|
||||
{
|
||||
if (!write_data(fd, x, len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read a string.
|
||||
* @param fd File descriptor
|
||||
* @param x Pointer to string pointer
|
||||
* @example write_str(fd, &str);
|
||||
* @notes This function will allocate memory for the data
|
||||
* and set the string pointer to this value.
|
||||
* If a NULL pointer was written via write_str()
|
||||
* then read_str() may also return a NULL pointer.
|
||||
* @returns 1 on success, 0 on failure.
|
||||
*/
|
||||
int read_str(FILE *fd, char **x)
|
||||
{
|
||||
uint16_t len;
|
||||
size_t size;
|
||||
|
||||
*x = NULL;
|
||||
|
||||
if (!read_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
|
||||
if (len == 0xffff)
|
||||
{
|
||||
/* Magic value meaning NULL */
|
||||
*x = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
/* 0 means empty string */
|
||||
*x = strdup("");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (len > 10000)
|
||||
return 0;
|
||||
|
||||
size = len;
|
||||
*x = MyMallocEx(size + 1);
|
||||
if (!read_data(fd, *x, size))
|
||||
{
|
||||
safefree(*x);
|
||||
return 0;
|
||||
}
|
||||
(*x)[len] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,14 @@ int (*tkl_hash)(unsigned int c);
|
|||
char (*tkl_typetochar)(int type);
|
||||
int (*tkl_chartotype)(char c);
|
||||
char *(*tkl_type_string)(aTKline *tk);
|
||||
aTKline *(*tkl_add_line)(int type, char *usermask, char *hostmask, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, time_t spamf_tkl_duration, char *spamf_tkl_reason, MatchType spamf_match_type, int soft, int flags);
|
||||
aTKline *(*tkl_add_serverban)(int type, char *usermask, char *hostmask, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, int soft, int flags);
|
||||
aTKline *(*tkl_add_nameban)(int type, char *name, int hold, char *reason, char *setby,
|
||||
time_t expire_at, time_t set_at, int flags);
|
||||
aTKline *(*tkl_add_spamfilter)(int type, unsigned short target, unsigned short action, aMatch *match, char *setby,
|
||||
time_t expire_at, time_t set_at,
|
||||
time_t spamf_tkl_duration, char *spamf_tkl_reason,
|
||||
int flags);
|
||||
aTKline *(*tkl_del_line)(aTKline *tkl);
|
||||
void (*tkl_check_local_remove_shun)(aTKline *tmp);
|
||||
int (*find_tkline_match)(aClient *cptr, int skip_soft);
|
||||
|
@ -128,6 +134,12 @@ void (*broadcast_md_globalvar)(ModDataInfo *mdi, ModData *md);
|
|||
void (*broadcast_md_globalvar_cmd)(aClient *except, aClient *sender, char *varname, char *value);
|
||||
int (*tkl_ip_hash)(char *ip);
|
||||
int (*tkl_ip_hash_type)(int type);
|
||||
void (*sendnotice_tkl_del)(char *removed_by, aTKline *tkl);
|
||||
void (*sendnotice_tkl_add)(aTKline *tkl);
|
||||
void (*free_tkl)(aTKline *tkl);
|
||||
aTKline *(*find_tkl_serverban)(int type, char *usermask, char *hostmask, int softban);
|
||||
aTKline *(*find_tkl_nameban)(int type, char *name, int hold);
|
||||
aTKline *(*find_tkl_spamfilter)(int type, char *match_string, unsigned short action, unsigned short target);
|
||||
|
||||
static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
|
||||
/* 00 */ {NULL, NULL, NULL},
|
||||
|
@ -140,7 +152,7 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
|
|||
/* 07 */ {"register_user", (void *)®ister_user, NULL},
|
||||
/* 08 */ {"tkl_hash", (void *)&tkl_hash, NULL},
|
||||
/* 09 */ {"tkl_typetochar", (void *)&tkl_typetochar, NULL},
|
||||
/* 10 */ {"tkl_add_line", (void *)&tkl_add_line, NULL},
|
||||
/* 10 */ {"tkl_add_serverban", (void *)&tkl_add_serverban, NULL},
|
||||
/* 11 */ {"tkl_del_line", (void *)&tkl_del_line, NULL},
|
||||
/* 12 */ {"tkl_check_local_remove_shun", (void *)&tkl_check_local_remove_shun, NULL},
|
||||
/* 13 */ {NULL, NULL, NULL},
|
||||
|
@ -200,7 +212,15 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
|
|||
/* 67 */ {"broadcast_md_globalvar_cmd", (void *)&broadcast_md_globalvar_cmd, NULL},
|
||||
/* 68 */ {"tkl_ip_hash", (void *)&tkl_ip_hash, NULL},
|
||||
/* 69 */ {"tkl_ip_hash_type", (void *)&tkl_ip_hash_type, NULL},
|
||||
/* 70 */ {NULL, NULL, NULL},
|
||||
/* 70 */ {"tkl_add_nameban", (void *)&tkl_add_nameban, NULL},
|
||||
/* 71 */ {"tkl_add_spamfilter", (void *)&tkl_add_spamfilter, NULL},
|
||||
/* 72 */ {"sendnotice_tkl_add", (void *)&sendnotice_tkl_add, NULL},
|
||||
/* 73 */ {"sendnotice_tkl_del", (void *)&sendnotice_tkl_del, NULL},
|
||||
/* 74 */ {"free_tkl", (void *)&free_tkl, NULL},
|
||||
/* 75 */ {"find_tkl_serverban", (void *)&find_tkl_serverban, NULL},
|
||||
/* 76 */ {"find_tkl_nameban", (void *)&find_tkl_nameban, NULL},
|
||||
/* 77 */ {"find_tkl_spamfilter", (void *)&find_tkl_spamfilter, NULL},
|
||||
/* 78 */ {NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
#ifdef UNDERSCORE
|
||||
|
|
|
@ -580,21 +580,6 @@ MOD_UNLOAD(antirandom)
|
|||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Sends a message to all (local) opers AND logs to the ircdlog (as LOG_ERROR) */
|
||||
static void multi_log(char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
static char buf[2048];
|
||||
|
||||
va_start(vl, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, vl);
|
||||
va_end(vl);
|
||||
|
||||
sendto_realops("%s", buf);
|
||||
ircd_log(LOG_ERROR, "%s", buf);
|
||||
}
|
||||
|
||||
|
||||
static void free_config(void)
|
||||
{
|
||||
safefree(cfg.ban_reason);
|
||||
|
@ -845,21 +830,21 @@ static int internal_getscore(char *str)
|
|||
{
|
||||
score += 5 + (digits - 5);
|
||||
#ifdef DEBUGMODE
|
||||
multi_log("score@'%s': MATCH for digits check", str);
|
||||
sendto_ops_and_log("score@'%s': MATCH for digits check", str);
|
||||
#endif
|
||||
}
|
||||
if (vowels >= 4)
|
||||
{
|
||||
score += 4 + (vowels - 4);
|
||||
#ifdef DEBUGMODE
|
||||
multi_log("score@'%s': MATCH for vowels check", str);
|
||||
sendto_ops_and_log("score@'%s': MATCH for vowels check", str);
|
||||
#endif
|
||||
}
|
||||
if (consonants >= 4)
|
||||
{
|
||||
score += 4 + (consonants - 4);
|
||||
#ifdef DEBUGMODE
|
||||
multi_log("score@'%s': MATCH for consonants check", str);
|
||||
sendto_ops_and_log("score@'%s': MATCH for consonants check", str);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -870,7 +855,7 @@ static int internal_getscore(char *str)
|
|||
{
|
||||
score++; /* OK */
|
||||
#ifdef DEBUGMODE
|
||||
multi_log("score@'%s': MATCH for '%s[%s]' %c/%c/%c", str, t->two, t->rest,
|
||||
sendto_ops_and_log("score@'%s': MATCH for '%s[%s]' %c/%c/%c", str, t->two, t->rest,
|
||||
s[0], s[1], s[2]);
|
||||
#endif
|
||||
}
|
||||
|
@ -934,7 +919,7 @@ static int get_spam_score(aClient *sptr)
|
|||
((tv_beta.tv_sec - tv_alpha.tv_sec) * 1000000) + (tv_beta.tv_usec - tv_alpha.tv_usec));
|
||||
#endif
|
||||
#ifdef DEBUGMODE
|
||||
multi_log("got score: %d/%d/%d = %d",
|
||||
sendto_ops_and_log("got score: %d/%d/%d = %d",
|
||||
nscore, uscore, gscore, score);
|
||||
#endif
|
||||
|
||||
|
@ -979,12 +964,12 @@ int antirandom_preconnect(aClient *sptr)
|
|||
{
|
||||
if (cfg.ban_action == BAN_ACT_WARN)
|
||||
{
|
||||
multi_log("[antirandom] would have denied access to user with score %d: %s!%s@%s:%s",
|
||||
sendto_ops_and_log("[antirandom] would have denied access to user with score %d: %s!%s@%s:%s",
|
||||
score, sptr->name, sptr->user->username, sptr->user->realhost, sptr->info);
|
||||
return 0;
|
||||
}
|
||||
if (cfg.show_failedconnects)
|
||||
multi_log("[antirandom] denied access to user with score %d: %s!%s@%s:%s",
|
||||
sendto_ops_and_log("[antirandom] denied access to user with score %d: %s!%s@%s:%s",
|
||||
score, sptr->name, sptr->user->username, sptr->user->realhost, sptr->info);
|
||||
return place_host_ban(sptr, cfg.ban_action, cfg.ban_reason, cfg.ban_time);
|
||||
}
|
||||
|
|
|
@ -448,16 +448,19 @@ int authprompt_place_host_ban(aClient *sptr, int action, char *reason, long dura
|
|||
}
|
||||
|
||||
/** Called upon "check for KLINE/GLINE" */
|
||||
int authprompt_find_tkline_match(aClient *sptr, aTKline *tk)
|
||||
int authprompt_find_tkline_match(aClient *sptr, aTKline *tkl)
|
||||
{
|
||||
/* If it's a soft-xx action and the user is not logged in
|
||||
* and the user is not yet online, then we will handle this user.
|
||||
*/
|
||||
if ((tk->subtype & TKL_SUBTYPE_SOFT) && !IsLoggedIn(sptr) && !IsPerson(sptr))
|
||||
if (TKLIsServerBan(tkl) &&
|
||||
(tkl->ptr.serverban->subtype & TKL_SUBTYPE_SOFT) &&
|
||||
!IsLoggedIn(sptr) &&
|
||||
!IsPerson(sptr))
|
||||
{
|
||||
/* Send ban reason */
|
||||
if (tk->reason)
|
||||
sendnotice(sptr, "%s", tk->reason);
|
||||
if (tkl->ptr.serverban->reason)
|
||||
sendnotice(sptr, "%s", tkl->ptr.serverban->reason);
|
||||
|
||||
/* And tag the user */
|
||||
authprompt_tag_as_auth_required(sptr);
|
||||
|
|
|
@ -51,12 +51,6 @@ EVENT(write_channeldb_evt);
|
|||
int write_channeldb(void);
|
||||
int write_channel_entry(FILE *fd, const char *tmpfname, aChannel *chptr);
|
||||
int read_channeldb(void);
|
||||
static inline int read_data(FILE *fd, void *buf, size_t len);
|
||||
static inline int write_data(FILE *fd, void *buf, size_t len);
|
||||
static inline int write_int64(FILE *fd, uint64_t t);
|
||||
static inline int write_int32(FILE *fd, uint32_t t);
|
||||
static int write_str(FILE *fd, char *x);
|
||||
static int read_str(FILE *fd, char **x);
|
||||
static void set_channel_mode(aChannel *chptr, char *modes, char *parameters);
|
||||
|
||||
// Globals
|
||||
|
@ -479,74 +473,6 @@ int read_channeldb(void)
|
|||
#undef FreeChannelEntry
|
||||
#undef R_SAFE
|
||||
|
||||
static inline int read_data(FILE *fd, void *buf, size_t len)
|
||||
{
|
||||
if (fread(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int write_data(FILE *fd, void *buf, size_t len)
|
||||
{
|
||||
if (fwrite(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int write_int64(FILE *fd, uint64_t t)
|
||||
{
|
||||
if (fwrite(&t, 1, sizeof(t), fd) < sizeof(t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
static inline int write_int32(FILE *fd, uint32_t t)
|
||||
{
|
||||
if (fwrite(&t, 1, sizeof(t), fd) < sizeof(t))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_str(FILE *fd, char *x)
|
||||
{
|
||||
uint16_t len = (x ? strlen(x) : 0);
|
||||
if (!write_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
if (len)
|
||||
{
|
||||
if (!write_data(fd, x, len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_str(FILE *fd, char **x)
|
||||
{
|
||||
uint16_t len;
|
||||
size_t size;
|
||||
|
||||
*x = NULL;
|
||||
|
||||
if (!read_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
|
||||
if (!len)
|
||||
{
|
||||
*x = strdup("");
|
||||
return 1;
|
||||
}
|
||||
|
||||
size = len;
|
||||
*x = MyMallocEx(size + 1);
|
||||
if (!read_data(fd, *x, size))
|
||||
{
|
||||
MyFree(*x);
|
||||
*x = NULL;
|
||||
return 0;
|
||||
}
|
||||
(*x)[len] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void set_channel_mode(aChannel *chptr, char *modes, char *parameters)
|
||||
{
|
||||
char buf[512];
|
||||
|
|
|
@ -530,7 +530,7 @@ int _do_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
}
|
||||
if (ValidatePermissionsForPath("immune:server-ban:deny-channel",sptr,NULL,NULL,NULL) && (tklban = find_qline(sptr, name, &ishold)))
|
||||
{
|
||||
sendnumeric(sptr, ERR_FORBIDDENCHANNEL, name, tklban->reason);
|
||||
sendnumeric(sptr, ERR_FORBIDDENCHANNEL, name, tklban->ptr.nameban->reason);
|
||||
continue;
|
||||
}
|
||||
/* ugly set::spamfilter::virus-help-channel-deny hack.. */
|
||||
|
|
|
@ -743,13 +743,13 @@ CMD_FUNC(m_nick)
|
|||
{
|
||||
if (ishold)
|
||||
{
|
||||
sendnumeric(sptr, ERR_ERRONEUSNICKNAME, nick, tklban->reason);
|
||||
sendnumeric(sptr, ERR_ERRONEUSNICKNAME, nick, tklban->ptr.nameban->reason);
|
||||
return 0;
|
||||
}
|
||||
if (!ValidatePermissionsForPath("immune:server-ban:ban-nick",sptr,NULL,NULL,nick))
|
||||
{
|
||||
sptr->local->since += 4; /* lag them up */
|
||||
sendnumeric(sptr, ERR_ERRONEUSNICKNAME, nick, tklban->reason);
|
||||
sendnumeric(sptr, ERR_ERRONEUSNICKNAME, nick, tklban->ptr.nameban->reason);
|
||||
sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.",
|
||||
nick, get_client_name(cptr, FALSE));
|
||||
return 0; /* NICK message ignored */
|
||||
|
|
|
@ -73,7 +73,7 @@ int _check_banned(aClient *cptr, int exitflags)
|
|||
|
||||
if ((tk = find_tkline_match_zap(cptr)))
|
||||
{
|
||||
return banned_client(cptr, "Z-Lined", tk->reason, (tk->type & TKL_GLOBAL)?1:0, exitflags);
|
||||
return banned_client(cptr, "Z-Lined", tk->ptr.serverban->reason, (tk->type & TKL_GLOBAL)?1:0, exitflags);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ TKLType tkl_types[] = {
|
|||
{ TKL_KILL | TKL_GLOBAL, 'G', "G-Line", "server-ban:gline:remove" },
|
||||
{ TKL_ZAP | TKL_GLOBAL, 'Z', "Global Z-Line", "server-ban:zline:global:remove" },
|
||||
{ TKL_SHUN | TKL_GLOBAL, 's', "Shun", "server-ban:shun:remove" },
|
||||
{ TKL_SPAMF | TKL_GLOBAL, 'F', "Global Spamfilter", "server-ban:spamfilter:remove" },
|
||||
// { TKL_SPAMF | TKL_GLOBAL, 'F', "Global Spamfilter", "server-ban:spamfilter:remove" }, TODO: re-add spamfilter support
|
||||
{ 0, 0, "Unknown *-Line", 0 },
|
||||
};
|
||||
|
||||
|
@ -71,8 +71,8 @@ static char *rmtkl_help[] = {
|
|||
" [remove \037all\037 supported TKLs except spamfilters]",
|
||||
" - \002/rmtkl *@*.mx GZ\002 * -skipperm",
|
||||
" [remove all Mexican G/Z-Lines while skipping over permanent ones]",
|
||||
" - \002/rmtkl * * *Zombie*\002",
|
||||
" [remove all non-spamfilter bans having \037Zombie\037 in the reason field]",
|
||||
/* " - \002/rmtkl * * *Zombie*\002",
|
||||
" [remove all non-spamfilter bans having \037Zombie\037 in the reason field]", TODO: re-add spamfilter support */
|
||||
"*** \002End of help\002 ***",
|
||||
NULL
|
||||
};
|
||||
|
@ -143,66 +143,37 @@ int rmtkl_tryremove(aClient *sptr, aClient *cptr, TKLType *tkltype, aTKline *tkl
|
|||
return 0;
|
||||
|
||||
// Let's not touch Q-Lines
|
||||
if (tkl->type & TKL_NICK)
|
||||
if (tkl->type & TKL_NAME)
|
||||
return 0;
|
||||
|
||||
if (tkl->type & TKL_SPAMF)
|
||||
{
|
||||
// Skip default spamfilters and ones added through configs, 'f' is the proper flag for that
|
||||
if (tkltype->flag == 'f')
|
||||
return 0;
|
||||
/* Don't touch TKL's that were added through config */
|
||||
if (tkl->flags & TKL_FLAG_CONFIG)
|
||||
return 0;
|
||||
|
||||
if (TKLIsSpamfilter(tkl))
|
||||
{
|
||||
#if 0
|
||||
//FIXME: re-add spamfilter support
|
||||
// Is a spamfilter added through IRC, we can remove this if the "user" mask matches the reason
|
||||
if (!match_simple(uhmask, tkl->reason))
|
||||
return 0;
|
||||
#endif
|
||||
} else
|
||||
if (TKLIsServerBan(tkl))
|
||||
{
|
||||
if (!match_simple(uhmask, make_user_host(tkl->usermask, tkl->hostmask)))
|
||||
if (!match_simple(uhmask, make_user_host(tkl->ptr.serverban->usermask, tkl->ptr.serverban->hostmask)))
|
||||
return 0;
|
||||
|
||||
if (commentmask && !match_simple(commentmask, tkl->reason))
|
||||
if (commentmask && !match_simple(commentmask, tkl->ptr.serverban->reason))
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
return 0;
|
||||
|
||||
if (skipperm && tkl->expire_at == 0)
|
||||
return 0;
|
||||
|
||||
// FIXME: use sendnotice_tkl_del() once it exists !!
|
||||
|
||||
// Convert "set at" timestamp to human readable time, we'll try to remove the TKL even if this fails (might be a bogus entry in that case)
|
||||
if (tkl->set_at)
|
||||
{
|
||||
if ((timeret = short_date(tkl->set_at, NULL)))
|
||||
strlcpy(gmt, timeret, sizeof(gmt));
|
||||
else
|
||||
strlcpy(gmt, "<INVALID TIMESTAMP>", sizeof(gmt));
|
||||
}
|
||||
|
||||
// Spamfilters have a slightly different format
|
||||
if (tkl->type & TKL_SPAMF)
|
||||
{
|
||||
if (!silent)
|
||||
{
|
||||
sendto_snomask(SNO_TKL, "%s removed %s [%s] %s (set at %s " "- reason: %s)",
|
||||
sptr->name, tkltype->txt, banact_valtostring(tkl->ptr.spamf->action),
|
||||
tkl->reason, gmt, tkl->ptr.spamf->tkl_reason);
|
||||
}
|
||||
|
||||
ircd_log(LOG_TKL, "%s removed %s [%s] %s (set at %s " "- reason: %s)",
|
||||
sptr->name, tkltype->txt, banact_valtostring(tkl->ptr.spamf->action),
|
||||
tkl->reason, gmt, tkl->ptr.spamf->tkl_reason);
|
||||
} else
|
||||
{
|
||||
if (!silent)
|
||||
{
|
||||
sendto_snomask(SNO_TKL, "%s removed %s %s@%s (set at %s - reason: %s)",
|
||||
sptr->name, tkltype->txt, tkl->usermask, tkl->hostmask,
|
||||
gmt, tkl->reason);
|
||||
}
|
||||
ircd_log(LOG_TKL, "%s removed %s %s@%s (set at %s - reason: %s)",
|
||||
sptr->name, tkltype->txt, tkl->usermask, tkl->hostmask,
|
||||
gmt, tkl->reason);
|
||||
}
|
||||
if (!silent)
|
||||
sendnotice_tkl_del(sptr->name, tkl);
|
||||
|
||||
RunHook5(HOOKTYPE_TKL_DEL, cptr, sptr, tkl, NULL, NULL);
|
||||
|
||||
|
|
|
@ -587,7 +587,7 @@ int stats_port(aClient *sptr, char *para)
|
|||
|
||||
int stats_bannick(aClient *sptr, char *para)
|
||||
{
|
||||
tkl_stats(sptr, TKL_NICK, para);
|
||||
tkl_stats(sptr, TKL_NAME, para);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1000,7 @@ int stats_banrealname(aClient *sptr, char *para)
|
|||
|
||||
int stats_sqline(aClient *sptr, char *para)
|
||||
{
|
||||
tkl_stats(sptr, TKL_NICK|TKL_GLOBAL, para);
|
||||
tkl_stats(sptr, TKL_NAME|TKL_GLOBAL, para);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
1510
src/modules/tkl.c
1510
src/modules/tkl.c
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,8 @@ ModuleHeader MOD_HEADER(tkldb) = {
|
|||
"unrealircd-5",
|
||||
};
|
||||
|
||||
#define TKL_DB_VERSION 1100
|
||||
#define TKL_DB_MAGIC 0x10101010
|
||||
#define TKL_DB_VERSION 4999
|
||||
#define TKL_DB_SAVE_EVERY 299
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
|
@ -45,15 +46,8 @@ ModuleHeader MOD_HEADER(tkldb) = {
|
|||
#define FreeTKLRead() \
|
||||
do { \
|
||||
/* Some of these might be NULL */ \
|
||||
safefree(tkltype); \
|
||||
safefree(usermask); \
|
||||
safefree(hostmask); \
|
||||
safefree(reason); \
|
||||
safefree(setby); \
|
||||
safefree(spamf_check); \
|
||||
safefree(spamf_expr); \
|
||||
safefree(spamf_matchtype); \
|
||||
safefree(spamf_tkl_reason); \
|
||||
if (tkl) \
|
||||
free_tkl(tkl); \
|
||||
} while(0)
|
||||
|
||||
#define R_SAFE(x) \
|
||||
|
@ -93,20 +87,12 @@ EVENT(write_tkldb_evt);
|
|||
int write_tkldb(void);
|
||||
int write_tkline(FILE *fd, const char *tmpfname, aTKline *tkl);
|
||||
int read_tkldb(void);
|
||||
static inline int read_data(FILE *fd, void *buf, size_t len);
|
||||
static inline int write_data(FILE *fd, void *buf, size_t len);
|
||||
static int write_str(FILE *fd, char *x);
|
||||
static int read_str(FILE *fd, char **x);
|
||||
|
||||
// Globals
|
||||
static ModDataInfo *tkldb_md;
|
||||
static uint32_t tkl_db_version = TKL_DB_VERSION;
|
||||
const uint32_t tkl_db_version = TKL_DB_VERSION;
|
||||
struct cfgstruct {
|
||||
char *database;
|
||||
|
||||
// Stored .db might still work with flags instead of actual values (will be corrected on next write)
|
||||
// This backport stuff will eventually be removed ;]
|
||||
unsigned int backport_tkl1000;
|
||||
};
|
||||
static struct cfgstruct cfg;
|
||||
|
||||
|
@ -177,7 +163,6 @@ void setcfg(void)
|
|||
// Default: data/tkl.db
|
||||
cfg.database = strdup("tkl.db");
|
||||
convert_to_absolute_path(&cfg.database, PERMDATADIR);
|
||||
cfg.backport_tkl1000 = 0;
|
||||
}
|
||||
|
||||
void freecfg(void)
|
||||
|
@ -262,6 +247,7 @@ int write_tkldb(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
W_SAFE(write_int32(fd, TKL_DB_MAGIC));
|
||||
W_SAFE(write_data(fd, &tkl_db_version, sizeof(tkl_db_version)));
|
||||
|
||||
// Count the *-Lines
|
||||
|
@ -337,83 +323,68 @@ int write_tkldb(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** Write a TKL entry */
|
||||
int write_tkline(FILE *fd, const char *tmpfname, aTKline *tkl)
|
||||
{
|
||||
// Since we can't just write 'tkl' in its entirety, we have to get the relevant variables instead
|
||||
// These will be used to reconstruct the proper internal m_tkl() call ;]
|
||||
char tkltype;
|
||||
char usermask_subtype[256]; // Might need to prefix something to usermask
|
||||
char spamf_action; // Storing the action not as unsigned short, but as char is more reliable for the future
|
||||
uint64_t expire_at, set_at, spamf_tkl_duration; // To prevent 32 vs 64 bit incompatibilies regarding the TS data type(def)
|
||||
char buf[256];
|
||||
|
||||
/* First, write the common attributes */
|
||||
tkltype = tkl_typetochar(tkl->type);
|
||||
W_SAFE(write_data(fd, &tkltype, sizeof(tkltype))); // TKL char
|
||||
|
||||
// Might be a softban
|
||||
if (!tkl->ptr.spamf && (tkl->subtype & TKL_SUBTYPE_SOFT))
|
||||
W_SAFE(write_str(fd, tkl->set_by));
|
||||
W_SAFE(write_int64(fd, tkl->set_at));
|
||||
W_SAFE(write_int64(fd, tkl->expire_at));
|
||||
|
||||
if (TKLIsServerBan(tkl))
|
||||
{
|
||||
snprintf(usermask_subtype, sizeof(usermask_subtype), "%%%s", tkl->usermask);
|
||||
W_SAFE(write_str(fd, usermask_subtype)); // User mask (targets for spamfilter, like 'cpnNPqdatu'), includes % for softbans
|
||||
char *usermask = tkl->ptr.serverban->usermask;
|
||||
if (tkl->ptr.serverban->subtype & TKL_SUBTYPE_SOFT)
|
||||
{
|
||||
snprintf(buf, sizeof(buf), "%%%s", tkl->ptr.serverban->usermask);
|
||||
usermask = buf;
|
||||
}
|
||||
W_SAFE(write_str(fd, usermask));
|
||||
W_SAFE(write_str(fd, tkl->ptr.serverban->hostmask));
|
||||
W_SAFE(write_str(fd, tkl->ptr.serverban->reason));
|
||||
} else
|
||||
if (TKLIsNameBan(tkl))
|
||||
{
|
||||
W_SAFE(write_str(fd, tkl->usermask));
|
||||
char *hold = tkl->ptr.nameban->hold ? "H" : "*";
|
||||
W_SAFE(write_str(fd, hold));
|
||||
W_SAFE(write_str(fd, tkl->ptr.nameban->name));
|
||||
W_SAFE(write_str(fd, tkl->ptr.nameban->reason));
|
||||
} else
|
||||
if (TKLIsSpamfilter(tkl))
|
||||
{
|
||||
char *match_type = unreal_match_method_valtostr(tkl->ptr.spamfilter->match->type);
|
||||
char *target = spamfilter_target_inttostring(tkl->ptr.spamfilter->target);
|
||||
char action = banact_valtochar(tkl->ptr.spamfilter->action);
|
||||
|
||||
W_SAFE(write_str(fd, match_type));
|
||||
W_SAFE(write_str(fd, tkl->ptr.spamfilter->match->str));
|
||||
W_SAFE(write_str(fd, target));
|
||||
W_SAFE(write_data(fd, &action, sizeof(action)));
|
||||
W_SAFE(write_str(fd, tkl->ptr.spamfilter->tkl_reason));
|
||||
W_SAFE(write_int64(fd, tkl->ptr.spamfilter->tkl_duration));
|
||||
}
|
||||
|
||||
W_SAFE(write_str(fd, tkl->hostmask)); // Host mask (action for spamfilter, like 'block')
|
||||
W_SAFE(write_str(fd, tkl->reason)); // Ban reason (TKL time for spamfilters, in case of *-Line actions)
|
||||
W_SAFE(write_str(fd, tkl->setby));
|
||||
|
||||
expire_at = tkl->expire_at;
|
||||
set_at = tkl->set_at;
|
||||
W_SAFE(write_data(fd, &expire_at, sizeof(expire_at)));
|
||||
W_SAFE(write_data(fd, &set_at, sizeof(set_at)));
|
||||
|
||||
if (tkl->ptr.spamf)
|
||||
{
|
||||
W_SAFE(write_str(fd, "SPAMF")); // Write a string so we know to expect more when reading the DB
|
||||
spamf_action = banact_valtochar(tkl->ptr.spamf->action); // Block, GZ-Line, etc; also refer to BAN_ACT_*
|
||||
W_SAFE(write_data(fd, &spamf_action, sizeof(spamf_action)));
|
||||
W_SAFE(write_str(fd, tkl->ptr.spamf->tkl_reason));
|
||||
spamf_tkl_duration = tkl->ptr.spamf->tkl_duration;
|
||||
W_SAFE(write_data(fd, &spamf_tkl_duration, sizeof(spamf_tkl_duration)));
|
||||
W_SAFE(write_str(fd, tkl->ptr.spamf->expr->str)); // Actual expression/regex/etc
|
||||
|
||||
// Expression type (simple/PCRE), see also enum MatchType
|
||||
if (tkl->ptr.spamf->expr->type == MATCH_PCRE_REGEX)
|
||||
W_SAFE(write_str(fd, "regex"));
|
||||
else
|
||||
W_SAFE(write_str(fd, "simple"));
|
||||
} else
|
||||
{
|
||||
W_SAFE(write_str(fd, "NOSPAMF"));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read all entries from the TKL db */
|
||||
int read_tkldb(void)
|
||||
{
|
||||
FILE *fd;
|
||||
uint64_t i;
|
||||
aTKline *tkl = NULL;
|
||||
uint32_t magic = 0;
|
||||
uint64_t cnt;
|
||||
uint64_t tklcount = 0;
|
||||
size_t tklcount_tkl1000 = 0;
|
||||
uint32_t version;
|
||||
int added = 0;
|
||||
int expired = 0;
|
||||
int added_cnt = 0;
|
||||
char c;
|
||||
|
||||
// Variables for all TKL types
|
||||
// Some of them need to be declared and NULL initialised early due to the macro FreeTKLRead() being used by R_SAFE() on error
|
||||
char *tkltype = NULL;
|
||||
char *usermask = NULL;
|
||||
char *hostmask = NULL;
|
||||
char *reason = NULL;
|
||||
char *setby = NULL;
|
||||
|
||||
// Some stuff related to spamfilters
|
||||
char *spamf_check = NULL;
|
||||
char *spamf_expr = NULL;
|
||||
char *spamf_matchtype = NULL;
|
||||
char *spamf_tkl_reason = NULL;
|
||||
char *str;
|
||||
|
||||
#ifdef BENCHMARK
|
||||
struct timeval tv_alpha, tv_beta;
|
||||
|
@ -421,9 +392,6 @@ int read_tkldb(void)
|
|||
gettimeofday(&tv_alpha, NULL);
|
||||
#endif
|
||||
|
||||
ircd_log(LOG_ERROR, "[tkldb] Reading stored *-Lines from '%s'", cfg.database);
|
||||
sendto_realops("[tkldb] Reading stored *-Lines from '%s'", cfg.database); // Probably won't be seen ever, but just in case ;]
|
||||
|
||||
fd = fopen(cfg.database, "rb");
|
||||
if (!fd)
|
||||
{
|
||||
|
@ -438,240 +406,224 @@ int read_tkldb(void)
|
|||
}
|
||||
}
|
||||
|
||||
R_SAFE(read_data(fd, &version, sizeof(version)));
|
||||
if (version > tkl_db_version)
|
||||
/* The database starts with a "magic value" - unless it's some old version or corrupt */
|
||||
R_SAFE(read_data(fd, &magic, sizeof(magic)));
|
||||
if (magic != TKL_DB_MAGIC)
|
||||
{
|
||||
// Older DBs should still work with newer versions of this module
|
||||
config_warn("[tkldb] Database '%s' has a wrong version: expected it to be <= %u but got %u instead", cfg.database, tkl_db_version, version);
|
||||
if (fclose(fd) != 0)
|
||||
config_warn("[tkldb] Got an error when trying to close database file '%s' (possible corruption occurred): %s", cfg.database, strerror(errno));
|
||||
config_error("[tkldb] Database '%s' uses an old and unsupported format OR is corrupt", cfg.database);
|
||||
config_status("If you are upgrading from UnrealIRCd 4 (or 5.0.0-alpha1) then we suggest you to "
|
||||
"delete the existing database. Just keep at least 1 server linked during the upgrade "
|
||||
"process to preserve your global *LINES and Spamfilters.");
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg.backport_tkl1000 = (version <= 1000 ? 1 : 0);
|
||||
if (cfg.backport_tkl1000)
|
||||
/* Now do a version check */
|
||||
R_SAFE(read_data(fd, &version, sizeof(version)));
|
||||
if (version < 4999)
|
||||
{
|
||||
R_SAFE(read_data(fd, &tklcount_tkl1000, sizeof(tklcount_tkl1000)));
|
||||
tklcount = tklcount_tkl1000;
|
||||
} else
|
||||
config_error("[tkldb] Database '%s' uses an unsupport - possibly old - format (%ld).", cfg.database, (long)version);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
if (version > tkl_db_version)
|
||||
{
|
||||
R_SAFE(read_data(fd, &tklcount, sizeof(tklcount)));
|
||||
config_warn("[tkldb] Database '%s' has version %lu while we only support %lu. Did you just downgrade UnrealIRCd? Sorry this is not suported",
|
||||
cfg.database, (unsigned long)tkl_db_version, (unsigned long)version);
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= tklcount; i++)
|
||||
R_SAFE(read_data(fd, &tklcount, sizeof(tklcount)));
|
||||
|
||||
for (cnt = 0; cnt < tklcount; cnt++)
|
||||
{
|
||||
int type;
|
||||
unsigned short subtype;
|
||||
int parc = 0;
|
||||
int do_not_add = 0;
|
||||
|
||||
// Variables for all TKL types
|
||||
usermask = NULL;
|
||||
hostmask = NULL;
|
||||
reason = NULL;
|
||||
setby = NULL;
|
||||
char tklflag;
|
||||
tkltype = NULL;
|
||||
uint64_t expire_at, set_at;
|
||||
time_t expire_at_tkl1000, set_at_tkl1000;
|
||||
char setTime[100], expTime[100], spamfTime[100];
|
||||
tkl = MyMallocEx(sizeof(aTKline));
|
||||
|
||||
// Some stuff related to spamfilters
|
||||
spamf_check = NULL;
|
||||
int spamf = 0;
|
||||
char spamf_action;
|
||||
unsigned short spamf_actionval;
|
||||
spamf_tkl_reason = NULL;
|
||||
time_t spamf_tkl_duration_tkl1000;
|
||||
uint64_t spamf_tkl_duration;
|
||||
spamf_expr = NULL;
|
||||
MatchType matchtype;
|
||||
spamf_matchtype = NULL;
|
||||
|
||||
int doadd = 1;
|
||||
aTKline *tkl;
|
||||
|
||||
char *tkllayer[13] = { // Args for m_tkl()
|
||||
me.name, // 0: Server name
|
||||
"+", // 1: Direction
|
||||
NULL, // 2: Type, like G
|
||||
NULL, // 3: User mask (targets for spamfilter)
|
||||
NULL, // 4: Host mask (action for spamfilter)
|
||||
NULL, // 5: Set by who
|
||||
NULL, // 6: Expiration time
|
||||
NULL, // 7: Set-at time
|
||||
NULL, // 8: Reason (TKL time for spamfilters, in case of *-Line actions)
|
||||
NULL, // 9: Spamfilter only: TKL reason (w/ underscores and all)
|
||||
NULL, // 10: Spamfilter only: Match type (simple/regex)
|
||||
NULL, // 11: Spamfilter only: Match string/regex
|
||||
NULL, // 12: Some functions rely on the post-last entry being NULL =]
|
||||
};
|
||||
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
R_SAFE(read_data(fd, &type, sizeof(type)));
|
||||
tklflag = tkl_typetochar(type);
|
||||
tkltype = MyMallocEx(2);
|
||||
tkltype[0] = tklflag;
|
||||
tkltype[1] = '\0';
|
||||
R_SAFE(read_data(fd, &subtype, sizeof(subtype))); // Subtype is kinda redundant so we're not using it past v1000 anymore
|
||||
}
|
||||
else {
|
||||
// No need for tkl_typetochar() on read anymore
|
||||
R_SAFE(read_data(fd, &tklflag, sizeof(tklflag)));
|
||||
tkltype = MyMallocEx(2);
|
||||
tkltype[0] = tklflag;
|
||||
tkltype[1] = '\0';
|
||||
}
|
||||
|
||||
R_SAFE(read_str(fd, &usermask));
|
||||
R_SAFE(read_str(fd, &hostmask));
|
||||
R_SAFE(read_str(fd, &reason));
|
||||
R_SAFE(read_str(fd, &setby));
|
||||
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
R_SAFE(read_data(fd, &expire_at_tkl1000, sizeof(expire_at_tkl1000)));
|
||||
R_SAFE(read_data(fd, &set_at_tkl1000, sizeof(set_at_tkl1000)));
|
||||
expire_at = expire_at_tkl1000;
|
||||
set_at = set_at_tkl1000;
|
||||
}
|
||||
else {
|
||||
R_SAFE(read_data(fd, &expire_at, sizeof(expire_at)));
|
||||
R_SAFE(read_data(fd, &set_at, sizeof(set_at)));
|
||||
}
|
||||
|
||||
R_SAFE(read_str(fd, &spamf_check));
|
||||
if (!strcmp(spamf_check, "SPAMF"))
|
||||
{
|
||||
spamf = 1;
|
||||
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
R_SAFE(read_data(fd, &spamf_actionval, sizeof(spamf_actionval)));
|
||||
// FIXME: BUG: spamf_action is not set
|
||||
} else {
|
||||
R_SAFE(read_data(fd, &spamf_action, sizeof(spamf_action)));
|
||||
spamf_actionval = banact_chartoval(spamf_action);
|
||||
}
|
||||
|
||||
R_SAFE(read_str(fd, &spamf_tkl_reason));
|
||||
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
R_SAFE(read_data(fd, &spamf_tkl_duration_tkl1000, sizeof(spamf_tkl_duration_tkl1000)));
|
||||
spamf_tkl_duration = spamf_tkl_duration_tkl1000;
|
||||
} else {
|
||||
R_SAFE(read_data(fd, &spamf_tkl_duration, sizeof(spamf_tkl_duration)));
|
||||
}
|
||||
|
||||
R_SAFE(read_str(fd, &spamf_expr));
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
R_SAFE(read_data(fd, &matchtype, sizeof(matchtype)));
|
||||
if (matchtype == MATCH_PCRE_REGEX)
|
||||
spamf_matchtype = strdup("regex");
|
||||
else
|
||||
spamf_matchtype = strdup("simple");
|
||||
}
|
||||
else {
|
||||
// We have better compatibility by just using the strings, since its MATCH_* counterpart might just change in value someday
|
||||
R_SAFE(read_str(fd, &spamf_matchtype));
|
||||
if (!strcmp(spamf_matchtype, "regex"))
|
||||
matchtype = MATCH_PCRE_REGEX;
|
||||
else
|
||||
matchtype = MATCH_SIMPLE;
|
||||
}
|
||||
}
|
||||
|
||||
// v1000 still stored local Q-Lines and spamfilters, but those are either added through a .conf or already built-in
|
||||
if (strchr("qf", tklflag))
|
||||
/* First, fetch the TKL type.. */
|
||||
R_SAFE(read_data(fd, &c, sizeof(c)));
|
||||
tkl->type = tkl_chartotype(c);
|
||||
if (!tkl->type)
|
||||
{
|
||||
/* We can't continue reading the DB if we don't know the TKL type,
|
||||
* since we don't know how long the entry will be, we can't skip it.
|
||||
* This is "impossible" anyway, unless we some day remove a TKL type
|
||||
* in core UnrealIRCd. In which case we should add some skipping code
|
||||
* here to gracefully handle that situation ;)
|
||||
*/
|
||||
config_error("[tkldb] Invalid type '%c' encountered - STOPPED READING DATABASE!", tkl->type);
|
||||
FreeTKLRead();
|
||||
continue;
|
||||
break; /* we MUST stop reading */
|
||||
}
|
||||
|
||||
// Don't add the TKL if it's expired
|
||||
if (expire_at != 0 && expire_at <= TStime())
|
||||
/* Read the common types (same for all TKLs) */
|
||||
R_SAFE(read_str(fd, &tkl->set_by));
|
||||
R_SAFE(read_int64(fd, &tkl->set_at));
|
||||
R_SAFE(read_int64(fd, &tkl->expire_at));
|
||||
|
||||
/* Save some CPU... if it's already expired then don't bother adding */
|
||||
if (tkl->expire_at != 0 && tkl->expire_at <= TStime())
|
||||
do_not_add = 1;
|
||||
|
||||
/* Now handle all the specific types */
|
||||
if (TKLIsServerBan(tkl))
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
ircd_log(LOG_ERROR, "[tkldb] Not re-adding expired %c:-Line '%s@%s' [%s]", tklflag, usermask, hostmask, reason);
|
||||
sendto_realops("[tkldb] Not re-adding expired %c-Line '%s@%s' [%s]", tklflag, usermask, hostmask, reason); // Probably won't be seen ever, but just in case ;]
|
||||
#endif
|
||||
expired++;
|
||||
int softban = 0;
|
||||
|
||||
tkl->ptr.serverban = MyMallocEx(sizeof(ServerBan));
|
||||
|
||||
/* Usermask - but taking into account that the
|
||||
* %-prefix means a soft ban.
|
||||
*/
|
||||
R_SAFE(read_str(fd, &str));
|
||||
if (*str == '%')
|
||||
{
|
||||
softban = 1;
|
||||
str++;
|
||||
}
|
||||
tkl->ptr.serverban->usermask = strdup(str);
|
||||
safefree(str);
|
||||
|
||||
/* And the other 2 fields.. */
|
||||
R_SAFE(read_str(fd, &tkl->ptr.serverban->hostmask));
|
||||
R_SAFE(read_str(fd, &tkl->ptr.serverban->reason));
|
||||
|
||||
if (find_tkl_serverban(tkl->type, tkl->ptr.serverban->usermask,
|
||||
tkl->ptr.serverban->hostmask, softban))
|
||||
{
|
||||
do_not_add = 1;
|
||||
}
|
||||
|
||||
if (!do_not_add)
|
||||
{
|
||||
tkl_add_serverban(tkl->type, tkl->ptr.serverban->usermask,
|
||||
tkl->ptr.serverban->hostmask,
|
||||
tkl->ptr.serverban->reason,
|
||||
tkl->set_by, tkl->expire_at,
|
||||
tkl->set_at, softban, 0);
|
||||
}
|
||||
} else
|
||||
if (TKLIsNameBan(tkl))
|
||||
{
|
||||
tkl->ptr.nameban = MyMallocEx(sizeof(NameBan));
|
||||
|
||||
R_SAFE(read_str(fd, &str));
|
||||
if (*str == 'H')
|
||||
tkl->ptr.nameban->hold = 1;
|
||||
safefree(str);
|
||||
R_SAFE(read_str(fd, &tkl->ptr.nameban->name));
|
||||
R_SAFE(read_str(fd, &tkl->ptr.nameban->reason));
|
||||
|
||||
if (find_tkl_nameban(tkl->type, tkl->ptr.nameban->name,
|
||||
tkl->ptr.nameban->hold))
|
||||
{
|
||||
do_not_add = 1;
|
||||
}
|
||||
|
||||
if (!do_not_add)
|
||||
{
|
||||
tkl_add_nameban(tkl->type, tkl->ptr.nameban->name,
|
||||
tkl->ptr.nameban->hold,
|
||||
tkl->ptr.nameban->reason,
|
||||
tkl->set_by, tkl->expire_at,
|
||||
tkl->set_at, 0);
|
||||
}
|
||||
} else
|
||||
if (TKLIsSpamfilter(tkl))
|
||||
{
|
||||
int match_method;
|
||||
char *err = NULL;
|
||||
|
||||
tkl->ptr.spamfilter = MyMallocEx(sizeof(Spamfilter));
|
||||
|
||||
/* Match method */
|
||||
R_SAFE(read_str(fd, &str));
|
||||
match_method = unreal_match_method_strtoval(str);
|
||||
if (!match_method)
|
||||
{
|
||||
config_warn("[tkldb] Unhandled spamfilter match method '%s' -- spamfilter entry not added", str);
|
||||
do_not_add = 1;
|
||||
}
|
||||
safefree(str);
|
||||
|
||||
/* Match string (eg: regex) */
|
||||
R_SAFE(read_str(fd, &str));
|
||||
tkl->ptr.spamfilter->match = unreal_create_match(match_method, str, &err);
|
||||
if (!tkl->ptr.spamfilter->match)
|
||||
{
|
||||
config_warn("[tkldb] Spamfilter '%s' does not compile: %s -- spamfilter entry not added", str, err);
|
||||
do_not_add = 1;
|
||||
}
|
||||
safefree(str);
|
||||
|
||||
/* Target (eg: cpn) */
|
||||
R_SAFE(read_str(fd, &str));
|
||||
tkl->ptr.spamfilter->target = spamfilter_gettargets(str, NULL);
|
||||
if (!tkl->ptr.spamfilter->target)
|
||||
{
|
||||
config_warn("[tkldb] Spamfilter '%s' without any valid targets (%s) -- spamfilter entry not added",
|
||||
tkl->ptr.spamfilter->match->str, str);
|
||||
do_not_add = 1;
|
||||
}
|
||||
safefree(str);
|
||||
|
||||
/* Action */
|
||||
R_SAFE(read_data(fd, &c, sizeof(c)));
|
||||
tkl->ptr.spamfilter->action = banact_chartoval(c);
|
||||
if (!tkl->ptr.spamfilter->action)
|
||||
{
|
||||
config_warn("[tkldb] Spamfilter '%s' without valid action (%c) -- spamfilter entry not added",
|
||||
tkl->ptr.spamfilter->match->str, c);
|
||||
do_not_add = 1;
|
||||
}
|
||||
|
||||
R_SAFE(read_str(fd, &tkl->ptr.spamfilter->tkl_reason));
|
||||
R_SAFE(read_int64(fd, &tkl->ptr.spamfilter->tkl_duration));
|
||||
|
||||
if (find_tkl_spamfilter(tkl->type, tkl->ptr.spamfilter->match->str,
|
||||
tkl->ptr.spamfilter->action,
|
||||
tkl->ptr.spamfilter->target))
|
||||
{
|
||||
do_not_add = 1;
|
||||
}
|
||||
|
||||
if (!do_not_add)
|
||||
{
|
||||
tkl_add_spamfilter(tkl->type, tkl->ptr.spamfilter->target,
|
||||
tkl->ptr.spamfilter->action,
|
||||
tkl->ptr.spamfilter->match,
|
||||
tkl->set_by, tkl->expire_at, tkl->set_at,
|
||||
tkl->ptr.spamfilter->tkl_duration,
|
||||
tkl->ptr.spamfilter->tkl_reason,
|
||||
0);
|
||||
/* tkl_add_spamfilter() does not copy the match but assign it.
|
||||
* so set to NULL here to avoid a read-after-free later on.
|
||||
*/
|
||||
tkl->ptr.spamfilter->match = NULL;
|
||||
}
|
||||
} else
|
||||
{
|
||||
config_error("[tkldb] Unhandled type!! TKLDB is missing support for type %ld -- STOPPED reading db entries!", (long)tkl->type);
|
||||
FreeTKLRead();
|
||||
continue;
|
||||
break; /* we MUST stop reading */
|
||||
}
|
||||
|
||||
ircsnprintf(setTime, sizeof(setTime), "%lld", (long long)set_at);
|
||||
ircsnprintf(expTime, sizeof(expTime), "%lld", (long long)expire_at);
|
||||
if (!do_not_add)
|
||||
added_cnt++;
|
||||
|
||||
// Build TKL args
|
||||
// All of these except [8] are the same for all (only odd one is spamfilter)
|
||||
parc = 9;
|
||||
tkllayer[2] = tkltype;
|
||||
tkllayer[3] = usermask;
|
||||
tkllayer[4] = hostmask;
|
||||
tkllayer[5] = setby;
|
||||
tkllayer[6] = expTime;
|
||||
tkllayer[7] = setTime;
|
||||
tkllayer[8] = reason;
|
||||
|
||||
if (spamf)
|
||||
{
|
||||
parc = 12;
|
||||
// Make sure this particular *-Line isn't already active somehow
|
||||
for (tkl = tklines[tkl_hash(tklflag)]; tkl; tkl = tkl->next)
|
||||
{
|
||||
// We can assume it's the same spamfilter if all of the following match: spamfilter expression, targets, TKL reason, action, matchtype and TKL duration
|
||||
if (!strcmp(tkl->ptr.spamf->expr->str, spamf_expr) && !strcmp(tkl->usermask, usermask) && !strcmp(tkl->ptr.spamf->tkl_reason, spamf_tkl_reason) &&
|
||||
tkl->ptr.spamf->action == spamf_action && tkl->ptr.spamf->expr->type == matchtype && tkl->ptr.spamf->tkl_duration == spamf_tkl_duration)
|
||||
{
|
||||
doadd = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doadd)
|
||||
{
|
||||
ircsnprintf(spamfTime, sizeof(spamfTime), "%lld", (long long)spamf_tkl_duration);
|
||||
tkllayer[8] = spamfTime;
|
||||
tkllayer[9] = spamf_tkl_reason;
|
||||
tkllayer[10] = spamf_matchtype;
|
||||
tkllayer[11] = spamf_expr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (tkl = tklines[tkl_hash(tklflag)]; tkl; tkl = tkl->next)
|
||||
{
|
||||
if (!strcmp(tkl->usermask, usermask) && !strcmp(tkl->hostmask, hostmask) && !strcmp(tkl->reason, reason) && tkl->expire_at == expire_at)
|
||||
{
|
||||
doadd = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doadd)
|
||||
{
|
||||
m_tkl(&me, &me, NULL, parc, tkllayer);
|
||||
added++;
|
||||
}
|
||||
FreeTKLRead();
|
||||
}
|
||||
|
||||
/* If everything went fine, then reading a single byte should cause an EOF error */
|
||||
if (fread(&c, 1, 1, fd) == 1)
|
||||
{
|
||||
ircd_log(LOG_ERROR, "[warning] [tkldb] Database possibly corrupt. Extra data found at end of DB file.");
|
||||
sendto_realops("[warning] [tkldb] Database possibly corrupt. Extra data found at end of DB file.");
|
||||
}
|
||||
config_warn("[tkldb] Database invalid. Extra data found at end of DB file.");
|
||||
fclose(fd);
|
||||
|
||||
if (added || expired)
|
||||
{
|
||||
ircd_log(LOG_ERROR, "[tkldb] Re-added %d *-Lines (skipped %d expired)", added, expired);
|
||||
sendto_realops("[tkldb] Re-added %d *-Lines (skipped %d expired)", added, expired); // Probably won't be seen ever, but just in case ;]
|
||||
}
|
||||
if (added_cnt)
|
||||
config_status("[tkldb] Re-added %d *-Lines", added_cnt);
|
||||
|
||||
#ifdef BENCHMARK
|
||||
gettimeofday(&tv_beta, NULL);
|
||||
ircd_log(LOG_ERROR, "[tkldb] Benchmark: LOAD DB: %lld microseconds",
|
||||
|
@ -680,69 +632,3 @@ int read_tkldb(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline int read_data(FILE *fd, void *buf, size_t len)
|
||||
{
|
||||
if (fread(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int write_data(FILE *fd, void *buf, size_t len)
|
||||
{
|
||||
if (fwrite(buf, 1, len, fd) < len)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int write_str(FILE *fd, char *x)
|
||||
{
|
||||
uint16_t len = (x ? strlen(x) : 0);
|
||||
if (!write_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
if (len)
|
||||
{
|
||||
if (!write_data(fd, x, len))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_str(FILE *fd, char **x)
|
||||
{
|
||||
uint16_t len;
|
||||
size_t len_tkl1000; // len used to be of type size_t, but this has portability problems when writing to/reading from binary files
|
||||
size_t size;
|
||||
|
||||
*x = NULL;
|
||||
|
||||
if (cfg.backport_tkl1000)
|
||||
{
|
||||
if (!read_data(fd, &len_tkl1000, sizeof(len_tkl1000)))
|
||||
return 0;
|
||||
len = len_tkl1000;
|
||||
} else
|
||||
{
|
||||
if (!read_data(fd, &len, sizeof(len)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!len)
|
||||
{
|
||||
*x = strdup(""); // It's safer for m_tkl to work with empty strings instead of NULLs
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (len > 10000)
|
||||
return 0;
|
||||
|
||||
size = len;
|
||||
*x = MyMallocEx(size + 1);
|
||||
if (!read_data(fd, *x, size))
|
||||
{
|
||||
MyFree(*x);
|
||||
*x = NULL;
|
||||
return 0;
|
||||
}
|
||||
(*x)[len] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue