From fb5d7d181578bcba25327dfd4c2d5727fa71ce33 Mon Sep 17 00:00:00 2001 From: cyberbotx Date: Sat, 22 Nov 2008 02:31:23 +0000 Subject: [PATCH] Properly initialized new objects when needed so they don't contain garbage data. Also, converted line endings in os_ignore_db from CR+LF to LF. git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@1784 5417fbe8-f217-4b02-8779-1006273d7864 --- include/account.h | 37 +- src/botserv.c | 6 + src/channels.c | 17 +- src/core/cs_identify.c | 1 + src/modules.c | 2 + src/modules/os_ignore_db.c | 1056 ++++++++++++++++++------------------ src/process.c | 3 +- src/sessions.c | 6 +- src/timeout.c | 1 + src/users.c | 6 +- 10 files changed, 585 insertions(+), 550 deletions(-) diff --git a/include/account.h b/include/account.h index 7ddc89e8e..0217753ad 100644 --- a/include/account.h +++ b/include/account.h @@ -6,6 +6,13 @@ class NickRequest { public: + NickRequest() + { + next = prev = NULL; + nick = passcode = email = NULL; + *password = 0; + requested = lastmail = 0; + } NickRequest *next, *prev; char *nick; char *passcode; @@ -20,16 +27,16 @@ class NickCore; class NickAlias { public: - NickAlias() - { - next = prev = NULL; - nick = last_quit = last_realname = last_usermask = NULL; - time_registered = last_seen = 0; - status = 0; - nc = NULL; - u = NULL; - } - + NickAlias() + { + next = prev = NULL; + nick = last_quit = last_realname = last_usermask = NULL; + time_registered = last_seen = 0; + status = 0; + nc = NULL; + u = NULL; + } + NickAlias *next, *prev; char *nick; /* Nickname */ char *last_quit; /* Last quit message */ @@ -47,16 +54,16 @@ class NickAlias class NickCore : public Extensible { public: - NickCore() - { + NickCore() + { next = prev = NULL; display = email = greet = url = NULL; pass[0] = '\0'; icq = flags = 0; language = accesscount = channelcount = 0; - lastmail = 0; - } - + lastmail = 0; + } + NickCore *next, *prev; char *display; /* How the nick is displayed */ diff --git a/src/botserv.c b/src/botserv.c index 371294c8c..404c8cefc 100644 --- a/src/botserv.c +++ b/src/botserv.c @@ -620,6 +620,8 @@ static BanData *get_ban_data(Channel * c, User * u) bd = new BanData; bd->mask = sstrdup(mask); bd->last_use = now; + for (int x = 0; x < TTB_SIZE; ++x) + bd->ttb[x] = 0; bd->prev = NULL; bd->next = c->bd; @@ -662,6 +664,10 @@ static UserData *get_user_data(Channel * c, User * u) } else { user->ud = new UserData; user->ud->last_use = time(NULL); + user->ud->lines = 0; + user->ud->last_start = 0; + user->ud->lastline = NULL; + user->ud->times = 0; return user->ud; } } diff --git a/src/channels.c b/src/channels.c index 203f53751..4d6f1a3c6 100644 --- a/src/channels.c +++ b/src/channels.c @@ -1527,11 +1527,13 @@ void chan_adduser2(User * user, Channel * c) struct c_userlist *u; u = new c_userlist; + u->prev = NULL; u->next = c->users; if (c->users) c->users->prev = u; c->users = u; u->user = user; + u->ud = NULL; c->usercount++; if (get_ignore(user->nick) == NULL) { @@ -1590,15 +1592,26 @@ Channel *chan_create(const char *chan, time_t ts) if (debug) alog("debug: Creating channel %s", chan); - /* Allocate pre-cleared memory */ c = new Channel; strscpy(c->name, chan, sizeof(c->name)); list = &chanlist[HASH(c->name)]; + c->prev = NULL; c->next = *list; if (*list) (*list)->prev = c; *list = c; c->creation_time = ts; + c->topic = NULL; + *c->topic_setter = 0; + c->topic_time = 0; + c->mode = c->limit = 0; + c->key = c->redirect = c->flood = NULL; + c->bans = c->excepts = c->invites = NULL; + c->users = NULL; + c->usercount = 0; + c->bd = NULL; + c->server_modetime = c->chanserv_modetime = 0; + c->server_modecount = c->chanserv_modecount = c->bouncy_modes = c->topic_sync = 0; /* Store ChannelInfo pointer in channel record */ c->ci = cs_findchan(chan); if (c->ci) @@ -1801,11 +1814,13 @@ Channel *join_user_update(User * user, Channel * chan, const char *name, alog("debug: %s joins %s", user->nick, chan->name); c = new u_chanlist; + c->prev = NULL; c->next = user->chans; if (user->chans) user->chans->prev = c; user->chans = c; c->chan = chan; + c->status = 0; chan_adduser2(user, chan); diff --git a/src/core/cs_identify.c b/src/core/cs_identify.c index 219c23ea4..e67b48c39 100644 --- a/src/core/cs_identify.c +++ b/src/core/cs_identify.c @@ -78,6 +78,7 @@ int do_identify(User * u) if ((res = enc_check_password(pass, ci->founderpass)) == 1) { if (!is_identified(u, ci)) { uc = new u_chaninfolist; + uc->prev = NULL; uc->next = u->founder_chans; if (u->founder_chans) u->founder_chans->prev = uc; diff --git a/src/modules.c b/src/modules.c index 9ce2f8853..9217915f6 100644 --- a/src/modules.c +++ b/src/modules.c @@ -229,6 +229,7 @@ Command *createCommand(const char *name, int (*func) (User * u), c->help_param2 = NULL; c->help_param3 = NULL; c->help_param4 = NULL; + c->core = 0; c->next = NULL; c->mod_name = NULL; c->service = NULL; @@ -554,6 +555,7 @@ Message *createMessage(const char *name, } m->name = sstrdup(name); m->func = func; + m->core = 0; m->next = NULL; return m; } diff --git a/src/modules/os_ignore_db.c b/src/modules/os_ignore_db.c index 55387fac3..860658a9f 100644 --- a/src/modules/os_ignore_db.c +++ b/src/modules/os_ignore_db.c @@ -1,528 +1,528 @@ -/* 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); - -/* ------------------------------------------------------------------------------- */ - -class OSIgnoreDB : public Module -{ - public: - OSIgnoreDB(const std::string &modname, const std::string &creator) : Module(modname, creator) - { - EvtHook *hook; - IgnoreDB = NULL; - - this->SetAuthor(AUTHOR); - this->SetVersion(VERSION); - this->SetType(SUPPORTED); - - hook = createEventHook(EVENT_RELOAD, reload_config); - if (this->AddEventHook(hook) != MOD_ERR_OK) - throw ModuleException("os_ignore_db: Can't hook to EVENT_RELOAD event"); - - hook = createEventHook(EVENT_DB_SAVING, save_ignoredb); - if (this->AddEventHook(hook) != MOD_ERR_OK) - throw ModuleException("os_ignore_db: Can't hook to EVENT_DB_SAVING event"); - - hook = createEventHook(EVENT_DB_BACKUP, backup_ignoredb); - if (this->AddEventHook(hook) != MOD_ERR_OK) - throw ModuleException("os_ignore_db: Can't hook to EVENT_DB_BACKUP event"); - - load_config(); - /* Load the ignore database and re-add them to anopes ignorelist. */ - load_ignore_db(); - } - - ~OSIgnoreDB() - { - /* Save the ignore database before bailing out.. */ - save_ignore_db(); - - if (IgnoreDB) - delete [] IgnoreDB; - } -}; - - - - -/* ------------------------------------------------------------------------------- */ - -void load_config(void) { - ConfigReader config; - std::string tmp = config.ReadValue("os_ignore", "database", DefIgnoreDB, 0); - - if (IgnoreDB) - delete [] IgnoreDB; - IgnoreDB = sstrdup(tmp.c_str()); - - 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 = new DBFile; - char *key, *value, *mask = NULL; - int retval = 0; - time_t expiry_time; - IgnoreData *ign; - - expiry_time = time(NULL); - 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)) { - delete 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); - delete dbptr; - return; - - } else if (retval == DB_EOF_ERROR) { - new_close_db(dbptr->fptr, &key, &value); - delete 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 = new IgnoreData; - ign->mask = (char *)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) delete [] mask; - mask = NULL; - expiry_time = time(NULL); - } else { /* DB_READ_SUCCESS */ - if (!*key || !*value) - continue; - - /* mask */ - if (!stricmp(key, "m")) { - if (mask) - delete [] 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 */ - - delete dbptr; -} - - -void save_ignore_db(void) { - DBFile *dbptr = new 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); - delete 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; - delete [] ign->mask; - delete 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 */ - delete dbptr; /* free the db struct */ - } -} - - -/* ------------------------------------------------------------------------------- */ - -/************************************************************************** - * Generic DataBase Functions (Borrowed this from Trystan :-) ) - **************************************************************************/ - - -int new_open_db_read(DBFile *dbptr, char **key, char **value) { - *key = new char [MAXKEYLEN]; - *value = new char [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); - } - delete [] *key; - *key = NULL; - delete [] *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); - } - delete [] *key; - *key = NULL; - delete [] *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); - } - delete [] *key; - *key = NULL; - delete [] *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); - } - delete [] *key; - *key = NULL; - delete [] *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) { - delete [] *key; - *key = NULL; - } - if (value && *value) { - delete [] *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); - delete 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; -} - -MODULE_INIT("os_ignore_db", OSIgnoreDB) +/* 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); + +/* ------------------------------------------------------------------------------- */ + +class OSIgnoreDB : public Module +{ + public: + OSIgnoreDB(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + EvtHook *hook; + IgnoreDB = NULL; + + this->SetAuthor(AUTHOR); + this->SetVersion(VERSION); + this->SetType(SUPPORTED); + + hook = createEventHook(EVENT_RELOAD, reload_config); + if (this->AddEventHook(hook) != MOD_ERR_OK) + throw ModuleException("os_ignore_db: Can't hook to EVENT_RELOAD event"); + + hook = createEventHook(EVENT_DB_SAVING, save_ignoredb); + if (this->AddEventHook(hook) != MOD_ERR_OK) + throw ModuleException("os_ignore_db: Can't hook to EVENT_DB_SAVING event"); + + hook = createEventHook(EVENT_DB_BACKUP, backup_ignoredb); + if (this->AddEventHook(hook) != MOD_ERR_OK) + throw ModuleException("os_ignore_db: Can't hook to EVENT_DB_BACKUP event"); + + load_config(); + /* Load the ignore database and re-add them to anopes ignorelist. */ + load_ignore_db(); + } + + ~OSIgnoreDB() + { + /* Save the ignore database before bailing out.. */ + save_ignore_db(); + + if (IgnoreDB) + delete [] IgnoreDB; + } +}; + + + + +/* ------------------------------------------------------------------------------- */ + +void load_config(void) { + ConfigReader config; + std::string tmp = config.ReadValue("os_ignore", "database", DefIgnoreDB, 0); + + if (IgnoreDB) + delete [] IgnoreDB; + IgnoreDB = sstrdup(tmp.c_str()); + + 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 = new DBFile; + char *key, *value, *mask = NULL; + int retval = 0; + time_t expiry_time; + IgnoreData *ign; + + expiry_time = time(NULL); + 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)) { + delete 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); + delete dbptr; + return; + + } else if (retval == DB_EOF_ERROR) { + new_close_db(dbptr->fptr, &key, &value); + delete 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 = new IgnoreData; + ign->mask = (char *)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) delete [] mask; + mask = NULL; + expiry_time = time(NULL); + } else { /* DB_READ_SUCCESS */ + if (!*key || !*value) + continue; + + /* mask */ + if (!stricmp(key, "m")) { + if (mask) + delete [] 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 */ + + delete dbptr; +} + + +void save_ignore_db(void) { + DBFile *dbptr = new 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); + delete 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; + delete [] ign->mask; + delete 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 */ + delete dbptr; /* free the db struct */ + } +} + + +/* ------------------------------------------------------------------------------- */ + +/************************************************************************** + * Generic DataBase Functions (Borrowed this from Trystan :-) ) + **************************************************************************/ + + +int new_open_db_read(DBFile *dbptr, char **key, char **value) { + *key = new char[MAXKEYLEN]; + *value = new char[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); + } + delete [] *key; + *key = NULL; + delete [] *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); + } + delete [] *key; + *key = NULL; + delete [] *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); + } + delete [] *key; + *key = NULL; + delete [] *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); + } + delete [] *key; + *key = NULL; + delete [] *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) { + delete [] *key; + *key = NULL; + } + if (value && *value) { + delete [] *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); + delete 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; +} + +MODULE_INIT("os_ignore_db", OSIgnoreDB) diff --git a/src/process.c b/src/process.c index eb2d9bf62..43ea0cf77 100644 --- a/src/process.c +++ b/src/process.c @@ -58,8 +58,7 @@ void add_ignore(const char *nick, time_t delta) snprintf(tmp, sizeof(tmp), "*!%s", nick); mask = sstrdup(tmp); } - - /* We only got a nick.. */ + /* We only got a nick.. */ } else { snprintf(tmp, sizeof(tmp), "%s!*@*", nick); mask = sstrdup(tmp); diff --git a/src/sessions.c b/src/sessions.c index 2a3344096..83c7d8474 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -254,11 +254,13 @@ int add_session(const char *nick, const char *host, char *hostip) session = new Session; session->host = sstrdup(host); list = &sessionlist[HASH(session->host)]; + session->prev = NULL; session->next = *list; if (*list) (*list)->prev = session; *list = session; session->count = 1; + session->hits = 0; return 1; } @@ -773,7 +775,7 @@ int do_exception(User * u) if ((n1 >= 0 && n1 < nexceptions) && (n2 >= 0 && n2 < nexceptions) && (n1 != n2)) { - exception = new Exception; + exception = (Exception *)smalloc(sizeof(Exception)); memcpy(exception, &exceptions[n1], sizeof(Exception)); if (n1 < n2) { @@ -788,7 +790,7 @@ int do_exception(User * u) memmove(&exceptions[n2], exception, sizeof(Exception)); } - delete exception; + free(exception); notice_lang(s_OperServ, u, OPER_EXCEPTION_MOVED, exceptions[n1].mask, n1 + 1, n2 + 1); diff --git a/src/timeout.c b/src/timeout.c index d3a69bf6d..e8cbf057a 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -75,6 +75,7 @@ Timeout *add_timeout(int delay, void (*code) (Timeout *), int repeat) t->repeat = repeat; t->next = timeouts; t->prev = NULL; + t->data = NULL; if (timeouts) timeouts->prev = t; timeouts = t; diff --git a/src/users.c b/src/users.c index 47a0ba1b9..93b7eef34 100644 --- a/src/users.c +++ b/src/users.c @@ -217,8 +217,10 @@ User::~User() if (this->uid) delete [] this->uid; - Anope_Free(this->realname); - delete [] this->hostip; + if (this->realname) + delete [] this->realname; + if (this->hostip) + delete [] this->hostip; if (debug >= 2) alog("debug: User::~User(): remove from channels");