diff --git a/Changes b/Changes index 881de947f..8ad4cec58 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,6 @@ Anope Version S V N -------------------- +10/01 A Added modular database back-end for IGNORE. [#948] 09/18 R Removed password truncating. [ #00] 09/15 F Dealt with the nss_dns.so.1 issue on freebsd 7. [ #00] 09/23 F Fixed numerous possible buffer overflows in NS and CS. [ #00] @@ -9,6 +10,7 @@ Anope Version S V N 09/30 F Fixed error in OPER help. [#943] 09/30 F Fixed OS IGNORE behaviour. [#941] 09/30 F Fixed error in the SASET help. [#950] +10/01 F Fixed an error in the OS IGNORE documentation. [#948] Provided by Robin Burchell - 2008 09/22 F Enabled UMODE functionality for InspIRCd 1.1 [ #00] diff --git a/Changes.conf b/Changes.conf index 50f8d80af..d78c47e7f 100644 --- a/Changes.conf +++ b/Changes.conf @@ -1,6 +1,13 @@ Anope Version S V N -------------------- ** ADDED CONFIGURATION DIRECTIVES ** +# OSIgnoreDBName [OPTIONAL] +# Module: os_ignore_db +# +# Use the given filename as database for services ignores. +# If not given, the default of "os_ignore.db" will be used. +# +#OSIgnoreDBName "os_ignore.db" ** MODIFIED CONFIGURATION DIRECTIVES ** diff --git a/Changes.lang b/Changes.lang index 2b9ef0b79..94815dfc5 100644 --- a/Changes.lang +++ b/Changes.lang @@ -4,6 +4,10 @@ Anope Version S V N PASSWORD_TOO_LONG *** Mod Strings: + OPER_HELP_OPER + NICK_HELP_SASET_PASSWORD + OPER_IGNORE_SYNTAX + OPER_HELP_IGNORE *** Del Strings: PASSWORD_TRUNCATED diff --git a/data/example.conf b/data/example.conf index b882f04af..2c494fa4a 100644 --- a/data/example.conf +++ b/data/example.conf @@ -1525,7 +1525,7 @@ OSOpersOnly # When compiled with module support, this contains a space separated list # of modules to automatically load as soon as possible, e.g. IRCD support modules. # -#ModuleAutoload "hs_moo ircd_defizzer" +#ModuleAutoload "hs_moo ircd_defizzer os_ignore_db" # ModuleDelayedAutoload [OPTIONAL] # @@ -1587,4 +1587,12 @@ ModuleDelayedAutoload "cs_appendtopic cs_enforce ns_maxemail os_info hs_request" # #HSRequestDBName "hs_request.db" +# OSIgnoreDBName [OPTIONAL] +# Module: os_ignore_db +# +# Use the given filename as database to store services' ignores. +# If not given, the default of "os_ignore.db" will be used. +# +#OSIgnoreDBName "os_ignore.db" + #EOF diff --git a/lang/cat.l b/lang/cat.l index 2cdc50c11..b2563a946 100644 --- a/lang/cat.l +++ b/lang/cat.l @@ -2964,7 +2964,7 @@ OPER_CANNOT_RESTART # LISTIGNORE responses OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask] OPER_IGNORE_VALID_TIME You have to enter a valid number as time. OPER_IGNORE_TIME_DONE @@ -5827,11 +5827,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Sintàxi: MODE canal Modes diff --git a/lang/de.l b/lang/de.l index 0cf7931d8..02ed7796c 100644 --- a/lang/de.l +++ b/lang/de.l @@ -2931,7 +2931,7 @@ OPER_CANNOT_RESTART # IGNORE respondes OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [Zeit] [Nickname] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [Zeit] [Nickname | Hostmaske] OPER_IGNORE_VALID_TIME Du musst eine zulässige Zahl als Zeit eingeben. OPER_IGNORE_TIME_DONE @@ -5859,11 +5859,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Syntax: MODE Channel Modi diff --git a/lang/en_us.l b/lang/en_us.l index f1ad63638..32b4054df 100644 --- a/lang/en_us.l +++ b/lang/en_us.l @@ -2876,7 +2876,7 @@ OPER_CANNOT_RESTART # IGNORE respondes OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask] OPER_IGNORE_VALID_TIME You have to enter a valid number as time. OPER_IGNORE_TIME_DONE @@ -5539,11 +5539,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. - To make Services permanently (untill next restart) ignore the - user, type 0 as time. + To make Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Syntax: MODE channel modes diff --git a/lang/es.l b/lang/es.l index c4b57c44a..b25dbbcea 100644 --- a/lang/es.l +++ b/lang/es.l @@ -2938,7 +2938,7 @@ OPER_CANNOT_RESTART # IGNORE responses OPER_IGNORE_SYNTAX - Sintaxis: IGNORE {ADD|DEL|LIST|CLEAR} [tiempo] [nick] + Sintaxis: IGNORE {ADD|DEL|LIST|CLEAR} [tiempo] [nick | mask] OPER_IGNORE_VALID_TIME Debes ingresar un numero valido como tiempo. OPER_IGNORE_TIME_DONE @@ -5794,11 +5794,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Sintaxis: MODE canal modos diff --git a/lang/fr.l b/lang/fr.l index ad633f20a..f964201ff 100644 --- a/lang/fr.l +++ b/lang/fr.l @@ -2989,7 +2989,7 @@ OPER_CANNOT_RESTART # LISTIGNORE responses OPER_IGNORE_SYNTAX - Syntaxe: IGNORE {ADD|DEL|LIST|CLEAR} [durée] [pseudo] + Syntaxe: IGNORE {ADD|DEL|LIST|CLEAR} [durée] [nick | mask] OPER_IGNORE_VALID_TIME Vous devez entrer une durée valide OPER_IGNORE_TIME_DONE @@ -5882,11 +5882,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Syntaxe: MODE canal modes diff --git a/lang/gr.l b/lang/gr.l index 651db9590..7788cff5e 100644 --- a/lang/gr.l +++ b/lang/gr.l @@ -2967,7 +2967,7 @@ OPER_CANNOT_RESTART # LISTIGNORE responses OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask] OPER_IGNORE_VALID_TIME You have to enter a valid number as time. OPER_IGNORE_TIME_DONE @@ -5751,11 +5751,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Óýíôáîç: MODE êáíÜëé modes diff --git a/lang/hun.l b/lang/hun.l index baa9ccb04..2d108a6a3 100644 --- a/lang/hun.l +++ b/lang/hun.l @@ -2928,7 +2928,7 @@ OPER_CANNOT_RESTART # IGNORE válaszok OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [idõ] [nick] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [idõ] [nick | mask] OPER_IGNORE_VALID_TIME Használj érvényes számot idõnek. (Adj meg érvényes számot az idõhöz.) @@ -5664,11 +5664,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Syntax: MODE #szoba módok diff --git a/lang/it.l b/lang/it.l index 366c0d715..5f16f57cb 100644 --- a/lang/it.l +++ b/lang/it.l @@ -2890,7 +2890,7 @@ OPER_CANNOT_RESTART # IGNORE responses OPER_IGNORE_SYNTAX - Sintassi: IGNORE {ADD|DEL|LIST|CLEAR} [tempo] [nick] + Sintassi: IGNORE {ADD|DEL|LIST|CLEAR} [tempo] [nick | mask] OPER_IGNORE_VALID_TIME Devi inserire un numero valido per indicare il tempo. OPER_IGNORE_TIME_DONE @@ -5701,11 +5701,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Sintassi: MODE canale modi diff --git a/lang/nl.l b/lang/nl.l index 540a05414..e3509b104 100644 --- a/lang/nl.l +++ b/lang/nl.l @@ -2938,7 +2938,7 @@ OPER_CANNOT_RESTART # IGNORE respondes OPER_IGNORE_SYNTAX - Gebruik: IGNORE {ADD|DEL|LIST|CLEAR} [tijd] [nick] + Gebruik: IGNORE {ADD|DEL|LIST|CLEAR} [tijd] [nick | mask] OPER_IGNORE_VALID_TIME Je moet een geldig nummer als tijd invoeren. OPER_IGNORE_TIME_DONE @@ -5711,11 +5711,13 @@ OPER_HELP_IGNORE Je kan de tijd opgegeven met behulup van units. Geldige units zijn: s voor seconden, m voor minuten, h voor uren en d voor dagen. Combinaties hiervan zijn niet toegestaan. - Om Services iemand permanent (tot de volgende heropstart) te laten - negeren kun je 0 opgeven als tijd. + Om Services iemand permanent te laten negeren kun je 0 opgeven als tijd. Als je een mask toevoegd moet deze in volgende format zijn: user@host of nick!user@host, iets anders wordt een nick beschouwd. Wildcards zijn toegestaan. + + IRC Operators zullen niet genegeerd worden, zelfs al komen + ze overeen met een mask uit de lijst. OPER_HELP_MODE Gebruik: MODE kanaal modes diff --git a/lang/pl.l b/lang/pl.l index 3c94eb5f2..a1d58d95c 100644 --- a/lang/pl.l +++ b/lang/pl.l @@ -3136,7 +3136,7 @@ OPER_CANNOT_RESTART # IGNORE respondes OPER_IGNORE_SYNTAX - Sk³adnia: IGNORE {ADD|DEL|LIST|CLEAR} [czas] [nick] + Sk³adnia: IGNORE {ADD|DEL|LIST|CLEAR} [czas] [nick | mask] OPER_IGNORE_VALID_TIME Musisz podaæ prawid³ow± liczbê dla czasu. OPER_IGNORE_TIME_DONE @@ -6152,11 +6152,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Syntax: MODE channel modes diff --git a/lang/pt.l b/lang/pt.l index 7e9be3127..98c248097 100644 --- a/lang/pt.l +++ b/lang/pt.l @@ -2902,7 +2902,7 @@ OPER_CANNOT_RESTART # LISTIGNORE responses OPER_IGNORE_SYNTAX - Sintaxe: IGNORE {ADD|DEL|LIST|CLEAR} [tempo] [nick] + Sintaxe: IGNORE {ADD|DEL|LIST|CLEAR} [tempo] [nick | mask] OPER_IGNORE_VALID_TIME Você precisa digitar um número válido como tempo. OPER_IGNORE_TIME_DONE @@ -5647,11 +5647,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Sintaxe: MODE canal modos diff --git a/lang/ru.l b/lang/ru.l index 6d3eb28cb..002c30737 100644 --- a/lang/ru.l +++ b/lang/ru.l @@ -2875,7 +2875,7 @@ OPER_CANNOT_RESTART # IGNORE respondes OPER_IGNORE_SYNTAX - Ñèíòàêñòñ: IGNORE {ADD|DEL|LIST|CLEAR} [âðåìÿ] [íèê] + Ñèíòàêñòñ: IGNORE {ADD|DEL|LIST|CLEAR} [âðåìÿ] [nick | mask] OPER_IGNORE_VALID_TIME Âû äîëæíû ââåñòè ïðàâèëüíîå çíà÷åíèå âðåìåíè. OPER_IGNORE_TIME_DONE @@ -5561,11 +5561,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Ñèíòàêñèñ: MODE #êàíàë ðåæèìû diff --git a/lang/tr.l b/lang/tr.l index 51e897b3a..0bf7d3ef5 100644 --- a/lang/tr.l +++ b/lang/tr.l @@ -2961,7 +2961,7 @@ OPER_CANNOT_RESTART # LISTIGNORE responses OPER_IGNORE_SYNTAX - Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick] + Syntax: IGNORE {ADD|DEL|LIST|CLEAR} [time] [nick | mask] OPER_IGNORE_VALID_TIME You have to enter a valid number as time. OPER_IGNORE_TIME_DONE @@ -5709,11 +5709,12 @@ OPER_HELP_IGNORE Valid units are: s for seconds, m for minutes, h for hours and d for days. Combinations of these units are not permitted. To make - Services permanently (untill next restart) ignore the user, - type 0 as time. + Services permanently ignore the user, type 0 as time. When adding a mask, it should be in the format user@host or nick!user@host, everything else will be considered a nick. Wildcards are permitted. + + Ignores will not be enforced on IRC Operators. OPER_HELP_MODE Kullanýmý: MODE kanaladý modlar diff --git a/src/modules/os_ignore_db.c b/src/modules/os_ignore_db.c new file mode 100644 index 000000000..11b25e1ad --- /dev/null +++ b/src/modules/os_ignore_db.c @@ -0,0 +1,544 @@ +/* os_ignore_db.c - Provides a database backend for OS IGNORE. + * + * (C) 2003-2008 Anope Team + * Contact us at info@anope.org + * + * Included in the Anope module pack since Anope 1.7.23 + * Anope Coder: Viper + * + * Please read COPYING and README for further details. + * + */ +/* ------------------------------------------------------------------------------- */ + +#include "module.h" + +#define AUTHOR "Viper" +#define VERSION "$Id$" + +/* Default database name */ +#define DefIgnoreDB "os_ignore.db" +#define IGNOREDBVERSION 1 + +/* Database seperators */ +#define SEPARATOR '^' /* End of a key, seperates keys from values */ +#define BLOCKEND '\n' /* End of a block, e.g. a whole ignore */ +#define VALUEEND '\000' /* End of a value */ +#define SUBSTART '\010' /* Beginning of a new subblock, closed by a BLOCKEND */ + +/* Database reading return values */ +#define DB_READ_SUCCESS 0 +#define DB_READ_ERROR 1 +#define DB_EOF_ERROR 2 +#define DB_VERSION_ERROR 3 +#define DB_READ_BLOCKEND 4 +#define DB_READ_SUBSTART 5 + +#define DB_WRITE_SUCCESS 0 +#define DB_WRITE_ERROR 1 +#define DB_WRITE_NOVAL 2 + +/* Database Key, Value max length */ +#define MAXKEYLEN 128 +#define MAXVALLEN 1024 + +/* Structs */ +typedef struct db_file_ DBFile; + +struct db_file_ { + FILE *fptr; /* Pointer to the opened file */ + int db_version; /* The db version of the datafiles (only needed for reading) */ + int core_db_version; /* The current db version of this anope source */ + char service[256]; /* StatServ/etc. */ + char filename[256]; /* Filename of the database */ + char temp_name[262]; /* Temp filename of the database */ +}; + + +/* Variables */ +char *IgnoreDB; + +/* Functions */ +int new_open_db_read(DBFile *dbptr, char **key, char **value); +int new_open_db_write(DBFile *dbptr); +void new_close_db(FILE *fptr, char **key, char **value); +int new_read_db_entry(char **key, char **value, FILE * fptr); +int new_write_db_entry(const char *key, DBFile *dbptr, const char *fmt, ...); +int new_write_db_endofblock(DBFile *dbptr); +void fill_db_ptr(DBFile *dbptr, int version, int core_version, char service[256], char filename[256]); + +int save_ignoredb(int argc, char **argv); +int backup_ignoredb(int argc, char **argv); +void load_ignore_db(void); +void save_ignore_db(void); +void load_config(void); +int reload_config(int argc, char **argv); + +/* ------------------------------------------------------------------------------- */ + +/** + * AnopeInit is called when the module is loaded + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) { + EvtHook *hook; + IgnoreDB = NULL; + + moduleAddAuthor(AUTHOR); + moduleAddVersion(VERSION); + moduleSetType(SUPPORTED); + + hook = createEventHook(EVENT_RELOAD, reload_config); + if (moduleAddEventHook(hook) != MOD_ERR_OK) { + alog("[\002os_ignore_db\002] Can't hook to EVENT_RELOAD event"); + return MOD_STOP; + } + + hook = createEventHook(EVENT_DB_SAVING, save_ignoredb); + if (moduleAddEventHook(hook) != MOD_ERR_OK) { + alog("[\002os_ignore_db\002] Can't hook to EVENT_DB_SAVING event"); + return MOD_STOP; + } + + hook = createEventHook(EVENT_DB_BACKUP, backup_ignoredb); + if (moduleAddEventHook(hook) != MOD_ERR_OK) { + alog("[\002os_ignore_db\002] Can't hook to EVENT_DB_BACKUP event"); + return MOD_STOP; + } + + load_config(); + /* Load the ignore database and re-add them to anopes ignorelist. */ + load_ignore_db(); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) { + /* Save the ignore database before bailing out.. */ + save_ignore_db(); + + if (IgnoreDB) + free(IgnoreDB); +} + +/* ------------------------------------------------------------------------------- */ + +void load_config(void) { + int i; + + Directive confvalues[][1] = { + {{"OSIgnoreDBName", {{PARAM_STRING, PARAM_RELOAD, &IgnoreDB}}}}, + }; + + if (IgnoreDB) + free(IgnoreDB); + IgnoreDB = NULL; + + for (i = 0; i < 1; i++) + moduleGetConfigDirective(confvalues[i]); + + if (!IgnoreDB) + IgnoreDB = sstrdup(DefIgnoreDB); + + if (debug) + alog("[os_ignore_db] debug: Set config vars: OSIgnoreDBName='%s'", IgnoreDB); +} + +/** + * Upon /os reload call the routines for reloading the configuration directives + **/ +int reload_config(int argc, char **argv) { + if (argc >= 1) { + if (!stricmp(argv[0], EVENT_START)) { + load_config(); + } + } + return MOD_CONT; +} + +/** + * When anope saves her databases, we do the same. + **/ +int save_ignoredb(int argc, char **argv) { + if ((argc >= 1) && (!stricmp(argv[0], EVENT_STOP))) + save_ignore_db(); + + return MOD_CONT; +} + + +/** + * When anope backs her databases up, we do the same. + **/ +int backup_ignoredb(int argc, char **argv) { + if ((argc >= 1) && (!stricmp(argv[0], EVENT_STOP))) { + if (debug) + alog("[os_ignore_db] debug: Backing up %s database...", IgnoreDB); + ModuleDatabaseBackup(IgnoreDB); + } + return MOD_CONT; +} + +/* ------------------------------------------------------------------------------- */ + +/************************************************************************** + * DataBase Handling + **************************************************************************/ + +void load_ignore_db(void) { + DBFile *dbptr = scalloc(1, sizeof(DBFile)); + char *key, *value, *mask = NULL; + int retval = 0; + time_t expiry_time; + IgnoreData *ign; + + fill_db_ptr(dbptr, 0, IGNOREDBVERSION, s_OperServ, IgnoreDB); + + /* let's remove existing temp files here, because we only load dbs on startup */ + remove(dbptr->temp_name); + + /* Open the db, fill the rest of dbptr and allocate memory for key and value */ + if (new_open_db_read(dbptr, &key, &value)) { + free(dbptr); + return; /* Bang, an error occurred */ + } + + while (1) { + /* read a new entry and fill key and value with it -Certus */ + retval = new_read_db_entry(&key, &value, dbptr->fptr); + + if (retval == DB_READ_ERROR) { + new_close_db(dbptr->fptr, &key, &value); + free(dbptr); + return; + + } else if (retval == DB_EOF_ERROR) { + new_close_db(dbptr->fptr, &key, &value); + free(dbptr); + return; + } else if (retval == DB_READ_BLOCKEND) { /* DB_READ_BLOCKEND */ + /* Check if we have everything to add the ignore.. + * We shouldn't bother with already expired ignores either.. */ + if (mask && (expiry_time > time(NULL) || expiry_time == 0)) { + /* We should check for double entries.. */ + for (ign = ignore; ign; ign = ign->next) + if (!stricmp(ign->mask, mask)) + break; + + if (!ign) { + /* Create a fresh entry.. */ + ign = scalloc(sizeof(*ign), 1); + ign->mask = sstrdup(mask); + ign->time = expiry_time; + ign->prev = NULL; + ign->next = ignore; + if (ignore) + ignore->prev = ign; + ignore = ign; + if (debug) + alog("[os_ignore_db] debug: Added new ignore entry for %s", mask); + } else { + /* Update time on existing entry. + * The longest expiry time survives.. */ + if (expiry_time == 0 || ign->time == 0) + ign->time = 0; + else if (expiry_time > ign->time) + ign->time = expiry_time; + } + } + + if (mask) free(mask); + mask = NULL; + expiry_time = time(NULL); + } else { /* DB_READ_SUCCESS */ + if (!*key || !*value) + continue; + + /* mask */ + if (!stricmp(key, "m")) { + if (mask) + free(mask); + mask = sstrdup(value); + + /* expiry time */ + } else if (!stricmp(key, "t")) { + expiry_time = atoi(value); + + } else if (!stricmp(key, "IGNORE_DB_VERSION")) { + if ((int)atoi(value) != IGNOREDBVERSION) { + alog("[\002os_ignore_db\002] Database version does not match any database versions supported by this module."); + alog("[\002os_ignore_db\002] Continuing with clean database..."); + break; + } + } + } /* else */ + } /* while */ + + free(dbptr); +} + + +void save_ignore_db(void) { + DBFile *dbptr = scalloc(1, sizeof(DBFile)); + time_t now; + IgnoreData *ign, *next; + + now = time(NULL); + fill_db_ptr(dbptr, 0, IGNOREDBVERSION, s_OperServ, IgnoreDB); + + /* time to backup the old db */ + rename(IgnoreDB, dbptr->temp_name); + + if (new_open_db_write(dbptr)) { + rename(dbptr->temp_name, IgnoreDB); + free(dbptr); + return; /* Bang, an error occurred */ + } + + /* Store the version of the DB in the DB as well... + * This will make stuff a lot easier if the database scheme needs to modified. */ + new_write_db_entry("IGNORE_DB_VERSION", dbptr, "%d", IGNOREDBVERSION); + new_write_db_endofblock(dbptr); + + /* Go over the entire ignorelist, check whether each entry is still valid + * and write it to the database if it is.*/ + for (ign = ignore; ign; ign = next) { + next = ign->next; + + if (ign->time != 0 && ign->time <= now) { + if (debug) + alog("[os_ignore_db] debug: Expiring ignore entry %s", ign->mask); + if (ign->prev) + ign->prev->next = ign->next; + else if (ignore == ign) + ignore = ign->next; + if (ign->next) + ign->next->prev = ign->prev; + free(ign->mask); + free(ign); + ign = NULL; + } else { + new_write_db_entry("m", dbptr, "%s", ign->mask); + new_write_db_entry("t", dbptr, "%d", ign->time); + new_write_db_endofblock(dbptr); + } + } + + if (dbptr) { + new_close_db(dbptr->fptr, NULL, NULL); /* close file */ + remove(dbptr->temp_name); /* saved successfully, no need to keep the old one */ + free(dbptr); /* free the db struct */ + } +} + + +/* ------------------------------------------------------------------------------- */ + +/************************************************************************** + * Generic DataBase Functions (Borrowed this from Trystan :-) ) + **************************************************************************/ + + +int new_open_db_read(DBFile *dbptr, char **key, char **value) { + *key = malloc(MAXKEYLEN); + *value = malloc(MAXVALLEN); + + if (!(dbptr->fptr = fopen(dbptr->filename, "rb"))) { + if (debug) { + alog("debug: Can't read %s database %s : errno(%d)", dbptr->service, + dbptr->filename, errno); + } + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return DB_READ_ERROR; + } + dbptr->db_version = fgetc(dbptr->fptr) << 24 | fgetc(dbptr->fptr) << 16 + | fgetc(dbptr->fptr) << 8 | fgetc(dbptr->fptr); + + if (ferror(dbptr->fptr)) { + if (debug) { + alog("debug: Error reading version number on %s", dbptr->filename); + } + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return DB_READ_ERROR; + } else if (feof(dbptr->fptr)) { + if (debug) { + alog("debug: Error reading version number on %s: End of file detected", + dbptr->filename); + } + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return DB_EOF_ERROR; + } else if (dbptr->db_version < 1) { + if (debug) { + alog("debug: Invalid version number (%d) on %s", dbptr->db_version, dbptr->filename); + } + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return DB_VERSION_ERROR; + } + return DB_READ_SUCCESS; +} + + +int new_open_db_write(DBFile *dbptr) { + if (!(dbptr->fptr = fopen(dbptr->filename, "wb"))) { + if (debug) { + alog("debug: %s Can't open %s database for writing", dbptr->service, dbptr->filename); + } + return DB_WRITE_ERROR; + } + + if (fputc(dbptr->core_db_version >> 24 & 0xFF, dbptr->fptr) < 0 || + fputc(dbptr->core_db_version >> 16 & 0xFF, dbptr->fptr) < 0 || + fputc(dbptr->core_db_version >> 8 & 0xFF, dbptr->fptr) < 0 || + fputc(dbptr->core_db_version & 0xFF, dbptr->fptr) < 0) { + if (debug) { + alog("debug: Error writing version number on %s", dbptr->filename); + } + return DB_WRITE_ERROR; + } + return DB_WRITE_SUCCESS; +} + + +void new_close_db(FILE *fptr, char **key, char **value) { + if (key && *key) { + free(*key); + *key = NULL; + } + if (value && *value) { + free(*value); + *value = NULL; + } + + if (fptr) { + fclose(fptr); + } +} + + +int new_read_db_entry(char **key, char **value, FILE *fptr) { + char *string = *key; + int character; + int i = 0; + + **key = '\0'; + **value = '\0'; + + while (1) { + if ((character = fgetc(fptr)) == EOF) { /* a problem occurred reading the file */ + if (ferror(fptr)) { + return DB_READ_ERROR; /* error! */ + } + return DB_EOF_ERROR; /* end of file */ + } else if (character == BLOCKEND) { /* END OF BLOCK */ + return DB_READ_BLOCKEND; + } else if (character == VALUEEND) { /* END OF VALUE */ + string[i] = '\0'; /* end of value */ + return DB_READ_SUCCESS; + } else if (character == SEPARATOR) { /* END OF KEY */ + string[i] = '\0'; /* end of key */ + string = *value; /* beginning of value */ + i = 0; /* start with the first character of our value */ + } else { + if ((i == (MAXKEYLEN - 1)) && (string == *key)) { /* max key length reached, continuing with value */ + string[i] = '\0'; /* end of key */ + string = *value; /* beginning of value */ + i = 0; /* start with the first character of our value */ + } else if ((i == (MAXVALLEN - 1)) && (string == *value)) { /* max value length reached, returning */ + string[i] = '\0'; + return DB_READ_SUCCESS; + } else { + string[i] = character; /* read string (key or value) */ + i++; + } + } + } +} + + +int new_write_db_entry(const char *key, DBFile *dbptr, const char *fmt, ...) { + char string[MAXKEYLEN + MAXVALLEN + 2], value[MAXVALLEN]; /* safety byte :P */ + va_list ap; + unsigned int length; + + if (!dbptr) { + return DB_WRITE_ERROR; + } + + va_start(ap, fmt); + vsnprintf(value, MAXVALLEN, fmt, ap); + va_end(ap); + + if (!stricmp(value, "(null)")) { + return DB_WRITE_NOVAL; + } + snprintf(string, MAXKEYLEN + MAXVALLEN + 1, "%s%c%s", key, SEPARATOR, value); + length = strlen(string); + string[length] = VALUEEND; + length++; + + if (fwrite(string, 1, length, dbptr->fptr) < length) { + if (debug) { + alog("debug: Error writing to %s", dbptr->filename); + } + new_close_db(dbptr->fptr, NULL, NULL); + if (debug) { + alog("debug: Restoring backup."); + } + remove(dbptr->filename); + rename(dbptr->temp_name, dbptr->filename); + free(dbptr); + dbptr = NULL; + return DB_WRITE_ERROR; + } + return DB_WRITE_SUCCESS; +} + + +int new_write_db_endofblock(DBFile *dbptr) { + if (!dbptr) { + return DB_WRITE_ERROR; + } + if (fputc(BLOCKEND, dbptr->fptr) == EOF) { + if (debug) { + alog("debug: Error writing to %s", dbptr->filename); + } + new_close_db(dbptr->fptr, NULL, NULL); + return DB_WRITE_ERROR; + } + return DB_WRITE_SUCCESS; +} + + + +void fill_db_ptr(DBFile *dbptr, int version, int core_version, + char service[256], char filename[256]) { + dbptr->db_version = version; + dbptr->core_db_version = core_version; + if (!service) + strcpy(dbptr->service, service); + else + strcpy(dbptr->service, ""); + + strcpy(dbptr->filename, filename); + snprintf(dbptr->temp_name, 261, "%s.temp", filename); + return; +} + +/* EOF */ diff --git a/version.log b/version.log index 24fe5c49a..be4fbd74c 100644 --- a/version.log +++ b/version.log @@ -9,10 +9,18 @@ VERSION_MAJOR="1" VERSION_MINOR="7" VERSION_PATCH="22" VERSION_EXTRA="-svn" -VERSION_BUILD="1458" +VERSION_BUILD="1460" # $Log$ # +# BUILD : 1.7.22 (1460) +# BUGS : 948 +# NOTES : Corrected some errors in the OS IGNORE help. +# +# BUILD : 1.7.22 (1459) +# BUGS : 948 +# NOTES : Added a supported module to provide a database back-end for OS IGNORE. +# # BUILD : 1.7.22 (1458) # BUGS : 950 # NOTES : Fixed an error in the help docs on SASET. Patch provided by chaz.