summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes.conf11
-rw-r--r--data/example.conf90
-rw-r--r--include/Makefile2
-rw-r--r--include/account.h4
-rw-r--r--include/config.h3
-rw-r--r--include/configreader.h18
-rw-r--r--include/datafiles.h25
-rw-r--r--include/extern.h2
-rw-r--r--include/modules.h105
-rw-r--r--include/pseudo.h1
-rw-r--r--src/Makefile5
-rw-r--r--src/chanserv.c7
-rw-r--r--src/config.c34
-rw-r--r--src/core/db_plain.cpp1148
-rw-r--r--src/core/ns_forbid.c4
-rw-r--r--src/core/ns_identify.c3
-rw-r--r--src/core/os_ignore.c58
-rw-r--r--src/core/os_modlist.c25
-rw-r--r--src/core/os_news.c42
-rw-r--r--src/datafiles.c203
-rw-r--r--src/init.c12
-rw-r--r--src/main.c4
-rw-r--r--src/modulemanager.cpp6
-rw-r--r--src/modules/hs_request.c150
-rw-r--r--src/modules/os_ignore_db.c490
-rw-r--r--src/modules/os_info.c193
-rw-r--r--src/regchannel.cpp11
-rw-r--r--src/tools/db-convert.c110
-rw-r--r--src/tools/db-convert.h19
-rw-r--r--src/users.c6
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> &params) { 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> &params) { 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> &params) { 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> &params) { 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> &params) { 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> &params)
+{
+ 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> &params)
+{
+ 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> &params)
+{
+ 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> &params)
+{
+ 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> &params)
+{
+ 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> &params)
+{
+ 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> &params)
+ {
+ 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> &params)
+ {
+ 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> &params)
+ {
+ 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> &params)
+ {
+ 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> &params)
+ {
+ 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> &params)
+ {
+ 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> &params)
{
+ 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> &params)
@@ -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> &params)
+ {
+ 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> &params)
@@ -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> &params)
+ {
+ 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> &params)
+ {
+ 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);
}