diff options
-rw-r--r-- | Changes.conf | 11 | ||||
-rw-r--r-- | data/example.conf | 90 | ||||
-rw-r--r-- | include/Makefile | 2 | ||||
-rw-r--r-- | include/account.h | 4 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/configreader.h | 18 | ||||
-rw-r--r-- | include/datafiles.h | 25 | ||||
-rw-r--r-- | include/extern.h | 2 | ||||
-rw-r--r-- | include/modules.h | 105 | ||||
-rw-r--r-- | include/pseudo.h | 1 | ||||
-rw-r--r-- | src/Makefile | 5 | ||||
-rw-r--r-- | src/chanserv.c | 7 | ||||
-rw-r--r-- | src/config.c | 34 | ||||
-rw-r--r-- | src/core/db_plain.cpp | 1148 | ||||
-rw-r--r-- | src/core/ns_forbid.c | 4 | ||||
-rw-r--r-- | src/core/ns_identify.c | 3 | ||||
-rw-r--r-- | src/core/os_ignore.c | 58 | ||||
-rw-r--r-- | src/core/os_modlist.c | 25 | ||||
-rw-r--r-- | src/core/os_news.c | 42 | ||||
-rw-r--r-- | src/datafiles.c | 203 | ||||
-rw-r--r-- | src/init.c | 12 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/modulemanager.cpp | 6 | ||||
-rw-r--r-- | src/modules/hs_request.c | 150 | ||||
-rw-r--r-- | src/modules/os_ignore_db.c | 490 | ||||
-rw-r--r-- | src/modules/os_info.c | 193 | ||||
-rw-r--r-- | src/regchannel.cpp | 11 | ||||
-rw-r--r-- | src/tools/db-convert.c | 110 | ||||
-rw-r--r-- | src/tools/db-convert.h | 19 | ||||
-rw-r--r-- | src/users.c | 6 |
30 files changed, 1570 insertions, 1221 deletions
diff --git a/Changes.conf b/Changes.conf index f084f452d..f4319af25 100644 --- a/Changes.conf +++ b/Changes.conf @@ -3,11 +3,22 @@ Anope Version 1.9.2 ** ADDED CONFIGURATION DIRECTIVES ** options:enablelogchannel added to auto turn on the logchannel on startup options:mlock added to configure the default mlock modes on new channels +options:database added for the database modules ** MODIFIED CONFIGURATION DIRECTIVES ** chanserv:modules added cs_unban ** DELETED CONFIGURATION DIRECTIVES ** +nickserv:database deleted because of new database system +nickserv:prenickdatabase deleted because of new database system +chanserv:database deleted because of the new database system +botserv:database deleted because of the new database system +hostserv:database deleted because of the new database system +operserv:database deleted because of the new database system +operserv:newsdatabase deleted because of the new database system +operserv:exceptiondatabase deleted because of the new database system +hs_request:database deleted because of the new database system +os_ignore:database deleted because of the new database system Anope Version 1.9.1 ------------------- diff --git a/data/example.conf b/data/example.conf index a0313947f..7299b5f04 100644 --- a/data/example.conf +++ b/data/example.conf @@ -238,7 +238,7 @@ networkinfo options { /* - * The encryption module to use when dealing with passwords. This determines how + * The encryption modules are used when dealing with passwords. This determines how * the passwords are stored in the databases, and does not add any security as * far as transmitting passwords over the network goes. * @@ -264,6 +264,12 @@ options encryption = "enc_none enc_sha1 enc_md5 enc_old" /* + * The database modules are used for saving and loading databases for Anope. + * Currently, there is only one database module - db_plain + */ + database = "db_plain" + + /* * These keys are used to initiate the random number generator. These numbers * MUST be random as you want your passcodes to be random. Don't give these * keys to anyone! Keep them private! @@ -702,19 +708,6 @@ nickserv description = "Nickname Registration Service" /* - * The filename of the NickServ database. The path is relative to the services - * executable. If not given, defaults to "nick.db". - */ - database = "nick.db" - - /* - * The filename of the NickServ Pre-Nick database. The path is relative to the - * services executable. This directive is only required if the e-mail registration - * option is enabled. - */ - #prenickdatabase = "prenick.db" - - /* * The core modules to load for NickServ. This is a space separated list that corresponds * to the base names of the modules for NickServ. This directive is optional, but highly recommended. */ @@ -890,12 +883,6 @@ chanserv description = "Channel Registration Service" /* - * The filename of the ChanServ database. The path is relative to the services - * executable. If not given, defaults to "chan.db". - */ - database = "chan.db" - - /* * The core modules to load for ChanServ. This is a space separated list that corresponds * to the base names of the modules for ChanServ. This directive is optional, but highly recommended. */ @@ -1073,12 +1060,6 @@ botserv description = "Bot Service" /* - * The filename of the BotServ database. The path is relative to the services - * executable. If not given, defaults to "bot.db". - */ - database = "bot.db" - - /* * The core modules to load for BotServ. This is a space separated list that corresponds * to the base names of the modules for BotServ. This directive is optional, but highly recommended. */ @@ -1172,12 +1153,6 @@ hostserv description = "vHost Service" /* - * The filename of the HostServ database. The path is relative to the services - * executable. If not given, defaults to "hosts.db". - */ - database = "hosts.db" - - /* * The core modules to load for HostServ. This is a space separated list that corresponds * to the base names of the modules for HostServ. This directive is optional, but highly recommended. */ @@ -1215,24 +1190,6 @@ operserv globaldescription = "Global Noticer" /* - * The filename of the OperServ database. The path is relative to the services - * executable. If not given, defaults to "oper.db". - */ - database = "oper.db" - - /* - * The filename of OperServ's News database. The path is relative to the services - * executable. If not given, defaults to "news.db". - */ - newsdatabase = "news.db" - - /* - * The filename of OperServ's Session Exception database. The path is relative to the services - * executable. If not given, defaults to "exception.db". - */ - exceptiondatabase = "exception.db" - - /* * The core modules to load for OperServ. This is a space separated list that corresponds * to the base names of the modules for OperServ. This directive is optional, but highly recommended. */ @@ -1529,22 +1486,6 @@ hs_request * If set, Services will send a memo to all Host Setters when a new vHost is requested. */ #memosetters = yes - - /* - * The filename of the vHost request database. The path is relative to the services - * executable. If not given, defaults to "hs_request.db". - */ - #database = "hs_request.db" -} - -ns_maxemail -{ - /* - * The limit to how many registered nicks can use the same e-mail address. If set to 0 or left - * commented, there will be no limit enforced when registering new accounts or using - * /msg NickServ SET EMAIL. - */ - #maxemails = 1 } ns_noop_convert @@ -1556,20 +1497,13 @@ ns_noop_convert #database = "autoop.db" } -os_ignore +ns_maxemail { /* - * The filename of the Services' ignore database. The path is relative to the services - * executable. If not given, defaults to "os_ignore.db". + * The limit to how many registered nicks can use the same e-mail address. If set to 0 or left + * commented, there will be no limit enforced when registering new accounts or using + * /msg NickServ SET EMAIL. */ - #database = "os_ignore.db" + #maxemails = 1 } -os_info -{ - /* - * The filename of the oper information database. The path is relative to the services - * executable. If not given, defaults to "os_info.db". - */ - #database = "os_info.db" -} diff --git a/include/Makefile b/include/Makefile index 13c5b8b2c..3d8067aa6 100644 --- a/include/Makefile +++ b/include/Makefile @@ -10,7 +10,7 @@ services.h: sysconf.h config.h extern.h extern.h: slist.h touch $@ -pseudo.h: commands.h timers.h datafiles.h slist.h +pseudo.h: commands.h timers.h slist.h touch $@ clean: diff --git a/include/account.h b/include/account.h index e20b70fe4..dc0d21c7d 100644 --- a/include/account.h +++ b/include/account.h @@ -58,8 +58,8 @@ enum NickCoreFlag NI_SUSPENDED, /* Autoop nickname in channels */ NI_AUTOOP, - /* Nick won't expire */ - NI_NOEXPIRE, + /* This nickcore is forbidden, which means the nickalias for it is aswell */ + NI_FORBIDDEN, NI_END }; diff --git a/include/config.h b/include/config.h index f9d8f4370..a5151e071 100644 --- a/include/config.h +++ b/include/config.h @@ -25,6 +25,9 @@ /* Name of configuration file (in Services directory) */ #define SERVICES_CONF "services.conf" +/* Name of anope datbase */ +#define DATABASE_FILE "anope.db" + /* Name of log file (in Services directory) */ #define LOG_FILENAME "services.log" diff --git a/include/configreader.h b/include/configreader.h index 97403b5fa..c9db6cb89 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -432,8 +432,6 @@ class ServerConfig /* Global realname */ char *desc_GlobalNoticer; - /* Name of the hostserv database */ - char *HostDBName; /* HostServ Name */ char *s_HostServ; /* HostServ realname */ @@ -443,18 +441,6 @@ class ServerConfig char *PIDFilename; /* MOTD filename */ char *MOTDFilename; - /* NickServ DB name */ - char *NickDBName; - /* DB name for nicks being registered */ - char *PreNickDBName; - /* Channel DB name */ - char *ChanDBName; - /* Botserv DB name */ - char *BotDBName; - /* OperServ db name */ - char *OperDBName; - /* News DB name */ - char *NewsDBName; /* True if its ok to not be able to save backs */ bool NoBackupOkay; @@ -695,8 +681,6 @@ class ServerConfig unsigned MaxSessionLimit; /* How long session akills should last */ time_t SessionAutoKillExpiry; - /* DB name for exceptions */ - char *ExceptionDBName; /* Reason to use for session kills */ char *SessionLimitExceeded; /* Optional second reason */ @@ -708,6 +692,8 @@ class ServerConfig std::list<std::string> ModulesAutoLoad; /* Encryption modules */ std::list<std::string> EncModuleList; + /* Database modules */ + std::list<std::string> DBModuleList; /* HostServ Core Modules */ std::list<std::string> HostServCoreModules; /* MemoServ Core Modules */ diff --git a/include/datafiles.h b/include/datafiles.h deleted file mode 100644 index fe8cb3d12..000000000 --- a/include/datafiles.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Database file descriptor structure and file handling routine prototypes. - * - * (C) 2003-2009 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for furhter details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * $Id$ - * - */ - -#ifndef DATAFILES_H -#define DATAFILES_H - -#ifndef _WIN32 -#include <sys/param.h> -#define DeleteFile unlink -#endif - - - -#endif /* DATAFILES_H */ diff --git a/include/extern.h b/include/extern.h index 10c4028b4..f570c39ff 100644 --- a/include/extern.h +++ b/include/extern.h @@ -393,8 +393,6 @@ E void SetDefaultMLock(); /**** modules.c ****/ E void modules_unload_all(bool unload_proto); /* Read warnings near function source */ -E void ModuleDatabaseBackup(const char *dbname); -E void ModuleRemoveBackups(const char *dbname); /**** nickserv.c ****/ diff --git a/include/modules.h b/include/modules.h index f4d9700f3..129e2666d 100644 --- a/include/modules.h +++ b/include/modules.h @@ -186,7 +186,7 @@ enum CommandReturn const char *ano_moderr(); #endif -typedef enum { CORE,PROTOCOL,THIRD,SUPPORTED,QATESTED,ENCRYPTION } MODType; +typedef enum { CORE,PROTOCOL,THIRD,SUPPORTED,QATESTED,ENCRYPTION,DATABASE } MODType; typedef enum { MOD_OP_LOAD, MOD_OP_UNLOAD } ModuleOperation; /*************************************************************************/ @@ -561,11 +561,15 @@ class CoreExport Module */ virtual void OnPostLoadDatabases() { } - /** Called when anope saves databases. - * NOTE: This event is deprecated pending new database handling. - * XXX. + /** Called when the databases are saved + * @return EVENT_CONTINUE to let other modules continue saving, EVENT_STOP to stop + */ + virtual EventReturn OnSaveDatabase() { return EVENT_CONTINUE; } + + /** Called when the databases are loaded + * @return EVENT_CONTINUE to let other modules continue saving, EVENT_STOP to stop */ - virtual void OnSaveDatabase() MARK_DEPRECATED { } + virtual EventReturn OnLoadDatabase() { return EVENT_CONTINUE; } /** Called when anope backs up databases. * NOTE: This event is deprecated pending new database handling. @@ -684,6 +688,73 @@ class CoreExport Module */ virtual void OnDatabaseExpire() MARK_DEPRECATED { } + /** Called when the flatfile dbs are being written + * @param Write A callback to the function used to insert a line into the database + */ + virtual void OnDatabaseWrite(void (*Write)(const std::string &)) { } + + /** Called when a line is read from the database + * @param params The params from the database + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing + */ + virtual EventReturn OnDatabaseRead(const std::vector<std::string> ¶ms) { return EVENT_CONTINUE; } + + /** Called when nickcore metadata is read from the database + * @param nc The nickcore + * @param key The metadata key + * @param params The params from the database + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing + */ + virtual EventReturn OnDatabaseReadMetadata(NickCore *nc, const std::string &key, const std::vector<std::string> ¶ms) { return EVENT_CONTINUE; } + + /** Called when nickcore metadata is read from the database + * @param na The nickalias + * @param key The metadata key + * @param params The params from the database + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing + */ + virtual EventReturn OnDatabaseReadMetadata(NickAlias *na, const std::string &key, const std::vector<std::string> ¶ms) { return EVENT_CONTINUE; } + + /** Called when botinfo metadata is read from the database + * @param bi The botinfo + * @param key The metadata key + * @param params The params from the database + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing + */ + virtual EventReturn OnDatabaseReadMetadata(BotInfo *bi, const std::string &key, const std::vector<std::string> ¶ms) { return EVENT_CONTINUE; } + + /** Called when chaninfo metadata is read from the database + * @param ci The chaninfo + * @param key The metadata key + * @param params The params from the database + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing + */ + virtual EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const std::string &key, const std::vector<std::string> ¶ms) { return EVENT_CONTINUE; } + + /** Called when we are writing metadata for a nickcore + * @param WriteMetata A callback function used to insert the metadata + * @param nc The nickcore + */ + virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), NickCore *nc) { } + + /** Called when we are wrting metadata for a nickalias + * @param WriteMetata A callback function used to insert the metadata + * @param na The nick alias + */ + virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), NickAlias *na) { } + + /** Called when we are writing metadata for a botinfo + * @param WriteMetata A callback function used to insert the metadata + * @param bi The botinfo + */ + virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), BotInfo *bi) { } + + /** Called when are are writing metadata for a channelinfo + * @param WriteMetata A callback function used to insert the metadata + * @param bi The channelinfo + */ + virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), ChannelInfo *ci) { } + /** Called before services restart */ virtual void OnPreRestart() { } @@ -983,6 +1054,18 @@ class CoreExport Module */ virtual EventReturn OnUnMLock(ChannelModeName Name) { return EVENT_CONTINUE; } + /** Called after a module is loaded + * @param u The user loading the module, can be NULL + * @param m The module + */ + virtual void OnModuleLoad(User *u, Module *m) { } + + /** Called before a module is unloaded + * @param u The user, can be NULL + * @param m The module + */ + virtual void OnModuleUnload(User *u, Module *m) { } + }; @@ -1019,9 +1102,17 @@ enum Implementation /* OperServ */ I_OnOperServHelp, I_OnDefconLevel, + /* Database */ + I_OnPostLoadDatabases, I_OnSaveDatabase, I_OnLoadDatabase, I_OnBackupDatabase, + I_OnDatabaseExpire, + I_OnDatabaseWrite, I_OnDatabaseRead, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata, + + /* Modules */ + I_OnModuleLoad, I_OnModuleUnload, + /* Other */ - I_OnReload, I_OnPreServerConnect, I_OnNewServer, I_OnServerConnect, I_OnPreCommandRun, I_OnPreCommand, I_OnPostCommand, I_OnPostLoadDatabases, I_OnSaveDatabase, I_OnBackupDatabase, - I_OnPreDatabaseExpire, I_OnDatabaseExpire, I_OnPreRestart, I_OnRestart, I_OnPreShutdown, I_OnShutdown, I_OnSignal, + I_OnReload, I_OnPreServerConnect, I_OnNewServer, I_OnServerConnect, I_OnPreCommandRun, I_OnPreCommand, I_OnPostCommand, + I_OnPreDatabaseExpire, I_OnPreRestart, I_OnRestart, I_OnPreShutdown, I_OnShutdown, I_OnSignal, I_OnServerQuit, I_OnTopicUpdated, I_OnEncrypt, I_OnEncryptInPlace, I_OnEncryptCheckLen, I_OnDecrypt, I_OnCheckPassword, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, diff --git a/include/pseudo.h b/include/pseudo.h index 65e5e81e7..d356aa953 100644 --- a/include/pseudo.h +++ b/include/pseudo.h @@ -15,5 +15,4 @@ #include "commands.h" #include "language.h" #include "timers.h" -#include "datafiles.h" #include "slist.h" diff --git a/src/Makefile b/src/Makefile index 8257d8cdf..90705ce29 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o commands.o compat.o \ - config.o datafiles.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ + config.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modules.o nickserv.o operserv.o \ process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o users.o module.o modulemanager.o configreader.o \ wildcard.o nickcore.o nickalias.o timers.o modes.o regchannel.o @@ -7,7 +7,7 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o comm INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \ ../include/pseudo.h ../include/sysconf.h ../include/config.h \ ../include/messages.h ../include/services.h \ - ../include/timers.h ../include/datafiles.h ../include/extern.h \ + ../include/timers.h ../include/extern.h \ ../include/modules.h ../include/slist.h ../include/hashcomp.h MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \ @@ -47,7 +47,6 @@ command.o: command.cpp $(INCLUDES) commands.o: commands.c $(INCLUDES) compat.o: compat.c $(INCLUDES) config.o: config.c $(INCLUDES) -datafiles.o: datafiles.c $(INCLUDES) encrypt.o: encrypt.c $(INCLUDES) init.o: init.c $(INCLUDES) ircd.o: ircd.c $(INCLUDES) diff --git a/src/chanserv.c b/src/chanserv.c index dc5345ed6..c0f8ac9bb 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -719,12 +719,9 @@ int check_kick(User * user, const char *chan, time_t chants) if (c) { - c->RemoveMode(NULL, CMODE_BAN, mask); - } - - c->SetMode(NULL, CMODE_BAN, mask); - if (c) + c->SetMode(NULL, CMODE_BAN, mask); ircdproto->SendKick(whosends(ci), c, user, "%s", reason); + } return 1; } diff --git a/src/config.c b/src/config.c index aa7577cbf..85eeed357 100644 --- a/src/config.c +++ b/src/config.c @@ -22,6 +22,7 @@ ServerConfig Config; static std::string Modules; static std::string EncModules; +static std::string DBModules; static std::string HostCoreModules; static std::string MemoCoreModules; static std::string BotCoreModules; @@ -180,12 +181,7 @@ bool ValidateEmailReg(ServerConfig *, const char *tag, const char *value, ValueI { if (Config.NSEmailReg) { - if (std::string(value) == "prenickdatabase") - { - if (data.GetValue().empty()) - throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when e-mail registrations are enabled!"); - } - else if (std::string(value) == "preregexpire") + if (std::string(value) == "preregexpire") { if (!data.GetInteger()) throw ConfigException(std::string("The value for <") + tag + ":" + value + "> must be non-zero when e-mail registration are enabled!"); @@ -240,7 +236,7 @@ bool ValidateBotServ(ServerConfig *, const char *tag, const char *value, ValueIt { if (Config.s_BotServ) { - if (std::string(value) == "description" || std::string(value) == "database") + if (std::string(value) == "description") { if (data.GetValue().empty()) throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when BotServ is enabled!"); @@ -258,7 +254,7 @@ bool ValidateHostServ(ServerConfig *, const char *tag, const char *value, ValueI { if (Config.s_HostServ) { - if (std::string(value) == "description" || std::string(value) == "database") + if (std::string(value) == "description") { if (data.GetValue().empty()) throw ConfigException(std::string("The value for <") + tag + ":" + value + "> cannot be empty when HostServ is enabled!"); @@ -613,6 +609,7 @@ int ServerConfig::Read(bool bail) {"networkinfo", "networkname", "", new ValueContainerChar(&Config.NetworkName), DT_CHARPTR, ValidateNotEmpty}, {"networkinfo", "nicklen", "0", new ValueContainerUInt(&Config.NickLen), DT_UINTEGER | DT_NORELOAD, ValidateNickLen}, {"options", "encryption", "", new ValueContainerString(&EncModules), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, + {"options", "database", "", new ValueContainerString(&DBModules), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"options", "userkey1", "0", new ValueContainerLUInt(&Config.UserKey1), DT_LUINTEGER, NoValidation}, {"options", "userkey2", "0", new ValueContainerLUInt(&Config.UserKey2), DT_LUINTEGER, NoValidation}, {"options", "userkey3", "0", new ValueContainerLUInt(&Config.UserKey3), DT_LUINTEGER, NoValidation}, @@ -645,9 +642,7 @@ int ServerConfig::Read(bool bail) {"options", "mlock", "+nrt", new ValueContainerString(&Config.MLock), DT_STRING, NoValidation}, {"nickserv", "nick", "NickServ", new ValueContainerChar(&Config.s_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, {"nickserv", "description", "Nickname Registration Service", new ValueContainerChar(&Config.desc_NickServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, - {"nickserv", "database", "nick.db", new ValueContainerChar(&Config.NickDBName), DT_CHARPTR, ValidateNotEmpty}, {"nickserv", "emailregistration", "no", new ValueContainerBool(&Config.NSEmailReg), DT_BOOLEAN, NoValidation}, - {"nickserv", "prenickdatabase", "", new ValueContainerChar(&Config.PreNickDBName), DT_CHARPTR, ValidateEmailReg}, {"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation}, {"nickserv", "forceemail", "no", new ValueContainerBool(&Config.NSForceEmail), DT_BOOLEAN, ValidateEmailReg}, {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation}, @@ -677,7 +672,6 @@ int ServerConfig::Read(bool bail) {"mail", "dontquoteaddresses", "no", new ValueContainerBool(&Config.DontQuoteAddresses), DT_BOOLEAN, NoValidation}, {"chanserv", "nick", "ChanServ", new ValueContainerChar(&Config.s_ChanServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, {"chanserv", "description", "Channel Registration Service", new ValueContainerChar(&Config.desc_ChanServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, - {"chanserv", "database", "chan.db", new ValueContainerChar(&Config.ChanDBName), DT_CHARPTR, ValidateNotEmpty}, {"chanserv", "modules", "", new ValueContainerString(&ChanCoreModules), DT_STRING, NoValidation}, {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, NoValidation}, {"chanserv", "maxregistered", "0", new ValueContainerUInt(&Config.CSMaxReg), DT_UINTEGER, NoValidation}, @@ -699,7 +693,6 @@ int ServerConfig::Read(bool bail) {"memoserv", "memoreceipt", "0", new ValueContainerUInt(&Config.MSMemoReceipt), DT_UINTEGER, NoValidation}, {"botserv", "nick", "", new ValueContainerChar(&Config.s_BotServ), DT_CHARPTR | DT_NORELOAD, NoValidation}, {"botserv", "description", "Bot Service", new ValueContainerChar(&Config.desc_BotServ), DT_CHARPTR | DT_NORELOAD, ValidateBotServ}, - {"botserv", "database", "bot.db", new ValueContainerChar(&Config.BotDBName), DT_CHARPTR, ValidateBotServ}, {"botserv", "modules", "", new ValueContainerString(&BotCoreModules), DT_STRING, NoValidation}, {"botserv", "defaults", "", new ValueContainerString(&BSDefaults), DT_STRING, NoValidation}, {"botserv", "minusers", "0", new ValueContainerUInt(&Config.BSMinUsers), DT_UINTEGER, ValidateBotServ}, @@ -711,15 +704,11 @@ int ServerConfig::Read(bool bail) {"botserv", "fantasycharacter", "!", new ValueContainerChar(&Config.BSFantasyCharacter), DT_CHARPTR, NoValidation}, {"hostserv", "nick", "", new ValueContainerChar(&Config.s_HostServ), DT_CHARPTR | DT_NORELOAD, NoValidation}, {"hostserv", "description", "vHost Service", new ValueContainerChar(&Config.desc_HostServ), DT_CHARPTR | DT_NORELOAD, ValidateHostServ}, - {"hostserv", "database", "hosts.db", new ValueContainerChar(&Config.HostDBName), DT_CHARPTR, ValidateHostServ}, {"hostserv", "modules", "", new ValueContainerString(&HostCoreModules), DT_STRING, NoValidation}, {"operserv", "nick", "OperServ", new ValueContainerChar(&Config.s_OperServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, {"operserv", "description", "Operator Service", new ValueContainerChar(&Config.desc_OperServ), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, {"operserv", "globalnick", "Global", new ValueContainerChar(&Config.s_GlobalNoticer), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, {"operserv", "globaldescription", "Global Noticer", new ValueContainerChar(&Config.desc_GlobalNoticer), DT_CHARPTR | DT_NORELOAD, ValidateNotEmpty}, - {"operserv", "database", "oper.db", new ValueContainerChar(&Config.OperDBName), DT_CHARPTR, ValidateNotEmpty}, - {"operserv", "newsdatabase", "news.db", new ValueContainerChar(&Config.NewsDBName), DT_CHARPTR, ValidateNotEmpty}, - {"operserv", "exceptiondatabase", "exception.db", new ValueContainerChar(&Config.ExceptionDBName), DT_CHARPTR, ValidateNotEmpty}, {"operserv", "modules", "", new ValueContainerString(&OperCoreModules), DT_STRING, NoValidation}, {"operserv", "superadmin", "no", new ValueContainerBool(&Config.SuperAdmin), DT_BOOLEAN, NoValidation}, {"operserv", "logmaxusers", "no", new ValueContainerBool(&Config.LogMaxUsers), DT_BOOLEAN, NoValidation}, @@ -1689,6 +1678,7 @@ int read_config(int reload) /* Modules Autoload building... :P */ Config.ModulesAutoLoad = BuildStringList(!Modules.empty() ? Modules : ""); Config.EncModuleList = BuildStringList(!EncModules.empty() ? EncModules : ""); + Config.DBModuleList = BuildStringList(!DBModules.empty() ? DBModules : ""); Config.HostServCoreModules = BuildStringList(!HostCoreModules.empty() ? HostCoreModules : ""); Config.MemoServCoreModules = BuildStringList(!MemoCoreModules.empty() ? MemoCoreModules : ""); Config.BotServCoreModules = BuildStringList(!BotCoreModules.empty() ? BotCoreModules : ""); @@ -1775,18 +1765,6 @@ int read_config(int reload) } } - /** - * If they try to enable any email registration option, - * make sure they have everything else they need too... - * - * rob - **/ - if (!Config.NSEmailReg) { - delete [] Config.PreNickDBName; - Config.PreNickDBName = NULL; - Config.NSRExpire = 0; - } - SetDefaultMLock(); if (!retval) { diff --git a/src/core/db_plain.cpp b/src/core/db_plain.cpp new file mode 100644 index 000000000..b551d0b5c --- /dev/null +++ b/src/core/db_plain.cpp @@ -0,0 +1,1148 @@ +/* + * + * (C) 2003-2009 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +std::fstream db; + +/** Enum used for what METADATA type we are reading + */ +enum MDType +{ + MD_NONE, + MD_NC, + MD_NA, + MD_BI, + MD_CH +}; + +/* Character for newlines, in my research I have concluded it is significantly faster + * to use \n instead of std::endl because std::endl also flushes the buffer, which + * is not necessary here + */ +static const char endl = '\n'; + +/** Read from the database and call the events + * @param m If specified it only calls the read events for the specific module + */ +static void ReadDatabase(Module *m = NULL) +{ + std::string buf; + EventReturn MOD_RESULT; + MDType Type = MD_NONE; + + db.open(DATABASE_FILE, std::ios_base::in); + + if (!db.is_open()) + { + ircdproto->SendGlobops(NULL, "Unable to open %s for reading!", DATABASE_FILE); + return; + } + + while (std::getline(db, buf)) + { + if (buf.empty()) + continue; + + spacesepstream sep(buf); + std::vector<std::string> params; + while (sep.GetToken(buf)) + { + if (buf[0] == ':') + { + buf.erase(buf.begin()); + if (!buf.empty()) + params.push_back(buf + " " + sep.GetRemaining()); + } + else + params.push_back(buf); + } + + if (m) + MOD_RESULT = m->OnDatabaseRead(params); + else + { + FOREACH_RESULT(I_OnDatabaseRead, OnDatabaseRead(params)); + } + if (MOD_RESULT == EVENT_STOP) + continue; + + std::string mdbuf; + NickCore *nc; + NickAlias *na; + BotInfo *bi; + ChannelInfo *ci; + if (!params.empty()) + { + if (params[0] == "NC") + { + nc = findcore(params[1].c_str()); + Type = MD_NC; + } + else if (params[0] == "NA") + { + na = findnick(params[2].c_str()); + Type = MD_NA; + } + else if (params[0] == "BI") + { + bi = findbot(params[1].c_str()); + Type = MD_BI; + } + else if (params[0] == "CH") + { + ci = cs_findchan(params[1].c_str()); + Type = MD_CH; + } + else if (params[0] == "MD") + { + std::string key = params[1]; + params.erase(params.begin()); + params.erase(params.begin()); + + if (nc && Type == MD_NC) + { + try + { + if (m) + MOD_RESULT = m->OnDatabaseReadMetadata(nc, key, params); + else + { + FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nc, key, params)); + } + } + catch (const char *err) + { + alog("[db_plain}: %s", err); + } + } + else if (na && Type == MD_NA) + { + try + { + if (m) + MOD_RESULT = m->OnDatabaseReadMetadata(na, key, params); + else + { + FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(na, key, params)); + } + } + catch (const char *err) + { + alog("[db_plain}: %s", err); + } + } + else if (bi && Type == MD_BI) + { + try + { + if (m) + MOD_RESULT = m->OnDatabaseReadMetadata(bi, key, params); + else + { + FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(bi, key, params)); + } + } + catch (const char *err) + { + alog("[db_plain}: %s", err); + } + } + else if (ci && Type == MD_CH) + { + try + { + if (m) + MOD_RESULT = m->OnDatabaseReadMetadata(ci, key, params); + else + { + FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, key, params)); + } + } + catch (const char *err) + { + alog("[db_plain}: %s", err); + } + } + } + } + } + + db.close(); +} + +struct LangInfo +{ + std::string Name; + int LanguageId; +}; + +struct ChannelModeInfo +{ + std::string Name; + ChannelModeName Value; +}; + +struct ChannelFlagInfo +{ + std::string Name; + ChannelInfoFlag Flag; +}; + +struct ChannelLevel +{ + std::string Name; + int Level; +}; + +struct BotFlagInfo +{ + std::string Name; + BotServFlag Flag; +}; + +struct NickCoreFlagInfo +{ + std::string Name; + NickCoreFlag Flag; +}; + +LangInfo LangInfos[] = { + {"en", LANG_EN_US}, + {"es", LANG_ES}, + {"pt", LANG_PT}, + {"fr", LANG_FR}, + {"tr", LANG_TR}, + {"it", LANG_IT}, + {"de", LANG_DE}, + {"ca", LANG_CAT}, + {"gr", LANG_GR}, + {"nl", LANG_NL}, + {"ru", LANG_RU}, + {"hu", LANG_HUN}, + {"pl", LANG_PL}, + {"", -1} +}; + +ChannelModeInfo ChannelModes[] = { + {"BLOCKCOLOR", CMODE_BLOCKCOLOR}, + {"FLOOD", CMODE_FLOOD}, + {"INVITE", CMODE_INVITE}, + {"KEY", CMODE_KEY}, + {"LIMIT", CMODE_LIMIT}, + {"MODERATED", CMODE_MODERATED}, + {"NOEXTERNAL", CMODE_NOEXTERNAL}, + {"PRIVATE", CMODE_PRIVATE}, + {"REGISTERED", CMODE_REGISTERED}, + {"SECRET", CMODE_SECRET}, + {"TOPIC", CMODE_TOPIC}, + {"AUDITORIUM", CMODE_AUDITORIUM}, + {"SSL", CMODE_SSL}, + {"ADMINONLY", CMODE_ADMINONLY}, + {"NOCTCP", CMODE_NOCTCP}, + {"FILTER", CMODE_FILTER}, + {"NOKNOCK", CMODE_NOKNOCK}, + {"REDIRECT", CMODE_REDIRECT}, + {"REGMODERATED", CMODE_REGMODERATED}, + {"NONICK", CMODE_NONICK}, + {"OPERONLY", CMODE_OPERONLY}, + {"NONICK", CMODE_NONICK}, + {"REGISTEREDONLY", CMODE_REGISTEREDONLY}, + {"STRIPCOLOR", CMODE_STRIPCOLOR}, + {"NONOTICE", CMODE_NONOTICE}, + {"NOINVITE", CMODE_NOINVITE}, + {"ALLINVITE", CMODE_ALLINVITE}, + {"BLOCKCAPS", CMODE_BLOCKCAPS}, + {"PERM", CMODE_PERM}, + {"NICKFLOOD", CMODE_NICKFLOOD}, + {"JOINFLOOD", CMODE_JOINFLOOD}, + {"", static_cast<ChannelModeName>(-1)} +}; + +ChannelFlagInfo ChannelInfoFlags[] = { + {"KEEPTOPIC", CI_KEEPTOPIC}, + {"SECUREOPS", CI_SECUREOPS}, + {"PRIVATE", CI_PRIVATE}, + {"TOPICLOCK", CI_TOPICLOCK}, + {"RESTRICTED", CI_RESTRICTED}, + {"PEACE", CI_PEACE}, + {"SECURE", CI_SECURE}, + {"FORBIDDEN", CI_FORBIDDEN}, + {"NO_EXPIRE", CI_NO_EXPIRE}, + {"MEMO_HARDMAX", CI_MEMO_HARDMAX}, + {"OPNOTICE", CI_OPNOTICE}, + {"SECUREFOUNDER", CI_SECUREFOUNDER}, + {"SIGNKICK", CI_SIGNKICK}, + {"SIGNKICK_LEVEL", CI_SIGNKICK_LEVEL}, + {"XOP", CI_XOP}, + {"SUSPENDED", CI_SUSPENDED}, + {"PERSIST", CI_PERSIST}, + {"", static_cast<ChannelInfoFlag>(-1)} +}; + +ChannelLevel ChannelLevels[] = { + {"INVITE", CA_INVITE}, + {"AKICK", CA_AKICK}, + {"SET", CA_SET}, + {"UNBAN", CA_UNBAN}, + {"AUTOOP", CA_AUTOOP}, + {"AUTODEOP", CA_AUTODEOP}, + {"AUTOVOICE", CA_AUTOVOICE}, + {"OPDEOP", CA_OPDEOP}, + {"ACCESS_LIST", CA_ACCESS_LIST}, + {"CLEAR", CA_CLEAR}, + {"NOJOIN", CA_NOJOIN}, + {"ACCESS_CHANGE", CA_ACCESS_CHANGE}, + {"MEMO", CA_MEMO}, + {"ASSIGN", CA_ASSIGN}, + {"BADWORDS", CA_BADWORDS}, + {"NOKICK", CA_NOKICK}, + {"FANTASIA", CA_FANTASIA}, + {"SAY", CA_SAY}, + {"GREET", CA_GREET}, + {"VOICEME", CA_VOICEME}, + {"VOICE", CA_VOICE}, + {"GETKEY", CA_GETKEY}, + {"AUTOHALFOP", CA_AUTOHALFOP}, + {"AUTOPROTECT", CA_AUTOPROTECT}, + {"OPDEOPME", CA_OPDEOPME}, + {"HALFOPME", CA_HALFOPME}, + {"HALFOP", CA_HALFOP}, + {"PROTECTME", CA_PROTECTME}, + {"PROTECT", CA_PROTECT}, + {"KICKME", CA_KICKME}, + {"KICK", CA_KICK}, + {"SIGNKICK", CA_SIGNKICK}, + {"BANME", CA_BANME}, + {"BAN", CA_BAN}, + {"TOPIC", CA_TOPIC}, + {"INFO", CA_INFO}, + {"AUTOOWNER", CA_AUTOOWNER}, + {"OWNER", CA_OWNER}, + {"OWNERME", CA_OWNERME}, + {"", -1} +}; + +BotFlagInfo BotFlags[] = { + {"DONTKICKOPS", BS_DONTKICKOPS}, + {"DONTKICKVOICES", BS_DONTKICKVOICES}, + {"FANTASY", BS_FANTASY}, + {"SYMBIOSIS", BS_SYMBIOSIS}, + {"GREET", BS_GREET}, + {"NOBOT", BS_NOBOT}, + {"KICK_BOLDS", BS_KICK_BOLDS}, + {"KICK_COLORS", BS_KICK_COLORS}, + {"KICK_REVERSES", BS_KICK_REVERSES}, + {"KICK_UNDERLINES", BS_KICK_UNDERLINES}, + {"KICK_BADWORDS", BS_KICK_BADWORDS}, + {"KICK_CAPS", BS_KICK_CAPS}, + {"KICK_FLOOD", BS_KICK_FLOOD}, + {"KICK_REPEAT", BS_KICK_REPEAT}, + {"", static_cast<BotServFlag>(-1)} +}; + +NickCoreFlagInfo NickCoreFlags[] = { + {"KILLPROTECT", NI_KILLPROTECT}, + {"SECURE", NI_SECURE}, + {"MSG", NI_MSG}, + {"MEMO_HARDMAX", NI_MEMO_HARDMAX}, + {"MEMO_SIGNON", NI_MEMO_SIGNON}, + {"MEMO_RECEIVE", NI_MEMO_RECEIVE}, + {"PRIVATE", NI_PRIVATE}, + {"HIDE_EMAIL", NI_HIDE_EMAIL}, + {"HIDE_MASK", NI_HIDE_MASK}, + {"HIDE_QUIT", NI_HIDE_QUIT}, + {"KILL_QUICK", NI_KILL_QUICK}, + {"KILL_IMMED", NI_KILL_IMMED}, + {"MEMO_MAIL", NI_MEMO_MAIL}, + {"HIDE_STATUS", NI_HIDE_STATUS}, + {"SUSPENDED", NI_SUSPENDED}, + {"AUTOOP", NI_AUTOOP}, + {"FORBIDDEN", NI_FORBIDDEN}, + {"", static_cast<NickCoreFlag>(-1)} +}; + +static void LoadNickCore(const std::vector<std::string> ¶ms) +{ + NickCore *nc = new NickCore(params[0]); + /* Clear default flags */ + nc->ClearFlags(); + + if (params.size() <= 2) + { + /* This is a forbidden nick */ + return; + } + + size_t tmp = params[1].find(':'); // XXX till we store the hash method internally with the nickcore + const char *pass = params[1].c_str() + tmp + 1; + char passbuf[PASSMAX]; + memset(&passbuf, 0, sizeof(passbuf)); + b64_decode(pass, passbuf, PASSMAX); + strscpy(nc->pass, passbuf, PASSMAX); + + for (int i = 0; LangInfos[i].LanguageId != -1; ++i) + if (params[2] == LangInfos[i].Name) + nc->language = LangInfos[i].LanguageId; + + nc->memos.memomax = atoi(params[3].c_str()); + nc->channelcount = atoi(params[4].c_str()); + + if (debug > 1) + alog("[db_plain]: Loaded NickCore %s", nc->display); +} + +static void LoadNickAlias(const std::vector<std::string> ¶ms) +{ + NickCore *nc = findcore(params[0].c_str()); + if (!nc) + { + alog("[db_plain]: Unable to find core %s", params[0].c_str()); + return; + } + + NickAlias *na = new NickAlias(params[1], nc); + + na->time_registered = strtol(params[2].c_str(), NULL, 10); + + na->last_seen = strtol(params[3].c_str(), NULL, 10); + + if (debug > 1) + alog("[db_plain}: Loaded nickalias for %s", na->nick); +} + +static void LoadBotInfo(const std::vector<std::string> ¶ms) +{ + BotInfo *bi = new BotInfo(params[0].c_str()); + bi->user = sstrdup(params[1].c_str()); + bi->host = sstrdup(params[2].c_str()); + bi->created = strtol(params[4].c_str(), NULL, 10); + bi->chancount = atol(params[5].c_str()); + bi->real = sstrdup(params[6].c_str()); + + if (debug > 1) + alog("[db_plain]: Loaded botinfo for %s", bi->nick); +} + +static void LoadChanInfo(const std::vector<std::string> ¶ms) +{ + ChannelInfo *ci = new ChannelInfo(params[0]); + /* CLear default mlock */ + ci->ClearMLock(); + /* Remove default channel flags */ + ci->ClearFlags(); + ci->botflags.ClearFlags(); + + ci->time_registered = strtol(params[1].c_str(), NULL, 10); + + ci->last_used = strtol(params[2].c_str(), NULL, 10); + + ci->bantype = atoi(params[3].c_str()); + + ci->memos.memomax = atoi(params[4].c_str()); + + if (debug > 1) + alog("[db_plain]: loaded channel %s", ci->name); +} + +static void LoadHostInfo(const std::vector<std::string> ¶ms) +{ + if (!findnick(params[0].c_str())) + return; + addHostCore(params[0].c_str(), params[4].empty() ? NULL : const_cast<char *>(params[4].c_str()), const_cast<char *>(params[3].c_str()), params[1].c_str(), strtol(params[2].c_str(), NULL, 10)); // XXX + if (debug > 1) + alog("[db_plain]: loaded vhost for %s", params[0].c_str()); +} + +static void LoadOperInfo(const std::vector<std::string> ¶ms) +{ + if (params[0] == "STATS") + { + maxusercnt = atol(params[1].c_str()); + maxusertime = strtol(params[2].c_str(), NULL, 10); + } + else if (params[0] == "AKILL" || params[0] == "SGLINE" || params[0] == "SQLINE" || params[0] == "SZLINE") + { + int (*add_sxline)(User *, const char *, const char *, time_t, const char *); + if (params[0] == "AKILL") + add_sxline = add_akill; + else if (params[0] == "SGLINE") + add_sxline = add_sgline; + else if (params[0] == "SQLINE") + add_sxline = add_sqline; + else if (params[0] == "SZLINE") + add_sxline = add_szline; + + add_sxline(NULL, (params[1] + "@" + params[2]).c_str(), params[3].c_str(), strtol(params[5].c_str(), NULL, 10), params[6].c_str()); + } + else if (params[0] == "EXCEPTION") + { + nexceptions++; + exceptions = static_cast<Exception *>(srealloc(exceptions, sizeof(Exception) * nexceptions)); + exceptions[nexceptions - 1].mask = sstrdup(params[1].c_str()); + exceptions[nexceptions - 1].limit = atol(params[2].c_str()); + strscpy(exceptions[nexceptions - 1].who, params[3].c_str(), NICKMAX); + exceptions[nexceptions - 1].time = strtol(params[4].c_str(), NULL, 10); + exceptions[nexceptions - 1].expires = strtol(params[5].c_str(), NULL, 10); + exceptions[nexceptions - 1].reason = sstrdup(params[6].c_str()); + exceptions[nexceptions - 1].num = nexceptions - 1; + } +} + +void Write(const std::string &buf) +{ + db << buf << endl; +} + +void WriteMetadata(const std::string &key, const std::string &data) +{ + Write("MD " + key + " " + data); +} + +class DBPlain : public Module +{ + public: + DBPlain(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetVersion("$Id$"); + this->SetType(DATABASE); + + Implementation i[] = { I_OnDatabaseRead, I_OnLoadDatabase, I_OnDatabaseReadMetadata, I_OnSaveDatabase, I_OnModuleLoad }; + ModuleManager::Attach(i, this, 5); + } + + EventReturn OnDatabaseRead(const std::vector<std::string> ¶ms) + { + std::string key = params[0]; + std::vector<std::string> otherparams = params; + otherparams.erase(otherparams.begin()); + + if (key == "NC") + LoadNickCore(otherparams); + else if (key == "NA") + LoadNickAlias(otherparams); + else if (key == "BI") + LoadBotInfo(otherparams); + else if (key == "CH") + LoadChanInfo(otherparams); + else if (key == "HI") + LoadHostInfo(otherparams); + else if (key == "OS") + LoadOperInfo(otherparams); + + return EVENT_CONTINUE; + } + + EventReturn OnLoadDatabase() + { + ReadDatabase(); + + /* No need to ever reload this again, although this should never be trigged again */ + ModuleManager::Detach(I_OnLoadDatabase, this); + ModuleManager::Detach(I_OnDatabaseReadMetadata, this); + + return EVENT_STOP; + } + + EventReturn OnDatabaseReadMetadata(NickCore *nc, const std::string &key, const std::vector<std::string> ¶ms) + { + if (key == "EMAIL") + nc->email = sstrdup(params[0].c_str()); + else if (key == "GREET") + nc->greet = sstrdup(params[0].c_str()); + else if (key == "ICQ") + nc->icq = atoi(params[0].c_str()); + else if (key == "URL") + nc->url = sstrdup(params[0].c_str()); + else if (key == "ACCESS") + nc->AddAccess(params[0]); + else if (key == "FLAGS") + { + for (unsigned j = 0; j < params.size(); ++j) + for (int i = 0; NickCoreFlags[i].Flag != -1; ++i) + if (NickCoreFlags[i].Name == params[j]) + nc->SetFlag(NickCoreFlags[i].Flag); + } + else if (key == "MI") + { + Memo *m = new Memo; + m->number = atoi(params[0].c_str()); + m->time = strtol(params[1].c_str(), NULL, 10); + strscpy(m->sender, params[2].c_str(), NICKMAX); + unsigned j; + for (j = 3; (params[j] == "UNREAD" || params[j] == "RECEIPT" || params[j] == "NOTIFYS"); ++j) + { + if (params[j] == "UNREAD") + m->SetFlag(MF_UNREAD); + else if (params[j] == "RECEIPT") + m->SetFlag(MF_RECEIPT); + else if (params[j] == "NOTIFYS") + m->SetFlag(MF_NOTIFYS); + } + m->text = sstrdup(params[j + 1].c_str()); + nc->memos.memos.push_back(m); + } + + return EVENT_CONTINUE; + } + + EventReturn OnDatabaseReadMetadata(NickAlias *na, const std::string &key, const std::vector<std::string> ¶ms) + { + if (key == "LAST_USERMASK") + na->last_usermask = sstrdup(params[0].c_str()); + else if (key == "LAST_REALNAME") + na->last_realname = sstrdup(params[0].c_str()); + else if (key == "LAST_QUIT") + na->last_quit = sstrdup(params[0].c_str()); + else if (key == "FLAGS") + { + for (unsigned j = 0; j < params.size(); ++j) + { + if (params[j] == "FORBIDDEN") + na->SetFlag(NS_FORBIDDEN); + else if (params[j] == "NOEXPIRE") + na->SetFlag(NS_NO_EXPIRE); + } + } + + return EVENT_CONTINUE; + } + + EventReturn OnDatabaseReadMetadata(BotInfo *bi, const std::string &key, const std::vector<std::string> ¶ms) + { + std::string buf; + + if (key == "FLAGS") + { + for (unsigned j = 0; j < params.size(); ++j) + { + if (params[j] == "PRIVATE") + bi->SetFlag(BI_PRIVATE); + else if (params[j] == "CHANSERV") + bi->SetFlag(BI_CHANSERV); + else if (params[j] == "BOTSERV") + bi->SetFlag(BI_BOTSERV); + else if (params[j] == "HOSTSERV") + bi->SetFlag(BI_HOSTSERV); + else if (params[j] == "OPERSERV") + bi->SetFlag(BI_OPERSERV); + else if (params[j] == "MEMOSERV") + bi->SetFlag(BI_MEMOSERV); + else if (params[j] == "NICKSERV") + bi->SetFlag(BI_NICKSERV); + else if (params[j] == "GLOBAL") + bi->SetFlag(BI_GLOBAL); + } + } + + return EVENT_CONTINUE; + } + + EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const std::string &key, const std::vector<std::string> ¶ms) + { + std::string buf; + int i; + + if (key == "FOUNDER") + { + ci->founder = findcore(params[0].c_str()); + if (!ci->founder) + { + alog("[db_plain]: Deleting founderless channel %s", ci->name); + delete ci; + ci = NULL; + throw "no founder"; + } + } + else if (key == "SUCCESSOR") + ci->successor = findcore(params[0].c_str()); + else if (key == "LEVELS") + { + for (unsigned j = 0; j < params.size(); ++j, ++j) + for (i = 0; ChannelLevels[i].Level != -1; ++i) + if (ChannelLevels[i].Name == params[j]) + ci->levels[ChannelLevels[i].Level] = atoi(params[j + 1].c_str()); + } + else if (key == "FLAGS") + { + for (unsigned j = 0; j < params.size(); ++j) + for (i = 0; ChannelInfoFlags[i].Flag != -1; ++i) + if (ChannelInfoFlags[i].Name == params[j]) + ci->SetFlag(ChannelInfoFlags[i].Flag); + } + else if (key == "DESC") + ci->desc = sstrdup(params[0].c_str()); + else if (key == "URL") + ci->url = sstrdup(params[0].c_str()); + else if (key == "EMAIL") + ci->email = sstrdup(params[0].c_str()); + else if (key == "TOPIC") + { + strscpy(ci->last_topic_setter, params[0].c_str(), NICKMAX); + ci->last_topic_time = strtol(params[1].c_str(), NULL, 10); + ci->last_topic = sstrdup(params[2].c_str()); + } + else if (key == "FORBID") + { + ci->forbidby = sstrdup(params[0].c_str()); + ci->forbidreason = sstrdup(params[1].c_str()); + } + else if (key == "ACCESS") + { + NickCore *nc = findcore(params[0].c_str()); + if (!nc) + throw "access entry for nonexistant core"; + int level = atoi(params[1].c_str()); + time_t last_seen = strtol(params[2].c_str(), NULL, 10); + ci->AddAccess(nc, level, buf, last_seen); + } + else if (key == "AKICK") + { + bool Stuck = params[0] == "STUCK" ? true : false; + bool Nick = params[1] == "NICK" ? true : false; + NickCore *nc = NULL; + if (Nick) + { + nc = findcore(params[2].c_str()); + if (!nc) + { + throw "akick for nonexistant core"; + } + } + AutoKick *ak; + if (Nick) + ak = ci->AddAkick(params[3], nc, params.size() > 5 ? params[5] : "", strtol(params[4].c_str(), NULL, 10)); + else + ak = ci->AddAkick(params[3], params[2], params.size() > 5 ? params[5] : "", strtol(params[4].c_str(), NULL, 10)); + if (Stuck) + ak->SetFlag(AK_STUCK); + if (Nick) + ak->SetFlag(AK_ISNICK); + + } + else if (key == "MLOCK_ON" || buf == "MLOCK_OFF") + { + bool Set = key == "MLOCK_ON" ? true : false; + + for (unsigned j = 0; j < params.size(); ++j) + for (i = 0; ChannelModes[i].Value != -1; ++i) + if (ChannelModes[i].Name == params[j]) + ci->SetMLock(ChannelModes[i].Value, Set); + } + else if (key == "MLP") + { + for (unsigned j = 0; j < params.size(); ++j, ++j) + for (i = 0; ChannelModes[i].Value != -1; ++i) + if (ChannelModes[i].Name == params[j]) + ci->SetMLock(ChannelModes[i].Value, true, params[j + 1]); + } + else if (key == "MI") + { + Memo *m = new Memo; + m->number = atoi(params[0].c_str()); + m->time = strtol(params[1].c_str(), NULL, 10); + strscpy(m->sender, params[2].c_str(), NICKMAX); + unsigned j; + for (j = 3; j < params.size() - 1 && (buf == "UNREAD" || buf == "RECEIPT" || buf == "NOTIFYS"); ++j) + { + if (params[j] == "UNREAD") + m->SetFlag(MF_UNREAD); + else if (params[j] == "RECEIPT") + m->SetFlag(MF_RECEIPT); + else if (params[j] == "NOTIFYS") + m->SetFlag(MF_NOTIFYS); + } + m->text = sstrdup(params[j + 1].c_str()); + ci->memos.memos.push_back(m); + } + else if (key == "ENTRYMSG") + ci->entry_message = sstrdup(params[0].c_str()); + else if (key == "BI") + { + if (params[0] == "NAME") + ci->bi = findbot(params[1].c_str()); + else if (params[0] == "FLAGS") + { + for (unsigned j = 1; j < params.size(); ++j) + for (i = 0; BotFlags[i].Flag != -1; ++i) + if (BotFlags[i].Name == params[j]) + ci->botflags.SetFlag(BotFlags[i].Flag); + } + else if (params[0] == "TTB") + { + for (unsigned j = 1; j < params.size(); ++j, ++j) + { + if (params[j] == "BOLDS") + ci->ttb[0] = atoi(params[j + 1].c_str()); + else if (params[j] == "COLORS") + ci->ttb[1] = atoi(params[j + 1].c_str()); + else if (params[j] == "REVERSES") + ci->ttb[2] = atoi(params[j + 1].c_str()); + else if (params[j] == "UNDERLINES") + ci->ttb[3] = atoi(params[j + 1].c_str()); + else if (params[j] == "BADWORDS") + ci->ttb[4] = atoi(params[j + 1].c_str()); + else if (params[j] == "CAPS") + ci->ttb[5] = atoi(params[j + 1].c_str()); + else if (params[j] == "FLOOD") + ci->ttb[6] = atoi(params[j + 1].c_str()); + else if (params[j] == "REPEAT") + ci->ttb[7] = atoi(params[j + 1].c_str()); + } + } + else if (params[0] == "CAPSMIN") + ci->capsmin = atoi(params[1].c_str()); + else if (params[0] == "CAPSPERCENT") + ci->capspercent = atoi(params[1].c_str()); + else if (params[0] == "FLOODLINES") + ci->floodlines = atoi(params[1].c_str()); + else if (params[0] == "FLOODSECS") + ci->floodsecs = atoi(params[1].c_str()); + else if (params[0] == "REPEATTIMES") + ci->repeattimes = atoi(params[1].c_str()); + else if (params[0] == "BADWORD") + { + BadWordType Type; + if (params[1] == "SINGLE") + Type = BW_SINGLE; + else if (params[1] == "START") + Type = BW_START; + else if (params[1] == "END") + Type = BW_END; + else + Type = BW_ANY; + ci->AddBadWord(params[2], Type); + } + } + + return EVENT_CONTINUE; + } + + EventReturn OnSaveDatabase() + { + db.open(DATABASE_FILE, std::ios_base::out | std::ios_base::trunc); + + if (!db.is_open()) + { + ircdproto->SendGlobops(NULL, "Unable to open %s for writing!", DATABASE_FILE); + return EVENT_CONTINUE; + } + + db << "VER 1" << endl; + + int i, j; + unsigned k; + NickCore *nc; + for (i = 0; i < 1024; ++i) + { + for (nc = nclists[i]; nc; nc = nc->next) + { + if (nc->HasFlag(NI_FORBIDDEN)) + { + db << "NC " << nc->display << endl; + db << "MD FLAGS FORBIDDEN" << endl; + FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nc)); + continue; + } + else + { + //XXX forced plain till we store hashm in pw + char temppass[5000]; + b64_encode(nc->pass, strlen(nc->pass), temppass, 5000); + db << "NC " << nc->display << " plain:" << temppass << " "; + } + for (j = 0; LangInfos[j].LanguageId != -1; ++j) + if (nc->language == LangInfos[j].LanguageId) + db << LangInfos[j].Name; + db << " " << nc->memos.memomax << " " << nc->channelcount << endl; + + if (nc->email) + db << "MD EMAIL " << nc->email << endl; + if (nc->greet) + db << "MD GREET :" << nc->greet << endl; + if (nc->icq) + db << "MD ICQ :" << nc->icq << endl; + if (nc->url) + db << "MD URL :" << nc->url << endl; + if (!nc->access.empty()) + { + for (std::vector<std::string>::iterator it = nc->access.begin(); it != nc->access.end(); ++it) + db << "MD ACCESS " << *it << endl; + } + if (nc->FlagCount()) + { + db << "MD FLAGS"; + for (j = 0; NickCoreFlags[j].Flag != -1; ++j) + if (nc->HasFlag(NickCoreFlags[j].Flag)) + db << " " << NickCoreFlags[j].Name; + db << endl; + } + if (!nc->memos.memos.empty()) + { + MemoInfo *mi = &nc->memos; + for (k = 0; k < mi->memos.size(); ++k) + { + db << "MD MI " << mi->memos[k]->number << " " << mi->memos[k]->time << " " << mi->memos[k]->sender; + if (mi->memos[k]->HasFlag(MF_UNREAD)) + db << " UNREAD"; + if (mi->memos[k]->HasFlag(MF_RECEIPT)) + db << " RECEIPT"; + if (mi->memos[k]->HasFlag(MF_NOTIFYS)) + db << " NOTIFYS"; + db << " :" << mi->memos[k]->text << endl; + } + } + + FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nc)); + + } + } + + NickAlias *na; + for (i = 0; i < 1024; ++i) + { + for (na = nalists[i]; na; na = na->next) + { + db << "NA " << na->nc->display << " " << na->nick << " " << na->time_registered << " " << na->last_seen << endl; + if (na->last_usermask) + db << "MD LAST_USERMASK " << na->last_usermask << endl; + if (na->last_realname) + db << "MD LAST_REALNAME :" << na->last_realname << endl; + if (na->last_quit) + db << "MD LAST_QUIT :" << na->last_quit << endl; + if (na->HasFlag(NS_FORBIDDEN) || na->HasFlag(NS_NO_EXPIRE)) + { + db << "MD FLAGS" << (na->HasFlag(NS_FORBIDDEN) ? " FORBIDDEN" : "") << (na->HasFlag(NS_NO_EXPIRE) ? " NOEXPIRE " : "") << endl; + } + + FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, na)); + } + } + + BotInfo *bi; + for (i = 0; i < 256; ++i) + { + for (bi = botlists[i]; bi; bi = bi->next) + { + db << "BI " << bi->nick << " " << bi->user << " " << bi->host << " " << bi->created << " " << bi->chancount << " :" << bi->real << endl; + if (bi->FlagCount()) + { + db << "MD FLAGS"; + if (bi->HasFlag(BI_PRIVATE)) + db << " PRIVATE"; + if (bi->HasFlag(BI_CHANSERV)) + db << " CHANSERV"; + else if (bi->HasFlag(BI_BOTSERV)) + db << " BOTSERV"; + else if (bi->HasFlag(BI_HOSTSERV)) + db << " HOSTSERV"; + else if (bi->HasFlag(BI_OPERSERV)) + db << " OPERSERV"; + else if (bi->HasFlag(BI_MEMOSERV)) + db << " MEMOSERV"; + else if (bi->HasFlag(BI_NICKSERV)) + db << " NICKSERV"; + else if (bi->HasFlag(BI_GLOBAL)) + db << " GLOBAL"; + db << endl; + } + + FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, bi)); + } + } + + ChannelInfo *ci; + for (i = 0; i < 256; ++i) + { + for (ci = chanlists[i]; ci; ci = ci->next) + { + db << "CH " << ci->name << " " << ci->time_registered << " " << ci->last_used; + db << " " << ci->bantype << " " << ci->memos.memomax << endl; + if (ci->founder) + db << "MD FOUNDER " << ci->founder->display << endl; + if (ci->successor) + db << "MD SUCCESSOR " << ci->successor->display << endl; + if (ci->desc) + db << "MD DESC :" << ci->desc << endl; + if (ci->url) + db << "MD URL :" << ci->url << endl; + if (ci->email) + db << "MD EMAIL :" << ci->email << endl; + if (ci->last_topic) + db << "MD TOPIC " << ci->last_topic_setter << " " << ci->last_topic_time << " :" << ci->last_topic << endl; + db << "MD LEVELS"; + for (j = 0; ChannelLevels[j].Level != -1; ++j) + db << " " << ChannelLevels[j].Name << " " << ci->levels[ChannelLevels[j].Level]; + db << endl; + if (ci->FlagCount()) + { + db << "MD FLAGS"; + for (j = 0; ChannelInfoFlags[j].Flag != -1; ++j) + if (ci->HasFlag(ChannelInfoFlags[j].Flag)) + db << " " << ChannelInfoFlags[j].Name; + db << endl; + if (ci->HasFlag(CI_FORBIDDEN)) + db << "MD FORBID " << ci->forbidby << " :" << ci->forbidreason << endl; + } + for (k = 0; k < ci->GetAccessCount(); ++k) + if (ci->GetAccess(k)->in_use) + db << "MD ACCESS " << ci->GetAccess(k)->nc->display << " " << ci->GetAccess(k)->level << " " + << ci->GetAccess(k)->last_seen << " " << ci->GetAccess(k)->creator << endl; + for (k = 0; k < ci->GetAkickCount(); ++k) + { + db << "MD AKICK " + << (ci->GetAkick(k)->HasFlag(AK_STUCK) ? "STUCK " : "UNSTUCK ") + << (ci->GetAkick(k)->HasFlag(AK_ISNICK) ? "NICK " : "MASK ") + << (ci->GetAkick(k)->HasFlag(AK_ISNICK) ? ci->GetAkick(k)->nc->display : ci->GetAkick(k)->mask) + << " " << ci->GetAkick(k)->creator << " " << ci->GetAkick(k)->addtime << " :"; + if (!ci->GetAkick(k)->reason.empty()) + db << ci->GetAkick(k)->reason; + db << endl; + } + if (ci->GetMLockCount(true)) + { + db << "MD MLOCK_ON"; + for (j = 0; ChannelModes[j].Value != -1; ++j) + if (ci->HasMLock(ChannelModes[j].Value, true)) + db << " " << ChannelModes[j].Name; + db << endl; + } + if (ci->GetMLockCount(false)) + { + db << "MD MLOCK_OFF"; + for (j = 0; ChannelModes[j].Value != -1; ++j) + if (ci->HasMLock(ChannelModes[j].Value, false)) + db << " " << ChannelModes[j].Name; + db << endl; + } + std::string Param; + for (j = 0; ChannelModes[j].Value != -1; ++j) + if (ci->GetParam(ChannelModes[j].Value, &Param)) + db << "MD MLP " << ChannelModes[j].Name << " " << Param; + if (!ci->memos.memos.empty()) + { + MemoInfo *memos = &ci->memos; + + for (k = 0; k < memos->memos.size(); ++k) + { + db << "MD MI " << memos->memos[k]->number << " " << memos->memos[k]->time << " " << memos->memos[k]->sender; + if (memos->memos[k]->HasFlag(MF_UNREAD)) + db << " UNREAD"; + if (memos->memos[k]->HasFlag(MF_RECEIPT)) + db << " RECEIPT"; + if (memos->memos[k]->HasFlag(MF_NOTIFYS)) + db << " NOTIFYS"; + db << " :" << memos->memos[k]->text << endl; + } + } + if (ci->entry_message) + db << "MD ENTRYMSG :" << ci->entry_message << endl; + if (ci->bi) + db << "MD BI NAME " << ci->bi->nick << endl; + if (ci->botflags.FlagCount()) + { + db << "MD BI FLAGS"; + for (j = 0; BotFlags[j].Flag != -1; ++j) + if (ci->botflags.HasFlag(BotFlags[j].Flag)) + db << " " << BotFlags[j].Name; + db << endl; + } + db << "MD BI TTB BOLDS " << ci->ttb[0] << " COLORS " << ci->ttb[1] << " REVERSES " << ci->ttb[2] << " UNDERLINES " << ci->ttb[3] << " BADWORDS " << ci->ttb[4] << " CAPS " << ci->ttb[5] << " FLOOD " << ci->ttb[6] << " REPEAT " << ci->ttb[7] << endl; + if (ci->capsmin) + db << "MD BI CAPSMINS " << ci->capsmin << endl; + if (ci->capspercent) + db << "MD BI CAPSPERCENT " << ci->capspercent << endl; + if (ci->floodlines) + db << "MD BI FLOODLINES " << ci->floodlines << endl; + if (ci->floodsecs) + db << "MD BI FLOODSECS " << ci->floodsecs << endl; + if (ci->repeattimes) + db << "MD BI REPEATTIMES " << ci->repeattimes << endl; + for (k = 0; k < ci->GetBadWordCount(); ++k) + db << "MD BI BADWORD " + << (ci->GetBadWord(k)->type == BW_ANY ? "ANY " : "") + << (ci->GetBadWord(k)->type == BW_SINGLE ? "SINGLE " : "") + << (ci->GetBadWord(k)->type == BW_START ? "START " : "") + << (ci->GetBadWord(k)->type == BW_END ? "END " : "") + << ":" << ci->GetBadWord(k)->word << endl; + + FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, ci)); + } + } + + HostCore *hc; + for (hc = hostCoreListHead(); hc; hc = hc->next) + { + db << "HI " << hc->nick << " " << hc->creator << " " << hc->time << " " << hc->vHost << " :" << hc->vIdent << endl; + } + + for (i = 0; i < akills.count; ++i) + { + Akill *ak = static_cast<Akill *>(akills.list[i]); + db << "OS AKILL " << ak->user << " " << ak->host << " " << ak->by << " " << ak->seton << " " << ak->expires << " :" << ak->reason << endl; + } + + db << "OS STATS " << maxusercnt << " " << maxusertime << endl; + SXLine *sx; + for (i = 0; i < sglines.count; ++i) + { + sx = static_cast<SXLine *>(sglines.list[i]); + db << "OS SGLINE " << sx->mask << " " << sx->by << " " << sx->seton << " " << sx->expires << " :" << sx->reason << endl; + } + for (i = 0; i < sqlines.count; ++i) + { + sx = static_cast<SXLine *>(sqlines.list[i]); + db << "OS SQLINE " << sx->mask << " " << sx->by << " " << sx->seton << " " << sx->expires << " :" << sx->reason << endl; + } + for (i = 0; i < szlines.count; ++i) + { + sx = static_cast<SXLine *>(szlines.list[i]); + db << "OS SZLINE " << sx->mask << " " << sx->by << " " << sx->seton << " " << sx->expires << " :" << sx->reason << endl; + } + + for (i = 0; i < nexceptions; i++) + { + db << "OS EXCEPTION " << exceptions[i].mask << " " << exceptions[i].limit << " " << exceptions[i].who << " " << exceptions[i].time << " " << exceptions[i].expires << " " << exceptions[i].reason << endl; + } + + FOREACH_MOD(I_OnDatabaseWrite, OnDatabaseWrite(Write)); + + db.close(); + + return EVENT_CONTINUE; + } + + void OnModuleLoad(User *u, Module *m) + { + if (!u) + return; + + Implementation events[] = { I_OnDatabaseRead, I_OnDatabaseReadMetadata }; + for (int i = 0; i < 2; ++i) + { + std::vector<Module *>::iterator it = std::find(ModuleManager::EventHandlers[events[i]].begin(), ModuleManager::EventHandlers[events[i]].end(), m); + /* This module wants to read from the database */ + if (it != ModuleManager::EventHandlers[events[i]].end()) + { + /* Loop over the database and call the events it would on a normal startup */ + ReadDatabase(m); + } + } + } +}; + +MODULE_INIT(DBPlain) + diff --git a/src/core/ns_forbid.c b/src/core/ns_forbid.c index f45dadceb..c58dda380 100644 --- a/src/core/ns_forbid.c +++ b/src/core/ns_forbid.c @@ -50,7 +50,9 @@ class CommandNSForbid : public Command } delete na; } - na = new NickAlias(nick, new NickCore(nick)); + NickCore *nc = new NickCore(nick); + nc->SetFlag(NI_FORBIDDEN); + na = new NickAlias(nick, nc); if (na) { na->SetFlag(NS_FORBIDDEN); diff --git a/src/core/ns_identify.c b/src/core/ns_identify.c index af111689c..dc9e6a59e 100644 --- a/src/core/ns_identify.c +++ b/src/core/ns_identify.c @@ -65,7 +65,6 @@ class CommandNSIdentify : public Command alog("%s: %s!%s@%s logged out of account %s", Config.s_NickServ, u->nick, u->GetIdent().c_str(), u->host, u->nc->display); } - u->UpdateHost(); if (na->last_realname) delete [] na->last_realname; na->last_realname = sstrdup(u->realname); @@ -75,6 +74,8 @@ class CommandNSIdentify : public Command ircdproto->SendAccountLogin(u, u->nc); ircdproto->SetAutoIdentificationToken(u); + u->UpdateHost(); + FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(u)); alog("%s: %s!%s@%s identified for nick %s", Config.s_NickServ, u->nick, u->GetIdent().c_str(), u->host, u->nick); diff --git a/src/core/os_ignore.c b/src/core/os_ignore.c index bd7487f36..e7bb27a52 100644 --- a/src/core/os_ignore.c +++ b/src/core/os_ignore.c @@ -140,12 +140,68 @@ class OSIgnore : public Module this->SetType(CORE); this->AddCommand(OPERSERV, new CommandOSIgnore()); - ModuleManager::Attach(I_OnOperServHelp, this); + Implementation i[] = { I_OnOperServHelp, I_OnDatabaseRead, I_OnDatabaseWrite }; + ModuleManager::Attach(i, this, 3); } + void OnOperServHelp(User *u) { notice_lang(Config.s_OperServ, u, OPER_HELP_CMD_IGNORE); } + + EventReturn OnDatabaseRead(const std::vector<std::string> ¶ms) + { + std::string buf; + + if (params[0] == "OS" && params.size() >= 4 && params[1] == "IGNORE") + { + IgnoreData *ign = new IgnoreData; + ign->mask = sstrdup(params[2].c_str()); + ign->time = strtol(params[3].c_str(), NULL, 10); + ign->prev = NULL; + ign->next = ignore; + if (ignore) + ignore->prev = ign; + ignore = ign; + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + void OnDatabaseWrite(void (*Write)(const std::string &)) + { + IgnoreData *ign, *next; + time_t now = time(NULL); + + for (ign = ignore; ign; ign = next) + { + next = ign->next; + + if (ign->time != 0 && ign->time <= now) + { + if (debug) + alog("[os_ignore] 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 + { + std::string buf = "OS IGNORE "; + buf += ign->mask; + buf += " " + ign->time; + Write(buf); + } + } + } }; MODULE_INIT(OSIgnore) diff --git a/src/core/os_modlist.c b/src/core/os_modlist.c index 1e159e551..d5e431e95 100644 --- a/src/core/os_modlist.c +++ b/src/core/os_modlist.c @@ -32,6 +32,7 @@ class CommandOSModList : public Command int showEnc = 1; int showSupported = 1; int showQA = 1; + int showDB = 1; ci::string param = params.size() ? params[0] : ""; ModuleHash *current = NULL; @@ -42,6 +43,7 @@ class CommandOSModList : public Command char enc[] = "Encryption"; char supported[] = "Supported"; char qa[] = "QATested"; + char db[] = "Database"; if (!param.empty()) { @@ -53,6 +55,7 @@ class CommandOSModList : public Command showEnc = 0; showSupported = 0; showQA = 0; + showDB = 0; } else if (param == third) { @@ -62,6 +65,7 @@ class CommandOSModList : public Command showQA = 0; showProto = 0; showEnc = 0; + showDB = 0; } else if (param == proto) { @@ -71,6 +75,7 @@ class CommandOSModList : public Command showEnc = 0; showSupported = 0; showQA = 0; + showDB = 0; } else if (param == supported) { @@ -80,6 +85,7 @@ class CommandOSModList : public Command showSupported = 1; showEnc = 0; showQA = 0; + showDB = 0; } else if (param == qa) { @@ -89,6 +95,7 @@ class CommandOSModList : public Command showSupported = 0; showEnc = 0; showQA = 1; + showDB = 0; } else if (param == enc) { @@ -98,6 +105,17 @@ class CommandOSModList : public Command showSupported = 0; showEnc = 1; showQA = 0; + showDB = 0; + } + else if (param == db) + { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 0; + showEnc = 0; + showQA = 0; + showDB = 1; } } @@ -150,6 +168,13 @@ class CommandOSModList : public Command notice_lang(Config.s_OperServ, u, OPER_MODULE_LIST, current->name, current->m->version.c_str(), enc); ++count; } + break; + case DATABASE: + if (showDB) + { + notice_lang(Config.s_OperServ, u, OPER_MODULE_LIST, current->name, current->m->version.c_str(), enc); + ++count; + } } } } diff --git a/src/core/os_news.c b/src/core/os_news.c index 05006501d..877dd71d6 100644 --- a/src/core/os_news.c +++ b/src/core/os_news.c @@ -401,12 +401,15 @@ class OSNews : public Module this->AddCommand(OPERSERV, new CommandOSOperNews()); this->AddCommand(OPERSERV, new CommandOSRandomNews()); - Implementation i[] = { I_OnOperServHelp, I_OnUserModeSet, I_OnUserConnect, I_OnSaveDatabase, I_OnPostLoadDatabases }; + Implementation i[] = { I_OnOperServHelp, I_OnUserModeSet, I_OnUserConnect, I_OnDatabaseRead, I_OnDatabaseWrite }; ModuleManager::Attach(i, this, 5); } ~OSNews() { + for (std::vector<NewsItem *>::iterator it = News.begin(); it != News.end(); ++it) + delete *it; + News.clear(); } void OnOperServHelp(User *u) @@ -430,12 +433,45 @@ class OSNews : public Module DisplayNews(u, NEWS_RANDOM); } - void OnSaveDatabase() + EventReturn OnDatabaseRead(const std::vector<std::string> ¶ms) { + if (params[0] == "OS" && params.size() >= 7 && params[1] == "NEWS") + { + NewsItem *n = new NewsItem; + n->num = atoi(params[2].c_str()); + n->time = strtol(params[3].c_str(), NULL, 10); + strscpy(n->who, params[4].c_str(), NICKMAX); + if (params[5] == "LOGON") + n->type = NEWS_LOGON; + else if (params[5] == "RANDOM") + n->type = NEWS_RANDOM; + else if (params[5] == "OPER") + n->type = NEWS_OPER; + n->Text = params[6]; + News.push_back(n); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; } - void OnPostLoadDatabases() + void OnDatabaseWrite(void (*Write)(const std::string &)) { + for (std::vector<NewsItem *>::iterator it = News.begin(); it != News.end(); ++it) + { + NewsItem *n = *it; + + char buf[512], *ntype; + if (n->type == NEWS_LOGON) + ntype = "LOGON"; + else if (n->type == NEWS_RANDOM) + ntype = "RANDOM"; + else if (n->type == NEWS_OPER) + ntype = "OPER"; + snprintf(buf, sizeof(buf), "OS NEWS %d %ld %s %s :%s", n->num, n->time, n->who, ntype, n->Text.c_str()); + Write(buf); + } } }; diff --git a/src/datafiles.c b/src/datafiles.c deleted file mode 100644 index 5292361ac..000000000 --- a/src/datafiles.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Database file handling routines. - * - * (C) 2003-2009 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * $Id$ - * - */ - -#include "services.h" -#include "datafiles.h" -#include "modules.h" -#include <fcntl.h> - -static int curday = 0; - -/*************************************************************************/ - -/** - * Renames a database - * - * @param name Database to name - * @param ext Extention - * @return void - */ -static void rename_database(const char *name, char *ext) -{ - - char destpath[PATH_MAX]; - - snprintf(destpath, sizeof(destpath), "backups/%s.%s", name, ext); - if (rename(name, destpath) != 0) { - alog("Backup of %s failed.", name); - ircdproto->SendGlobops(findbot(Config.s_OperServ), "WARNING! Backup of %s failed.", - name); - } -} - -/*************************************************************************/ - -/** - * Removes old databases - * - * @return void - */ -static void remove_backups() -{ - - char ext[9]; - char path[PATH_MAX]; - - time_t t; - struct tm tm; - - time(&t); - t -= (60 * 60 * 24 * Config.KeepBackups); - tm = *localtime(&t); - strftime(ext, sizeof(ext), "%Y%m%d", &tm); - - snprintf(path, sizeof(path), "backups/%s.%s", Config.NickDBName, ext); - DeleteFile(path); - - snprintf(path, sizeof(path), "backups/%s.%s", Config.ChanDBName, ext); - DeleteFile(path); - - snprintf(path, sizeof(path), "backups/%s.%s", Config.OperDBName, ext); - DeleteFile(path); - - snprintf(path, sizeof(path), "backups/%s.%s", Config.NewsDBName, ext); - DeleteFile(path); - - snprintf(path, sizeof(path), "backups/%s.%s", Config.ExceptionDBName, ext); - DeleteFile(path); - - if (Config.s_BotServ) { - snprintf(path, sizeof(path), "backups/%s.%s", Config.BotDBName, ext); - DeleteFile(path); - } - if (Config.s_HostServ) { - snprintf(path, sizeof(path), "backups/%s.%s", Config.HostDBName, ext); - DeleteFile(path); - } - if (Config.NSEmailReg) { - snprintf(path, sizeof(path), "backups/%s.%s", Config.PreNickDBName, ext); - DeleteFile(path); - } -} - -/*************************************************************************/ - -/** - * Handles database backups. - * - * @return void - */ -void backup_databases() -{ - - time_t t; - struct tm tm; - - if (!Config.KeepBackups) { - return; - } - - time(&t); - tm = *localtime(&t); - - if (!curday) { - curday = tm.tm_yday; - return; - } - - if (curday != tm.tm_yday) { - - char ext[9]; - - - alog("Backing up databases"); - FOREACH_MOD(I_OnBackupDatabase, OnBackupDatabase()) - - remove_backups(); - - curday = tm.tm_yday; - strftime(ext, sizeof(ext), "%Y%m%d", &tm); - - rename_database(Config.NickDBName, ext); - if (Config.s_BotServ) { - rename_database(Config.BotDBName, ext); - } - rename_database(Config.ChanDBName, ext); - if (Config.s_HostServ) { - rename_database(Config.HostDBName, ext); - } - if (Config.NSEmailReg) { - rename_database(Config.PreNickDBName, ext); - } - - rename_database(Config.OperDBName, ext); - rename_database(Config.NewsDBName, ext); - rename_database(Config.ExceptionDBName, ext); - } -} - -/*************************************************************************/ - -void ModuleDatabaseBackup(const char *dbname) -{ - - time_t t; - struct tm tm; - - if (!Config.KeepBackups) { - return; - } - - time(&t); - tm = *localtime(&t); - - if (!curday) { - curday = tm.tm_yday; - return; - } - - if (curday != tm.tm_yday) { - - char ext[9]; - - if (debug) { - alog("Module Database Backing up %s", dbname); - } - ModuleRemoveBackups(dbname); - curday = tm.tm_yday; - strftime(ext, sizeof(ext), "%Y%m%d", &tm); - rename_database(dbname, ext); - } -} - -/*************************************************************************/ - -void ModuleRemoveBackups(const char *dbname) -{ - char ext[9]; - char path[PATH_MAX]; - - time_t t; - struct tm tm; - - time(&t); - t -= (60 * 60 * 24 * Config.KeepBackups); - tm = *localtime(&t); - strftime(ext, sizeof(ext), "%Y%m%d", &tm); - - snprintf(path, sizeof(path), "backups/%s.%s", dbname, ext); - DeleteFile(path); -} - -/*************************************************************************/ diff --git a/src/init.c b/src/init.c index 924c02c62..bde426578 100644 --- a/src/init.c +++ b/src/init.c @@ -388,6 +388,10 @@ int init_primary(int ac, char **av) /* Add Encryption Modules */ ModuleManager::LoadModuleList(Config.EncModuleList); + + /* Add Database Modules */ + ModuleManager::LoadModuleList(Config.DBModuleList); + return 0; } @@ -500,7 +504,10 @@ int init_secondary(int ac, char **av) add_entropy_userkeys(); /* Load up databases */ - //alog("Databases loaded"); + alog("Loading databases..."); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnLoadDatabase, OnLoadDatabase()); + alog("Databases loaded"); // XXX: this is duplicated in type loading. for (std::list<std::pair<std::string, std::string> >::iterator it = Config.Opers.begin(); it != Config.Opers.end(); it++) @@ -561,9 +568,6 @@ int init_secondary(int ac, char **av) } FOREACH_MOD(I_OnPostLoadDatabases, OnPostLoadDatabases()); - /* Save the databases back to file/mysql to reflect any changes */ - alog("Info: Reflecting database records."); - save_databases(); FOREACH_MOD(I_OnPreServerConnect, OnPreServerConnect()); /* Connect to the remote server */ diff --git a/src/main.c b/src/main.c index 9d6fc1c94..3bbf8cf2a 100644 --- a/src/main.c +++ b/src/main.c @@ -29,7 +29,6 @@ #include "services.h" #include "timers.h" #include "version.h" -#include "datafiles.h" #include "modules.h" // getrlimit. @@ -136,7 +135,8 @@ extern void expire_all() void save_databases() { - FOREACH_MOD(I_OnSaveDatabase, OnSaveDatabase()) + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnSaveDatabase, OnSaveDatabase()); if (debug) alog("debug: Saving FFF databases"); } diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index 813bc2d50..085f9f848 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -255,6 +255,8 @@ int ModuleManager::LoadModule(const std::string &modname, User * u) m->OnPostLoadDatabases(); } + FOREACH_MOD(I_OnModuleLoad, OnModuleLoad(u, m)); + return MOD_ERR_OK; } @@ -267,7 +269,7 @@ int ModuleManager::UnloadModule(Module *m, User *u) return MOD_ERR_PARAMS; } - if (m->GetPermanent() || m->type == PROTOCOL || m->type == ENCRYPTION) + if (m->GetPermanent() || m->type == PROTOCOL || m->type == ENCRYPTION || m->type == DATABASE) { if (u) notice_lang(Config.s_OperServ, u, OPER_MODULE_NO_UNLOAD); @@ -280,6 +282,8 @@ int ModuleManager::UnloadModule(Module *m, User *u) notice_lang(Config.s_OperServ, u, OPER_MODULE_UNLOADED, m->name.c_str()); } + FOREACH_MOD(I_OnModuleUnload, OnModuleUnload(u, m)); + DeleteModule(m); return MOD_ERR_OK; } diff --git a/src/modules/hs_request.c b/src/modules/hs_request.c index 85cf9e21a..5255649f7 100644 --- a/src/modules/hs_request.c +++ b/src/modules/hs_request.c @@ -24,9 +24,6 @@ int HSRequestMemoUser = 0; int HSRequestMemoOper = 0; int HSRequestMemoSetters = 0; -char *HSRequestDBName = NULL; - -#define HSREQ_DEFAULT_DBNAME "hs_request.db" /* Language defines */ #define LNG_NUM_STRINGS 21 @@ -58,8 +55,6 @@ int my_isvalidchar(const char c); void my_memo_lang(User *u, const char *name, int z, int number, ...); void req_send_memos(User *u, char *vIdent, char *vHost); -void hsreq_load_db(); - void my_load_config(); void my_add_languages(); @@ -410,10 +405,6 @@ class HSRequest : public Module this->AddCommand(HOSTSERV, new CommandHSReject()); this->AddCommand(HOSTSERV, new CommandHSWaiting()); - ModuleManager::Attach(I_OnPreCommand, this); - ModuleManager::Attach(I_OnSaveDatabase, this); - ModuleManager::Attach(I_OnBackupDatabase, this); - this->SetAuthor(AUTHOR); this->SetVersion(VERSION); this->SetType(SUPPORTED); @@ -421,8 +412,6 @@ class HSRequest : public Module my_load_config(); hs_request_head = NULL; - hsreq_load_db(); - const char* langtable_en_us[] = { /* LNG_REQUEST_SYNTAX */ "Syntax: \002REQUEST \037vhost\037\002", @@ -679,7 +668,8 @@ class HSRequest : public Module this->InsertLanguage(LANG_RU, LNG_NUM_STRINGS, langtable_ru); this->InsertLanguage(LANG_IT, LNG_NUM_STRINGS, langtable_it); - ModuleManager::Attach(I_OnHostServHelp, this); + Implementation i[] = { I_OnHostServHelp, I_OnPreCommand, I_OnDatabaseRead, I_OnDatabaseWrite }; + ModuleManager::Attach(i, this, 4); } ~HSRequest() @@ -689,8 +679,6 @@ class HSRequest : public Module /* Clean up all open host requests */ while (hs_request_head) hs_request_head = deleteHostCore(hs_request_head, NULL); - - delete [] HSRequestDBName; } EventReturn OnPreCommand(User *u, const std::string &service, const ci::string &command, const std::vector<ci::string> ¶ms) @@ -726,51 +714,42 @@ class HSRequest : public Module return EVENT_CONTINUE; } - void OnSaveDatabase() + void OnHostServHelp(User *u) { - FILE *fp; - const char *db_filename; - const char *vident; - HostCore *current; - - if (HSRequestDBName) - db_filename = HSRequestDBName; - else - db_filename = HSREQ_DEFAULT_DBNAME; + this->NoticeLang(Config.s_HostServ, u, LNG_HELP); + this->NoticeLang(Config.s_HostServ, u, LNG_HELP_SETTER); + } - fp = fopen(db_filename, "w"); - if (!fp) + EventReturn OnDatabaseRead(const std::vector<std::string> ¶ms) + { + if (params[0] == "HS_REQUEST" && params.size() >= 6) { - alog("[hs_request] Unable to open database ('%s') for writing", db_filename); - return; - } + my_add_host_request(const_cast<char *>(params[1].c_str()), const_cast<char *>(params[2].c_str()), const_cast<char *>(params[3].c_str()), const_cast<char *>(params[4].c_str()), strtol(params[5].c_str(), NULL, 10)); - current = hs_request_head; - while (current) - { - vident = current->vIdent ? current->vIdent : "(null)"; - fprintf(fp, "%s:%s:%s:%X:%s\n", current->nick, vident, current->vHost, static_cast<uint32>(current->time), current->creator); - current = current->next; + return EVENT_STOP; } - fclose(fp); - - if (debug) - alog("[hs_request] Successfully saved database"); - } - - void OnBackupDatabase() - { - if (HSRequestDBName) - ModuleDatabaseBackup(HSRequestDBName); - else - ModuleDatabaseBackup(HSREQ_DEFAULT_DBNAME); + return EVENT_CONTINUE; } - void OnHostServHelp(User *u) + void OnDatabaseWrite(void (*Write)(const std::string &)) { - this->NoticeLang(Config.s_HostServ, u, LNG_HELP); - this->NoticeLang(Config.s_HostServ, u, LNG_HELP_SETTER); + for (HostCore *current = hs_request_head; current; current = current->next) + { + const char *vident = current->vIdent ? current->vIdent : "(null)"; + std::string buf = "HS_REQUEST "; + // We really need a better + operator to make this easier ... + buf += current->nick; + buf += " "; + buf += vident; + buf += " "; + buf += current->vHost; + buf += " "; + buf += current->time; + buf += " "; + buf += current->creator; + Write(buf); + } } }; @@ -872,84 +851,15 @@ int my_isvalidchar(const char c) return 0; } -void hsreq_load_db() -{ - FILE *fp; - const char *db_filename; - char readbuf[1024]; - char *nick, *vident, *vhost, *creator, *tmp; - int32 tmp_time; - char *buf; - - if (HSRequestDBName) - db_filename = HSRequestDBName; - else - db_filename = HSREQ_DEFAULT_DBNAME; - - fp = fopen(db_filename, "r"); - if (!fp) - { - alog("[hs_request] Unable to open database ('%s') for reading", db_filename); - return; - } - - while (fgets(readbuf, 1024, fp)) - { - buf = normalizeBuffer(readbuf); - if (buf || *buf) - { - nick = myStrGetToken(buf, ':', 0); - vident = myStrGetToken(buf, ':', 1); - vhost = myStrGetToken(buf, ':', 2); - tmp = myStrGetToken(buf, ':', 3); - if (tmp) - { - tmp_time = strtol(tmp, NULL, 16); - delete [] tmp; - } - else - tmp_time = 0; - creator = myStrGetToken(buf, ':', 4); - if (!nick || !vident || !vhost || !creator) - { - alog("[hs_request] Error while reading database, skipping record"); - continue; - } - if (!stricmp(vident, "(null)")) - { - delete [] vident; - vident = NULL; - } - my_add_host_request(nick, vident, vhost, creator, tmp_time); - delete [] nick; - delete [] vhost; - delete [] creator; - if (vident) - delete [] vident; - } - delete [] buf; - } - - fclose(fp); - - if (debug) - alog("[hs_request] Successfully loaded database"); -} - void my_load_config() { ConfigReader config; HSRequestMemoUser = config.ReadFlag("hs_request", "memouser", "no", 0); HSRequestMemoOper = config.ReadFlag("hs_request", "memooper", "no", 0); HSRequestMemoSetters = config.ReadFlag("hs_request", "memosetters", "no", 0); - std::string tmp = config.ReadValue("hs_request", "database", HSREQ_DEFAULT_DBNAME, 0); - - if (HSRequestDBName) - delete [] HSRequestDBName; - HSRequestDBName = sstrdup(tmp.c_str()); if (debug) - alog("debug: [hs_request] Set config vars: MemoUser=%d MemoOper=%d MemoSetters=%d DBName='%s'", HSRequestMemoUser, HSRequestMemoOper, HSRequestMemoSetters, HSRequestDBName); + alog("debug: [hs_request] Set config vars: MemoUser=%d MemoOper=%d MemoSetters=%d", HSRequestMemoUser, HSRequestMemoOper, HSRequestMemoSetters); } MODULE_INIT(HSRequest) diff --git a/src/modules/os_ignore_db.c b/src/modules/os_ignore_db.c deleted file mode 100644 index 3989bde85..000000000 --- a/src/modules/os_ignore_db.c +++ /dev/null @@ -1,490 +0,0 @@ -/* os_ignore_db.c - Provides a database backend for OS IGNORE. - * - * (C) 2003-2009 Anope Team - * Contact us at team@anope.org - * - * Included in the Anope module pack since Anope 1.7.23 - * Anope Coder: Viper <viper@anope.org> - * - * 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]); - -void load_ignore_db(); -void load_config(); - -/* ------------------------------------------------------------------------------- */ - -class OSIgnoreDB : public Module -{ - public: - OSIgnoreDB(const std::string &modname, const std::string &creator) : Module(modname, creator) - { - IgnoreDB = NULL; - - this->SetAuthor(AUTHOR); - this->SetVersion(VERSION); - this->SetType(SUPPORTED); - - ModuleManager::Attach(I_OnSaveDatabase, this); - ModuleManager::Attach(I_OnBackupDatabase, this); - - load_config(); - /* Load the ignore database and re-add them to anopes ignorelist. */ - load_ignore_db(); - ModuleManager::Attach(I_OnReload, this); - } - - ~OSIgnoreDB() - { - /* Save the ignore database before bailing out.. */ - OnSaveDatabase(); - - if (IgnoreDB) - delete [] IgnoreDB; - } - - void OnReload(bool starting) - { - load_config(); - } - - void OnSaveDatabase() - { - DBFile *dbptr = new DBFile; - time_t now; - IgnoreData *ign, *next; - - now = time(NULL); - fill_db_ptr(dbptr, 0, IGNOREDBVERSION, Config.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 */ - } - } - - void OnBackupDatabase() - { - ModuleDatabaseBackup(IgnoreDB); - } - - -}; - - -/* ------------------------------------------------------------------------------- */ - -void load_config() { - 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); -} - -/* ------------------------------------------------------------------------------- */ - -/************************************************************************** - * DataBase Handling - **************************************************************************/ - -void load_ignore_db() { - 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, Config.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 = 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 (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; -} - - -/* ------------------------------------------------------------------------------- */ - -/************************************************************************** - * 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) - strlcpy(dbptr->service, service, sizeof(dbptr->service)); - else - strlcpy(dbptr->service, "", sizeof(dbptr->service)); - - strlcpy(dbptr->filename, filename, sizeof(dbptr->filename)); - snprintf(dbptr->temp_name, sizeof(dbptr->temp_name), "%s.temp", filename); - return; -} - -MODULE_INIT(OSIgnoreDB) diff --git a/src/modules/os_info.c b/src/modules/os_info.c index a4b2cffc4..39522d6c0 100644 --- a/src/modules/os_info.c +++ b/src/modules/os_info.c @@ -21,9 +21,6 @@ #define AUTHOR "Rob" #define VERSION "$Id$" -/* Default database name */ -#define DEFAULT_DB_NAME "os_info.db" - /* Multi-language stuff */ #define LANG_NUM_STRINGS 10 @@ -40,11 +37,6 @@ /*************************************************************************/ -char *OSInfoDBName = NULL; - -int mLoadData(); -int mLoadConfig(); - static Module *me; /*************************************************************************/ @@ -201,19 +193,9 @@ class OSInfo : public Module this->SetVersion(VERSION); this->SetType(SUPPORTED); - if (mLoadConfig()) - throw ModuleException("Unable to load config"); - this->AddCommand(NICKSERV, new CommandNSOInfo()); this->AddCommand(CHANSERV, new CommandCSOInfo()); - ModuleManager::Attach(I_OnPostCommand, this); - ModuleManager::Attach(I_OnSaveDatabase, this); - ModuleManager::Attach(I_OnBackupDatabase, this); - - mLoadData(); - ModuleManager::Attach(I_OnReload, this); - const char* langtable_en_us[] = { /* OINFO_SYNTAX */ "Syntax: OINFO [ADD|DEL] nick <info>", @@ -427,8 +409,8 @@ class OSInfo : public Module this->InsertLanguage(LANG_RU, LANG_NUM_STRINGS, langtable_ru); this->InsertLanguage(LANG_IT, LANG_NUM_STRINGS, langtable_it); - Implementation i[] = { I_OnNickServHelp, I_OnChanServHelp }; - ModuleManager::Attach(i, this, 2); + Implementation i[] = { I_OnNickServHelp, I_OnChanServHelp, I_OnPostCommand, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; + ModuleManager::Attach(i, this, 5); } ~OSInfo() @@ -455,18 +437,6 @@ class OSInfo : public Module ci->Shrink("os_info"); } } - - if (OSInfoDBName) - delete [] OSInfoDBName; - } - - void OnReload(bool starting) - { - alog("os_info: Reloading configuration directives..."); - int ret = mLoadConfig(); - - if (ret) - alog("os_info.c: ERROR: An error has occured while reloading the configuration file"); } void OnPostCommand(User *u, const std::string &service, const ci::string &command, const std::vector<ci::string> ¶ms) @@ -508,52 +478,6 @@ class OSInfo : public Module } } - void OnSaveDatabase() - { - ChannelInfo *ci = NULL; - NickCore *nc = NULL; - int i = 0; - int ret = 0; - FILE *out; - - if (!(out = fopen(OSInfoDBName, "w"))) - { - alog("os_info: ERROR: can not open the database file!"); - ircdproto->SendGlobops(findbot(Config.s_OperServ), "os_info: ERROR: can not open the database file!"); - ret = 1; - } - else - { - for (i = 0; i < 1024; ++i) - { - for (nc = nclists[i]; nc; nc = nc->next) - { - /* If we have any info on this user */ - char *c; - if (nc->GetExtArray("os_info", c)) - fprintf(out, "N %s %s\n", nc->display, c); - } - } - - for (i = 0; i < 256; ++i) - { - for (ci = chanlists[i]; ci; ci = ci->next) - { - /* If we have any info on this channel */ - char *c; - if (ci->GetExtArray("os_info", c)) - fprintf(out, "C %s %s\n", ci->name, c); - } - } - fclose(out); - } - } - - void OnBackupDatabase() - { - ModuleDatabaseBackup(OSInfoDBName); - } - void OnNickServHelp(User *u) { this->NoticeLang(Config.s_NickServ, u, OINFO_HELP_CMD); @@ -563,91 +487,56 @@ class OSInfo : public Module { this->NoticeLang(Config.s_ChanServ, u, OCINFO_HELP_CMD); } -}; - -/*************************************************************************/ - -/** - * Load data from the db file, and populate our OperInfo lines - * @return 0 for success - **/ -int mLoadData() -{ - int ret = 0; - FILE *in; - - char *type = NULL; - char *name = NULL; - char *info = NULL; - int len = 0; - - ChannelInfo *ci = NULL; - NickAlias *na = NULL; - /* will _never_ be this big thanks to the 512 limit of a message */ - char buffer[2000]; - if (!(in = fopen(OSInfoDBName, "r"))) + void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), NickCore *nc) { - alog("os_info: WARNING: can not open the database file! (it might not exist, this is not fatal)"); - ret = 1; + char *c; + + if (nc->GetExtArray("os_info", c)) + { + std::string buf = ":"; + buf += c; + WriteMetadata("OS_INFO", buf.c_str()); + } } - else + + void OnDatabaseWriteMetadata(void (*WriteMetadata)(const std::string &, const std::string &), ChannelInfo *ci) { - while (fgets(buffer, 1500, in)) + char *c; + + if (ci->GetExtArray("os_info", c)) { - type = myStrGetToken(buffer, ' ', 0); - name = myStrGetToken(buffer, ' ', 1); - info = myStrGetTokenRemainder(buffer, ' ', 2); - if (type) - { - if (name) - { - if (info) - { - len = strlen(info); - /* Take the \n from the end of the line */ - info[len - 1] = '\0'; - if (!stricmp(type, "C")) - { - if ((ci = cs_findchan(name))) - ci->Extend("os_info", new ExtensibleItemPointerArray<char>(sstrdup(info))); - } - else if (!stricmp(type, "N")) - { - if ((na = findnick(name))) - na->nc->Extend("os_info", new ExtensibleItemPointerArray<char>(sstrdup(info))); - } - delete [] info; - } - delete [] name; - } - delete [] type; - } + std::string buf = ":"; + buf += c; + WriteMetadata("OS_INFO", buf.c_str()); } } - return ret; -} - -/** - * Load the configuration directives from Services configuration file. - * @return 0 for success - **/ -int mLoadConfig() -{ - ConfigReader config; - std::string tmp = config.ReadValue("os_info", "database", DEFAULT_DB_NAME, 0); - if (OSInfoDBName) - delete [] OSInfoDBName; - - OSInfoDBName = sstrdup(tmp.c_str()); + EventReturn OnDatabaseReadMetadata(NickCore *nc, const std::string &key, const std::vector<std::string> ¶ms) + { + if (key == "OS_INFO") + { + nc->Shrink("os_info"); + nc->Extend("os_info", new ExtensibleItemPointerArray<char>(sstrdup(params[0].c_str()))); /// We really should use std::string here... - alog("os_info: Directive OSInfoDBName loaded (%s)...", OSInfoDBName); + return EVENT_STOP; + } - return 0; -} + return EVENT_CONTINUE; + } + EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const std::string &key, const std::vector<std::string> ¶ms) + { + if (key == "OS_INFO") + { + ci->Shrink("os_info"); + ci->Extend("os_info", new ExtensibleItemPointerArray<char>(sstrdup(params[0].c_str()))); + + return EVENT_STOP; + } -/*************************************************************************/ + return EVENT_CONTINUE; + } +}; MODULE_INIT(OSInfo) diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 9f5c51c8e..bbb63a13e 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -34,16 +34,13 @@ ChannelInfo::ChannelInfo(const std::string &chname) capsmin = capspercent = 0; floodlines = floodsecs = 0; repeattimes = 0; + bi = NULL; strscpy(this->name, chname.c_str(), CHANMAX); - /* If ircd doesn't exist, this is from DB load and mlock is set later */ - if (ircd) - { - mlock_on = DefMLockOn; - mlock_off = DefMLockOff; - Params = DefMLockParams; - } + mlock_on = DefMLockOn; + mlock_off = DefMLockOff; + Params = DefMLockParams; size_t t; /* Set default channel flags */ diff --git a/src/tools/db-convert.c b/src/tools/db-convert.c index 790588cfb..fbef58eed 100644 --- a/src/tools/db-convert.c +++ b/src/tools/db-convert.c @@ -297,26 +297,6 @@ int main(int argc, char *argv[]) na->nc = findcore(s, 0); na->nc->aliascount++; free(s); - - if (!na->nc->last_quit && quit) - na->nc->last_quit = strdup(quit); - if (!na->nc->last_realname && real) - na->nc->last_realname = strdup(real); - if (!na->nc->last_usermask && mask) - na->nc->last_usermask = strdup(mask); - - // Convert nick NOEXPIRE to group NOEXPIRE - if (na->status & 0x0004) - { - na->nc->flags |= 0x00100000; - } - - // Convert nick FORBIDDEN to group FORBIDDEN - if (na->status & 0x0002) - { - na->nc->flags |= 0x80000000; - } - free(mask); free(real); free(quit); @@ -370,10 +350,12 @@ int main(int argc, char *argv[]) // Enc pass b64_encode(nc->pass, hashm == "plain" ? strlen(nc->pass) : 32, (char *)cpass, 5000); - fs << "NC " << nc->display << " " << hashm << ":" << cpass << " " << nc->email; + fs << "NC " << nc->display << " " << hashm << ":" << cpass << " "; fs << " " << GetLanguageID(nc->language) << " " << nc->memos.memomax << " " << nc->channelcount << std::endl; std::cout << "Wrote account for " << nc->display << " passlen " << strlen(cpass) << std::endl; + if (nc->email) + fs << "MD EMAIL " << nc->email << std::endl; if (nc->greet) fs << "MD GREET :" << nc->greet << std::endl; if (nc->icq) @@ -404,13 +386,21 @@ int main(int argc, char *argv[]) << ((nc->flags & NI_HIDE_STATUS ) ? "HIDE_STATUS " : "") << ((nc->flags & NI_SUSPENDED ) ? "SUSPENDED " : "") << ((nc->flags & NI_AUTOOP ) ? "AUTOOP " : "") - << ((nc->flags & NI_NOEXPIRE ) ? "NOEXPIRE " : "") << ((nc->flags & NI_FORBIDDEN ) ? "FORBIDDEN " : "") << std::endl; if (nc->memos.memocount) { memos = nc->memos.memos; for (j = 0; j < nc->memos.memocount; j++, memos++) - fs << "MD MI " << memos->number << " " << memos->flags << " " << memos->time << " " << memos->sender << " :" << memos->text << std::endl; + { + fs << "MD MI " << memos->number << " " << memos->time << " " << memos->sender; + if (memos->flags & MF_UNREAD) + fs << " UNREAD"; + if (memos->flags & MF_RECEIPT) + fs << " RECEIPT"; + if (memos->flags & MF_NOTIFYS) + fs << " NOTIFYS"; + fs << " :" << memos->text << std::endl; + } } /* we could do this in a seperate loop, I'm doing it here for tidiness. */ @@ -430,12 +420,12 @@ int main(int argc, char *argv[]) std::cout << "Writing: " << na->nc->display << "'s nick: " << na->nick << std::endl; fs << "NA " << na->nc->display << " " << na->nick << " " << na->time_registered << " " << na->last_seen << std::endl; - if (nc->last_usermask) - fs << "MD LAST_USERMASK " << nc->last_usermask << std::endl; - if (nc->last_realname) - fs << "MD LAST_REALNAME :" << nc->last_realname << std::endl; - if (nc->last_quit) - fs << "MD LAST_QUIT :" << nc->last_quit << std::endl; + if (na->last_usermask) + fs << "MD LAST_USERMASK " << na->last_usermask << std::endl; + if (na->last_realname) + fs << "MD LAST_REALNAME :" << na->last_realname << std::endl; + if (na->last_quit) + fs << "MD LAST_QUIT :" << na->last_quit << std::endl; if ((na->status & NS_FORBIDDEN) || (na->status & NS_NO_EXPIRE)) { fs << "MD FLAGS" @@ -728,10 +718,9 @@ int main(int argc, char *argv[]) } *last = NULL; } - } - - close_db(f); + close_db(f); + } ChannelInfo *ci; @@ -762,7 +751,7 @@ int main(int argc, char *argv[]) << ((ci->flags & CI_PEACE ) ? " PEACE" : "") << ((ci->flags & CI_SECURE ) ? " SECURE" : "") << ((ci->flags & CI_FORBIDDEN ) ? " FORBIDDEN" : "") - << ((ci->flags & CI_NO_EXPIRE ) ? " NOEXPIRE" : "") + << ((ci->flags & CI_NO_EXPIRE ) ? " NO_EXPIRE" : "") << ((ci->flags & CI_MEMO_HARDMAX ) ? " MEMO_HARDMAX" : "") << ((ci->flags & CI_OPNOTICE ) ? " OPNOTICE" : "") << ((ci->flags & CI_SECUREFOUNDER ) ? " SECUREFOUNDER" : "") @@ -782,7 +771,7 @@ int main(int argc, char *argv[]) fs << "MD FORBID " << ci->forbidby << " :" << ci->forbidreason << std::endl; for (j = 0; j < ci->accesscount; j++) - { // MD CH access <display> <level> <last_seen> <creator> - creator isn't in 1.9.0-1, but is in 1.9.2 + { // MD ACCESS <display> <level> <last_seen> <creator> - creator isn't in 1.9.0-1, but is in 1.9.2 if (ci->access[j].in_use) fs << "MD ACCESS " << ci->access[j].nc->display << " " << ci->access[j].level << " " @@ -790,14 +779,18 @@ int main(int argc, char *argv[]) } for (j = 0; j < ci->akickcount; j++) - { // MD CH akick <USED/NOTUSED> <STUCK/UNSTUCK> <NICK/MASK> <akick> <creator> <addtime> :<reason> - fs << "MD AKICK " - << ((ci->akick[j].flags & AK_USED) ? "USED " : "NOTUSED ") - << ((ci->akick[j].flags & AK_STUCK) ? "STUCK " : "UNSTUCK " ) - << ((ci->akick[j].flags & AK_ISNICK) ? "NICK " : "MASK ") - << ((ci->akick[j].flags & AK_ISNICK) ? ci->akick[j].u.nc->display : ci->akick[j].u.mask ) - << " " << ci->akick[j].creator << " " << ci->akick[j].addtime << " :" << ci->akick[j].reason - << std::endl; + { // MD AKICK <STUCK/UNSTUCK> <NICK/MASK> <akick> <creator> <addtime> :<reason> + if (ci->akick[j].flags & 0x0001) + { + fs << "MD AKICK " + << ((ci->akick[j].flags & AK_STUCK) ? "STUCK " : "UNSTUCK " ) + << ((ci->akick[j].flags & AK_ISNICK) ? "NICK " : "MASK ") + << ((ci->akick[j].flags & AK_ISNICK) ? ci->akick[j].u.nc->display : ci->akick[j].u.mask ) + << " " << ci->akick[j].creator << " " << ci->akick[j].addtime << " :"; + if (ci->akick[j].reason) + fs << ci->akick[j].reason; + fs << std::endl; + } } if (ci->mlock_on) @@ -816,13 +809,13 @@ int main(int argc, char *argv[]) { fs << "MD MLP"; if (ci->mlock_limit) - fs << " LIMIT" << ci->mlock_limit; + fs << " CMODE_LIMIT " << ci->mlock_limit; if (ci->mlock_key) - fs << " KEY" << ci->mlock_key; + fs << " CMODE_KEY " << ci->mlock_key; if (ci->mlock_flood) - fs << " FLOOD" << ci->mlock_flood; + fs << " CMODE_FLOOD " << ci->mlock_flood; if (ci->mlock_redirect) - fs << " REDIRECT" << ci->mlock_redirect; + fs << " CMODE_REDIRECT " << ci->mlock_redirect; fs << std::endl; } if (ci->memos.memocount) @@ -831,8 +824,14 @@ int main(int argc, char *argv[]) memos = ci->memos.memos; for (j = 0; j < ci->memos.memocount; j++, memos++) { - fs << "MD MI " << memos->number << " " << memos->flags << " " - << memos->time << " " << memos->sender << " :" << memos->text << std::endl; + fs << "MD MI " << memos->number << " " << memos->time << " " << memos->sender; + if (memos->flags & MF_UNREAD) + fs << " UNREAD"; + if (memos->flags & MF_RECEIPT) + fs << " RECEIPT"; + if (memos->flags & MF_NOTIFYS) + fs << " NOTIFYS"; + fs << " :" << memos->text << std::endl; } } @@ -878,12 +877,15 @@ int main(int argc, char *argv[]) fs << "MD BI REPEATTIMES " << ci->repeattimes << std::endl; for (j = 0; j < ci->bwcount; j++) { - fs << "MD BI BADWORD " - << (( ci->badwords[j].type == 0 ) ? "ANY " : "" ) - << (( ci->badwords[j].type == 1 ) ? "SINGLE " : "" ) - << (( ci->badwords[j].type == 3 ) ? "START " : "" ) - << (( ci->badwords[j].type == 4 ) ? "END " : "" ) - << ":" << ci->badwords[j].word << std::endl; + if (ci->badwords[j].in_use) + { + fs << "MD BI BADWORD " + << (( ci->badwords[j].type == 0 ) ? "ANY " : "" ) + << (( ci->badwords[j].type == 1 ) ? "SINGLE " : "" ) + << (( ci->badwords[j].type == 3 ) ? "START " : "" ) + << (( ci->badwords[j].type == 4 ) ? "END " : "" ) + << ":" << ci->badwords[j].word << std::endl; + } } } /* for (chanlists[i]) */ diff --git a/src/tools/db-convert.h b/src/tools/db-convert.h index 27fd636b5..6ffcdffdb 100644 --- a/src/tools/db-convert.h +++ b/src/tools/db-convert.h @@ -116,6 +116,10 @@ struct nickalias_ { time_t last_seen; /* When it was seen online for the last time */ uint16 status; /* See NS_* below */ NickCore *nc; /* I'm an alias of this */ + + char *last_usermask; + char *last_realname; + char *last_quit; }; struct nickcore_ { @@ -136,9 +140,6 @@ struct nickcore_ { int unused; /* Used for nick collisions */ int aliascount; /* How many aliases link to us? Remove the core if 0 */ - char *last_quit; /* Last quit message */ - char *last_realname; /* Last realname */ - char *last_usermask; /* Last usermask */ }; struct chaninfo_ { @@ -694,6 +695,12 @@ int delnick(NickAlias *na, int donttouchthelist) nalists[HASH(na->nick)] = na->next; } + if (na->last_usermask) + free(na->last_usermask); + if (na->last_realname) + free(na->last_realname); + if (na->last_quit) + free(na->last_quit); /* free() us */ free(na->nick); free(na); @@ -720,12 +727,6 @@ int delcore(NickCore *nc) free(nc->greet); if (nc->url) free(nc->url); - if (nc->last_usermask) - free(nc->last_usermask); - if (nc->last_realname) - free(nc->last_realname); - if (nc->last_quit) - free(nc->last_quit); if (nc->access) { for (i = 0; i < nc->accesscount; i++) { if (nc->access[i]) diff --git a/src/users.c b/src/users.c index 96c95bbfb..02112c7cf 100644 --- a/src/users.c +++ b/src/users.c @@ -921,11 +921,7 @@ User *do_nick(const char *source, const char *nick, const char *username, const else { ntmp->last_seen = time(NULL); - - if (ntmp->last_usermask) - delete [] ntmp->last_usermask; - std::string last_usermask = user->GetIdent() + "@" + user->GetDisplayedHost(); - ntmp->last_usermask = sstrdup(last_usermask.c_str()); + user->UpdateHost(); ircdproto->SetAutoIdentificationToken(user); alog("%s: %s!%s@%s automatically identified for nick %s", Config.s_NickServ, user->nick, user->GetIdent().c_str(), user->host, user->nick); } |