From 1f2399de364c09adcce4193895cd362d80ffdfc5 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 25 Sep 2011 04:19:15 -0400 Subject: Added a new database format and sqlite support. Also moved db-convert to a module. --- data/CMakeLists.txt | 2 +- data/example.conf | 77 +- data/modules.example.conf | 20 +- data/tables.sql | 426 --------- include/access.h | 3 + include/account.h | 14 +- include/bots.h | 5 +- include/extensible.h | 160 +--- include/hashcomp.h | 24 - include/modules.h | 91 +- include/oper.h | 8 +- include/regchannel.h | 49 +- include/serialize.h | 160 ++++ include/services.h | 83 +- modules/commands/bs_kick.cpp | 123 ++- modules/commands/cs_access.cpp | 42 +- modules/commands/cs_entrymsg.cpp | 128 +-- modules/commands/cs_flags.cpp | 39 +- modules/commands/cs_info.cpp | 7 +- modules/commands/cs_seen.cpp | 151 ++- modules/commands/cs_set_misc.cpp | 69 +- modules/commands/cs_suspend.cpp | 11 +- modules/commands/cs_xop.cpp | 38 +- modules/commands/hs_request.cpp | 165 ++-- modules/commands/ns_ajoin.cpp | 164 ++-- modules/commands/ns_register.cpp | 19 +- modules/commands/ns_resetpass.cpp | 29 +- modules/commands/ns_set_email.cpp | 12 +- modules/commands/ns_set_misc.cpp | 70 +- modules/commands/os_forbid.cpp | 45 +- modules/commands/os_forbid.h | 40 +- modules/commands/os_ignore.cpp | 52 +- modules/commands/os_ignore.h | 32 +- modules/commands/os_login.cpp | 6 +- modules/commands/os_module.cpp | 14 - modules/commands/os_news.cpp | 48 +- modules/commands/os_news.h | 36 +- modules/commands/os_oper.cpp | 64 +- modules/commands/os_session.cpp | 70 +- modules/commands/os_session.h | 46 + modules/commands/os_shutdown.cpp | 4 +- modules/database/db_flatfile.cpp | 191 ++++ modules/database/db_mysql.cpp | 1568 ------------------------------- modules/database/db_mysql_live.cpp | 222 ----- modules/database/db_old.cpp | 1021 ++++++++++++++++++++ modules/database/db_plain.cpp | 706 +++++++------- modules/database/db_sql.cpp | 169 ++++ modules/database/db_sql_live_read.cpp | 434 +++++++++ modules/database/db_sql_live_write.cpp | 247 +++++ modules/extra/m_dnsbl.cpp | 4 +- modules/extra/m_ldap_authentication.cpp | 8 +- modules/extra/m_mysql.cpp | 55 +- modules/extra/m_sqlite.cpp | 235 +++++ modules/extra/sql.h | 2 + modules/protocol/inspircd11.cpp | 7 +- modules/pseudoclients/memoserv.cpp | 1 + modules/pseudoclients/operserv.cpp | 13 + src/access.cpp | 1 - src/base.cpp | 16 + src/bin/CMakeLists.txt | 2 +- src/bin/cp-recursive | 21 - src/bin/langtool | 239 ----- src/bin/mydbgen | 148 --- src/bots.cpp | 23 + src/hostserv.cpp | 2 +- src/init.cpp | 4 +- src/main.cpp | 1 + src/memoserv.cpp | 32 + src/misc.cpp | 13 + src/modes.cpp | 2 +- src/nickalias.cpp | 44 + src/nickcore.cpp | 51 + src/operserv.cpp | 41 +- src/regchannel.cpp | 221 ++++- src/tools/db-convert.cpp | 1032 -------------------- src/tools/db-convert.h | 975 ------------------- 76 files changed, 4330 insertions(+), 6067 deletions(-) delete mode 100644 data/tables.sql create mode 100644 include/serialize.h create mode 100644 modules/database/db_flatfile.cpp delete mode 100644 modules/database/db_mysql.cpp delete mode 100644 modules/database/db_mysql_live.cpp create mode 100644 modules/database/db_old.cpp create mode 100644 modules/database/db_sql.cpp create mode 100644 modules/database/db_sql_live_read.cpp create mode 100644 modules/database/db_sql_live_write.cpp create mode 100644 modules/extra/m_sqlite.cpp delete mode 100755 src/bin/cp-recursive delete mode 100755 src/bin/langtool delete mode 100755 src/bin/mydbgen delete mode 100644 src/tools/db-convert.cpp delete mode 100644 src/tools/db-convert.h diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index a9f27a5f8..94aa3d8ca 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,6 +1,6 @@ # Only install example.chk and example.conf from this directory # NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file) -set(DATA example.chk tables.sql botserv.example.conf example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf) +set(DATA example.chk botserv.example.conf example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf) install(FILES ${DATA} DESTINATION data ) diff --git a/data/example.conf b/data/example.conf index b9a37a275..b29e56280 100644 --- a/data/example.conf +++ b/data/example.conf @@ -1032,11 +1032,29 @@ dns */ /* - * db_plain + * [DEPRECATED] db_old * - * This is the default flatfile database format. + * This is the old binary database format from late Anope 1.7.x, Anope 1.8.x, and + * early Anope 1.9.x. This module only loads these databases, and will NOT save them. + * You should only use this to upgrade old databases to a newer database format by loading + * other database modules in addition to this one, which will be used when saving databases. + */ +#module { name = "db_old" } +db_old +{ + /* + * This is the encryption type used by the databases. This must be set correctly or + * your passwords will not work. Valid options are: md5, oldmd5, sha1, and plain. + */ + #hash = "md5" +} + +/* + * [DEPRECATED] db_plain + * + * This is the flatfile database format from Anope-1.9.2 to Anope-1.9.5. */ -module { name = "db_plain" } +#module { name = "db_plain" } db_plain { /* @@ -1046,25 +1064,52 @@ db_plain } /* - * db_mysql and db_mysql_live + * db_flatfile + * + * This is the default flatfile database format. + */ +module { name = "db_flatfile" } +db_flatfile +{ + /* + * The database name db_flatfile should use + */ + database = "anope.db" +} + +/* + * db_sql + * + * This module allows saving and loading databases using one of the SQL engines. + */ +#module { name = "db_sql" } +db_sql +{ + /* + * The SQL service db_sql should use, these are configured in modules.conf. + * For MySQL, this should probably be mysql/main. + */ + engine = "sqlite/main" +} + +/* + * db_sql_live_read, db_sql_live_write * - * Enables (live) MySQL support. + * Enables (live) SQL support. * - * The db_mysql_live module is an extension to db_mysql, and should only be used if - * db_mysql is being used. This module pulls data in real time from SQL as it is - * requested by the core as a result of someone executing commands. + * The db_sql_live modules are an extension to db_sql, and should only be used if + * db_sql is being used. * - * This effectively allows you to edit your database and have it be immediately - * reflected back in Anope. + * The db_sql_live_read module pulls data in real time from + * SQL as it is needed by the core. + * At this time this three main tables: ChannelInfo, NickAlias, and NickCore. * - * At this time db_mysql_live only supports pulling data in real time from the three - * main tables: anope_cs_info, anope_ns_alias, and anope_ns_core. + * The db_sql_live_write module writes data to SQL in real time as it is modified by + * the core. * - * db_mysql provides the command operserv/sqlsync, which is used for importing other database - * methods into MySQL. */ -#module { name = "db_mysql" } -#module { name = "db_mysql_live" } +#module { name = "db_sql_live_read" } +#module { name = "db_sql_live_write" } /* * [REQUIRED] Encryption modules. diff --git a/data/modules.example.conf b/data/modules.example.conf index 74c8bff5d..e03761fb2 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -197,13 +197,13 @@ m_ldap_oper /* * m_mysql * - * This module allows other modules (db_mysql/db_mysql_live) to use MySQL. - * Be sure you have imported the table schema with mydbgen before - * trying to use MySQL + * This module allows other modules to use MySQL. */ #module { name = "m_mysql" } mysql { + /* The name of this service */ + name = "mysql/main" database = "anope" server = "127.0.0.1" username = "anope" @@ -296,6 +296,20 @@ proxyscan reason = "You have an open proxy running on your host (%t:%i:%p)" } +/* + * m_sqlite + * + * This module allows other modules to use SQLite. + */ +#module { name = "m_sqlite" } +sqlite +{ + /* The name of this service */ + name = "sqlite/main" + /* The database name, it will be created if it does not exist. */ + database = "anope.db" +} + /* * m_ssl * diff --git a/data/tables.sql b/data/tables.sql deleted file mode 100644 index ec99b7479..000000000 --- a/data/tables.sql +++ /dev/null @@ -1,426 +0,0 @@ --- phpMyAdmin SQL Dump --- version 3.3.5 --- http://www.phpmyadmin.net --- --- Host: localhost --- Generation Time: Aug 07, 2011 at 03:53 PM --- Server version: 5.1.50 --- PHP Version: 5.3.6-pl0-gentoo - -SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; - --- --- Database: `anope` --- - --- -------------------------------------------------------- - --- --- Table structure for table `anope_bs_badwords` --- - -CREATE TABLE IF NOT EXISTS `anope_bs_badwords` ( - `channel` varchar(255) NOT NULL DEFAULT '', - `word` varchar(255) NOT NULL, - `type` varchar(50) NOT NULL, - UNIQUE KEY `channel` (`channel`,`word`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_bs_core` --- - -CREATE TABLE IF NOT EXISTS `anope_bs_core` ( - `nick` varchar(255) NOT NULL DEFAULT '', - `user` varchar(255) NOT NULL DEFAULT '', - `host` text NOT NULL, - `rname` text NOT NULL, - `flags` text NOT NULL, - `created` int(10) unsigned NOT NULL DEFAULT '0', - `chancount` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`nick`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_bs_info_metadata` --- - -CREATE TABLE IF NOT EXISTS `anope_bs_info_metadata` ( - `botname` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `value` text NOT NULL, - KEY `FK_anope_bs_info_metadata_botname` (`botname`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_access` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_access` ( - `provider` varchar(255) NOT NULL DEFAULT '', - `data` varchar(255) NOT NULL DEFAULT '', - `mask` varchar(255) NOT NULL DEFAULT '', - `channel` varchar(255) NOT NULL DEFAULT '', - `last_seen` int(10) unsigned NOT NULL DEFAULT '0', - `creator` varchar(255) NOT NULL DEFAULT '', - `created` int(11) unsigned NOT NULL DEFAULT '0', - UNIQUE KEY `channel` (`channel`,`mask`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_akick` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_akick` ( - `channel` varchar(255) NOT NULL DEFAULT '', - `flags` varchar(255) NOT NULL DEFAULT '', - `mask` varchar(255) NOT NULL DEFAULT '', - `reason` text NOT NULL, - `creator` varchar(255) NOT NULL DEFAULT '', - `created` int(10) unsigned NOT NULL DEFAULT '0', - `last_used` int(10) unsigned NOT NULL DEFAULT '0', - UNIQUE KEY `channel` (`channel`,`mask`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_info` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_info` ( - `name` varchar(255) NOT NULL DEFAULT '', - `founder` text NOT NULL, - `successor` text NOT NULL, - `descr` text NOT NULL, - `time_registered` int(10) unsigned NOT NULL DEFAULT '0', - `last_used` int(10) unsigned NOT NULL DEFAULT '0', - `last_topic` text NOT NULL, - `last_topic_setter` text NOT NULL, - `last_topic_time` int(10) unsigned NOT NULL DEFAULT '0', - `flags` text NOT NULL, - `bantype` smallint(6) NOT NULL DEFAULT '0', - `memomax` smallint(5) unsigned NOT NULL DEFAULT '0', - `botnick` varchar(255) NOT NULL DEFAULT '', - `botflags` text NOT NULL, - `capsmin` smallint(6) NOT NULL DEFAULT '0', - `capspercent` smallint(6) NOT NULL DEFAULT '0', - `floodlines` smallint(6) NOT NULL DEFAULT '0', - `floodsecs` smallint(6) NOT NULL DEFAULT '0', - `repeattimes` smallint(6) NOT NULL DEFAULT '0', - PRIMARY KEY (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_info_metadata` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_info_metadata` ( - `channel` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `value` text NOT NULL, - KEY `FK_anope_cs_info_metadata_channel` (`channel`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_levels` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_levels` ( - `channel` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `level` int(11) NOT NULL DEFAULT '0', - UNIQUE KEY `channel` (`channel`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_mlock` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_mlock` ( - `channel` varchar(255) NOT NULL, - `mode` varchar(127) NOT NULL, - `status` int(11) NOT NULL, - `setter` varchar(255) NOT NULL, - `created` int(11) NOT NULL, - `param` varchar(255) NOT NULL, - UNIQUE KEY `entry` (`channel`,`mode`,`status`,`setter`,`param`), - KEY `FK_anope_cs_mlock` (`channel`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_cs_ttb` --- - -CREATE TABLE IF NOT EXISTS `anope_cs_ttb` ( - `channel` varchar(255) NOT NULL DEFAULT '', - `ttb_id` int(11) NOT NULL DEFAULT '0', - `value` int(11) NOT NULL DEFAULT '0', - UNIQUE KEY `channel` (`channel`,`ttb_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_extra` --- - -CREATE TABLE IF NOT EXISTS `anope_extra` ( - `data` text NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_hs_core` --- - -CREATE TABLE IF NOT EXISTS `anope_hs_core` ( - `nick` varchar(255) NOT NULL, - `vident` varchar(64) NOT NULL, - `vhost` varchar(255) NOT NULL, - `creator` varchar(255) NOT NULL, - `time` int(11) NOT NULL, - KEY `FK_anope_hs_core_nick` (`nick`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_info` --- - -CREATE TABLE IF NOT EXISTS `anope_info` ( - `version` int(11) DEFAULT NULL, - `date` datetime DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ms_info` --- - -CREATE TABLE IF NOT EXISTS `anope_ms_info` ( - `receiver` varchar(255) NOT NULL, - `flags` int(11) NOT NULL DEFAULT '0', - `time` int(10) unsigned NOT NULL DEFAULT '0', - `sender` text NOT NULL, - `text` blob NOT NULL, - `serv` enum('NICK','CHAN') NOT NULL DEFAULT 'NICK', - KEY `FK_anope_ms_info_receiver` (`receiver`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ns_access` --- - -CREATE TABLE IF NOT EXISTS `anope_ns_access` ( - `display` varchar(255) NOT NULL DEFAULT '', - `access` varchar(160) NOT NULL, - KEY `FK_anope_ns_access_display` (`display`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ns_alias` --- - -CREATE TABLE IF NOT EXISTS `anope_ns_alias` ( - `nick` varchar(255) NOT NULL DEFAULT '', - `last_quit` text NOT NULL, - `last_realname` text NOT NULL, - `last_usermask` text NOT NULL, - `last_realhost` text NOT NULL, - `time_registered` int(10) unsigned NOT NULL DEFAULT '0', - `last_seen` int(10) unsigned NOT NULL DEFAULT '0', - `flags` text NOT NULL, - `display` varchar(255) NOT NULL DEFAULT '', - PRIMARY KEY (`nick`), - KEY `FK_anope_ns_alias_display` (`display`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ns_alias_metadata` --- - -CREATE TABLE IF NOT EXISTS `anope_ns_alias_metadata` ( - `nick` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `value` text NOT NULL, - KEY `FK_anope_ns_alias_metadata_nick` (`nick`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ns_core` --- - -CREATE TABLE IF NOT EXISTS `anope_ns_core` ( - `display` varchar(255) NOT NULL DEFAULT '', - `pass` text NOT NULL, - `email` text NOT NULL, - `greet` text NOT NULL, - `flags` text NOT NULL, - `language` varchar(5) NOT NULL DEFAULT '', - `memomax` smallint(5) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`display`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_ns_core_metadata` --- - -CREATE TABLE IF NOT EXISTS `anope_ns_core_metadata` ( - `nick` varchar(255) NOT NULL DEFAULT '', - `name` varchar(255) NOT NULL DEFAULT '', - `value` text NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_os_core` --- - -CREATE TABLE IF NOT EXISTS `anope_os_core` ( - `maxusercnt` int(11) NOT NULL DEFAULT '0', - `maxusertime` int(10) unsigned NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_os_exceptions` --- - -CREATE TABLE IF NOT EXISTS `anope_os_exceptions` ( - `mask` varchar(255) NOT NULL, - `slimit` int(11) NOT NULL DEFAULT '0', - `who` text NOT NULL, - `reason` text NOT NULL, - `time` int(10) unsigned NOT NULL DEFAULT '0', - `expires` int(10) unsigned NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Table structure for table `anope_os_xlines` --- - -CREATE TABLE IF NOT EXISTS `anope_os_xlines` ( - `type` varchar(1) NOT NULL, - `mask` varchar(255) NOT NULL, - `xby` text NOT NULL, - `reason` text NOT NULL, - `seton` int(10) unsigned NOT NULL DEFAULT '0', - `expire` int(10) unsigned NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- --- Constraints for dumped tables --- - --- --- Constraints for table `anope_bs_badwords` --- -ALTER TABLE `anope_bs_badwords` - ADD CONSTRAINT `FK_anope_bs_badwords_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_bs_info_metadata` --- -ALTER TABLE `anope_bs_info_metadata` - ADD CONSTRAINT `FK_anope_bs_info_metadata_botname` FOREIGN KEY (`botname`) REFERENCES `anope_bs_core` (`nick`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_access` --- -ALTER TABLE `anope_cs_access` - ADD CONSTRAINT `FK_anope_cs_access_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_akick` --- -ALTER TABLE `anope_cs_akick` - ADD CONSTRAINT `FK_anope_cs_akick_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_info_metadata` --- -ALTER TABLE `anope_cs_info_metadata` - ADD CONSTRAINT `FK_anope_cs_info_metadata_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_levels` --- -ALTER TABLE `anope_cs_levels` - ADD CONSTRAINT `FK_anope_cs_levels_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_mlock` --- -ALTER TABLE `anope_cs_mlock` - ADD CONSTRAINT `FK_anope_cs_mlock_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_cs_ttb` --- -ALTER TABLE `anope_cs_ttb` - ADD CONSTRAINT `FK_anope_cs_ttb_channel` FOREIGN KEY (`channel`) REFERENCES `anope_cs_info` (`name`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_hs_core` --- -ALTER TABLE `anope_hs_core` - ADD CONSTRAINT `FK_anope_hs_core_nick` FOREIGN KEY (`nick`) REFERENCES `anope_ns_alias` (`nick`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_ms_info` --- -ALTER TABLE `anope_ms_info` - ADD CONSTRAINT `FK_anope_ms_info_receiver` FOREIGN KEY (`receiver`) REFERENCES `anope_ns_alias` (`nick`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_ns_access` --- -ALTER TABLE `anope_ns_access` - ADD CONSTRAINT `FK_anope_ns_access_display` FOREIGN KEY (`display`) REFERENCES `anope_ns_core` (`display`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_ns_alias` --- -ALTER TABLE `anope_ns_alias` - ADD CONSTRAINT `FK_anope_ns_alias_display` FOREIGN KEY (`display`) REFERENCES `anope_ns_core` (`display`) ON DELETE CASCADE ON UPDATE CASCADE; - --- --- Constraints for table `anope_ns_alias_metadata` --- -ALTER TABLE `anope_ns_alias_metadata` - ADD CONSTRAINT `FK_anope_ns_alias_metadata_nick` FOREIGN KEY (`nick`) REFERENCES `anope_ns_alias` (`nick`) ON DELETE CASCADE ON UPDATE CASCADE; - diff --git a/include/access.h b/include/access.h index 229a16f4b..d86539d8f 100644 --- a/include/access.h +++ b/include/access.h @@ -41,6 +41,9 @@ class CoreExport ChanAccess time_t last_seen; time_t created; + virtual Anope::string serialize_name() = 0; + virtual SerializableBase::serialized_data serialize() = 0; + ChanAccess(AccessProvider *p); virtual ~ChanAccess(); virtual bool Matches(User *u, NickCore *nc) = 0; diff --git a/include/account.h b/include/account.h index 6c6295f5c..3cfb803f8 100644 --- a/include/account.h +++ b/include/account.h @@ -93,9 +93,7 @@ const Anope::string NickCoreFlagStrings[] = { "MEMO_MAIL", "HIDE_STATUS", "SUSPENDED", "AUTOOP", "FORBIDDEN", "UNCONFIRMED", "" }; -class NickCore; - -class CoreExport NickAlias : public Extensible, public Flags +class CoreExport NickAlias : public Extensible, public Flags, public Serializable { public: /** Default constructor @@ -118,6 +116,9 @@ class CoreExport NickAlias : public Extensible, public Flags +class CoreExport NickCore : public Extensible, public Flags, public Serializable { public: /** Default constructor @@ -153,14 +154,17 @@ class CoreExport NickCore : public Extensible, public Flags access; /* Access list, vector of strings */ std::vector cert; /* ssl certificate list, vector of strings */ MemoInfo memos; - uint16 channelcount; /* Number of channels currently registered */ Oper *o; /* Unsaved data */ + uint16 channelcount; /* Number of channels currently registered */ time_t lastmail; /* Last time this nick record got a mail */ std::list aliases; /* List of aliases */ + serialized_data serialize(); + static void unserialize(serialized_data &); + /** Checks whether this account is a services oper or not. * @return True if this account is a services oper, false otherwise. */ diff --git a/include/bots.h b/include/bots.h index 20daeddcf..c23a354fc 100644 --- a/include/bots.h +++ b/include/bots.h @@ -32,7 +32,7 @@ enum BotFlag static const Anope::string BotFlagString[] = { "BEGIN", "CORE", "PRIVATE", "CONF", "" }; -class CoreExport BotInfo : public User, public Flags +class CoreExport BotInfo : public User, public Flags, public Serializable { public: uint32 chancount; @@ -57,6 +57,9 @@ class CoreExport BotInfo : public User, public Flags */ virtual ~BotInfo(); + serialized_data serialize(); + static void unserialize(serialized_data &); + void GenerateUID(); /** Change the nickname for the bot. diff --git a/include/extensible.h b/include/extensible.h index 2d7fb5509..c5de2dae4 100644 --- a/include/extensible.h +++ b/include/extensible.h @@ -7,61 +7,28 @@ #ifndef EXTENSIBLE_H #define EXTENSIBLE_H +#include "anope.h" #include "hashcomp.h" -/** Dummy base class we use to cast everything to/from - */ -class ExtensibleItemBase +class ExtensibleItem { public: - ExtensibleItemBase() { } - virtual ~ExtensibleItemBase() { } -}; - -/** Class used to represent an extensible item that doesn't hold a pointer - */ -template class ExtensibleItemRegular : public ExtensibleItemBase -{ - protected: - T Item; - - public: - ExtensibleItemRegular(T item) : Item(item) { } - virtual ~ExtensibleItemRegular() { } - T &GetItem() { return Item; } + ExtensibleItem(); + virtual ~ExtensibleItem(); + virtual void OnDelete(); }; -/** Class used to represent an extensible item that holds a pointer - */ -template class ExtensibleItemPointer : public ExtensibleItemBase +class ExtensibleString : public Anope::string, public ExtensibleItem { - protected: - T *Item; - public: - ExtensibleItemPointer(T *item) : Item(item) { } - virtual ~ExtensibleItemPointer() { delete Item; } - T *GetItem() { return Item; } -}; - -/** Class used to represent an extensible item that holds a pointer to an arrray - */ -template class ExtensibleItemPointerArray : public ExtensibleItemBase -{ - protected: - T *Item; - - public: - ExtensibleItemPointerArray(T *item) : Item(item) { } - virtual ~ExtensibleItemPointerArray() { delete [] Item; } - T *GetItem() { return Item; } + ExtensibleString(const Anope::string &s) : Anope::string(s), ExtensibleItem() { } }; class CoreExport Extensible : public Base { private: - typedef std::map extensible_map; - extensible_map Extension_Items; + typedef Anope::map extensible_map; + extensible_map extension_items; public: /** Default constructor, does nothing @@ -73,9 +40,10 @@ class CoreExport Extensible : public Base */ virtual ~Extensible() { - for (extensible_map::iterator it = Extension_Items.begin(), it_end = Extension_Items.end(); it != it_end; ++it) - delete it->second; - Extension_Items.clear(); + for (extensible_map::iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it) + if (it->second) + it->second->OnDelete(); + extension_items.clear(); } /** Extend an Extensible class. @@ -89,26 +57,10 @@ class CoreExport Extensible : public Base * * @return Returns true on success, false if otherwise */ - void Extend(const Anope::string &key, ExtensibleItemBase *p) + void Extend(const Anope::string &key, ExtensibleItem *p) { this->Shrink(key); - this->Extension_Items.insert(std::make_pair(key, p)); - } - - /** Extend an Extensible class. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * - * You must provide a key to store the data as via the parameter 'key', this single-parameter - * version takes no 'data' parameter, this is used purely for boolean values. - * The key will be inserted into the map with a NULL 'data' pointer. If the key already exists - * then you may not insert it twice, Extensible::Extend will return false in this case. - * - * @return Returns true on success, false if otherwise - */ - void Extend(const Anope::string &key) - { - this->Extend(key, new ExtensibleItemPointer(NULL)); + this->extension_items[key] = p; } /** Shrink an Extensible class. @@ -121,91 +73,43 @@ class CoreExport Extensible : public Base */ bool Shrink(const Anope::string &key) { - extensible_map::iterator it = this->Extension_Items.find(key); - if (it != this->Extension_Items.end()) + extensible_map::iterator it = this->extension_items.find(key); + if (it != this->extension_items.end()) { - delete it->second; + if (it->second != NULL) + it->second->OnDelete(); /* map::size_type map::erase( const key_type& key ); * returns the number of elements removed, std::map * is single-associative so this should only be 0 or 1 */ - return this->Extension_Items.erase(key); - } - - return false; - } - - /** Get an extension item that is not a pointer. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * @param p If you provide a non-existent key, this value will be 0. Otherwise a copy to the item you requested will be placed in this templated parameter. - * @return Returns true if the item was found and false if it was nor, regardless of wether 'p' is NULL. This allows you to store NULL values in Extensible. - */ - template bool GetExtRegular(const Anope::string &key, T &p) - { - extensible_map::iterator it = this->Extension_Items.find(key); - - if (it != this->Extension_Items.end()) - { - p = debug_cast *>(it->second)->GetItem(); - return true; + return this->extension_items.erase(key) > 0; } return false; } - /** Get an extension item that is a pointer. - * - * @param key The key parameter is an arbitary string which identifies the extension data - * * @param p If you provide a non-existent key, this value will be NULL. Otherwise a pointer to the item you requested will be placed in this templated parameter. - * @return Returns true if the item was found and false if it was nor, regardless of wether 'p' is NULL. This allows you to store NULL values in Extensible. - */ - template bool GetExtPointer(const Anope::string &key, T *&p) - { - extensible_map::iterator it = this->Extension_Items.find(key); - - if (it != this->Extension_Items.end()) - { - p = debug_cast *>(it->second)->GetItem(); - return true; - } - - p = NULL; - return false; - } - - /** Get an extension item that is a pointer to an array + /** Get an extension item. * * @param key The key parameter is an arbitary string which identifies the extension data - * @param p If you provide a non-existent key, this value will be NULL. Otherwise a pointer to the item you requested will be placed in this templated parameter. - * @return Returns true if the item was found and false if it was nor, regardless of wether 'p' is NULL. This allows you to store NULL values in Extensible. + * @return The item found */ - template bool GetExtArray(const Anope::string &key, T *&p) + template T GetExt(const Anope::string &key) { - extensible_map::iterator it = this->Extension_Items.find(key); + extensible_map::iterator it = this->extension_items.find(key); + if (it != this->extension_items.end()) + return debug_cast(it->second); - if (it != this->Extension_Items.end()) - { - p = debug_cast *>(it->second)->GetItem(); - return true; - } - - p = NULL; - return false; + return NULL; } - /** Get an extension item. + /** Check if an extension item exists. * * @param key The key parameter is an arbitary string which identifies the extension data - * @return Returns true if the item was found and false if it was not. - * - * This single-parameter version only checks if the key exists, it does nothing with - * the 'data' field and is probably only useful in conjunction with the single-parameter - * version of Extend(). + * @return True if the item was found. */ - bool GetExt(const Anope::string &key) + bool HasExt(const Anope::string &key) { - return this->Extension_Items.find(key) != this->Extension_Items.end(); + return this->extension_items.count(key) > 0; } /** Get a list of all extension items names. @@ -215,7 +119,7 @@ class CoreExport Extensible : public Base */ void GetExtList(std::deque &list) { - for (extensible_map::iterator it = Extension_Items.begin(), it_end = Extension_Items.end(); it != it_end; ++it) + for (extensible_map::iterator it = extension_items.begin(), it_end = extension_items.end(); it != it_end; ++it) list.push_back(it->first); } }; diff --git a/include/hashcomp.h b/include/hashcomp.h index 9c1f0d2dc..c36211cde 100644 --- a/include/hashcomp.h +++ b/include/hashcomp.h @@ -316,30 +316,6 @@ namespace std }; } -/* Define operators for using >> and << with irc::string to an ostream on an istream. */ -/* This was endless fun. No. Really. */ -/* It was also the first core change Ommeh made, if anyone cares */ - -/** Operator >> for irc::string - */ -inline std::istream &operator>>(std::istream &is, irc::string &str) -{ - std::string tmp; - is >> tmp; - str = tmp.c_str(); - return is; -} - -/** Operator >> for ci::string - */ -inline std::istream &operator>>(std::istream &is, ci::string &str) -{ - std::string tmp; - is >> tmp; - str = tmp.c_str(); - return is; -} - /* Define operators for + and == with irc::string to std::string for easy assignment * and comparison * diff --git a/include/modules.h b/include/modules.h index d35c1f2ba..00e48250b 100644 --- a/include/modules.h +++ b/include/modules.h @@ -342,11 +342,6 @@ class CoreExport Module : public Extensible */ virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector ¶ms) { } - /** Called after the core has finished loading the databases, but before - * we connect to the server - */ - virtual void OnPostLoadDatabases() { } - /** Called when the databases are saved * @return EVENT_CONTINUE to let other modules continue saving, EVENT_STOP to stop */ @@ -485,73 +480,6 @@ class CoreExport Module : public Extensible */ virtual void OnServerDisconnect() { } - /** 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 Anope::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 ¶ms) { return EVENT_CONTINUE; } - - /** Called when nickcore metadata is read from the database - * @param nc The nickcore - * @param key The metadata key - * @param params The params from the database - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing - */ - virtual EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector ¶ms) { return EVENT_CONTINUE; } - - /** Called when nickcore metadata is read from the database - * @param na The nickalias - * @param key The metadata key - * @param params The params from the database - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing - */ - virtual EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector ¶ms) { return EVENT_CONTINUE; } - - /** Called when botinfo metadata is read from the database - * @param bi The botinfo - * @param key The metadata key - * @param params The params from the database - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing - */ - virtual EventReturn OnDatabaseReadMetadata(BotInfo *bi, const Anope::string &key, const std::vector ¶ms) { return EVENT_CONTINUE; } - - /** Called when chaninfo metadata is read from the database - * @param ci The chaninfo - * @param key The metadata key - * @param params The params from the database - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing - */ - virtual EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector ¶ms) { return EVENT_CONTINUE; } - - /** Called when we are writing metadata for a nickcore - * @param WriteMetata A callback function used to insert the metadata - * @param nc The nickcore - */ - virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::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 Anope::string &, const Anope::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 Anope::string &, const Anope::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 Anope::string &, const Anope::string &), ChannelInfo *ci) { } - /** Called when services restart */ virtual void OnRestart() { } @@ -673,11 +601,6 @@ class CoreExport Module : public Extensible */ virtual void OnChanDrop(const Anope::string &chname) { } - /** Called when a channel is forbidden - * @param ci The channel - */ - virtual void OnChanForbidden(ChannelInfo *ci) { } - /** Called when a channel is registered * @param ci The channel */ @@ -979,10 +902,10 @@ class CoreExport Module : public Extensible /** Called when a mode is about to be unlocked * @param ci The channel the mode is being unlocked from - * @param mode The mode being unlocked + * @param lock The mode lock * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock. */ - virtual EventReturn OnUnMLock(ChannelInfo *ci, ChannelMode *mode, const Anope::string ¶m) { return EVENT_CONTINUE; } + virtual EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) { return EVENT_CONTINUE; } /** Called after a module is loaded * @param u The user loading the module, can be NULL @@ -1042,7 +965,7 @@ enum Implementation I_OnNickUpdate, /* ChanServ */ - I_OnChanForbidden, I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, + I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, I_OnAccessDel, I_OnAccessClear, I_OnLevelChange, I_OnChanRegistered, I_OnChanUnsuspend, I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick, I_OnChanInfo, I_OnFindChan, I_OnCheckPriv, I_OnGroupCheckPriv, @@ -1066,8 +989,7 @@ enum Implementation I_OnAddXLine, I_OnDelXLine, I_IsServicesOper, /* Database */ - I_OnPostLoadDatabases, I_OnSaveDatabase, I_OnLoadDatabase, - I_OnDatabaseWrite, I_OnDatabaseRead, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata, + I_OnSaveDatabase, I_OnLoadDatabase, /* Modules */ I_OnModuleLoad, I_OnModuleUnload, @@ -1235,6 +1157,11 @@ class service_reference : public dynamic_reference { } + inline void operator=(const Anope::string &n) + { + this->name = n; + } + operator bool() { if (this->invalid) diff --git a/include/oper.h b/include/oper.h index 8c587794b..fb046bdbe 100644 --- a/include/oper.h +++ b/include/oper.h @@ -11,14 +11,17 @@ class XLineManager; -class CoreExport XLine +class CoreExport XLine : public Serializable { + protected: + XLine(); public: Anope::string Mask; Anope::string By; time_t Created; time_t Expires; Anope::string Reason; + Anope::string Manager; XLine(const Anope::string &mask, const Anope::string &reason = ""); @@ -28,6 +31,9 @@ class CoreExport XLine Anope::string GetUser() const; Anope::string GetHost() const; sockaddrs GetIP() const; + + serialized_data serialize(); + static void unserialize(serialized_data &data); }; class CoreExport XLineManager : public Service diff --git a/include/regchannel.h b/include/regchannel.h index 017b93afe..680be5b44 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -60,6 +60,30 @@ const Anope::string ChannelInfoFlagStrings[] = { "SIGNKICK", "SIGNKICK_LEVEL", "SUSPENDED", "PERSIST", "" }; +/** Flags for badwords + */ +enum BadWordType +{ + /* Always kicks if the word is said */ + BW_ANY, + /* User must way the entire word */ + BW_SINGLE, + /* The word has to start with the badword */ + BW_START, + /* The word has to end with the badword */ + BW_END +}; + +/* Structure used to contain bad words. */ +struct BadWord : Serializable +{ + Anope::string word; + BadWordType type; + + serialized_data serialize(); + static void unserialize(serialized_data &); +}; + /** Flags for auto kick */ enum AutoKickFlag @@ -71,7 +95,7 @@ enum AutoKickFlag const Anope::string AutoKickFlagString[] = { "AK_ISNICK", "" }; /* AutoKick data. */ -class AutoKick : public Flags +class AutoKick : public Flags, public Serializable { public: AutoKick() : Flags(AutoKickFlagString) { } @@ -83,20 +107,29 @@ class AutoKick : public Flags Anope::string creator; time_t addtime; time_t last_used; + + serialized_data serialize(); + static void unserialize(serialized_data &); }; -struct ModeLock +struct ModeLock : Serializable { + ModeLock() { } + public: + ChannelInfo *ci; bool set; ChannelModeName name; Anope::string param; Anope::string setter; time_t created; - ModeLock(bool s, ChannelModeName n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime) : set(s), name(n), param(p), setter(se), created(c) { } + ModeLock(ChannelInfo *ch, bool s, ChannelModeName n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime) : ci(ch), set(s), name(n), param(p), setter(se), created(c) { } + + serialized_data serialize(); + static void unserialize(serialized_data &); }; -struct LogSetting +struct LogSetting : Serializable { /* Our service name of the command */ Anope::string service_name; @@ -107,9 +140,12 @@ struct LogSetting Anope::string method, extra; Anope::string creator; time_t created; + + serialized_data serialize(); + static void unserialize(serialized_data &); }; -class CoreExport ChannelInfo : public Extensible, public Flags +class CoreExport ChannelInfo : public Extensible, public Flags, public Serializable { private: NickCore *founder; /* Channel founder */ @@ -163,6 +199,9 @@ class CoreExport ChannelInfo : public Extensible, public Flagsstr(); } + template std::istream &operator>>(T &val) + { + std::istringstream is(this->str()); + is >> val; + return *this; + } + std::istream &operator>>(Anope::string &val) { return *this >> val.str(); } + stringstream &setType(DataType t) + { + this->type = t; + return *this; + } + DataType getType() const + { + return this->type; + } + stringstream &setKey() + { + this->key = true; + return *this; + } + bool getKey() const + { + return this->key; + } + stringstream &setMax(unsigned m) + { + this->max = m; + return *this; + } + unsigned getMax() const + { + return this->max; + } + }; +} + +class SerializableBase; + +extern std::vector serialized_types; +extern std::list serialized_items; +extern void RegisterTypes(); + +class SerializableBase +{ + public: + typedef std::map serialized_data; + + virtual Anope::string serialize_name() = 0; + virtual serialized_data serialize() = 0; + virtual void alloc(serialized_data &) = 0; +}; + +template class Serializable : public SerializableBase +{ + public: + static class SerializableAllocator : public SerializableBase + { + Anope::string name; + + public: + SerializableAllocator() + { + } + + ~SerializableAllocator() + { + Unregister(); + } + + void Register(const Anope::string &n, int pos = -1) + { + this->name = n; + serialized_types.insert(serialized_types.begin() + (pos < 0 ? serialized_types.size() : pos), this); + } + + void Unregister() + { + std::vector::iterator it = std::find(serialized_types.begin(), serialized_types.end(), this); + if (it != serialized_types.end()) + serialized_types.erase(it); + } + + Anope::string serialize_name() + { + if (this->name.empty()) + throw CoreException(); + return this->name; + } + + serialized_data serialize() + { + throw CoreException(); + } + + void alloc(serialized_data &data) + { + Type::unserialize(data); + } + } Alloc; + + private: + std::list::iterator s_iter; + + protected: + Serializable() + { + serialized_items.push_front(this); + this->s_iter = serialized_items.begin(); + } + + Serializable(const Serializable &) + { + serialized_items.push_front(this); + this->s_iter = serialized_items.begin(); + } + + ~Serializable() + { + if (!serialized_items.empty()) + serialized_items.erase(this->s_iter); + } + + public: + Anope::string serialize_name() + { + return Alloc.serialize_name(); + } + + void alloc(serialized_data &) + { + throw CoreException(); + } +}; + +template typename Serializable::SerializableAllocator Serializable::Alloc; + +#endif // SERIALIZE_H diff --git a/include/services.h b/include/services.h index 77b9e9cd1..e863ab8d1 100644 --- a/include/services.h +++ b/include/services.h @@ -227,21 +227,6 @@ class ModuleException : public CoreException virtual ~ModuleException() throw() { } }; -class DatabaseException : public CoreException -{ - public: - /** This constructor can be used to specify an error message before throwing. - * @param mmessage The exception - */ - DatabaseException(const Anope::string &message) : CoreException(message, "A database module") { } - - /** Destructor - * @throws Nothing - */ - virtual ~DatabaseException() throw() { } -}; - - /** Debug cast to be used instead of dynamic_cast, this uses dynamic_cast * for debug builds and static_cast on releass builds to speed up the program * because dynamic_cast relies on RTTI. @@ -313,7 +298,29 @@ template class Flags Flag_Values.reset(); } - std::vector ToString() + Anope::string ToString() + { + std::vector v = ToVector(); + Anope::string flag_buf; + for (unsigned i = 0; i < v.size(); ++i) + flag_buf += v[i] + " "; + flag_buf.trim(); + return flag_buf; + } + + void FromString(const Anope::string &str) + { + spacesepstream sep(str); + Anope::string buf; + std::vector v; + + while (sep.GetToken(buf)) + v.push_back(buf); + + FromVector(v); + } + + std::vector ToVector() { std::vector ret; for (unsigned i = 0; this->Flag_Strings && !this->Flag_Strings[i].empty(); ++i) @@ -322,7 +329,7 @@ template class Flags return ret; } - void FromString(const std::vector &strings) + void FromVector(const std::vector &strings) { for (unsigned i = 0; this->Flag_Strings && !this->Flag_Strings[i].empty(); ++i) for (unsigned j = 0; j < strings.size(); ++j) @@ -478,6 +485,7 @@ class Entry; #include "threadengine.h" #include "opertype.h" #include "modes.h" +#include "serialize.h" /*************************************************************************/ @@ -527,10 +535,14 @@ const Anope::string MemoFlagStrings[] = { /* Memo info structures. Since both nicknames and channels can have memos, * we encapsulate memo data in a MemoList to make it easier to handle. */ -class CoreExport Memo : public Flags +class CoreExport Memo : public Flags, public Serializable { public: - Memo(); + Memo(); + serialized_data serialize(); + static void unserialize(serialized_data &); + + Anope::string owner; time_t time; /* When it was sent */ Anope::string sender; Anope::string text; @@ -555,15 +567,7 @@ struct Session unsigned hits; /* Number of subsequent kills for a host */ }; -struct Exception -{ - Anope::string mask; /* Hosts to which this exception applies */ - unsigned limit; /* Session limit for exception */ - Anope::string who; /* Nick of person who added the exception */ - Anope::string reason; /* Reason for exception's addition */ - time_t time; /* When this exception was added */ - time_t expires; /* Time when it expires. 0 == no expiry */ -}; +struct Exception; /*************************************************************************/ @@ -611,28 +615,7 @@ class CoreExport HostInfo /** Retrieve when the vhost was crated * @return the time it was created */ - const time_t GetTime() const; -}; - -/** Flags for badwords - */ -enum BadWordType -{ - /* Always kicks if the word is said */ - BW_ANY, - /* User must way the entire word */ - BW_SINGLE, - /* The word has to start with the badword */ - BW_START, - /* The word has to end with the badword */ - BW_END -}; - -/* Structure used to contain bad words. */ -struct BadWord -{ - Anope::string word; - BadWordType type; + time_t GetTime() const; }; /* BotServ SET flags */ diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index 74ccaf05c..2c41b4b90 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -577,26 +577,60 @@ class CommandBSKick : public Command } }; -struct BanData +struct BanData : public ExtensibleItem { - Anope::string mask; - time_t last_use; - int16 ttb[TTB_SIZE]; + struct Data + { + Anope::string mask; + time_t last_use; + int16 ttb[TTB_SIZE]; + + Data() + { + this->Clear(); + } + + void Clear() + { + last_use = 0; + for (int i = 0; i < TTB_SIZE; ++i) + this->ttb[i] = 0; + } + }; + + private: + typedef std::map > data_type; + data_type data_map; - BanData() + public: + Data &get(const Anope::string &key) { - this->Clear(); + return this->data_map[key]; } - void Clear() + bool empty() const + { + return this->data_map.empty(); + } + + void purge() { - last_use = 0; - for (int i = 0; i < TTB_SIZE; ++i) - this->ttb[i] = 0; + for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;) + { + const Anope::string &user = it->first; + Data &bd = it->second; + ++it; + + if (Anope::CurTime - bd.last_use > Config->BSKeepData) + { + data_map.erase(user); + continue; + } + } } }; -struct UserData +struct UserData : public ExtensibleItem { UserData() { @@ -621,6 +655,11 @@ struct UserData Anope::string lastline; Anope::string lasttarget; int16 times; + + void OnDelete() + { + delete this; + } }; @@ -637,23 +676,11 @@ class BanDataPurger : public CallBack { Channel *c = it->second; - std::map bandata; - if (c->GetExtRegular("bs_main_bandata", bandata)) + BanData *bd = c->GetExt("bs_main_bandata"); + if (bd != NULL) { - for (std::map::iterator it2 = bandata.begin(), it2_end = bandata.end(); it2 != it2_end;) - { - const Anope::string &user = it2->first; - BanData *bd = &it2->second; - ++it2; - - if (Anope::CurTime - bd->last_use > Config->BSKeepData) - { - bandata.erase(user); - continue; - } - } - - if (bandata.empty()) + bd->purge(); + if (bd->empty()) c->Shrink("bs_main_bandata"); } } @@ -665,30 +692,32 @@ class BSKick : public Module CommandBSKick commandbskick; BanDataPurger purger; - BanData *GetBanData(User *u, Channel *c) + BanData::Data &GetBanData(User *u, Channel *c) { - std::map bandatamap; - if (!c->GetExtRegular("bs_main_bandata", bandatamap)); - c->Extend("bs_main_bandata", new ExtensibleItemRegular >(bandatamap)); - c->GetExtRegular("bs_main_bandata", bandatamap); - - BanData *bd = &bandatamap[u->GetMask()]; - if (bd->last_use && Anope::CurTime - bd->last_use > Config->BSKeepData) - bd->Clear(); - bd->last_use = Anope::CurTime; - return bd; + BanData *bd = c->GetExt("bs_main_bandata"); + if (bd == NULL) + { + bd = new BanData(); + c->Extend("bs_main_bandata", bd); + } + + return bd->get(u->GetMask()); } UserData *GetUserData(User *u, Channel *c) { - UserData *ud = NULL; UserContainer *uc = c->FindUser(u); - if (uc != NULL && !uc->GetExtPointer("bs_main_userdata", ud)) + if (uc == NULL) + return NULL; + + UserData *ud = uc->GetExt("bs_main_userdata"); + if (ud == NULL) { ud = new UserData(); - uc->Extend("bs_main_userdata", new ExtensibleItemPointer(ud)); + uc->Extend("bs_main_userdata", ud); } - return ud; + + return ud; } void check_ban(ChannelInfo *ci, User *u, int ttbtype) @@ -697,17 +726,17 @@ class BSKick : public Module if (u->server->IsULined()) return; - BanData *bd = this->GetBanData(u, ci->c); + BanData::Data &bd = this->GetBanData(u, ci->c); - ++bd->ttb[ttbtype]; - if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) + ++bd.ttb[ttbtype]; + if (ci->ttb[ttbtype] && bd.ttb[ttbtype] >= ci->ttb[ttbtype]) { - /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype] + /* Should not use == here because bd.ttb[ttbtype] could possibly be > ci->ttb[ttbtype] * if the TTB was changed after it was not set (0) before and the user had already been * kicked a few times. Bug #1056 - Adam */ Anope::string mask; - bd->ttb[ttbtype] = 0; + bd.ttb[ttbtype] = 0; get_idealban(ci, u, mask); diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 2821ba5c3..3e737b709 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -28,7 +28,7 @@ static void reset_levels(ChannelInfo *ci) ci->SetLevel(it->first, it->second); } -class AccessChanAccess : public ChanAccess +class AccessChanAccess : public ChanAccess, public Serializable { public: int level; @@ -86,6 +86,41 @@ class AccessChanAccess : public ChanAccess return highest; } } + + Anope::string serialize_name() { return "AccessChanAccess"; } + serialized_data serialize() + { + serialized_data data; + + data["provider"] << this->provider->name; + data["ci"] << this->ci->name; + data["mask"] << this->mask; + data["creator"] << this->creator; + data["last_seen"].setType(Serialize::DT_INT) << this->last_seen; + data["created"].setType(Serialize::DT_INT) << this->created; + data["level"].setType(Serialize::DT_INT) << this->level; + + return data; + } + + static void unserialize(SerializableBase::serialized_data &data) + { + service_reference aprovider(data["provider"].astr()); + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!aprovider || !ci) + return; + + AccessChanAccess *access = new AccessChanAccess(aprovider); + access->provider = aprovider; + access->ci = ci; + data["mask"] >> access->mask; + data["creator"] >> access->creator; + data["last_seen"] >> access->last_seen; + data["created"] >> access->created; + data["level"] >> access->level; + + ci->AddAccess(access); + } }; class AccessAccessProvider : public AccessProvider @@ -459,10 +494,10 @@ class CommandCSAccess : public Command source.Reply(ACCESS_DENIED); else { - ci->ClearAccess(); - FOREACH_MOD(I_OnAccessClear, OnAccessClear(ci, u)); + ci->ClearAccess(); + source.Reply(_("Channel %s access list has been cleared."), ci->name.c_str()); bool override = !IsFounder(u, ci); @@ -833,6 +868,7 @@ class CSAccess : public Module { this->SetAuthor("Anope"); + Serializable::Alloc.Register("AccessChanAccess"); Implementation i[] = { I_OnReload, I_OnCreateChan, I_OnGroupCheckPriv }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp index 05b97e027..6fa8d5dd3 100644 --- a/modules/commands/cs_entrymsg.cpp +++ b/modules/commands/cs_entrymsg.cpp @@ -13,34 +13,70 @@ #include "module.h" -struct EntryMsg +struct EntryMsg : Serializable { - static unsigned MaxEntries; + ChannelInfo *ci; + Anope::string creator; + Anope::string message; + time_t when; - EntryMsg(const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) + EntryMsg(ChannelInfo *c, const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) { + + this->ci = c; this->creator = cname; this->message = cmessage; this->when = ct; } - Anope::string creator; - Anope::string message; - time_t when; + serialized_data serialize() + { + serialized_data data; + + data["ci"] << this->ci->name; + data["creator"] << this->creator; + data["message"] << this->message; + data["when"].setType(Serialize::DT_INT) << this->when; + + return data; + } + + static void unserialize(serialized_data &data); }; -unsigned EntryMsg::MaxEntries = 0; + +static unsigned MaxEntries = 0; + +struct EntryMessageList : std::vector, ExtensibleItem +{ +}; + +void EntryMsg::unserialize(serialized_data &data) +{ + ChannelInfo *ci = cs_findchan(data["ci"].astr()); + if (!ci) + return; + + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) + { + messages = new EntryMessageList(); + ci->Extend("cs_entrymsg", messages); + } + + messages->push_back(EntryMsg(ci, data["creator"].astr(), data["message"].astr())); +} class CommandEntryMessage : public Command { private: void DoList(CommandSource &source, ChannelInfo *ci) { - std::vector messages; - if (ci->GetExtRegular("cs_entrymsg", messages)) + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) { source.Reply(_("Entry message list for \2%s\2:"), ci->name.c_str()); - for (unsigned i = 0; i < messages.size(); ++i) - source.Reply(CHAN_LIST_ENTRY, i + 1, messages[i].message.c_str(), messages[i].creator.c_str(), do_strftime(messages[i].when).c_str()); + for (unsigned i = 0; i < messages->size(); ++i) + source.Reply(CHAN_LIST_ENTRY, i + 1, (*messages)[i].message.c_str(), (*messages)[i].creator.c_str(), do_strftime((*messages)[i].when).c_str()); source.Reply(_("End of entry message list.")); } else @@ -49,35 +85,36 @@ class CommandEntryMessage : public Command void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &message) { - std::vector messages; - ci->GetExtRegular("cs_entrymsg", messages); + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); + if (messages == NULL) + { + messages = new EntryMessageList(); + ci->Extend("cs_entrymsg", messages); + } - if (EntryMsg::MaxEntries && messages.size() >= EntryMsg::MaxEntries) + if (MaxEntries && messages->size() >= MaxEntries) source.Reply(_("The entry message list for \2%s\2 is full."), ci->name.c_str()); else { - messages.push_back(EntryMsg(source.u->nick, message)); - ci->Extend("cs_entrymsg", new ExtensibleItemRegular >(messages)); + messages->push_back(EntryMsg(ci, source.u->nick, message)); source.Reply(_("Entry message added to \2%s\2"), ci->name.c_str()); } } void DoDel(CommandSource &source, ChannelInfo *ci, const Anope::string &message) { - std::vector messages; + EntryMessageList *messages = ci->GetExt("cs_entrymsg"); if (!message.is_pos_number_only()) source.Reply(("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str()); - else if (ci->GetExtRegular("cs_entrymsg", messages)) + else if (messages != NULL) { try { unsigned i = convertTo(message); - if (i > 0 && i <= messages.size()) + if (i > 0 && i <= messages->size()) { - messages.erase(messages.begin() + i - 1); - if (!messages.empty()) - ci->Extend("cs_entrymsg", new ExtensibleItemRegular >(messages)); - else + messages->erase(messages->begin() + i - 1); + if (messages->empty()) ci->Shrink("cs_entrymsg"); source.Reply(_("Entry message \2%i\2 for \2%s\2 deleted."), i, ci->name.c_str()); } @@ -165,58 +202,27 @@ class CSEntryMessage : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnJoinChannel, I_OnReload, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - - this->OnReload(); + + Serializable::Alloc.Register("EntryMsg"); } void OnJoinChannel(User *u, Channel *c) { if (u && c && c->ci && u->server->IsSynced()) { - std::vector messages; + EntryMessageList *messages = c->ci->GetExt("cs_entrymsg"); - if (c->ci->GetExtRegular("cs_entrymsg", messages)) - for (unsigned i = 0; i < messages.size(); ++i) - u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); + if (messages != NULL) + for (unsigned i = 0; i < messages->size(); ++i) + u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), (*messages)[i].message.c_str()); } } void OnReload() { ConfigReader config; - EntryMsg::MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true); - } - - EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector ¶ms) - { - if (key.find("CS_ENTRYMSG_") == 0 && params.size() > 2) - { - Anope::string creator = pa