mirror of
https://github.com/anope/anope.git
synced 2026-07-07 11:03:13 +02:00
Added a new database format and sqlite support. Also moved db-convert to a module.
This commit is contained in:
+1
-1
@@ -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
|
||||
)
|
||||
|
||||
+65
-20
@@ -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_plain" }
|
||||
#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" }
|
||||
db_plain
|
||||
{
|
||||
/*
|
||||
@@ -1046,25 +1064,52 @@ db_plain
|
||||
}
|
||||
|
||||
/*
|
||||
* db_mysql and db_mysql_live
|
||||
* db_flatfile
|
||||
*
|
||||
* Enables (live) MySQL 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.
|
||||
*
|
||||
* This effectively allows you to edit your database and have it be immediately
|
||||
* reflected back in Anope.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* db_mysql provides the command operserv/sqlsync, which is used for importing other database
|
||||
* methods into MySQL.
|
||||
* This is the default flatfile database format.
|
||||
*/
|
||||
#module { name = "db_mysql" }
|
||||
#module { name = "db_mysql_live" }
|
||||
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) SQL support.
|
||||
*
|
||||
* The db_sql_live modules are an extension to db_sql, and should only be used if
|
||||
* db_sql is being used.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The db_sql_live_write module writes data to SQL in real time as it is modified by
|
||||
* the core.
|
||||
*
|
||||
*/
|
||||
#module { name = "db_sql_live_read" }
|
||||
#module { name = "db_sql_live_write" }
|
||||
|
||||
/*
|
||||
* [REQUIRED] Encryption modules.
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
-426
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+9
-5
@@ -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<NickNameFlag, NS_END>
|
||||
class CoreExport NickAlias : public Extensible, public Flags<NickNameFlag, NS_END>, public Serializable<NickAlias>
|
||||
{
|
||||
public:
|
||||
/** Default constructor
|
||||
@@ -118,6 +116,9 @@ class CoreExport NickAlias : public Extensible, public Flags<NickNameFlag, NS_EN
|
||||
NickCore *nc; /* I'm an alias of this */
|
||||
HostInfo hostinfo;
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &);
|
||||
|
||||
/** Release a nick
|
||||
* See the comment in users.cpp
|
||||
*/
|
||||
@@ -131,7 +132,7 @@ class CoreExport NickAlias : public Extensible, public Flags<NickNameFlag, NS_EN
|
||||
void OnCancel(User *u);
|
||||
};
|
||||
|
||||
class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END>
|
||||
class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END>, public Serializable<NickCore>
|
||||
{
|
||||
public:
|
||||
/** Default constructor
|
||||
@@ -153,14 +154,17 @@ class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END
|
||||
std::vector<Anope::string> access; /* Access list, vector of strings */
|
||||
std::vector<Anope::string> 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<NickAlias *> 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.
|
||||
*/
|
||||
|
||||
+4
-1
@@ -32,7 +32,7 @@ enum BotFlag
|
||||
|
||||
static const Anope::string BotFlagString[] = { "BEGIN", "CORE", "PRIVATE", "CONF", "" };
|
||||
|
||||
class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>
|
||||
class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>, public Serializable<BotInfo>
|
||||
{
|
||||
public:
|
||||
uint32 chancount;
|
||||
@@ -57,6 +57,9 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>
|
||||
*/
|
||||
virtual ~BotInfo();
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &);
|
||||
|
||||
void GenerateUID();
|
||||
|
||||
/** Change the nickname for the bot.
|
||||
|
||||
+38
-134
@@ -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() { }
|
||||
ExtensibleItem();
|
||||
virtual ~ExtensibleItem();
|
||||
virtual void OnDelete();
|
||||
};
|
||||
|
||||
/** Class used to represent an extensible item that doesn't hold a pointer
|
||||
*/
|
||||
template<typename T> class ExtensibleItemRegular : public ExtensibleItemBase
|
||||
class ExtensibleString : public Anope::string, public ExtensibleItem
|
||||
{
|
||||
protected:
|
||||
T Item;
|
||||
|
||||
public:
|
||||
ExtensibleItemRegular(T item) : Item(item) { }
|
||||
virtual ~ExtensibleItemRegular() { }
|
||||
T &GetItem() { return Item; }
|
||||
};
|
||||
|
||||
/** Class used to represent an extensible item that holds a pointer
|
||||
*/
|
||||
template<typename T> class ExtensibleItemPointer : public ExtensibleItemBase
|
||||
{
|
||||
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<typename T> 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<Anope::string, ExtensibleItemBase *> extensible_map;
|
||||
extensible_map Extension_Items;
|
||||
typedef Anope::map<ExtensibleItem *> 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<char *>(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 this->extension_items.erase(key) > 0;
|
||||
}
|
||||
|
||||
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<typename T> 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<ExtensibleItemRegular<T> *>(it->second)->GetItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
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<typename T> 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<ExtensibleItemPointer<T> *>(it->second)->GetItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
p = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get an extension item that is a pointer to an array
|
||||
*
|
||||
* @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<typename T> bool GetExtArray(const Anope::string &key, T *&p)
|
||||
{
|
||||
extensible_map::iterator it = this->Extension_Items.find(key);
|
||||
|
||||
if (it != this->Extension_Items.end())
|
||||
{
|
||||
p = debug_cast<ExtensibleItemPointerArray<T> *>(it->second)->GetItem();
|
||||
return true;
|
||||
}
|
||||
|
||||
p = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get an extension item.
|
||||
*
|
||||
* @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 The item found
|
||||
*/
|
||||
bool GetExt(const Anope::string &key)
|
||||
template<typename T> T GetExt(const Anope::string &key)
|
||||
{
|
||||
return this->Extension_Items.find(key) != this->Extension_Items.end();
|
||||
extensible_map::iterator it = this->extension_items.find(key);
|
||||
if (it != this->extension_items.end())
|
||||
return debug_cast<T>(it->second);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Check if an extension item exists.
|
||||
*
|
||||
* @param key The key parameter is an arbitary string which identifies the extension data
|
||||
* @return True if the item was found.
|
||||
*/
|
||||
bool HasExt(const Anope::string &key)
|
||||
{
|
||||
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<Anope::string> &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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
+9
-82
@@ -342,11 +342,6 @@ class CoreExport Module : public Extensible
|
||||
*/
|
||||
virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶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<Anope::string> ¶ms) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when nickcore metadata is read from the database
|
||||
* @param nc The nickcore
|
||||
* @param key The metadata key
|
||||
* @param params The params from the database
|
||||
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
|
||||
*/
|
||||
virtual EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when nickcore metadata is read from the database
|
||||
* @param na The nickalias
|
||||
* @param key The metadata key
|
||||
* @param params The params from the database
|
||||
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
|
||||
*/
|
||||
virtual EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when botinfo metadata is read from the database
|
||||
* @param bi The botinfo
|
||||
* @param key The metadata key
|
||||
* @param params The params from the database
|
||||
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
|
||||
*/
|
||||
virtual EventReturn OnDatabaseReadMetadata(BotInfo *bi, const Anope::string &key, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when chaninfo metadata is read from the database
|
||||
* @param ci The chaninfo
|
||||
* @param key The metadata key
|
||||
* @param params The params from the database
|
||||
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing
|
||||
*/
|
||||
virtual EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; }
|
||||
|
||||
/** Called when we are writing metadata for a nickcore
|
||||
* @param WriteMetata A callback function used to insert the metadata
|
||||
* @param nc The nickcore
|
||||
*/
|
||||
virtual void OnDatabaseWriteMetadata(void (*WriteMetadata)(const 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<T>
|
||||
{
|
||||
}
|
||||
|
||||
inline void operator=(const Anope::string &n)
|
||||
{
|
||||
this->name = n;
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
if (this->invalid)
|
||||
|
||||
+7
-1
@@ -11,14 +11,17 @@
|
||||
|
||||
class XLineManager;
|
||||
|
||||
class CoreExport XLine
|
||||
class CoreExport XLine : public Serializable<XLine>
|
||||
{
|
||||
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<XLineManager>
|
||||
|
||||
+44
-5
@@ -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<BadWord>
|
||||
{
|
||||
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<AutoKickFlag>
|
||||
class AutoKick : public Flags<AutoKickFlag>, public Serializable<AutoKick>
|
||||
{
|
||||
public:
|
||||
AutoKick() : Flags<AutoKickFlag>(AutoKickFlagString) { }
|
||||
@@ -83,20 +107,29 @@ class AutoKick : public Flags<AutoKickFlag>
|
||||
Anope::string creator;
|
||||
time_t addtime;
|
||||
time_t last_used;
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &);
|
||||
};
|
||||
|
||||
struct ModeLock
|
||||
struct ModeLock : Serializable<ModeLock>
|
||||
{
|
||||
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<LogSetting>
|
||||
{
|
||||
/* 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<ChannelInfoFlag, CI_END>
|
||||
class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag, CI_END>, public Serializable<ChannelInfo>
|
||||
{
|
||||
private:
|
||||
NickCore *founder; /* Channel founder */
|
||||
@@ -163,6 +199,9 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag,
|
||||
int16 floodlines, floodsecs; /* For FLOOD kicker */
|
||||
int16 repeattimes; /* For REPEAT kicker */
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &);
|
||||
|
||||
/** Change the founder of the channek
|
||||
* @params nc The new founder
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#ifndef SERIALIZE_H
|
||||
#define SERIALIZE_H
|
||||
|
||||
namespace Serialize
|
||||
{
|
||||
enum DataType
|
||||
{
|
||||
DT_TEXT,
|
||||
DT_INT
|
||||
};
|
||||
|
||||
class stringstream : public std::stringstream
|
||||
{
|
||||
private:
|
||||
DataType type;
|
||||
bool key;
|
||||
unsigned max;
|
||||
|
||||
public:
|
||||
stringstream() : std::stringstream(), type(DT_TEXT), key(false), max(0) { }
|
||||
stringstream(const stringstream &ss) : std::stringstream(ss.str()), type(DT_TEXT), key(false), max(0) { }
|
||||
Anope::string astr() const { return this->str(); }
|
||||
template<typename T> 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<SerializableBase *> serialized_types;
|
||||
extern std::list<SerializableBase *> serialized_items;
|
||||
extern void RegisterTypes();
|
||||
|
||||
class SerializableBase
|
||||
{
|
||||
public:
|
||||
typedef std::map<Anope::string, Serialize::stringstream> serialized_data;
|
||||
|
||||
virtual Anope::string serialize_name() = 0;
|
||||
virtual serialized_data serialize() = 0;
|
||||
virtual void alloc(serialized_data &) = 0;
|
||||
};
|
||||
|
||||
template<typename Type> 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<SerializableBase *>::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<SerializableBase *>::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 T> typename Serializable<T>::SerializableAllocator Serializable<T>::Alloc;
|
||||
|
||||
#endif // SERIALIZE_H
|
||||
+33
-50
@@ -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<typename T, size_t Size = 32> class Flags
|
||||
Flag_Values.reset();
|
||||
}
|
||||
|
||||
std::vector<Anope::string> ToString()
|
||||
Anope::string ToString()
|
||||
{
|
||||
std::vector<Anope::string> 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<Anope::string> v;
|
||||
|
||||
while (sep.GetToken(buf))
|
||||
v.push_back(buf);
|
||||
|
||||
FromVector(v);
|
||||
}
|
||||
|
||||
std::vector<Anope::string> ToVector()
|
||||
{
|
||||
std::vector<Anope::string> ret;
|
||||
for (unsigned i = 0; this->Flag_Strings && !this->Flag_Strings[i].empty(); ++i)
|
||||
@@ -322,7 +329,7 @@ template<typename T, size_t Size = 32> class Flags
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FromString(const std::vector<Anope::string> &strings)
|
||||
void FromVector(const std::vector<Anope::string> &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<MemoFlag>
|
||||
class CoreExport Memo : public Flags<MemoFlag>, public Serializable<Memo>
|
||||
{
|
||||
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 */
|
||||
|
||||
@@ -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];
|
||||
|
||||
BanData()
|
||||
struct Data
|
||||
{
|
||||
this->Clear();
|
||||
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<Anope::string, Data, std::less<ci::string> > data_type;
|
||||
data_type data_map;
|
||||
|
||||
public:
|
||||
Data &get(const Anope::string &key)
|
||||
{
|
||||
return this->data_map[key];
|
||||
}
|
||||
|
||||
void Clear()
|
||||
bool empty() const
|
||||
{
|
||||
last_use = 0;
|
||||
for (int i = 0; i < TTB_SIZE; ++i)
|
||||
this->ttb[i] = 0;
|
||||
return this->data_map.empty();
|
||||
}
|
||||
|
||||
void purge()
|
||||
{
|
||||
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<Anope::string, BanData> bandata;
|
||||
if (c->GetExtRegular("bs_main_bandata", bandata))
|
||||
BanData *bd = c->GetExt<BanData *>("bs_main_bandata");
|
||||
if (bd != NULL)
|
||||
{
|
||||
for (std::map<Anope::string, BanData>::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<Anope::string, BanData> bandatamap;
|
||||
if (!c->GetExtRegular("bs_main_bandata", bandatamap));
|
||||
c->Extend("bs_main_bandata", new ExtensibleItemRegular<std::map<Anope::string, BanData> >(bandatamap));
|
||||
c->GetExtRegular("bs_main_bandata", bandatamap);
|
||||
BanData *bd = c->GetExt<BanData *>("bs_main_bandata");
|
||||
if (bd == NULL)
|
||||
{
|
||||
bd = new BanData();
|
||||
c->Extend("bs_main_bandata", bd);
|
||||
}
|
||||
|
||||
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;
|
||||
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<UserData *>("bs_main_userdata");
|
||||
if (ud == NULL)
|
||||
{
|
||||
ud = new UserData();
|
||||
uc->Extend("bs_main_userdata", new ExtensibleItemPointer<UserData>(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);
|
||||
|
||||
|
||||
@@ -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<AccessChanAccess>
|
||||
{
|
||||
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<AccessProvider> 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<AccessChanAccess>::Alloc.Register("AccessChanAccess");
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnCreateChan, I_OnGroupCheckPriv };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
@@ -13,34 +13,70 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct EntryMsg
|
||||
struct EntryMsg : Serializable<EntryMsg>
|
||||
{
|
||||
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<EntryMsg>, ExtensibleItem
|
||||
{
|
||||
};
|
||||
|
||||
void EntryMsg::unserialize(serialized_data &data)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(data["ci"].astr());
|
||||
if (!ci)
|
||||
return;
|
||||
|
||||
EntryMessageList *messages = ci->GetExt<EntryMessageList *>("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<EntryMsg> messages;
|
||||
if (ci->GetExtRegular("cs_entrymsg", messages))
|
||||
EntryMessageList *messages = ci->GetExt<EntryMessageList *>("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<EntryMsg> messages;
|
||||
ci->GetExtRegular("cs_entrymsg", messages);
|
||||
EntryMessageList *messages = ci->GetExt<EntryMessageList *>("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<std::vector<EntryMsg> >(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<EntryMsg> messages;
|
||||
EntryMessageList *messages = ci->GetExt<EntryMessageList *>("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<unsigned>(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<std::vector<EntryMsg> >(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<EntryMsg>::Alloc.Register("EntryMsg");
|
||||
}
|
||||
|
||||
void OnJoinChannel(User *u, Channel *c)
|
||||
{
|
||||
if (u && c && c->ci && u->server->IsSynced())
|
||||
{
|
||||
std::vector<EntryMsg> messages;
|
||||
EntryMessageList *messages = c->ci->GetExt<EntryMessageList *>("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<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.find("CS_ENTRYMSG_") == 0 && params.size() > 2)
|
||||
{
|
||||
Anope::string creator = params[0];
|
||||
time_t t = params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
|
||||
Anope::string message = params[2];
|
||||
for (unsigned j = 3; j < params.size(); ++j)
|
||||
message += " " + params[j];
|
||||
|
||||
std::vector<EntryMsg> messages;
|
||||
ci->GetExtRegular("cs_entrymsg", messages);
|
||||
messages.push_back(EntryMsg(creator, message, t));
|
||||
ci->Extend("cs_entrymsg", new ExtensibleItemRegular<std::vector<EntryMsg> >(messages));
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), ChannelInfo *ci)
|
||||
{
|
||||
std::vector<EntryMsg> messages;
|
||||
if (ci->GetExtRegular("cs_entrymsg", messages))
|
||||
for (unsigned i = 0; i < messages.size(); ++i)
|
||||
WriteMetadata("CS_ENTRYMSG_" + stringify(i), messages[i].creator + " " + stringify(messages[i].when) + " " + messages[i].message);
|
||||
MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
static std::map<Anope::string, char> defaultFlags;
|
||||
|
||||
class FlagsChanAccess : public ChanAccess
|
||||
class FlagsChanAccess : public ChanAccess, public Serializable<FlagsChanAccess>
|
||||
{
|
||||
public:
|
||||
std::set<char> flags;
|
||||
@@ -65,6 +65,41 @@ class FlagsChanAccess : public ChanAccess
|
||||
|
||||
return Anope::string(buffer.begin(), buffer.end());
|
||||
}
|
||||
|
||||
Anope::string serialize_name() { return "FlagsChanAccess"; }
|
||||
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["flags"] << this->Serialize();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
service_reference<AccessProvider> aprovider(data["provider"].astr());
|
||||
ChannelInfo *ci = cs_findchan(data["ci"].astr());
|
||||
if (!aprovider || !ci)
|
||||
return;
|
||||
|
||||
FlagsChanAccess *access = new FlagsChanAccess(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;
|
||||
access->Unserialize(data["flags"].astr());
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
};
|
||||
|
||||
class FlagsAccessProvider : public AccessProvider
|
||||
@@ -385,6 +420,8 @@ class CSFlags : public Module
|
||||
ModuleManager::Attach(i, this, 1);
|
||||
|
||||
this->OnReload();
|
||||
|
||||
Serializable<FlagsChanAccess>::Alloc.Register("FlagsChanAccess");
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
|
||||
@@ -100,10 +100,9 @@ class CommandCSInfo : public Command
|
||||
}
|
||||
if (ci->HasFlag(CI_SUSPENDED))
|
||||
{
|
||||
Anope::string by, reason;
|
||||
ci->GetExtRegular("suspend_by", by);
|
||||
ci->GetExtRegular("suspend_reason", reason);
|
||||
source.Reply(_(" Suspended: [%s] %s"), by.c_str(), !reason.empty() ? reason.c_str() : NO_REASON);
|
||||
Anope::string *by = ci->GetExt<Anope::string *>("suspend_by"), *reason = ci->GetExt<Anope::string *>("suspend_reason");
|
||||
if (by != NULL)
|
||||
source.Reply(_(" Suspended: [%s] %s"), by->c_str(), (reason && !reason->empty() ? reason->c_str() : NO_REASON));
|
||||
}
|
||||
|
||||
FOREACH_MOD(I_OnChanInfo, OnChanInfo(source, ci, show_all));
|
||||
|
||||
@@ -19,26 +19,55 @@ enum TypeInfo
|
||||
NEW, NICK_TO, NICK_FROM, JOIN, PART, QUIT, KICK
|
||||
};
|
||||
|
||||
struct SeenInfo
|
||||
struct SeenInfo;
|
||||
typedef Anope::insensitive_map<SeenInfo *> database_map;
|
||||
database_map database;
|
||||
|
||||
struct SeenInfo : Serializable<SeenInfo>
|
||||
{
|
||||
Anope::string nick;
|
||||
Anope::string vhost;
|
||||
TypeInfo type;
|
||||
Anope::string nick2; // for nickchanges and kicks
|
||||
Anope::string channel; // for join/part/kick
|
||||
Anope::string message; // for part/kick/quit
|
||||
time_t last; // the time when the user was last seen
|
||||
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["nick"] << nick;
|
||||
data["vhost"] << vhost;
|
||||
data["type"] << type;
|
||||
data["nick2"] << nick2;
|
||||
data["channel"] << channel;
|
||||
data["message"] << message;
|
||||
data["last"].setType(Serialize::DT_INT) << last;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &data)
|
||||
{
|
||||
SeenInfo *s = new SeenInfo();
|
||||
|
||||
data["nick"] >> s->nick;
|
||||
data["vhost"] >> s->vhost;
|
||||
unsigned int n;
|
||||
data["type"] >> n;
|
||||
s->type = static_cast<TypeInfo>(n);
|
||||
data["nick2"] >> s->nick2;
|
||||
data["channel"] >> s->channel;
|
||||
data["message"] >> s->message;
|
||||
data["last"] >> s->last;
|
||||
|
||||
database[s->nick] = s;
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleConfigClass
|
||||
{
|
||||
public:
|
||||
time_t purgetime;
|
||||
time_t expiretimeout;
|
||||
};
|
||||
ModuleConfigClass ModuleConfig;
|
||||
|
||||
typedef Anope::insensitive_map<SeenInfo *> database_map;
|
||||
database_map database;
|
||||
static time_t purgetime;
|
||||
static time_t expiretimeout;
|
||||
|
||||
static SeenInfo *FindInfo(const Anope::string &nick)
|
||||
{
|
||||
@@ -262,7 +291,7 @@ class DataBasePurger : public CallBack
|
||||
database_map::iterator cur = it;
|
||||
++it;
|
||||
|
||||
if ((Anope::CurTime - cur->second->last) > ModuleConfig.purgetime)
|
||||
if ((Anope::CurTime - cur->second->last) > purgetime)
|
||||
{
|
||||
Log(LOG_DEBUG) << cur->first << " was last seen " << do_strftime(cur->second->last) << ", purging entry";
|
||||
delete cur->second;
|
||||
@@ -289,48 +318,55 @@ class CSSeen : public Module
|
||||
I_OnUserQuit,
|
||||
I_OnJoinChannel,
|
||||
I_OnPartChannel,
|
||||
I_OnUserKicked,
|
||||
I_OnDatabaseRead,
|
||||
I_OnDatabaseWrite };
|
||||
I_OnUserKicked };
|
||||
ModuleManager::Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
|
||||
|
||||
|
||||
OnReload();
|
||||
|
||||
Serializable<SeenInfo>::Alloc.Register("SeenInfo");
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
ModuleConfig.purgetime = dotime(config.ReadValue("cs_seen", "purgetime", "30d", 0));
|
||||
ModuleConfig.expiretimeout = dotime(config.ReadValue("cs_seen", "expiretimeout", "1d", 0));
|
||||
purgetime = dotime(config.ReadValue("cs_seen", "purgetime", "30d", 0));
|
||||
expiretimeout = dotime(config.ReadValue("cs_seen", "expiretimeout", "1d", 0));
|
||||
|
||||
if (purger.GetSecs() != ModuleConfig.expiretimeout)
|
||||
purger.SetSecs(ModuleConfig.expiretimeout);
|
||||
if (purger.GetSecs() != expiretimeout)
|
||||
purger.SetSecs(expiretimeout);
|
||||
}
|
||||
|
||||
void OnUserConnect(User *u)
|
||||
{
|
||||
UpdateUser(u, NEW, u->nick, "", "", "");
|
||||
}
|
||||
|
||||
void OnUserNickChange(User *u, const Anope::string &oldnick)
|
||||
{
|
||||
UpdateUser(u, NICK_TO, oldnick, u->nick, "", "");
|
||||
UpdateUser(u, NICK_FROM, u->nick, oldnick, "", "");
|
||||
}
|
||||
|
||||
void OnUserQuit(User *u, const Anope::string &msg)
|
||||
{
|
||||
UpdateUser(u, QUIT, u->nick, "", "", msg);
|
||||
}
|
||||
|
||||
void OnJoinChannel(User *u, Channel *c)
|
||||
{
|
||||
UpdateUser(u, JOIN, u->nick, "", c->name, "");
|
||||
}
|
||||
|
||||
void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg)
|
||||
{
|
||||
UpdateUser(u, PART, u->nick, "", channel, msg);
|
||||
}
|
||||
|
||||
void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &msg)
|
||||
{
|
||||
UpdateUser(target, KICK, target->nick, source, c->name, msg);
|
||||
}
|
||||
|
||||
void UpdateUser(const User *u, const TypeInfo Type, const Anope::string &nick, const Anope::string &nick2, const Anope::string &channel, const Anope::string &message)
|
||||
{
|
||||
SeenInfo *info = FindInfo(nick);
|
||||
@@ -339,6 +375,7 @@ class CSSeen : public Module
|
||||
info = new SeenInfo;
|
||||
database.insert(std::pair<Anope::string, SeenInfo *>(nick, info));
|
||||
}
|
||||
info->nick = nick;
|
||||
info->vhost = u->GetVIdent() + "@" + u->GetDisplayedHost();
|
||||
info->type = Type;
|
||||
info->last = Anope::CurTime;
|
||||
@@ -346,82 +383,6 @@ class CSSeen : public Module
|
||||
info->channel = channel;
|
||||
info->message = message;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params[0].equals_ci("SEEN") && (params.size() >= 5))
|
||||
{
|
||||
SeenInfo *info = new SeenInfo;
|
||||
database.insert(std::pair<Anope::string, SeenInfo *>(params[1], info));
|
||||
info->vhost = params[2];
|
||||
info->last = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : 0 ;
|
||||
if (params[4].equals_ci("NEW"))
|
||||
{
|
||||
info->type = NEW;
|
||||
}
|
||||
else if (params[4].equals_ci("NICK_TO") && params.size() == 6)
|
||||
{
|
||||
info->type = NICK_TO;
|
||||
info->nick2 = params[5];
|
||||
}
|
||||
else if (params[4].equals_ci("NICK_FROM") && params.size() == 6)
|
||||
{
|
||||
info->type = NICK_FROM;
|
||||
info->nick2 = params[5];
|
||||
}
|
||||
else if (params[4].equals_ci("JOIN") && params.size() == 6)
|
||||
{
|
||||
info->type = JOIN;
|
||||
info->channel = params[5];
|
||||
}
|
||||
else if (params[4].equals_ci("PART") && params.size() == 7)
|
||||
{
|
||||
info->type = PART;
|
||||
info->channel = params[5];
|
||||
info->message = params[6];
|
||||
}
|
||||
else if (params[4].equals_ci("QUIT") && params.size() == 6)
|
||||
{
|
||||
info->type = QUIT;
|
||||
info->message = params[5];
|
||||
}
|
||||
else if (params[4].equals_ci("KICK") && params.size() == 8)
|
||||
{
|
||||
info->type = KICK;
|
||||
info->nick2 = params[5];
|
||||
info->channel = params[6];
|
||||
info->message = params[7];
|
||||
}
|
||||
return EVENT_STOP;
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
{
|
||||
for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end; ++it)
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << "SEEN " << it->first.c_str() << " " << it->second->vhost << " " << it->second->last << " ";
|
||||
switch (it->second->type)
|
||||
{
|
||||
case NEW:
|
||||
buf << "NEW"; break;
|
||||
case NICK_TO:
|
||||
buf << "NICK_TO " << it->second->nick2; break;
|
||||
case NICK_FROM:
|
||||
buf << "NICK_FROM " << it->second->nick2; break;
|
||||
case JOIN:
|
||||
buf << "JOIN " << it->second->channel; break;
|
||||
case PART:
|
||||
buf << "PART " << it->second->channel << " :" << it->second->message; break;
|
||||
case QUIT:
|
||||
buf << "QUIT :" << it->second->message; break;
|
||||
case KICK:
|
||||
buf << "KICK " << it->second->nick2 << " " << it->second->channel << " :" << it->second->message; break;
|
||||
}
|
||||
Write(buf.str());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(CSSeen)
|
||||
|
||||
@@ -12,6 +12,37 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct MiscData : Anope::string, ExtensibleItem, Serializable<MiscData>
|
||||
{
|
||||
ChannelInfo *ci;
|
||||
Anope::string name;
|
||||
Anope::string data;
|
||||
|
||||
MiscData(ChannelInfo *c, const Anope::string &n, const Anope::string &d) : ci(c), name(n), data(d)
|
||||
{
|
||||
}
|
||||
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data sdata;
|
||||
|
||||
sdata["ci"] << this->ci->name;
|
||||
sdata["name"] << this->name;
|
||||
sdata["data"] << this->data;
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &data)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(data["ci"].astr());
|
||||
if (ci == NULL)
|
||||
return;
|
||||
|
||||
ci->Extend(data["name"].astr(), new MiscData(ci, data["name"].astr(), data["data"].astr()));
|
||||
}
|
||||
};
|
||||
|
||||
class CommandCSSetMisc : public Command
|
||||
{
|
||||
public:
|
||||
@@ -34,10 +65,11 @@ class CommandCSSetMisc : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
ci->Shrink("cs_set_misc:" + source.command.replace_all_cs(" ", "_"));
|
||||
Anope::string key = "cs_set_misc:" + source.command.replace_all_cs(" ", "_");
|
||||
ci->Shrink(key);
|
||||
if (params.size() > 1)
|
||||
{
|
||||
ci->Extend("cs_set_misc:" + source.command.replace_all_cs(" ", "_"), new ExtensibleItemRegular<Anope::string>(params[1]));
|
||||
ci->Extend(key, new MiscData(ci, key, params[1]));
|
||||
source.Reply(CHAN_SETTING_CHANGED, source.command.c_str(), ci->name.c_str(), params[1].c_str());
|
||||
}
|
||||
else
|
||||
@@ -64,9 +96,10 @@ class CSSetMisc : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnChanInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata };
|
||||
Implementation i[] = { I_OnChanInfo };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
Serializable<MiscData>::Alloc.Register("CSMisc");
|
||||
}
|
||||
|
||||
void OnChanInfo(CommandSource &source, ChannelInfo *ci, bool ShowHidden)
|
||||
@@ -79,35 +112,11 @@ class CSSetMisc : public Module
|
||||
if (list[i].find("cs_set_misc:") != 0)
|
||||
continue;
|
||||
|
||||
Anope::string value;
|
||||
if (ci->GetExtRegular(list[i], value))
|
||||
source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), value.c_str());
|
||||
MiscData *data = ci->GetExt<MiscData *>(list[i]);
|
||||
if (data != NULL)
|
||||
source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), data->data.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), ChannelInfo *ci)
|
||||
{
|
||||
std::deque<Anope::string> list;
|
||||
ci->GetExtList(list);
|
||||
|
||||
for (unsigned i = 0; i < list.size(); ++i)
|
||||
{
|
||||
if (list[i].find("cs_set_misc:") != 0)
|
||||
continue;
|
||||
|
||||
Anope::string value;
|
||||
if (ci->GetExtRegular(list[i], value))
|
||||
WriteMetadata(list[i], ":" + value);
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.find("cs_set_misc:") == 0)
|
||||
ci->Extend(key, new ExtensibleItemRegular<Anope::string>(params[0]));
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(CSSetMisc)
|
||||
|
||||
@@ -45,9 +45,9 @@ class CommandCSSuspend : public Command
|
||||
}
|
||||
|
||||
ci->SetFlag(CI_SUSPENDED);
|
||||
ci->Extend("suspend_by", new ExtensibleItemRegular<Anope::string>(u->nick));
|
||||
ci->Extend("suspend_by", new ExtensibleString(u->nick));
|
||||
if (!reason.empty())
|
||||
ci->Extend("suspend_reason", new ExtensibleItemRegular<Anope::string>(reason));
|
||||
ci->Extend("suspend_reason", new ExtensibleString(reason));
|
||||
|
||||
if (ci->c)
|
||||
{
|
||||
@@ -113,10 +113,9 @@ class CommandCSUnSuspend : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
Anope::string by, reason;
|
||||
ci->GetExtRegular("suspend_by", by);
|
||||
ci->GetExtRegular("suspend_reason", reason);
|
||||
Log(LOG_ADMIN, u, this, ci) << " which was suspended by " << by << " for: " << (!reason.empty() ? reason : "No reason");
|
||||
Anope::string *by = ci->GetExt<Anope::string *>("suspend_by"), *reason = ci->GetExt<Anope::string *>("suspend_reason");
|
||||
if (by != NULL)
|
||||
Log(LOG_ADMIN, u, this, ci) << " which was suspended by " << *by << " for: " << (reason && !reason->empty() ? *reason : "No reason");
|
||||
|
||||
ci->UnsetFlag(CI_SUSPENDED);
|
||||
ci->Shrink("suspend_by");
|
||||
|
||||
@@ -90,7 +90,7 @@ static struct XOPAccess
|
||||
}
|
||||
};
|
||||
|
||||
class XOPChanAccess : public ChanAccess
|
||||
class XOPChanAccess : public ChanAccess, public Serializable<XOPChanAccess>
|
||||
{
|
||||
public:
|
||||
XOPType type;
|
||||
@@ -188,6 +188,41 @@ class XOPChanAccess : public ChanAccess
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
Anope::string serialize_name() { return "XOPChanAccess"; }
|
||||
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"] << this->last_seen;
|
||||
data["created"] << this->created;
|
||||
data["type"] << this->Serialize();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
service_reference<AccessProvider> aprovider(data["provider"].astr());
|
||||
ChannelInfo *ci = cs_findchan(data["ci"].astr());
|
||||
if (!aprovider || !ci)
|
||||
return;
|
||||
|
||||
XOPChanAccess *access = new XOPChanAccess(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;
|
||||
access->Unserialize(data["type"].astr());
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
};
|
||||
|
||||
class XOPAccessProvider : public AccessProvider
|
||||
@@ -868,6 +903,7 @@ class CSXOP : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Serializable<XOPChanAccess>::Alloc.Register("XOPChanAccess");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -21,18 +21,42 @@
|
||||
static bool HSRequestMemoUser = false;
|
||||
static bool HSRequestMemoOper = false;
|
||||
|
||||
void my_add_host_request(const Anope::string &nick, const Anope::string &vIdent, const Anope::string &vhost, const Anope::string &creator, time_t tmp_time);
|
||||
void req_send_memos(CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost);
|
||||
|
||||
struct HostRequest
|
||||
struct HostRequest : ExtensibleItem, Serializable<HostRequest>
|
||||
{
|
||||
Anope::string nick;
|
||||
Anope::string ident;
|
||||
Anope::string host;
|
||||
time_t time;
|
||||
};
|
||||
|
||||
typedef std::map<Anope::string, HostRequest *, std::less<ci::string> > RequestMap;
|
||||
RequestMap Requests;
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["nick"] << this->nick;
|
||||
data["ident"] << this->ident;
|
||||
data["host"] << this->host;
|
||||
data["time"].setType(Serialize::DT_INT) << this->time;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &data)
|
||||
{
|
||||
NickAlias *na = findnick(data["nick"].astr());
|
||||
if (na == NULL)
|
||||
return;
|
||||
|
||||
HostRequest *req = new HostRequest;
|
||||
req->nick = na->nick;
|
||||
data["ident"] >> req->ident;
|
||||
data["host"] >> req->host;
|
||||
data["time"] >> req->time;
|
||||
|
||||
na->Extend("hs_request", req);
|
||||
}
|
||||
};
|
||||
|
||||
class CommandHSRequest : public Command
|
||||
{
|
||||
@@ -54,6 +78,12 @@ class CommandHSRequest : public Command
|
||||
{
|
||||
User *u = source.u;
|
||||
|
||||
NickAlias *na = findnick(u->nick);
|
||||
if (na == NULL)
|
||||
na = findnick(u->Account()->display);
|
||||
if (!na)
|
||||
return;
|
||||
|
||||
Anope::string rawhostmask = params[0];
|
||||
|
||||
Anope::string user, host;
|
||||
@@ -111,7 +141,14 @@ class CommandHSRequest : public Command
|
||||
u->lastmemosend = Anope::CurTime;
|
||||
return;
|
||||
}
|
||||
my_add_host_request(u->nick, user, host, u->nick, Anope::CurTime);
|
||||
|
||||
|
||||
HostRequest *req = new HostRequest;
|
||||
req->nick = u->nick;
|
||||
req->ident = user;
|
||||
req->host = host;
|
||||
req->time = Anope::CurTime;
|
||||
na->Extend("hs_request", req);
|
||||
|
||||
source.Reply(_("Your vHost has been requested"));
|
||||
req_send_memos(source, user, host);
|
||||
@@ -147,29 +184,21 @@ class CommandHSActivate : public Command
|
||||
const Anope::string &nick = params[0];
|
||||
|
||||
NickAlias *na = findnick(nick);
|
||||
if (na)
|
||||
HostRequest *req = na ? na->GetExt<HostRequest *>("hs_request") : NULL;
|
||||
if (req)
|
||||
{
|
||||
RequestMap::iterator it = Requests.find(na->nick);
|
||||
if (it != Requests.end())
|
||||
{
|
||||
na->hostinfo.SetVhost(it->second->ident, it->second->host, u->nick, it->second->time);
|
||||
FOREACH_MOD(I_OnSetVhost, OnSetVhost(na));
|
||||
na->hostinfo.SetVhost(req->ident, req->host, u->nick, req->time);
|
||||
FOREACH_MOD(I_OnSetVhost, OnSetVhost(na));
|
||||
|
||||
if (HSRequestMemoUser && memoserv)
|
||||
memoserv->Send(Config->HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true);
|
||||
if (HSRequestMemoUser && memoserv)
|
||||
memoserv->Send(Config->HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true);
|
||||
|
||||
source.Reply(_("vHost for %s has been activated"), na->nick.c_str());
|
||||
Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!it->second->ident.empty() ? it->second->ident + "@" : "") << it->second->host;
|
||||
delete it->second;
|
||||
Requests.erase(it);
|
||||
}
|
||||
else
|
||||
source.Reply(_("No request for nick %s found."), nick.c_str());
|
||||
source.Reply(_("vHost for %s has been activated"), na->nick.c_str());
|
||||
Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host;
|
||||
na->Shrink("hs_request");
|
||||
}
|
||||
else
|
||||
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
|
||||
|
||||
return;
|
||||
source.Reply(_("No request for nick %s found."), nick.c_str());
|
||||
}
|
||||
|
||||
bool OnHelp(CommandSource &source, const Anope::string &subcommand)
|
||||
@@ -199,11 +228,11 @@ class CommandHSReject : public Command
|
||||
const Anope::string &nick = params[0];
|
||||
const Anope::string &reason = params.size() > 1 ? params[1] : "";
|
||||
|
||||
RequestMap::iterator it = Requests.find(nick);
|
||||
if (it != Requests.end())
|
||||
NickAlias *na = findnick(nick);
|
||||
HostRequest *req = na ? na->GetExt<HostRequest *>("hs_request") : NULL;
|
||||
if (req)
|
||||
{
|
||||
delete it->second;
|
||||
Requests.erase(it);
|
||||
na->Shrink("hs_request");
|
||||
|
||||
if (HSRequestMemoUser && memoserv)
|
||||
{
|
||||
@@ -246,9 +275,13 @@ class HSListBase : public Command
|
||||
int from = 0, to = 0;
|
||||
unsigned display_counter = 0;
|
||||
|
||||
for (RequestMap::iterator it = Requests.begin(), it_end = Requests.end(); it != it_end; ++it)
|
||||
for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
|
||||
{
|
||||
HostRequest *hr = it->second;
|
||||
NickAlias *na = it->second;
|
||||
HostRequest *hr = na->GetExt<HostRequest *>("hs_request");
|
||||
if (!hr)
|
||||
continue;
|
||||
|
||||
if (((counter >= from && counter <= to) || (!from && !to)) && display_counter < Config->NSListMax)
|
||||
{
|
||||
++display_counter;
|
||||
@@ -260,8 +293,6 @@ class HSListBase : public Command
|
||||
++counter;
|
||||
}
|
||||
source.Reply(_("Displayed all records (Count: \002%d\002)"), display_counter);
|
||||
|
||||
return;
|
||||
}
|
||||
public:
|
||||
HSListBase(Module *creator, const Anope::string &cmd, int min, int max) : Command(creator, cmd, min, max)
|
||||
@@ -306,8 +337,7 @@ class HSRequest : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
|
||||
Implementation i[] = { I_OnDelNick, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload };
|
||||
Implementation i[] = { I_OnReload };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
this->OnReload();
|
||||
@@ -315,47 +345,8 @@ class HSRequest : public Module
|
||||
|
||||
~HSRequest()
|
||||
{
|
||||
/* Clean up all open host requests */
|
||||
while (!Requests.empty())
|
||||
{
|
||||
delete Requests.begin()->second;
|
||||
Requests.erase(Requests.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void OnDelNick(NickAlias *na)
|
||||
{
|
||||
RequestMap::iterator it = Requests.find(na->nick);
|
||||
|
||||
if (it != Requests.end())
|
||||
{
|
||||
delete it->second;
|
||||
Requests.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params[0].equals_ci("HS_REQUEST") && params.size() >= 5)
|
||||
{
|
||||
Anope::string vident = params[2].equals_ci("(null)") ? "" : params[2];
|
||||
my_add_host_request(params[1], vident, params[3], params[1], params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
{
|
||||
for (RequestMap::iterator it = Requests.begin(), it_end = Requests.end(); it != it_end; ++it)
|
||||
{
|
||||
HostRequest *hr = it->second;
|
||||
std::stringstream buf;
|
||||
buf << "HS_REQUEST " << it->first << " " << (hr->ident.empty() ? "(null)" : hr->ident) << " " << hr->host << " " << hr->time;
|
||||
Write(buf.str());
|
||||
}
|
||||
for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
|
||||
it->second->Shrink("hs_request");
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
@@ -393,28 +384,4 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An
|
||||
}
|
||||
}
|
||||
|
||||
void my_add_host_request(const Anope::string &nick, const Anope::string &vIdent, const Anope::string &vhost, const Anope::string &creator, time_t tmp_time)
|
||||
{
|
||||
HostRequest *hr = new HostRequest;
|
||||
hr->ident = vIdent;
|
||||
hr->host = vhost;
|
||||
hr->time = tmp_time;
|
||||
RequestMap::iterator it = Requests.find(nick);
|
||||
if (it != Requests.end())
|
||||
{
|
||||
delete it->second;
|
||||
Requests.erase(it);
|
||||
}
|
||||
Requests.insert(std::make_pair(nick, hr));
|
||||
}
|
||||
|
||||
void my_load_config()
|
||||
{
|
||||
ConfigReader config;
|
||||
HSRequestMemoUser = config.ReadFlag("hs_request", "memouser", "no", 0);
|
||||
HSRequestMemoOper = config.ReadFlag("hs_request", "memooper", "no", 0);
|
||||
|
||||
Log(LOG_DEBUG) << "[hs_request] Set config vars: MemoUser=" << HSRequestMemoUser << " MemoOper=" << HSRequestMemoOper;
|
||||
}
|
||||
|
||||
MODULE_INIT(HSRequest)
|
||||
|
||||
@@ -13,66 +13,113 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct AJoinList : std::vector<std::pair<Anope::string, Anope::string> >, ExtensibleItem, Serializable<AJoinList>
|
||||
{
|
||||
NickCore *nc;
|
||||
|
||||
AJoinList(NickCore *n) : nc(n) { }
|
||||
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data sd;
|
||||
|
||||
sd["nc"] << this->nc->display;
|
||||
Anope::string channels;
|
||||
for (unsigned i = 0; i < this->size(); ++i)
|
||||
channels += this->at(i).first + "," + this->at(i).second;
|
||||
sd["channels"] << channels;
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &sd)
|
||||
{
|
||||
NickCore *nc = findcore(sd["nc"].astr());
|
||||
if (nc == NULL)
|
||||
return;
|
||||
|
||||
AJoinList *aj = new AJoinList(nc);
|
||||
nc->Extend("ns_ajoin_channels", aj);
|
||||
|
||||
Anope::string token;
|
||||
spacesepstream ssep(sd["channels"].astr());
|
||||
while (ssep.GetToken(token))
|
||||
{
|
||||
size_t c = token.find(',');
|
||||
Anope::string chan, key;
|
||||
if (c == Anope::string::npos)
|
||||
chan = token;
|
||||
else
|
||||
{
|
||||
chan = token.substr(0, c);
|
||||
key = token.substr(c + 1);
|
||||
}
|
||||
|
||||
aj->push_back(std::make_pair(chan, key));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CommandNSAJoin : public Command
|
||||
{
|
||||
void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
source.u->Account()->GetExtRegular("ns_ajoin_channels", channels);
|
||||
AJoinList *channels = source.u->Account()->GetExt<AJoinList *>("ns_ajoin_channels");
|
||||
|
||||
if (channels.empty())
|
||||
if (channels == NULL || channels->empty())
|
||||
source.Reply(_("Your auto join list is empty."));
|
||||
else
|
||||
{
|
||||
source.Reply(_("Your auto join list:\n"
|
||||
" Num Channel Key"));
|
||||
for (unsigned i = 0; i < channels.size(); ++i)
|
||||
source.Reply(" %3d %-12s %s", i + 1, channels[i].first.c_str(), channels[i].second.c_str());
|
||||
for (unsigned i = 0; i < channels->size(); ++i)
|
||||
source.Reply(" %3d %-12s %s", i + 1, channels->at(i).first.c_str(), channels->at(i).second.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
source.u->Account()->GetExtRegular("ns_ajoin_channels", channels);
|
||||
AJoinList *channels = source.u->Account()->GetExt<AJoinList *>("ns_ajoin_channels");
|
||||
if (channels == NULL)
|
||||
{
|
||||
channels = new AJoinList(source.u->Account());
|
||||
source.u->Account()->Extend("ns_ajoin_channels", channels);
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < channels.size(); ++i)
|
||||
if (channels[i].first.equals_ci(params[1]))
|
||||
break;
|
||||
unsigned i = 0;
|
||||
if (channels != NULL)
|
||||
for (; i < channels->size(); ++i)
|
||||
if (channels->at(i).first.equals_ci(params[1]))
|
||||
break;
|
||||
|
||||
if (channels.size() >= Config->AJoinMax)
|
||||
if (channels->size() >= Config->AJoinMax)
|
||||
source.Reply(_("Your auto join list is full."));
|
||||
else if (i != channels.size())
|
||||
else if (i != channels->size())
|
||||
source.Reply(_("%s is already on your auto join list."), params[1].c_str());
|
||||
else if (ircdproto->IsChannelValid(params[1]) == false)
|
||||
source.Reply(CHAN_X_INVALID, params[1].c_str());
|
||||
else
|
||||
{
|
||||
channels.push_back(std::make_pair(params[1], params.size() > 2 ? params[2] : ""));
|
||||
channels->push_back(std::make_pair(params[1], params.size() > 2 ? params[2] : ""));
|
||||
source.Reply(_("Added %s to your auto join list."), params[1].c_str());
|
||||
source.u->Account()->Extend("ns_ajoin_channels", new ExtensibleItemRegular<std::vector<
|
||||
std::pair<Anope::string, Anope::string> > >(channels));
|
||||
}
|
||||
}
|
||||
|
||||
void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
source.u->Account()->GetExtRegular("ns_ajoin_channels", channels);
|
||||
AJoinList *channels = source.u->Account()->GetExt<AJoinList *>("ns_ajoin_channels");
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < channels.size(); ++i)
|
||||
if (channels[i].first.equals_ci(params[1]))
|
||||
break;
|
||||
unsigned i = 0;
|
||||
if (channels != NULL)
|
||||
for (; i < channels->size(); ++i)
|
||||
if (channels->at(i).first.equals_ci(params[1]))
|
||||
break;
|
||||
|
||||
if (i == channels.size())
|
||||
if (channels == NULL || i == channels->size())
|
||||
source.Reply(_("%s was not found on your auto join list."), params[1].c_str());
|
||||
else
|
||||
{
|
||||
channels.erase(channels.begin() + i);
|
||||
source.u->Account()->Extend("ns_ajoin_channels", new ExtensibleItemRegular<std::vector<
|
||||
std::pair<Anope::string, Anope::string> > >(channels));
|
||||
channels->erase(channels->begin() + i);
|
||||
source.Reply(_("%s was removed from your auto join list."), params[1].c_str());
|
||||
}
|
||||
}
|
||||
@@ -120,25 +167,28 @@ class NSAJoin : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
|
||||
Implementation i[] = { I_OnNickIdentify, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata };
|
||||
Implementation i[] = { I_OnNickIdentify };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
Serializable<AJoinList>::Alloc.Register("AJoinList");
|
||||
}
|
||||
|
||||
void OnNickIdentify(User *u)
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
u->Account()->GetExtRegular("ns_ajoin_channels", channels);
|
||||
AJoinList *channels = u->Account()->GetExt<AJoinList *>("ns_ajoin_channels");
|
||||
|
||||
for (unsigned i = 0; i < channels.size(); ++i)
|
||||
if (channels == NULL)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < channels->size(); ++i)
|
||||
{
|
||||
Channel *c = findchan(channels[i].first);
|
||||
ChannelInfo *ci = c != NULL ? c->ci : cs_findchan(channels[i].first);
|
||||
Channel *c = findchan(channels->at(i).first);
|
||||
ChannelInfo *ci = c != NULL ? c->ci : cs_findchan(channels->at(i).first);
|
||||
if (c == NULL && ci != NULL)
|
||||
c = ci->c;
|
||||
|
||||
bool need_invite = false;
|
||||
Anope::string key = channels[i].second;
|
||||
Anope::string key = channels->at(i).second;
|
||||
|
||||
if (ci != NULL)
|
||||
{
|
||||
@@ -192,54 +242,12 @@ class NSAJoin : public Module
|
||||
BotInfo *bi = findbot(Config->NickServ);
|
||||
if (!bi || !ci->AccessFor(u).HasPriv("INVITE"))
|
||||
continue;
|
||||
ircdproto->SendInvite(bi, channels[i].first, u->nick);
|
||||
ircdproto->SendInvite(bi, channels->at(i).first, u->nick);
|
||||
}
|
||||
|
||||
ircdproto->SendSVSJoin(Config->NickServ, u->nick, channels[i].first, key);
|
||||
ircdproto->SendSVSJoin(Config->NickServ, u->nick, channels->at(i).first, key);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickCore *nc)
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
nc->GetExtRegular("ns_ajoin_channels", channels);
|
||||
|
||||
Anope::string chans;
|
||||
for (unsigned i = 0; i < channels.size(); ++i)
|
||||
chans += " " + channels[i].first + "," + channels[i].second;
|
||||
|
||||
if (!chans.empty())
|
||||
{
|
||||
chans.erase(chans.begin());
|
||||
WriteMetadata("NS_AJOIN", chans);
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key == "NS_AJOIN")
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > channels;
|
||||
nc->GetExtRegular("ns_ajoin_channels", channels);
|
||||
|
||||
for (unsigned i = 0; i < params.size(); ++i)
|
||||
{
|
||||
Anope::string chan, chankey;
|
||||
commasepstream sep(params[i]);
|
||||
sep.GetToken(chan);
|
||||
sep.GetToken(chankey);
|
||||
|
||||
channels.push_back(std::make_pair(chan, chankey));
|
||||
}
|
||||
|
||||
nc->Extend("ns_ajoin_channels", new ExtensibleItemRegular<std::vector<
|
||||
std::pair<Anope::string, Anope::string> > >(channels));
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSAJoin)
|
||||
|
||||
@@ -46,8 +46,8 @@ class CommandNSConfirm : public Command
|
||||
}
|
||||
else if (u->Account())
|
||||
{
|
||||
Anope::string code;
|
||||
if (u->Account()->GetExtRegular<Anope::string>("ns_register_passcode", code) && code == passcode)
|
||||
Anope::string *code = u->Account()->GetExt<Anope::string *>("ns_register_passcode");
|
||||
if (code != NULL && *code == passcode)
|
||||
{
|
||||
u->Account()->Shrink("ns_register_passcode");
|
||||
Log(LOG_COMMAND, u, this) << "to confirm their email";
|
||||
@@ -320,8 +320,9 @@ class NSRegister : public Module
|
||||
|
||||
static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi)
|
||||
{
|
||||
Anope::string code;
|
||||
if (na->nc->GetExtRegular<Anope::string>("ns_register_passcode", code) == false)
|
||||
Anope::string *code = na->nc->GetExt<Anope::string *>("ns_register_passcode");
|
||||
Anope::string codebuf;
|
||||
if (code == NULL)
|
||||
{
|
||||
int chars[] = {
|
||||
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
@@ -332,20 +333,22 @@ static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi)
|
||||
};
|
||||
int idx, min = 1, max = 62;
|
||||
for (idx = 0; idx < 9; ++idx)
|
||||
code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
|
||||
na->nc->Extend("ns_register_passcode", new ExtensibleItemRegular<Anope::string>(code));
|
||||
codebuf += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
|
||||
na->nc->Extend("ns_register_passcode", new ExtensibleString(codebuf));
|
||||
}
|
||||
else
|
||||
codebuf = *code;
|
||||
|
||||
Anope::string subject = translate(na->nc, Config->MailRegistrationSubject.c_str());
|
||||
Anope::string message = translate(na->nc, Config->MailRegistrationMessage.c_str());
|
||||
|
||||
subject = subject.replace_all_cs("%n", na->nick);
|
||||
subject = subject.replace_all_cs("%N", Config->NetworkName);
|
||||
subject = subject.replace_all_cs("%c", code);
|
||||
subject = subject.replace_all_cs("%c", codebuf);
|
||||
|
||||
message = message.replace_all_cs("%n", na->nick);
|
||||
message = message.replace_all_cs("%N", Config->NetworkName);
|
||||
message = message.replace_all_cs("%c", code);
|
||||
message = message.replace_all_cs("%c", codebuf);
|
||||
|
||||
return Mail(u, na->nc, bi, subject, message);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,12 @@ class CommandNSResetPass : public Command
|
||||
}
|
||||
};
|
||||
|
||||
struct ResetInfo : ExtensibleItem
|
||||
{
|
||||
Anope::string code;
|
||||
time_t time;
|
||||
};
|
||||
|
||||
class NSResetPass : public Module
|
||||
{
|
||||
CommandNSResetPass commandnsresetpass;
|
||||
@@ -80,28 +86,25 @@ class NSResetPass : public Module
|
||||
User *u = source.u;
|
||||
NickAlias *na = findnick(params[0]);
|
||||
|
||||
time_t t;
|
||||
Anope::string c;
|
||||
if (na && na->nc->GetExtRegular("ns_resetpass_code", c) && na->nc->GetExtRegular("ns_resetpass_time", t))
|
||||
ResetInfo *ri = na ? na->nc->GetExt<ResetInfo *>("ns_resetpass") : NULL;
|
||||
if (na && ri)
|
||||
{
|
||||
const Anope::string &passcode = params[1];
|
||||
if (t < Anope::CurTime - 3600)
|
||||
if (ri->time < Anope::CurTime - 3600)
|
||||
{
|
||||
na->nc->Shrink("ns_resetpass_code");
|
||||
na->nc->Shrink("ns_resetpass_time");
|
||||
na->nc->Shrink("ns_resetpass");
|
||||
source.Reply(_("Your password reset request has expired."));
|
||||
}
|
||||
else if (passcode.equals_cs(c))
|
||||
else if (passcode.equals_cs(ri->code))
|
||||
{
|
||||
na->nc->Shrink("ns_resetpass_code");
|
||||
na->nc->Shrink("ns_resetpass_time");
|
||||
na->nc->Shrink("ns_resetpass");
|
||||
|
||||
Log(LOG_COMMAND, u, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify to " << na->nick;
|
||||
|
||||
na->nc->UnsetFlag(NI_UNCONFIRMED);
|
||||
u->Identify(na);
|
||||
|
||||
source.Reply(_("You are now identified for your nick. Change your passwor now."));
|
||||
source.Reply(_("You are now identified for your nick. Change your password now."));
|
||||
|
||||
}
|
||||
else
|
||||
@@ -142,8 +145,10 @@ static bool SendResetEmail(User *u, NickAlias *na, BotInfo *bi)
|
||||
message = message.replace_all_cs("%N", Config->NetworkName);
|
||||
message = message.replace_all_cs("%c", passcode);
|
||||
|
||||
na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<Anope::string>(passcode));
|
||||
na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(Anope::CurTime));
|
||||
ResetInfo *ri = new ResetInfo;
|
||||
ri->code = passcode;
|
||||
ri->time = Anope::CurTime;
|
||||
na->nc->Extend("ns_resetpass", ri);
|
||||
|
||||
return Mail(u, na->nc, bi, subject, message);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ static bool SendConfirmMail(User *u, BotInfo *bi)
|
||||
Anope::string code;
|
||||
for (idx = 0; idx < 9; ++idx)
|
||||
code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
|
||||
u->Account()->Extend("ns_set_email_passcode", new ExtensibleItemRegular<Anope::string>(code));
|
||||
u->Account()->Extend("ns_set_email_passcode", new ExtensibleString(code));
|
||||
|
||||
Anope::string subject = Config->MailEmailchangeSubject;
|
||||
Anope::string message = Config->MailEmailchangeMessage;
|
||||
@@ -80,7 +80,7 @@ class CommandNSSetEmail : public Command
|
||||
|
||||
if (!param.empty() && Config->NSConfirmEmailChanges && !u->IsServicesOper())
|
||||
{
|
||||
u->Account()->Extend("ns_set_email", new ExtensibleItemRegular<Anope::string>(param));
|
||||
u->Account()->Extend("ns_set_email", new ExtensibleString(param));
|
||||
Anope::string old = u->Account()->email;
|
||||
u->Account()->email = param;
|
||||
if (SendConfirmMail(u, source.owner))
|
||||
@@ -163,12 +163,12 @@ class NSSetEmail : public Module
|
||||
User *u = source.u;
|
||||
if (command->name == "nickserv/confirm" && !params.empty() && u->IsIdentified())
|
||||
{
|
||||
Anope::string new_email, passcode;
|
||||
if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode))
|
||||
Anope::string *new_email = u->Account()->GetExt<Anope::string *>("ns_set_email"), *passcode = u->Account()->GetExt<Anope::string *>("ns_set_email_passcode");
|
||||
if (new_email && passcode)
|
||||
{
|
||||
if (params[0] == passcode)
|
||||
if (params[0] == *passcode)
|
||||
{
|
||||
u->Account()->email = new_email;
|
||||
u->Account()->email = *new_email;
|
||||
Log(LOG_COMMAND, u, command) << "to confirm their email address change to " << u->Account()->email;
|
||||
source.Reply(_("Your email address has been changed to \002%s\002."), u->Account()->email.c_str());
|
||||
u->Account()->Shrink("ns_set_email");
|
||||
|
||||
@@ -13,6 +13,38 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct MiscData : Anope::string, ExtensibleItem, Serializable<MiscData>
|
||||
{
|
||||
NickCore *nc;
|
||||
Anope::string name;
|
||||
Anope::string data;
|
||||
|
||||
MiscData(NickCore *ncore, const Anope::string &n, const Anope::string &d) : nc(ncore), name(n), data(d)
|
||||
{
|
||||
}
|
||||
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data sdata;
|
||||
|
||||
sdata["nc"] << this->nc->display;
|
||||
sdata["name"] << this->name;
|
||||
sdata["data"] << this->data;
|
||||
|
||||
return sdata;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &data)
|
||||
{
|
||||
NickCore *nc = findcore(data["nc"].astr());
|
||||
if (nc == NULL)
|
||||
return;
|
||||
|
||||
nc->Extend(data["name"].astr(), new MiscData(nc, data["name"].astr(), data["data"].astr()));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CommandNSSetMisc : public Command
|
||||
{
|
||||
public:
|
||||
@@ -31,10 +63,11 @@ class CommandNSSetMisc : public Command
|
||||
}
|
||||
NickCore *nc = na->nc;
|
||||
|
||||
nc->Shrink("ns_set_misc:" + source.command.replace_all_cs(" ", "_"));
|
||||
Anope::string key = "ns_set_misc:" + source.command.replace_all_cs(" ", "_");
|
||||
nc->Shrink(key);
|
||||
if (!param.empty())
|
||||
{
|
||||
nc->Extend("ns_set_misc:" + source.command.replace_all_cs(" ", "_"), new ExtensibleItemRegular<Anope::string>(param));
|
||||
nc->Extend(key, new MiscData(nc, key, param));
|
||||
source.Reply(CHAN_SETTING_CHANGED, source.command.c_str(), nc->display.c_str(), param.c_str());
|
||||
}
|
||||
else
|
||||
@@ -75,9 +108,10 @@ class NSSetMisc : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnNickInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata };
|
||||
Implementation i[] = { I_OnNickInfo };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
Serializable<MiscData>::Alloc.Register("NSMisc");
|
||||
}
|
||||
|
||||
void OnNickInfo(CommandSource &source, NickAlias *na, bool ShowHidden)
|
||||
@@ -90,35 +124,11 @@ class NSSetMisc : public Module
|
||||
if (list[i].find("ns_set_misc:") != 0)
|
||||
continue;
|
||||
|
||||
Anope::string value;
|
||||
if (na->nc->GetExtRegular(list[i], value))
|
||||
source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), value.c_str());
|
||||
MiscData *data = na->nc->GetExt<MiscData *>(list[i]);
|
||||
if (data)
|
||||
source.Reply(" %s: %s", list[i].substr(12).replace_all_cs("_", " ").c_str(), data->data.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void OnDatabaseWriteMetadata(void (*WriteMetadata)(const Anope::string &, const Anope::string &), NickCore *nc)
|
||||
{
|
||||
std::deque<Anope::string> list;
|
||||
nc->GetExtList(list);
|
||||
|
||||
for (unsigned i = 0; i < list.size(); ++i)
|
||||
{
|
||||
if (list[i].find("ns_set_misc:") != 0)
|
||||
continue;
|
||||
|
||||
Anope::string value;
|
||||
if (nc->GetExtRegular(list[i], value))
|
||||
WriteMetadata(list[i], ":" + value);
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.find("ns_set_misc:") == 0)
|
||||
nc->Extend(key, new ExtensibleItemRegular<Anope::string>(params[0]));
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(NSSetMisc)
|
||||
|
||||
@@ -214,10 +214,11 @@ class OSForbid : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnUserConnect, I_OnUserNickChange, I_OnJoinChannel, I_OnPreCommand, I_OnDatabaseWrite, I_OnDatabaseRead };
|
||||
Implementation i[] = { I_OnUserConnect, I_OnUserNickChange, I_OnJoinChannel, I_OnPreCommand };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
|
||||
Serializable<ForbidData>::Alloc.Register("Forbid");
|
||||
}
|
||||
|
||||
void OnUserConnect(dynamic_reference<User> &u, bool &exempt)
|
||||
@@ -301,48 +302,6 @@ class OSForbid : public Module
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
{
|
||||
std::vector<ForbidData *> forbids = this->forbidService.GetForbids();
|
||||
for (unsigned i = 0; i < forbids.size(); ++i)
|
||||
{
|
||||
ForbidData *f = forbids[i];
|
||||
Anope::string ftype;
|
||||
if (f->type == FT_NICK)
|
||||
ftype = "NICK";
|
||||
else if (f->type == FT_CHAN)
|
||||
ftype = "CHAN";
|
||||
else if (f->type == FT_EMAIL)
|
||||
ftype = "EMAIL";
|
||||
Write("FORBID " + f->mask + " " + f->creator + " " + stringify(f->created) + " " + stringify(f->expires) + " " + ftype + " " + f->reason);
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params.size() > 5 && params[0] == "FORBID")
|
||||
{
|
||||
ForbidData *f = new ForbidData();
|
||||
f->mask = params[1];
|
||||
f->creator = params[2];
|
||||
f->created = convertTo<time_t>(params[3]);
|
||||
f->expires = convertTo<time_t>(params[4]);
|
||||
if (params[5] == "NICK")
|
||||
f->type = FT_NICK;
|
||||
else if (params[5] == "CHAN")
|
||||
f->type = FT_CHAN;
|
||||
else if (params[5] == "EMAIL")
|
||||
f->type = FT_EMAIL;
|
||||
else
|
||||
f->type = FT_NONE;
|
||||
f->reason = params.size() > 6 ? params[6] : "";
|
||||
|
||||
this->forbidService.AddForbid(f);
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(OSForbid)
|
||||
|
||||
@@ -9,7 +9,7 @@ enum ForbidType
|
||||
FT_EMAIL
|
||||
};
|
||||
|
||||
struct ForbidData
|
||||
struct ForbidData : Serializable<ForbidData>
|
||||
{
|
||||
Anope::string mask;
|
||||
Anope::string creator;
|
||||
@@ -17,6 +17,9 @@ struct ForbidData
|
||||
time_t created;
|
||||
time_t expires;
|
||||
ForbidType type;
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &data);
|
||||
};
|
||||
|
||||
class ForbidService : public Service<Base>
|
||||
@@ -33,5 +36,40 @@ class ForbidService : public Service<Base>
|
||||
virtual const std::vector<ForbidData *> &GetForbids() = 0;
|
||||
};
|
||||
|
||||
static service_reference<ForbidService, Base> forbid_service("forbid");
|
||||
|
||||
SerializableBase::serialized_data ForbidData::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["creator"] << this->creator;
|
||||
data["reason"] << this->reason;
|
||||
data["created"] << this->created;
|
||||
data["expires"] << this->expires;
|
||||
data["type"] << this->type;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ForbidData::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (!forbid_service)
|
||||
return;
|
||||
|
||||
ForbidData *fb = new ForbidData;
|
||||
|
||||
data["mask"] >> fb->mask;
|
||||
data["creator"] >> fb->creator;
|
||||
data["reason"] >> fb->reason;
|
||||
data["created"] >> fb->created;
|
||||
data["expires"] >> fb->expires;
|
||||
unsigned int t;
|
||||
data["type"] >> t;
|
||||
fb->type = static_cast<ForbidType>(t);
|
||||
|
||||
forbid_service->AddForbid(fb);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
class OSIgnoreService : public IgnoreService
|
||||
{
|
||||
public:
|
||||
OSIgnoreService(Module *o, const Anope::string &n) : IgnoreService(o, n) { }
|
||||
OSIgnoreService(Module *o) : IgnoreService(o) { }
|
||||
|
||||
void AddIgnore(const Anope::string &mask, const Anope::string &creator, const Anope::string &reason, time_t delta = Anope::CurTime)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ class OSIgnoreService : public IgnoreService
|
||||
}
|
||||
|
||||
/* Check whether the entry has timed out */
|
||||
if (ign != ign_end)// && (*ign)->time && (*ign)->time <= Anope::CurTime)
|
||||
if (ign != ign_end)
|
||||
{
|
||||
IgnoreData &id = *ign;
|
||||
|
||||
@@ -146,7 +146,6 @@ class CommandOSIgnore : public Command
|
||||
private:
|
||||
void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
if (!ignore_service)
|
||||
return;
|
||||
|
||||
@@ -181,7 +180,6 @@ class CommandOSIgnore : public Command
|
||||
|
||||
void DoList(CommandSource &source)
|
||||
{
|
||||
service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
if (!ignore_service)
|
||||
return;
|
||||
|
||||
@@ -205,7 +203,6 @@ class CommandOSIgnore : public Command
|
||||
|
||||
void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
if (!ignore_service)
|
||||
return;
|
||||
|
||||
@@ -222,7 +219,6 @@ class CommandOSIgnore : public Command
|
||||
|
||||
void DoClear(CommandSource &source)
|
||||
{
|
||||
service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
if (!ignore_service)
|
||||
return;
|
||||
|
||||
@@ -287,53 +283,15 @@ class OSIgnore : public Module
|
||||
|
||||
public:
|
||||
OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE),
|
||||
osignoreservice(this, "ignore"), commandosignore(this)
|
||||
osignoreservice(this), commandosignore(this)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
|
||||
Implementation i[] = { I_OnDatabaseRead, I_OnDatabaseWrite, I_OnBotPrivmsg };
|
||||
Implementation i[] = { I_OnBotPrivmsg };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params.size() >= 4 && params[0].equals_ci("OS") && params[1].equals_ci("IGNORE"))
|
||||
{
|
||||
service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
if (ignore_service)
|
||||
{
|
||||
const Anope::string &mask = params[2];
|
||||
time_t time = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : 0;
|
||||
const Anope::string &creator = params.size() > 4 ? params[4] : "";
|
||||
const Anope::string &reason = params.size() > 5 ? params[5] : "";
|
||||
ignore_service->AddIgnore(mask, creator, reason, time - Anope::CurTime);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
{
|
||||
for (std::list<IgnoreData>::iterator ign = this->osignoreservice.GetIgnores().begin(), ign_end = this->osignoreservice.GetIgnores().end(); ign != ign_end; )
|
||||
{
|
||||
if (ign->time && ign->time <= Anope::CurTime)
|
||||
{
|
||||
Log(LOG_DEBUG) << "[os_ignore] Expiring ignore entry " << ign->mask;
|
||||
ign = this->osignoreservice.GetIgnores().erase(ign);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << "OS IGNORE " << ign->mask << " " << ign->time << " " << ign->creator << " :" << ign->reason;
|
||||
Write(buf.str());
|
||||
++ign;
|
||||
}
|
||||
}
|
||||
Serializable<IgnoreData>::Alloc.Register("Ignore");
|
||||
}
|
||||
|
||||
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message)
|
||||
|
||||
@@ -10,12 +10,15 @@
|
||||
*/
|
||||
|
||||
|
||||
struct IgnoreData
|
||||
struct IgnoreData : Serializable<IgnoreData>
|
||||
{
|
||||
Anope::string mask;
|
||||
Anope::string creator;
|
||||
Anope::string reason;
|
||||
time_t time; /* When do we stop ignoring them? */
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &data);
|
||||
};
|
||||
|
||||
class IgnoreService : public Service<Base>
|
||||
@@ -23,7 +26,7 @@ class IgnoreService : public Service<Base>
|
||||
protected:
|
||||
std::list<IgnoreData> ignores;
|
||||
|
||||
IgnoreService(Module *c, const Anope::string &n) : Service<Base>(c, n) { }
|
||||
IgnoreService(Module *c) : Service<Base>(c, "ignore") { }
|
||||
|
||||
public:
|
||||
virtual void AddIgnore(const Anope::string &mask, const Anope::string &creator, const Anope::string &reason, time_t delta = Anope::CurTime) = 0;
|
||||
@@ -37,3 +40,28 @@ class IgnoreService : public Service<Base>
|
||||
inline std::list<IgnoreData> &GetIgnores() { return this->ignores; }
|
||||
};
|
||||
|
||||
static service_reference<IgnoreService, Base> ignore_service("ignore");
|
||||
|
||||
SerializableBase::serialized_data IgnoreData::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["creator"] << this->creator;
|
||||
data["reason"] << this->reason;
|
||||
data["time"] << this->time;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void IgnoreData::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (!ignore_service)
|
||||
return;
|
||||
|
||||
time_t t;
|
||||
data["time"] >> t;
|
||||
|
||||
ignore_service->AddIgnore(data["mask"].astr(), data["creator"].astr(), data["reason"].astr(), t);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class CommandOSLogin : public Command
|
||||
source.Reply(_("No oper block for your nick."));
|
||||
else if (o->password.empty())
|
||||
source.Reply(_("Your oper block doesn't require logging in."));
|
||||
else if (source.u->GetExt("os_login_password_correct"))
|
||||
else if (source.u->HasExt("os_login_password_correct"))
|
||||
source.Reply(_("You are already identified."));
|
||||
else if (o->password != password)
|
||||
{
|
||||
@@ -42,7 +42,7 @@ class CommandOSLogin : public Command
|
||||
else
|
||||
{
|
||||
Log(LOG_ADMIN, source.u, this) << "and successfully identified to " << source.owner->nick;
|
||||
source.u->Extend("os_login_password_correct");
|
||||
source.u->Extend("os_login_password_correct", NULL);
|
||||
source.Reply(_("Password accepted."));
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class OSLogin : public Module
|
||||
{
|
||||
if (!u->Account()->o->password.empty())
|
||||
{
|
||||
if (u->GetExt("os_login_password_correct"))
|
||||
if (u->HasExt("os_login_password_correct"))
|
||||
return EVENT_ALLOW;
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
@@ -32,13 +32,6 @@ class CommandOSModLoad : public Command
|
||||
{
|
||||
ircdproto->SendGlobops(source.owner, "%s loaded module %s", u->nick.c_str(), mname.c_str());
|
||||
source.Reply(_("Module \002%s\002 loaded"), mname.c_str());
|
||||
|
||||
/* If a user is loading this module, then the core databases have already been loaded
|
||||
* so trigger the event manually
|
||||
*/
|
||||
Module *m = ModuleManager::FindModule(mname);
|
||||
if (m)
|
||||
m->OnPostLoadDatabases();
|
||||
}
|
||||
else if (status == MOD_ERR_EXISTS)
|
||||
source.Reply(_("Module \002%s\002 is already loaded."), mname.c_str());
|
||||
@@ -100,13 +93,6 @@ class CommandOSModReLoad : public Command
|
||||
{
|
||||
ircdproto->SendGlobops(source.owner, "%s reloaded module %s", u->nick.c_str(), mname.c_str());
|
||||
source.Reply(_("Module \002%s\002 reloaded"), mname.c_str());
|
||||
|
||||
/* If a user is loading this module, then the core databases have already been loaded
|
||||
* so trigger the event manually
|
||||
*/
|
||||
m = ModuleManager::FindModule(mname);
|
||||
if (m)
|
||||
m->OnPostLoadDatabases();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -377,9 +377,10 @@ class OSNews : public Module
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
|
||||
Implementation i[] = { I_OnUserModeSet, I_OnUserConnect, I_OnDatabaseRead, I_OnDatabaseWrite };
|
||||
Implementation i[] = { I_OnUserModeSet, I_OnUserConnect };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
Serializable<NewsItem>::Alloc.Register("NewsItem");
|
||||
}
|
||||
|
||||
void OnUserModeSet(User *u, UserModeName Name)
|
||||
@@ -396,51 +397,6 @@ class OSNews : public Module
|
||||
DisplayNews(user, NEWS_LOGON);
|
||||
DisplayNews(user, NEWS_RANDOM);
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params[0].equals_ci("OS") && params.size() >= 7 && params[1].equals_ci("NEWS"))
|
||||
{
|
||||
NewsItem *n = new NewsItem();
|
||||
// params[2] was news number
|
||||
n->time = params[3].is_number_only() ? convertTo<time_t>(params[3]) : 0;
|
||||
n->who = params[4];
|
||||
if (params[5].equals_ci("LOGON"))
|
||||
n->type = NEWS_LOGON;
|
||||
else if (params[5].equals_ci("RANDOM"))
|
||||
n->type = NEWS_RANDOM;
|
||||
else if (params[5].equals_ci("OPER"))
|
||||
n->type = NEWS_OPER;
|
||||
n->text = params[6];
|
||||
|
||||
this->newsservice.AddNewsItem(n);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
{
|
||||
for (unsigned i = 0; i < 3; ++i)
|
||||
{
|
||||
std::vector<NewsItem *> &list = this->newsservice.GetNewsList(static_cast<NewsType>(i));
|
||||
for (std::vector<NewsItem *>::iterator it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
NewsItem *n = *it;
|
||||
Anope::string ntype;
|
||||
if (n->type == NEWS_LOGON)
|
||||
ntype = "LOGON";
|
||||
else if (n->type == NEWS_RANDOM)
|
||||
ntype = "RANDOM";
|
||||
else if (n->type == NEWS_OPER)
|
||||
ntype = "OPER";
|
||||
Anope::string buf = "OS NEWS 0 " + stringify(n->time) + " " + n->who + " " + ntype + " :" + n->text;
|
||||
Write(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(OSNews)
|
||||
|
||||
@@ -15,12 +15,15 @@ struct NewsMessages
|
||||
const char *msgs[10];
|
||||
};
|
||||
|
||||
struct NewsItem
|
||||
struct NewsItem : Serializable<NewsItem>
|
||||
{
|
||||
NewsType type;
|
||||
Anope::string text;
|
||||
Anope::string who;
|
||||
time_t time;
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &data);
|
||||
};
|
||||
|
||||
class NewsService : public Service<Base>
|
||||
@@ -35,5 +38,36 @@ class NewsService : public Service<Base>
|
||||
virtual std::vector<NewsItem *> &GetNewsList(NewsType t) = 0;
|
||||
};
|
||||
|
||||
static service_reference<NewsService, Base> news_service("news");
|
||||
|
||||
SerializableBase::serialized_data NewsItem::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["type"] << this->type;
|
||||
data["text"] << this->text;
|
||||
data["who"] << this->who;
|
||||
data["time"] << this->time;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void NewsItem::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (!news_service)
|
||||
return;
|
||||
|
||||
NewsItem *ni = new NewsItem();
|
||||
|
||||
unsigned int t;
|
||||
data["type"] >> t;
|
||||
ni->type = static_cast<NewsType>(t);
|
||||
data["text"] >> ni->text;
|
||||
data["who"] >> ni->who;
|
||||
data["time"] >> ni->time;
|
||||
|
||||
news_service->AddNewsItem(ni);
|
||||
}
|
||||
|
||||
#endif // OS_NEWS
|
||||
|
||||
|
||||
@@ -13,6 +13,34 @@
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct MyOper : Oper, Serializable<MyOper>
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o) { }
|
||||
|
||||
serialized_data serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["name"] << this->name;
|
||||
data["type"] << this->ot->GetName();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void unserialize(serialized_data &data)
|
||||
{
|
||||
OperType *ot = OperType::Find(data["type"].astr());
|
||||
if (ot == NULL)
|
||||
return;
|
||||
NickCore *nc = findcore(data["name"].astr());
|
||||
if (nc == NULL)
|
||||
return;
|
||||
|
||||
nc->o = new MyOper(nc->display, ot);
|
||||
Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
|
||||
}
|
||||
};
|
||||
|
||||
class CommandOSOper : public Command
|
||||
{
|
||||
public:
|
||||
@@ -46,8 +74,7 @@ class CommandOSOper : public Command
|
||||
source.Reply(_("Oper type \2%s\2 has not been configured."), type.c_str());
|
||||
else
|
||||
{
|
||||
delete na->nc->o;
|
||||
na->nc->o = new Oper(na->nc->display, ot);
|
||||
na->nc->o = new MyOper(na->nc->display, ot);
|
||||
|
||||
Log(LOG_ADMIN, source.u, this) << "ADD " << na->nick << " as type " << ot->GetName();
|
||||
source.Reply("%s (%s) added to the \2%s\2 list.", na->nick.c_str(), na->nc->display.c_str(), ot->GetName().c_str());
|
||||
@@ -177,43 +204,18 @@ class OSOper : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnDatabaseWrite, I_OnDatabaseRead };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
Serializable<MyOper>::Alloc.Register("Oper");
|
||||
}
|
||||
|
||||
void OnDatabaseWrite(void (*Write)(const Anope::string &))
|
||||
~OSOper()
|
||||
{
|
||||
for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it)
|
||||
{
|
||||
NickCore *nc = it->second;
|
||||
if (!nc->o)
|
||||
continue;
|
||||
bool found = false;
|
||||
for (std::list<NickAlias *>::const_iterator it2 = nc->aliases.begin(), it2_end = nc->aliases.end(); it2 != it2_end; ++it2)
|
||||
if (Oper::Find((*it2)->nick) != NULL)
|
||||
found = true;
|
||||
if (found == false)
|
||||
{
|
||||
Write("OPER " + nc->display + " :" + nc->o->ot->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (params[0] == "OPER" && params.size() > 2)
|
||||
{
|
||||
NickCore *nc = findcore(params[1]);
|
||||
if (!nc || nc->o)
|
||||
return EVENT_CONTINUE;
|
||||
OperType *ot = OperType::Find(params[2]);
|
||||
if (ot == NULL)
|
||||
return EVENT_CONTINUE;
|
||||
nc->o = new Oper(nc->display, ot);
|
||||
Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
|
||||
if (nc->o && !nc->o->config)
|
||||
delete nc->o;
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
#include "module.h"
|
||||
#include "os_session.h"
|
||||
|
||||
static service_reference<SessionService, Base> sessionservice("session");
|
||||
|
||||
class MySessionService : public SessionService
|
||||
{
|
||||
SessionMap Sessions;
|
||||
@@ -94,18 +92,18 @@ class ExpireTimer : public Timer
|
||||
|
||||
void Tick(time_t)
|
||||
{
|
||||
if (!sessionservice)
|
||||
if (!session_service)
|
||||
return;
|
||||
for (unsigned i = sessionservice->GetExceptions().size(); i > 0; --i)
|
||||
for (unsigned i = session_service->GetExceptions().size(); i > 0; --i)
|
||||
{
|
||||
Exception *e = sessionservice->GetExceptions()[i - 1];
|
||||
Exception *e = session_service->GetExceptions()[i - 1];
|
||||
|
||||
if (!e->expires || e->expires > Anope::CurTime)
|
||||
continue;
|
||||
BotInfo *bi = findbot(Config->OperServ);
|
||||
if (Config->WallExceptionExpire && bi)
|
||||
ircdproto->SendGlobops(bi, "Session exception for %s has expired.", e->mask.c_str());
|
||||
sessionservice->DelException(e);
|
||||
session_service->DelException(e);
|
||||
delete e;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +131,7 @@ class ExceptionDelCallback : public NumberList
|
||||
|
||||
virtual void HandleNumber(unsigned Number)
|
||||
{
|
||||
if (!Number || Number > sessionservice->GetExceptions().size())
|
||||
if (!Number || Number > session_service->GetExceptions().size())
|
||||
return;
|
||||
|
||||
++Deleted;
|
||||
@@ -143,10 +141,10 @@ class ExceptionDelCallback : public NumberList
|
||||
|
||||
static void DoDel(CommandSource &source, unsigned index)
|
||||
{
|
||||
Exception *e = sessionservice->GetExceptions()[index];
|
||||
Exception *e = session_service->GetExceptions()[index];
|
||||
FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(source.u, e));
|
||||
|
||||
sessionservice->DelException(e);
|
||||
session_service->DelException(e);
|
||||
delete e;
|
||||
}
|
||||
};
|
||||
@@ -163,7 +161,7 @@ class ExceptionListCallback : public NumberList
|
||||
|
||||
virtual void HandleNumber(unsigned Number)
|
||||
{
|
||||
if (!Number || Number > sessionservice->GetExceptions().size())
|
||||
if (!Number || Number > session_service->GetExceptions().size())
|
||||
return;
|
||||
|
||||
if (!SentHeader)
|
||||
@@ -178,10 +176,10 @@ class ExceptionListCallback : public NumberList
|
||||
|
||||
static void DoList(CommandSource &source, unsigned index)
|
||||
{
|
||||
if (index >= sessionservice->GetExceptions().size())
|
||||
if (index >= session_service->GetExceptions().size())
|
||||
return;
|
||||
|
||||
source.Reply(_("%3d %4d %s"), index + 1, sessionservice->GetExceptions()[index]->limit, sessionservice->GetExceptions()[index]->mask.c_str());
|
||||
source.Reply(_("%3d %4d %s"), index + 1, session_service->GetExceptions()[index]->limit, session_service->GetExceptions()[index]->mask.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -194,7 +192,7 @@ class ExceptionViewCallback : public ExceptionListCallback
|
||||
|
||||
void HandleNumber(unsigned Number)
|
||||
{
|
||||
if (!Number || Number > sessionservice->GetExceptions().size())
|
||||
if (!Number || Number > session_service->GetExceptions().size())
|
||||
return;
|
||||
|
||||
if (!SentHeader)
|
||||
@@ -208,12 +206,12 @@ class ExceptionViewCallback : public ExceptionListCallback
|
||||
|
||||
static void DoList(CommandSource &source, unsigned index)
|
||||
{
|
||||
if (index >= sessionservice->GetExceptions().size())
|
||||
if (index >= session_service->GetExceptions().size())
|
||||
return;
|
||||
|
||||
Anope::string expirebuf = expire_left(source.u->Account(), sessionservice->GetExceptions()[index]->expires);
|
||||
Anope::string expirebuf = expire_left(source.u->Account(), session_service->GetExceptions()[index]->expires);
|
||||
|
||||
source.Reply(_("%3d. %s (by %s on %s; %s)\n " " Limit: %-4d - %s"), index + 1, sessionservice->GetExceptions()[index]->mask.c_str(), !sessionservice->GetExceptions()[index]->who.empty() ? sessionservice->GetExceptions()[index]->who.c_str() : "<unknown>", do_strftime((sessionservice->GetExceptions()[index]->time ? sessionservice->GetExceptions()[index]->time : Anope::CurTime)).c_str(), expirebuf.c_str(), sessionservice->GetExceptions()[index]->limit, sessionservice->GetExceptions()[index]->reason.c_str());
|
||||
source.Reply(_("%3d. %s (by %s on %s; %s)\n " " Limit: %-4d - %s"), index + 1, session_service->GetExceptions()[index]->mask.c_str(), !session_service->GetExceptions()[index]->who.empty() ? session_service->GetExceptions()[index]->who.c_str() : "<unknown>", do_strftime((session_service->GetExceptions()[index]->time ? session_service->GetExceptions()[index]->time : Anope::CurTime)).c_str(), expirebuf.c_str(), session_service->GetExceptions()[index]->limit, session_service->GetExceptions()[index]->reason.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -238,7 +236,7 @@ class CommandOSSession : public Command
|
||||
source.Reply(_("Hosts with at least \002%d\002 sessions:"), mincount);
|
||||
source.Reply(_("Sessions Host"));
|
||||
|
||||
for (SessionService::SessionMap::iterator it = sessionservice->GetSessions().begin(), it_end = sessionservice->GetSessions().end(); it != it_end; ++it)
|
||||
for (SessionService::SessionMap::iterator it = session_service->GetSessions().begin(), it_end = session_service->GetSessions().end(); it != it_end; ++it)
|
||||
{
|
||||
Session *session = it->second;
|
||||
|
||||
@@ -253,13 +251,13 @@ class CommandOSSession : public Command
|
||||
void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string param = params[1];
|
||||
Session *session = sessionservice->FindSession(param);
|
||||
Session *session = session_service->FindSession(param);
|
||||
|
||||
if (!session)
|
||||
source.Reply(_("\002%s\002 not found on session list."), param.c_str());
|
||||
else
|
||||
{
|
||||
Exception *exception = sessionservice->FindException(param);
|
||||
Exception *exception = session_service->FindException(param);
|
||||
source.Reply(_("The host \002%s\002 currently has \002%d\002 sessions with a limit of \002%d\002."), param.c_str(), session->count, exception ? exception-> limit : Config->DefSessionLimit);
|
||||
}
|
||||
|
||||
@@ -375,7 +373,7 @@ class CommandOSException : public Command
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::vector<Exception *>::iterator it = sessionservice->GetExceptions().begin(), it_end = sessionservice->GetExceptions().end(); it != it_end; ++it)
|
||||
for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it)
|
||||
{
|
||||
Exception *e = *it;
|
||||
if (e->mask.equals_ci(mask))
|
||||
@@ -405,7 +403,7 @@ class CommandOSException : public Command
|
||||
delete exception;
|
||||
else
|
||||
{
|
||||
sessionservice->AddException(exception);
|
||||
session_service->AddException(exception);
|
||||
source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit);
|
||||
if (readonly)
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
@@ -432,9 +430,9 @@ class CommandOSException : public Command
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned i = 0, end = sessionservice->GetExceptions().size();
|
||||
unsigned i = 0, end = session_service->GetExceptions().size();
|
||||
for (; i < end; ++i)
|
||||
if (mask.equals_ci(sessionservice->GetExceptions()[i]->mask))
|
||||
if (mask.equals_ci(session_service->GetExceptions()[i]->mask))
|
||||
{
|
||||
ExceptionDelCallback::DoDel(source, i);
|
||||
source.Reply(_("\002%s\002 deleted from session-limit exception list."), mask.c_str());
|
||||
@@ -470,13 +468,13 @@ class CommandOSException : public Command
|
||||
}
|
||||
catch (const ConvertException &) { }
|
||||
|
||||
if (n1 >= 0 && n1 < sessionservice->GetExceptions().size() && n2 >= 0 && n2 < sessionservice->GetExceptions().size() && n1 != n2)
|
||||
if (n1 >= 0 && n1 < session_service->GetExceptions().size() && n2 >= 0 && n2 < session_service->GetExceptions().size() && n1 != n2)
|
||||
{
|
||||
Exception *temp = sessionservice->GetExceptions()[n1];
|
||||
sessionservice->GetExceptions()[n1] = sessionservice->GetExceptions()[n2];
|
||||
sessionservice->GetExceptions()[n2] = temp;
|
||||
Exception *temp = session_service->GetExceptions()[n1];
|
||||
session_service->GetExceptions()[n1] = session_service->GetExceptions()[n2];
|
||||
session_service->GetExceptions()[n2] = temp;
|
||||
|
||||
source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), sessionservice->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1);
|
||||
source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), session_service->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1);
|
||||
|
||||
if (readonly)
|
||||
source.Reply(READ_ONLY_MODE);
|
||||
@@ -500,8 +498,8 @@ class CommandOSException : public Command
|
||||
{
|
||||
bool SentHeader = false;
|
||||
|
||||
for (unsigned i = 0, end = sessionservice->GetExceptions().size(); i < end; ++i)
|
||||
if (mask.empty() || Anope::Match(sessionservice->GetExceptions()[i]->mask, mask))
|
||||
for (unsigned i = 0, end = session_service->GetExceptions().size(); i < end; ++i)
|
||||
if (mask.empty() || Anope::Match(session_service->GetExceptions()[i]->mask, mask))
|
||||
{
|
||||
if (!SentHeader)
|
||||
{
|
||||
@@ -533,8 +531,8 @@ class CommandOSException : public Command
|
||||
{
|
||||
bool SentHeader = false;
|
||||
|
||||
for (unsigned i = 0, end = sessionservice->GetExceptions().size(); i < end; ++i)
|
||||
if (mask.empty() || Anope::Match(sessionservice->GetExceptions()[i]->mask, mask))
|
||||
for (unsigned i = 0, end = session_service->GetExceptions().size(); i < end; ++i)
|
||||
if (mask.empty() || Anope::Match(session_service->GetExceptions()[i]->mask, mask))
|
||||
{
|
||||
if (!SentHeader)
|
||||
{
|
||||
@@ -614,10 +612,10 @@ class CommandOSException : public Command
|
||||
"the format of the optional \037expiry\037 parameter.\n"
|
||||
"\002EXCEPTION DEL\002 removes the given mask from the exception list.\n"
|
||||
"\002EXCEPTION MOVE\002 moves exception \037num\037 to \037position\037. The\n"
|
||||
"sessionservice->GetExceptions() inbetween will be shifted up or down to fill the gap.\n"
|
||||
"sessions inbetween will be shifted up or down to fill the gap.\n"
|
||||
"\002EXCEPTION LIST\002 and \002EXCEPTION VIEW\002 show all current\n"
|
||||
"sessionservice->GetExceptions(); if the optional mask is given, the list is limited\n"
|
||||
"to those sessionservice->GetExceptions() matching the mask. The difference is that\n"
|
||||
"sessions if the optional mask is given, the list is limited\n"
|
||||
"to those sessions matching the mask. The difference is that\n"
|
||||
"\002EXCEPTION VIEW\002 is more verbose, displaying the name of the\n"
|
||||
"person who added the exception, its session limit, reason, \n"
|
||||
"host mask and the expiry date and time.\n"
|
||||
@@ -728,7 +726,7 @@ class OSSession : public Module
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
ModuleManager::SetPriority(this, PRIORITY_FIRST);
|
||||
|
||||
|
||||
Serializable<Exception>::Alloc.Register("Exception");
|
||||
}
|
||||
|
||||
void OnUserConnect(dynamic_reference<User> &user, bool &exempt)
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
#ifndef OS_SESSION_H
|
||||
#define OS_SESSION_H
|
||||
|
||||
struct Exception : Serializable<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 */
|
||||
|
||||
serialized_data serialize();
|
||||
static void unserialize(serialized_data &data);
|
||||
};
|
||||
|
||||
|
||||
class SessionService : public Service<Base>
|
||||
{
|
||||
public:
|
||||
@@ -28,5 +42,37 @@ class SessionService : public Service<Base>
|
||||
virtual SessionMap &GetSessions() = 0;
|
||||
};
|
||||
|
||||
static service_reference<SessionService, Base> session_service("session");
|
||||
|
||||
SerializableBase::serialized_data Exception::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["mask"] << this->mask;
|
||||
data["limit"] << this->limit;
|
||||
data["who"] << this->who;
|
||||
data["reason"] << this->reason;
|
||||
data["time"] << this->time;
|
||||
data["expires"] << this->expires;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Exception::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (!session_service)
|
||||
return;
|
||||
|
||||
Exception *ex = new Exception;
|
||||
data["mask"] >> ex->mask;
|
||||
data["limit"] >> ex->limit;
|
||||
data["who"] >> ex->who;
|
||||
data["reason"] >> ex->reason;
|
||||
data["time"] >> ex->time;
|
||||
data["expires"] >> ex->expires;
|
||||
|
||||
session_service->AddException(ex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ class CommandOSRestart : public Command
|
||||
{
|
||||
User *u = source.u;
|
||||
quitmsg = "RESTART command received from " + u->nick;
|
||||
save_databases();
|
||||
quitting = restarting = true;
|
||||
save_databases();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ class CommandOSShutdown : public Command
|
||||
{
|
||||
User *u = source.u;
|
||||
quitmsg = source.command + " command received from " + u->nick;
|
||||
save_databases();
|
||||
quitting = true;
|
||||
save_databases();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* (C) 2003-2011 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.
|
||||
*/
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
Anope::string DatabaseFile;
|
||||
|
||||
class DBFlatFile : public Module
|
||||
{
|
||||
/* Day the last backup was on */
|
||||
int LastDay;
|
||||
/* Backup file names */
|
||||
std::list<Anope::string> Backups;
|
||||
|
||||
SerializableBase *find(const Anope::string &sname)
|
||||
{
|
||||
for (unsigned i = 0; i < serialized_types.size(); ++i)
|
||||
if (serialized_types[i]->serialize_name() == sname)
|
||||
return serialized_types[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
DBFlatFile(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
OnReload();
|
||||
|
||||
LastDay = 0;
|
||||
}
|
||||
|
||||
void BackupDatabase()
|
||||
{
|
||||
/* Do not backup a database that doesn't exist */
|
||||
if (!IsFile(DatabaseFile))
|
||||
return;
|
||||
|
||||
time_t now = Anope::CurTime;
|
||||
tm *tm = localtime(&now);
|
||||
|
||||
if (tm->tm_mday != LastDay)
|
||||
{
|
||||
LastDay = tm->tm_mday;
|
||||
Anope::string newname = "backups/" + DatabaseFile + "." + stringify(tm->tm_year) + stringify(tm->tm_mon) + stringify(tm->tm_mday);
|
||||
|
||||
/* Backup already exists */
|
||||
if (IsFile(newname))
|
||||
return;
|
||||
|
||||
Log(LOG_DEBUG) << "db_flatfile: Attemping to rename " << DatabaseFile << " to " << newname;
|
||||
if (rename(DatabaseFile.c_str(), newname.c_str()))
|
||||
{
|
||||
Log() << "Unable to back up database!";
|
||||
|
||||
if (!Config->NoBackupOkay)
|
||||
quitting = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Backups.push_back(newname);
|
||||
|
||||
if (Config->KeepBackups > 0 && Backups.size() > static_cast<unsigned>(Config->KeepBackups))
|
||||
{
|
||||
DeleteFile(Backups.front().c_str());
|
||||
Backups.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
DatabaseFile = config.ReadValue("flatfile", "database", "anope.db", 0);
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase()
|
||||
{
|
||||
std::fstream db;
|
||||
db.open(DatabaseFile.c_str(), std::ios_base::in);
|
||||
|
||||
if (!db.is_open())
|
||||
{
|
||||
Log() << "Unable to open " << DatabaseFile << " for reading!";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
SerializableBase *sb = NULL;
|
||||
SerializableBase::serialized_data data;
|
||||
std::multimap<SerializableBase *, SerializableBase::serialized_data> objects;
|
||||
for (Anope::string buf, token; std::getline(db, buf.str());)
|
||||
{
|
||||
spacesepstream sep(buf);
|
||||
|
||||
if (!sep.GetToken(token))
|
||||
continue;
|
||||
|
||||
if (token == "OBJECT" && sep.GetToken(token))
|
||||
{
|
||||
sb = this->find(token);
|
||||
data.clear();
|
||||
}
|
||||
else if (token == "DATA" && sb != NULL && sep.GetToken(token))
|
||||
data[token] << sep.GetRemaining();
|
||||
else if (token == "END" && sb != NULL)
|
||||
{
|
||||
objects.insert(std::make_pair(sb, data));
|
||||
|
||||
sb = NULL;
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < serialized_types.size(); ++i)
|
||||
{
|
||||
SerializableBase *stype = serialized_types[i];
|
||||
|
||||
std::multimap<SerializableBase *, SerializableBase::serialized_data>::iterator it = objects.find(stype), it_end = objects.upper_bound(stype);
|
||||
if (it == objects.end())
|
||||
continue;
|
||||
for (; it != it_end; ++it)
|
||||
it->first->alloc(it->second);
|
||||
}
|
||||
|
||||
db.close();
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
|
||||
EventReturn OnSaveDatabase()
|
||||
{
|
||||
BackupDatabase();
|
||||
|
||||
Anope::string tmp_db = DatabaseFile + ".tmp";
|
||||
if (IsFile(DatabaseFile))
|
||||
rename(DatabaseFile.c_str(), tmp_db.c_str());
|
||||
|
||||
std::fstream db(DatabaseFile.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||
if (!db.is_open())
|
||||
{
|
||||
Log() << "Unable to open " << DatabaseFile << " for writing";
|
||||
if (IsFile(tmp_db))
|
||||
rename(tmp_db.c_str(), DatabaseFile.c_str());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
for (std::list<SerializableBase *>::iterator it = serialized_items.begin(), it_end = serialized_items.end(); it != it_end; ++it)
|
||||
{
|
||||
SerializableBase *base = *it;
|
||||
SerializableBase::serialized_data data = base->serialize();
|
||||
|
||||
db << "OBJECT " << base->serialize_name() << "\n";
|
||||
for (SerializableBase::serialized_data::iterator dit = data.begin(), dit_end = data.end(); dit != dit_end; ++dit)
|
||||
db << "DATA " << dit->first << " " << dit->second.astr() << "\n";
|
||||
db << "END\n";
|
||||
}
|
||||
|
||||
db.close();
|
||||
|
||||
if (db.good() == false)
|
||||
{
|
||||
Log() << "Unable to write database";
|
||||
if (!Config->NoBackupOkay)
|
||||
quitting = true;
|
||||
if (IsFile(tmp_db))
|
||||
rename(tmp_db.c_str(), DatabaseFile.c_str());
|
||||
}
|
||||
else
|
||||
DeleteFile(tmp_db.c_str());
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBFlatFile)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+333
-373
@@ -15,7 +15,14 @@
|
||||
|
||||
Anope::string DatabaseFile;
|
||||
std::stringstream db_buffer;
|
||||
service_reference<SessionService, Base> SessionInterface("session");
|
||||
|
||||
class DatabaseException : public CoreException
|
||||
{
|
||||
public:
|
||||
DatabaseException(const Anope::string &reason = "") : CoreException(reason) { }
|
||||
|
||||
virtual ~DatabaseException() throw() { }
|
||||
};
|
||||
|
||||
/** Enum used for what METADATA type we are reading
|
||||
*/
|
||||
@@ -28,6 +35,300 @@ enum MDType
|
||||
MD_CH
|
||||
};
|
||||
|
||||
static void LoadNickCore(const std::vector<Anope::string> ¶ms);
|
||||
static void LoadNickAlias(const std::vector<Anope::string> ¶ms);
|
||||
static void LoadBotInfo(const std::vector<Anope::string> ¶ms);
|
||||
static void LoadChanInfo(const std::vector<Anope::string> ¶ms);
|
||||
static void LoadOperInfo(const std::vector<Anope::string> ¶ms);
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string key = params[0];
|
||||
std::vector<Anope::string> otherparams = params;
|
||||
otherparams.erase(otherparams.begin());
|
||||
|
||||
if (key.equals_ci("NC"))
|
||||
LoadNickCore(otherparams);
|
||||
else if (key.equals_ci("NA"))
|
||||
LoadNickAlias(otherparams);
|
||||
else if (key.equals_ci("BI"))
|
||||
LoadBotInfo(otherparams);
|
||||
else if (key.equals_ci("CH"))
|
||||
LoadChanInfo(otherparams);
|
||||
else if (key.equals_ci("OS"))
|
||||
LoadOperInfo(otherparams);
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key.equals_ci("LANGUAGE"))
|
||||
nc->language = params[0];
|
||||
else if (key.equals_ci("MEMOMAX"))
|
||||
nc->memos.memomax = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : -1;
|
||||
else if (key.equals_ci("EMAIL"))
|
||||
nc->email = params[0];
|
||||
else if (key.equals_ci("GREET"))
|
||||
nc->greet = params[0];
|
||||
else if (key.equals_ci("ACCESS"))
|
||||
nc->AddAccess(params[0]);
|
||||
else if (key.equals_ci("CERT"))
|
||||
nc->AddCert(params[0]);
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
nc->FromVector(params);
|
||||
else if (key.equals_ci("MI"))
|
||||
{
|
||||
Memo *m = new Memo;
|
||||
m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
|
||||
m->sender = params[1];
|
||||
for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j)
|
||||
{
|
||||
if (params[j].equals_ci("UNREAD"))
|
||||
m->SetFlag(MF_UNREAD);
|
||||
else if (params[j].equals_ci("RECEIPT"))
|
||||
m->SetFlag(MF_RECEIPT);
|
||||
}
|
||||
m->text = params[params.size() - 1];
|
||||
nc->memos.memos.push_back(m);
|
||||
}
|
||||
else if (key.equals_ci("MIG"))
|
||||
nc->memos.ignores.push_back(params[0].ci_str());
|
||||
}
|
||||
catch (const ConvertException &ex)
|
||||
{
|
||||
throw DatabaseException(ex.GetReason());
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.equals_ci("LAST_USERMASK"))
|
||||
na->last_usermask = params[0];
|
||||
else if (key.equals_ci("LAST_REALHOST"))
|
||||
na->last_realhost = params[0];
|
||||
else if (key.equals_ci("LAST_REALNAME"))
|
||||
na->last_realname = params[0];
|
||||
else if (key.equals_ci("LAST_QUIT"))
|
||||
na->last_quit = params[0];
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
na->FromVector(params);
|
||||
else if (key.equals_ci("VHOST"))
|
||||
na->hostinfo.SetVhost(params.size() > 3 ? params[3] : "", params[2], params[0], params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0);
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(BotInfo *bi, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.equals_ci("FLAGS"))
|
||||
bi->FromVector(params);
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key.equals_ci("BANTYPE"))
|
||||
ci->bantype = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : Config->CSDefBantype;
|
||||
else if (key.equals_ci("MEMOMAX"))
|
||||
ci->memos.memomax = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : -1;
|
||||
else if (key.equals_ci("FOUNDER"))
|
||||
ci->SetFounder(findcore(params[0]));
|
||||
else if (key.equals_ci("SUCCESSOR"))
|
||||
ci->successor = findcore(params[0]);
|
||||
else if (key.equals_ci("LEVELS"))
|
||||
{
|
||||
for (unsigned j = 0, end = params.size(); j < end; j += 2)
|
||||
{
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(params[j]);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
ci->SetLevel(p->name, params[j + 1].is_number_only() ? convertTo<int16>(params[j + 1]) : 0);
|
||||
}
|
||||
}
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
ci->FromVector(params);
|
||||
else if (key.equals_ci("DESC"))
|
||||
ci->desc = params[0];
|
||||
else if (key.equals_ci("TOPIC"))
|
||||
{
|
||||
ci->last_topic_setter = params[0];
|
||||
ci->last_topic_time = params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0;
|
||||
ci->last_topic = params[2];
|
||||
}
|
||||
else if (key.equals_ci("SUSPEND"))
|
||||
{
|
||||
ci->Extend("suspend_by", new ExtensibleString(params[0]));
|
||||
ci->Extend("suspend_reason", new ExtensibleString(params[1]));
|
||||
}
|
||||
else if (key.equals_ci("ACCESS")) // Older access system, from Anope 1.9.4.
|
||||
{
|
||||
service_reference<AccessProvider> provider("access/access");
|
||||
if (!provider)
|
||||
throw DatabaseException("Old access entry for nonexistant provider");
|
||||
|
||||
ChanAccess *access = provider->Create();
|
||||
access->ci = ci;
|
||||
access->mask = params[0];
|
||||
access->Unserialize(params[1]);
|
||||
access->last_seen = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0;
|
||||
access->creator = params[3];
|
||||
access->created = Anope::CurTime;
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
else if (key.equals_ci("ACCESS2"))
|
||||
{
|
||||
service_reference<AccessProvider> provider(params[0]);
|
||||
if (!provider)
|
||||
throw DatabaseException("Access entry for nonexistant provider " + params[0]);
|
||||
|
||||
ChanAccess *access = provider->Create();
|
||||
access->ci = ci;
|
||||
access->mask = params[1];
|
||||
access->Unserialize(params[2]);
|
||||
access->last_seen = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : 0;
|
||||
access->creator = params[4];
|
||||
access->created = params.size() > 5 && params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
else if (key.equals_ci("AKICK"))
|
||||
{
|
||||
// 0 is the old stuck
|
||||
bool Nick = params[1].equals_ci("NICK");
|
||||
NickCore *nc = NULL;
|
||||
if (Nick)
|
||||
{
|
||||
nc = findcore(params[2]);
|
||||
if (!nc)
|
||||
throw DatabaseException("Akick for nonexistant core " + params[2] + " on " + ci->name);
|
||||
}
|
||||
|
||||
AutoKick *ak;
|
||||
if (Nick)
|
||||
ak = ci->AddAkick(params[3], nc, params.size() > 6 ? params[6] : "", params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0, params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0);
|
||||
else
|
||||
ak = ci->AddAkick(params[3], params[2], params.size() > 6 ? params[6] : "", params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0, params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0);
|
||||
if (Nick)
|
||||
ak->SetFlag(AK_ISNICK);
|
||||
|
||||
}
|
||||
else if (key.equals_ci("LOG"))
|
||||
{
|
||||
LogSetting l;
|
||||
|
||||
l.service_name = params[0];
|
||||
l.command_service = params[1];
|
||||
l.command_name = params[2];
|
||||
l.method = params[3];
|
||||
l.creator = params[4];
|
||||
l.created = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
|
||||
l.extra = params.size() > 6 ? params[6] : "";
|
||||
|
||||
ci->log_settings.push_back(l);
|
||||
}
|
||||
else if (key.equals_ci("MLOCK"))
|
||||
{
|
||||
bool set = params[0] == "1" ? true : false;
|
||||
Anope::string mode_name = params[1];
|
||||
Anope::string setter = params[2];
|
||||
time_t mcreated = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : Anope::CurTime;
|
||||
Anope::string param = params.size() > 4 ? params[4] : "";
|
||||
for (size_t i = CMODE_BEGIN + 1; i < CMODE_END; ++i)
|
||||
if (ChannelModeNameStrings[i] == mode_name)
|
||||
{
|
||||
ChannelModeName n = static_cast<ChannelModeName>(i);
|
||||
ci->mode_locks.insert(std::make_pair(n, ModeLock(ci, set, n, param, setter, mcreated)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (key.equals_ci("MI"))
|
||||
{
|
||||
Memo *m = new Memo;
|
||||
m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
|
||||
m->sender = params[1];
|
||||
for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j)
|
||||
{
|
||||
if (params[j].equals_ci("UNREAD"))
|
||||
m->SetFlag(MF_UNREAD);
|
||||
else if (params[j].equals_ci("RECEIPT"))
|
||||
m->SetFlag(MF_RECEIPT);
|
||||
}
|
||||
m->text = params[params.size() - 1];
|
||||
ci->memos.memos.push_back(m);
|
||||
}
|
||||
else if (key.equals_ci("MIG"))
|
||||
ci->memos.ignores.push_back(params[0].ci_str());
|
||||
else if (key.equals_ci("BI"))
|
||||
{
|
||||
if (params[0].equals_ci("NAME"))
|
||||
ci->bi = findbot(params[1]);
|
||||
else if (params[0].equals_ci("FLAGS"))
|
||||
ci->botflags.FromVector(params);
|
||||
else if (params[0].equals_ci("TTB"))
|
||||
{
|
||||
for (unsigned j = 1, end = params.size(); j < end; j += 2)
|
||||
{
|
||||
if (params[j].equals_ci("BOLDS"))
|
||||
ci->ttb[0] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("COLORS"))
|
||||
ci->ttb[1] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("REVERSES"))
|
||||
ci->ttb[2] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("UNDERLINES"))
|
||||
ci->ttb[3] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("BADWORDS"))
|
||||
ci->ttb[4] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("CAPS"))
|
||||
ci->ttb[5] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("FLOOD"))
|
||||
ci->ttb[6] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("REPEAT"))
|
||||
ci->ttb[7] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("ITALICS"))
|
||||
ci->ttb[8] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("AMSGS"))
|
||||
ci->ttb[9] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
}
|
||||
}
|
||||
else if (params[0].equals_ci("CAPSMIN"))
|
||||
ci->capsmin = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("CAPSPERCENT"))
|
||||
ci->capspercent = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("FLOODLINES"))
|
||||
ci->floodlines = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("FLOODSECS"))
|
||||
ci->floodsecs = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("REPEATTIMES"))
|
||||
ci->repeattimes = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("BADWORD"))
|
||||
{
|
||||
BadWordType Type;
|
||||
if (params[1].equals_ci("SINGLE"))
|
||||
Type = BW_SINGLE;
|
||||
else if (params[1].equals_ci("START"))
|
||||
Type = BW_START;
|
||||
else if (params[1].equals_ci("END"))
|
||||
Type = BW_END;
|
||||
else
|
||||
Type = BW_ANY;
|
||||
ci->AddBadWord(params[2], Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const ConvertException &ex)
|
||||
{
|
||||
throw DatabaseException(ex.GetReason());
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
/* 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
|
||||
@@ -39,7 +340,7 @@ static const char endl = '\n';
|
||||
*/
|
||||
static void ReadDatabase(Module *m = NULL)
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
//EventReturn MOD_RESULT;
|
||||
MDType Type = MD_NONE;
|
||||
|
||||
std::fstream db;
|
||||
@@ -81,12 +382,13 @@ static void ReadDatabase(Module *m = NULL)
|
||||
params.push_back(buf);
|
||||
}
|
||||
|
||||
if (m)
|
||||
/*if (m)
|
||||
MOD_RESULT = m->OnDatabaseRead(params);
|
||||
else
|
||||
FOREACH_RESULT(I_OnDatabaseRead, OnDatabaseRead(params));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
continue;
|
||||
continue;*/
|
||||
OnDatabaseRead(params);
|
||||
|
||||
if (!params.empty())
|
||||
{
|
||||
@@ -120,10 +422,7 @@ static void ReadDatabase(Module *m = NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m)
|
||||
m->OnDatabaseReadMetadata(nc, key, params);
|
||||
else
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nc, key, params));
|
||||
OnDatabaseReadMetadata(nc, key, params);
|
||||
}
|
||||
catch (const DatabaseException &ex)
|
||||
{
|
||||
@@ -134,10 +433,7 @@ static void ReadDatabase(Module *m = NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m)
|
||||
m->OnDatabaseReadMetadata(na, key, params);
|
||||
else
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(na, key, params));
|
||||
OnDatabaseReadMetadata(na, key, params);
|
||||
}
|
||||
catch (const DatabaseException &ex)
|
||||
{
|
||||
@@ -148,10 +444,7 @@ static void ReadDatabase(Module *m = NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m)
|
||||
m->OnDatabaseReadMetadata(bi, key, params);
|
||||
else
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(bi, key, params));
|
||||
OnDatabaseReadMetadata(bi, key, params);
|
||||
}
|
||||
catch (const DatabaseException &ex)
|
||||
{
|
||||
@@ -162,10 +455,7 @@ static void ReadDatabase(Module *m = NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m)
|
||||
m->OnDatabaseReadMetadata(ci, key, params);
|
||||
else
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, key, params));
|
||||
OnDatabaseReadMetadata(ci, key, params);
|
||||
}
|
||||
catch (const DatabaseException &ex)
|
||||
{
|
||||
@@ -179,19 +469,6 @@ static void ReadDatabase(Module *m = NULL)
|
||||
db.close();
|
||||
}
|
||||
|
||||
static Anope::string ToString(const std::vector<Anope::string> &strings)
|
||||
{
|
||||
Anope::string ret;
|
||||
|
||||
for (unsigned i = 0; i < strings.size(); ++i)
|
||||
ret += " " + strings[i];
|
||||
|
||||
if (!ret.empty())
|
||||
ret.erase(ret.begin());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void LoadNickCore(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
NickCore *nc = new NickCore(params[0]);
|
||||
@@ -278,7 +555,7 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (params[0].equals_ci("EXCEPTION") && SessionInterface)
|
||||
else if (params[0].equals_ci("EXCEPTION") && session_service)
|
||||
{
|
||||
Exception *exception = new Exception();
|
||||
exception->mask = params[1];
|
||||
@@ -287,7 +564,7 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms)
|
||||
exception->time = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0;
|
||||
exception->expires = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0;
|
||||
exception->reason = params[6];
|
||||
SessionInterface->AddException(exception);
|
||||
session_service->AddException(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +589,7 @@ class DBPlain : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnDatabaseRead, I_OnLoadDatabase, I_OnDatabaseReadMetadata, I_OnSaveDatabase, I_OnModuleLoad };
|
||||
Implementation i[] = { I_OnReload, I_OnLoadDatabase, I_OnSaveDatabase };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
OnReload();
|
||||
@@ -370,308 +647,17 @@ class DBPlain : public Module
|
||||
DatabaseFile = config.ReadValue("db_plain", "database", "anope.db", 0);
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
Anope::string key = params[0];
|
||||
std::vector<Anope::string> otherparams = params;
|
||||
otherparams.erase(otherparams.begin());
|
||||
|
||||
if (key.equals_ci("NC"))
|
||||
LoadNickCore(otherparams);
|
||||
else if (key.equals_ci("NA"))
|
||||
LoadNickAlias(otherparams);
|
||||
else if (key.equals_ci("BI"))
|
||||
LoadBotInfo(otherparams);
|
||||
else if (key.equals_ci("CH"))
|
||||
LoadChanInfo(otherparams);
|
||||
else if (key.equals_ci("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);
|
||||
//ModuleManager::Detach(I_OnDatabaseReadMetadata, this);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key.equals_ci("LANGUAGE"))
|
||||
nc->language = params[0];
|
||||
else if (key.equals_ci("MEMOMAX"))
|
||||
nc->memos.memomax = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : -1;
|
||||
else if (key.equals_ci("EMAIL"))
|
||||
nc->email = params[0];
|
||||
else if (key.equals_ci("GREET"))
|
||||
nc->greet = params[0];
|
||||
else if (key.equals_ci("ACCESS"))
|
||||
nc->AddAccess(params[0]);
|
||||
else if (key.equals_ci("CERT"))
|
||||
nc->AddCert(params[0]);
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
nc->FromString(params);
|
||||
else if (key.equals_ci("MI"))
|
||||
{
|
||||
Memo *m = new Memo;
|
||||
m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
|
||||
m->sender = params[1];
|
||||
for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j)
|
||||
{
|
||||
if (params[j].equals_ci("UNREAD"))
|
||||
m->SetFlag(MF_UNREAD);
|
||||
else if (params[j].equals_ci("RECEIPT"))
|
||||
m->SetFlag(MF_RECEIPT);
|
||||
}
|
||||
m->text = params[params.size() - 1];
|
||||
nc->memos.memos.push_back(m);
|
||||
}
|
||||
else if (key.equals_ci("MIG"))
|
||||
nc->memos.ignores.push_back(params[0].ci_str());
|
||||
}
|
||||
catch (const ConvertException &ex)
|
||||
{
|
||||
throw DatabaseException(ex.GetReason());
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.equals_ci("LAST_USERMASK"))
|
||||
na->last_usermask = params[0];
|
||||
else if (key.equals_ci("LAST_REALHOST"))
|
||||
na->last_realhost = params[0];
|
||||
else if (key.equals_ci("LAST_REALNAME"))
|
||||
na->last_realname = params[0];
|
||||
else if (key.equals_ci("LAST_QUIT"))
|
||||
na->last_quit = params[0];
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
na->FromString(params);
|
||||
else if (key.equals_ci("VHOST"))
|
||||
na->hostinfo.SetVhost(params.size() > 3 ? params[3] : "", params[2], params[0], params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0);
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(BotInfo *bi, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
if (key.equals_ci("FLAGS"))
|
||||
bi->FromString(params);
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (key.equals_ci("BANTYPE"))
|
||||
ci->bantype = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : Config->CSDefBantype;
|
||||
else if (key.equals_ci("MEMOMAX"))
|
||||
ci->memos.memomax = params[0].is_pos_number_only() ? convertTo<int16>(params[0]) : -1;
|
||||
else if (key.equals_ci("FOUNDER"))
|
||||
ci->SetFounder(findcore(params[0]));
|
||||
else if (key.equals_ci("SUCCESSOR"))
|
||||
ci->successor = findcore(params[0]);
|
||||
else if (key.equals_ci("LEVELS"))
|
||||
{
|
||||
for (unsigned j = 0, end = params.size(); j < end; j += 2)
|
||||
{
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(params[j]);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
ci->SetLevel(p->name, params[j + 1].is_number_only() ? convertTo<int16>(params[j + 1]) : 0);
|
||||
}
|
||||
}
|
||||
else if (key.equals_ci("FLAGS"))
|
||||
ci->FromString(params);
|
||||
else if (key.equals_ci("DESC"))
|
||||
ci->desc = params[0];
|
||||
else if (key.equals_ci("TOPIC"))
|
||||
{
|
||||
ci->last_topic_setter = params[0];
|
||||
ci->last_topic_time = params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0;
|
||||
ci->last_topic = params[2];
|
||||
}
|
||||
else if (key.equals_ci("SUSPEND"))
|
||||
{
|
||||
ci->Extend("suspend_by", new ExtensibleItemRegular<Anope::string>(params[0]));
|
||||
ci->Extend("suspend_reason", new ExtensibleItemRegular<Anope::string>(params[1]));
|
||||
}
|
||||
else if (key.equals_ci("ACCESS")) // Older access system, from Anope 1.9.4.
|
||||
{
|
||||
service_reference<AccessProvider> provider("access/access");
|
||||
if (!provider)
|
||||
throw DatabaseException("Old access entry for nonexistant provider");
|
||||
|
||||
ChanAccess *access = provider->Create();
|
||||
access->ci = ci;
|
||||
access->mask = params[0];
|
||||
access->Unserialize(params[1]);
|
||||
access->last_seen = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0;
|
||||
access->creator = params[3];
|
||||
access->created = Anope::CurTime;
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
else if (key.equals_ci("ACCESS2"))
|
||||
{
|
||||
service_reference<AccessProvider> provider(params[0]);
|
||||
if (!provider)
|
||||
throw DatabaseException("Access entry for nonexistant provider " + params[0]);
|
||||
|
||||
ChanAccess *access = provider->Create();
|
||||
access->ci = ci;
|
||||
access->mask = params[1];
|
||||
access->Unserialize(params[2]);
|
||||
access->last_seen = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : 0;
|
||||
access->creator = params[4];
|
||||
access->created = params.size() > 5 && params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
|
||||
|
||||
ci->AddAccess(access);
|
||||
}
|
||||
else if (key.equals_ci("AKICK"))
|
||||
{
|
||||
// 0 is the old stuck
|
||||
bool Nick = params[1].equals_ci("NICK");
|
||||
NickCore *nc = NULL;
|
||||
if (Nick)
|
||||
{
|
||||
nc = findcore(params[2]);
|
||||
if (!nc)
|
||||
throw DatabaseException("Akick for nonexistant core " + params[2] + " on " + ci->name);
|
||||
}
|
||||
|
||||
AutoKick *ak;
|
||||
if (Nick)
|
||||
ak = ci->AddAkick(params[3], nc, params.size() > 6 ? params[6] : "", params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0, params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0);
|
||||
else
|
||||
ak = ci->AddAkick(params[3], params[2], params.size() > 6 ? params[6] : "", params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0, params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0);
|
||||
if (Nick)
|
||||
ak->SetFlag(AK_ISNICK);
|
||||
|
||||
}
|
||||
else if (key.equals_ci("LOG"))
|
||||
{
|
||||
LogSetting l;
|
||||
|
||||
l.service_name = params[0];
|
||||
l.command_service = params[1];
|
||||
l.command_name = params[2];
|
||||
l.method = params[3];
|
||||
l.creator = params[4];
|
||||
l.created = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
|
||||
l.extra = params.size() > 6 ? params[6] : "";
|
||||
|
||||
ci->log_settings.push_back(l);
|
||||
}
|
||||
else if (key.equals_ci("MLOCK"))
|
||||
{
|
||||
bool set = params[0] == "1" ? true : false;
|
||||
Anope::string mode_name = params[1];
|
||||
Anope::string setter = params[2];
|
||||
time_t mcreated = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : Anope::CurTime;
|
||||
Anope::string param = params.size() > 4 ? params[4] : "";
|
||||
|
||||
for (size_t i = CMODE_BEGIN + 1; i < CMODE_END; ++i)
|
||||
if (ChannelModeNameStrings[i] == mode_name)
|
||||
{
|
||||
ChannelModeName n = static_cast<ChannelModeName>(i);
|
||||
ci->mode_locks.insert(std::make_pair(n, ModeLock(set, n, param, setter, mcreated)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (key.equals_ci("MI"))
|
||||
{
|
||||
Memo *m = new Memo;
|
||||
m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0;
|
||||
m->sender = params[1];
|
||||
for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j)
|
||||
{
|
||||
if (params[j].equals_ci("UNREAD"))
|
||||
m->SetFlag(MF_UNREAD);
|
||||
else if (params[j].equals_ci("RECEIPT"))
|
||||
m->SetFlag(MF_RECEIPT);
|
||||
}
|
||||
m->text = params[params.size() - 1];
|
||||
ci->memos.memos.push_back(m);
|
||||
}
|
||||
else if (key.equals_ci("MIG"))
|
||||
ci->memos.ignores.push_back(params[0].ci_str());
|
||||
else if (key.equals_ci("BI"))
|
||||
{
|
||||
if (params[0].equals_ci("NAME"))
|
||||
ci->bi = findbot(params[1]);
|
||||
else if (params[0].equals_ci("FLAGS"))
|
||||
ci->botflags.FromString(params);
|
||||
else if (params[0].equals_ci("TTB"))
|
||||
{
|
||||
for (unsigned j = 1, end = params.size(); j < end; j += 2)
|
||||
{
|
||||
if (params[j].equals_ci("BOLDS"))
|
||||
ci->ttb[0] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("COLORS"))
|
||||
ci->ttb[1] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("REVERSES"))
|
||||
ci->ttb[2] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("UNDERLINES"))
|
||||
ci->ttb[3] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("BADWORDS"))
|
||||
ci->ttb[4] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("CAPS"))
|
||||
ci->ttb[5] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("FLOOD"))
|
||||
ci->ttb[6] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("REPEAT"))
|
||||
ci->ttb[7] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("ITALICS"))
|
||||
ci->ttb[8] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
else if (params[j].equals_ci("AMSGS"))
|
||||
ci->ttb[9] = params[j + 1].is_pos_number_only() ? convertTo<int16>(params[j + 1]) : 0;
|
||||
}
|
||||
}
|
||||
else if (params[0].equals_ci("CAPSMIN"))
|
||||
ci->capsmin = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("CAPSPERCENT"))
|
||||
ci->capspercent = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("FLOODLINES"))
|
||||
ci->floodlines = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("FLOODSECS"))
|
||||
ci->floodsecs = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("REPEATTIMES"))
|
||||
ci->repeattimes = params[1].is_pos_number_only() ? convertTo<int16>(params[1]) : 0;
|
||||
else if (params[0].equals_ci("BADWORD"))
|
||||
{
|
||||
BadWordType Type;
|
||||
if (params[1].equals_ci("SINGLE"))
|
||||
Type = BW_SINGLE;
|
||||
else if (params[1].equals_ci("START"))
|
||||
Type = BW_START;
|
||||
else if (params[1].equals_ci("END"))
|
||||
Type = BW_END;
|
||||
else
|
||||
Type = BW_ANY;
|
||||
ci->AddBadWord(params[2], Type);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const ConvertException &ex)
|
||||
{
|
||||
throw DatabaseException(ex.GetReason());
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnSaveDatabase()
|
||||
{
|
||||
@@ -705,7 +691,7 @@ class DBPlain : public Module
|
||||
db_buffer << "MD CERT " << *it << endl;
|
||||
}
|
||||
if (nc->FlagCount())
|
||||
db_buffer << "MD FLAGS " << ToString(nc->ToString()) << endl;
|
||||
db_buffer << "MD FLAGS " << nc->ToString() << endl;
|
||||
MemoInfo *mi = &nc->memos;
|
||||
for (unsigned k = 0, end = mi->memos.size(); k < end; ++k)
|
||||
{
|
||||
@@ -718,7 +704,7 @@ class DBPlain : public Module
|
||||
}
|
||||
for (unsigned k = 0, end = mi->ignores.size(); k < end; ++k)
|
||||
db_buffer << "MD MIG " << Anope::string(mi->ignores[k]) << endl;
|
||||
FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nc));
|
||||
//FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, nc));
|
||||
}
|
||||
|
||||
for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it)
|
||||
@@ -735,11 +721,11 @@ class DBPlain : public Module
|
||||
if (!na->last_quit.empty())
|
||||
db_buffer << "MD LAST_QUIT :" << na->last_quit << endl;
|
||||
if (na->FlagCount())
|
||||
db_buffer << "MD FLAGS " << ToString(na->ToString()) << endl;
|
||||
db_buffer << "MD FLAGS " << na->ToString() << endl;
|
||||
if (na->hostinfo.HasVhost())
|
||||
db_buffer << "MD VHOST " << na->hostinfo.GetCreator() << " " << na->hostinfo.GetTime() << " " << na->hostinfo.GetHost() << " :" << na->hostinfo.GetIdent() << endl;
|
||||
|
||||
FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, na));
|
||||
//FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, na));
|
||||
}
|
||||
|
||||
for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it)
|
||||
@@ -751,7 +737,7 @@ class DBPlain : public Module
|
||||
|
||||
db_buffer << "BI " << bi->nick << " " << bi->GetIdent() << " " << bi->host << " " << bi->created << " " << bi->chancount << " :" << bi->realname << endl;
|
||||
if (bi->FlagCount())
|
||||
db_buffer << "MD FLAGS " << ToString(bi->ToString()) << endl;
|
||||
db_buffer << "MD FLAGS " << bi->ToString() << endl;
|
||||
}
|
||||
|
||||
for (registered_channel_map::const_iterator cit = RegisteredChannelList.begin(), cit_end = RegisteredChannelList.end(); cit != cit_end; ++cit)
|
||||
@@ -778,13 +764,12 @@ class DBPlain : public Module
|
||||
}
|
||||
db_buffer << endl;
|
||||
if (ci->FlagCount())
|
||||
db_buffer << "MD FLAGS " << ToString(ci->ToString()) << endl;
|
||||
db_buffer << "MD FLAGS " << ci->ToString() << endl;
|
||||
if (ci->HasFlag(CI_SUSPENDED))
|
||||
{
|
||||
Anope::string by, reason;
|
||||
ci->GetExtRegular("suspend_by", by);
|
||||
ci->GetExtRegular("suspend_reason", reason);
|
||||
db_buffer << "MD SUSPEND " << by << " :" << reason << endl;
|
||||
Anope::string *by = ci->GetExt<Anope::string *>("suspend_by"), *reason = ci->GetExt<Anope::string *>("suspend_reason");
|
||||
if (by && reason)
|
||||
db_buffer << "MD SUSPEND " << *by << " :" << *reason << endl;
|
||||
}
|
||||
for (unsigned k = 0, end = ci->GetAccessCount(); k < end; ++k)
|
||||
{
|
||||
@@ -805,21 +790,12 @@ class DBPlain : public Module
|
||||
|
||||
db_buffer << "MD LOG " << l.service_name << " " << l.command_service << " " << l.command_name << " " << l.method << " " << l.creator << " " << l.created << " " << l.extra << endl;
|
||||
}
|
||||
for (std::multimap<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it)
|
||||
{
|
||||
std::vector<Anope::string> mlocks;
|
||||
if (ci->GetExtRegular("db_mlock", mlocks))
|
||||
for (unsigned i = 0; i < mlocks.size(); ++i)
|
||||
db_buffer << mlocks[i] << endl;
|
||||
else
|
||||
{
|
||||
for (std::multimap<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it)
|
||||
{
|
||||
const ModeLock &ml = it->second;
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name);
|
||||
if (cm != NULL)
|
||||
db_buffer << "MD MLOCK " << (ml.set ? 1 : 0) << " " << cm->NameAsString() << " " << ml.setter << " " << ml.created << " " << ml.param << endl;
|
||||
}
|
||||
}
|
||||
const ModeLock &ml = it->second;
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name);
|
||||
if (cm != NULL)
|
||||
db_buffer << "MD MLOCK " << (ml.set ? 1 : 0) << " " << cm->NameAsString() << " " << ml.setter << " " << ml.created << " " << ml.param << endl;
|
||||
}
|
||||
MemoInfo *memos = &ci->memos;
|
||||
for (unsigned k = 0, end = memos->memos.size(); k < end; ++k)
|
||||
@@ -836,7 +812,7 @@ class DBPlain : public Module
|
||||
if (ci->bi)
|
||||
db_buffer << "MD BI NAME " << ci->bi->nick << endl;
|
||||
if (ci->botflags.FlagCount())
|
||||
db_buffer << "MD BI FLAGS " << ToString(ci->botflags.ToString()) << endl;
|
||||
db_buffer << "MD BI FLAGS " << ci->botflags.ToString() << endl;
|
||||
db_buffer << "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] << " ITALICS " << ci->ttb[8] << " AMSGS " << ci->ttb[9] << endl;
|
||||
if (ci->capsmin)
|
||||
db_buffer << "MD BI CAPSMIN " << ci->capsmin << endl;
|
||||
@@ -852,7 +828,7 @@ class DBPlain : public Module
|
||||
db_buffer << "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));
|
||||
//FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteMetadata, ci));
|
||||
}
|
||||
|
||||
db_buffer << "OS STATS " << maxusercnt << " " << maxusertime << endl;
|
||||
@@ -867,14 +843,14 @@ class DBPlain : public Module
|
||||
}
|
||||
}
|
||||
|
||||
if (SessionInterface)
|
||||
for (SessionService::ExceptionVector::iterator it = SessionInterface->GetExceptions().begin(); it != SessionInterface->GetExceptions().end(); ++it)
|
||||
if (session_service)
|
||||
for (SessionService::ExceptionVector::iterator it = session_service->GetExceptions().begin(); it != session_service->GetExceptions().end(); ++it)
|
||||
{
|
||||
Exception *e = *it;
|
||||
db_buffer << "OS EXCEPTION " << e->mask << " " << e->limit << " " << e->who << " " << e->time << " " << e->expires << " " << e->reason << endl;
|
||||
}
|
||||
|
||||
FOREACH_MOD(I_OnDatabaseWrite, OnDatabaseWrite(Write));
|
||||
//FOREACH_MOD(I_OnDatabaseWrite, OnDatabaseWrite(Write));
|
||||
|
||||
std::fstream db;
|
||||
db.open(DatabaseFile.c_str(), std::ios_base::out | std::ios_base::trunc);
|
||||
@@ -892,22 +868,6 @@ class DBPlain : public Module
|
||||
|
||||
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)
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* (C) 2003-2011 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.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
|
||||
class SQLSQLInterface : public SQLInterface
|
||||
{
|
||||
public:
|
||||
SQLSQLInterface(Module *o) : SQLInterface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r)
|
||||
{
|
||||
Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r)
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
else
|
||||
Log(LOG_DEBUG) << "Error executing query: " << r.GetError();
|
||||
}
|
||||
};
|
||||
|
||||
class DBSQL : public Module
|
||||
{
|
||||
service_reference<SQLProvider, Base> sql;
|
||||
SQLSQLInterface sqlinterface;
|
||||
|
||||
void RunBackground(const SQLQuery &q)
|
||||
{
|
||||
if (!quitting)
|
||||
this->sql->Run(&sqlinterface, q);
|
||||
else
|
||||
this->sql->RunQuery(q);
|
||||
}
|
||||
|
||||
void DropTable(const Anope::string &table)
|
||||
{
|
||||
SQLQuery query("DROP TABLE `" + table + "`");
|
||||
this->RunBackground(query);
|
||||
}
|
||||
|
||||
void AlterTable(const Anope::string &table, const SerializableBase::serialized_data &oldd, const SerializableBase::serialized_data &newd)
|
||||
{
|
||||
for (SerializableBase::serialized_data::const_iterator it = newd.begin(), it_end = newd.end(); it != it_end; ++it)
|
||||
{
|
||||
if (oldd.count(it->first) > 0)
|
||||
continue;
|
||||
|
||||
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + it->first + "` ";
|
||||
if (it->second.getType() == Serialize::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else if (it->second.getMax() > 0)
|
||||
query_text += "varchar(" + stringify(it->second.getMax()) + ")";
|
||||
else
|
||||
query_text += "text";
|
||||
|
||||
this->RunBackground(SQLQuery(query_text));
|
||||
}
|
||||
}
|
||||
|
||||
void Insert(const Anope::string &table, const SerializableBase::serialized_data &data)
|
||||
{
|
||||
Anope::string query_text = "INSERT INTO `" + table + "` (";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += "`" + it->first + "`,";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ") VALUES (";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += "@" + it->first + "@,";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ")";
|
||||
|
||||
SQLQuery query(query_text);
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query.setValue(it->first, it->second.astr());
|
||||
|
||||
this->RunBackground(query);
|
||||
}
|
||||
|
||||
public:
|
||||
DBSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sql(""), sqlinterface(this)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnSaveDatabase, I_OnLoadDatabase };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
this->OnReload();
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
|
||||
this->sql = engine;
|
||||
}
|
||||
|
||||
EventReturn OnSaveDatabase()
|
||||
{
|
||||
if (!this->sql)
|
||||
{
|
||||
Log() << "db_sql: Unable to save databases, is SQL configured correctly?";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
std::map<Anope::string, SerializableBase::serialized_data> table_layout;
|
||||
for (std::list<SerializableBase *>::iterator it = serialized_items.begin(), it_end = serialized_items.end(); it != it_end; ++it)
|
||||
{
|
||||
SerializableBase *base = *it;
|
||||
SerializableBase::serialized_data data = base->serialize();
|
||||
|
||||
if (data.empty())
|
||||
continue;
|
||||
|
||||
if (table_layout.count(base->serialize_name()) == 0)
|
||||
{
|
||||
this->DropTable(base->serialize_name());
|
||||
this->RunBackground(this->sql->CreateTable(base->serialize_name(), data));
|
||||
}
|
||||
else
|
||||
this->AlterTable(base->serialize_name(), table_layout[base->serialize_name()], data);
|
||||
table_layout[base->serialize_name()] = data;
|
||||
|
||||
this->Insert(base->serialize_name(), data);
|
||||
}
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase()
|
||||
{
|
||||
if (!this->sql)
|
||||
{
|
||||
Log() << "db_sql: Unable to load databases, is SQL configured correctly?";
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
for (std::vector<SerializableBase *>::iterator it = serialized_types.begin(), it_end = serialized_types.end(); it != it_end; ++it)
|
||||
{
|
||||
SerializableBase *sb = *it;
|
||||
|
||||
SQLQuery query("SELECT * FROM `" + sb->serialize_name() + "`");
|
||||
SQLResult res = this->sql->RunQuery(query);
|
||||
for (int i = 0; i < res.Rows(); ++i)
|
||||
{
|
||||
SerializableBase::serialized_data data;
|
||||
const std::map<Anope::string, Anope::string> &row = res.Row(i);
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator rit = row.begin(), rit_end = row.end(); rit != rit_end; ++rit)
|
||||
data[rit->first] << rit->second;
|
||||
|
||||
sb->alloc(data);
|
||||
}
|
||||
}
|
||||
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBSQL)
|
||||
|
||||
@@ -0,0 +1,434 @@
|
||||
#include "module.h"
|
||||
#include "../extra/sql.h"
|
||||
#include "../commands/os_session.h"
|
||||
|
||||
class MySQLInterface : public SQLInterface
|
||||
{
|
||||
public:
|
||||
MySQLInterface(Module *o) : SQLInterface(o) { }
|
||||
|
||||
void OnResult(const SQLResult &r)
|
||||
{
|
||||
Log(LOG_DEBUG) << "SQL successfully executed query: " << r.finished_query;
|
||||
}
|
||||
|
||||
void OnError(const SQLResult &r)
|
||||
{
|
||||
if (!r.GetQuery().query.empty())
|
||||
Log(LOG_DEBUG) << "Error executing query " << r.finished_query << ": " << r.GetError();
|
||||
else
|
||||
Log(LOG_DEBUG) << "Error executing query: " << r.GetError();
|
||||
}
|
||||
};
|
||||
|
||||
class DBMySQL : public Module
|
||||
{
|
||||
private:
|
||||
MySQLInterface sqlinterface;
|
||||
service_reference<SQLProvider, Base> SQL;
|
||||
std::set<Anope::string> tables;
|
||||
|
||||
void RunQuery(const SQLQuery &query)
|
||||
{
|
||||
if (SQL)
|
||||
{
|
||||
if (readonly && this->ro)
|
||||
{
|
||||
readonly = this->ro = false;
|
||||
BotInfo *bi = findbot(Config->OperServ);
|
||||
if (bi)
|
||||
ircdproto->SendGlobops(bi, "Found SQL again, going out of readonly mode...");
|
||||
}
|
||||
|
||||
SQL->Run(&sqlinterface, query);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Anope::CurTime - Config->UpdateTimeout > lastwarn)
|
||||
{
|
||||
BotInfo *bi = findbot(Config->OperServ);
|
||||
if (bi)
|
||||
ircdproto->SendGlobops(bi, "Unable to locate SQL reference, going to readonly...");
|
||||
readonly = this->ro = true;
|
||||
this->lastwarn = Anope::CurTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Insert(const Anope::string &table, const SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (tables.count(table) == 0 && SQL)
|
||||
{
|
||||
this->RunQuery(this->SQL->CreateTable(table, data));
|
||||
tables.insert(table);
|
||||
}
|
||||
|
||||
Anope::string query_text = "INSERT INTO `" + table + "` (";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += "`" + it->first + "`,";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ") VALUES (";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += "@" + it->first + "@,";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ") ON DUPLICATE KEY UPDATE ";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += it->first + "=VALUES(" + it->first + "),";
|
||||
query_text.erase(query_text.end() - 1);
|
||||
|
||||
SQLQuery query(query_text);
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query.setValue(it->first, it->second.astr());
|
||||
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
void Delete(const Anope::string &table, const SerializableBase::serialized_data &data)
|
||||
{
|
||||
Anope::string query_text = "DELETE FROM `" + table + "` WHERE ";
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query_text += "`" + it->first + "` = @" + it->first + "@";
|
||||
|
||||
SQLQuery query(query_text);
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
query.setValue(it->first, it->second.astr());
|
||||
|
||||
this->RunQuery(query);
|
||||
}
|
||||
|
||||
public:
|
||||
time_t lastwarn;
|
||||
bool ro;
|
||||
|
||||
DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sqlinterface(this), SQL("")
|
||||
{
|
||||
this->lastwarn = 0;
|
||||
this->ro = false;
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnServerConnect };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
OnReload();
|
||||
|
||||
if (CurrentUplink)
|
||||
OnServerConnect();
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
|
||||
this->SQL = engine;
|
||||
}
|
||||
|
||||
void OnServerConnect()
|
||||
{
|
||||
Implementation i[] = {
|
||||
/* Misc */
|
||||
I_OnPostCommand,
|
||||
/* NickServ */
|
||||
I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearAccess,
|
||||
I_OnDelCore, I_OnNickForbidden, I_OnNickGroup,
|
||||
I_OnNickRegister, I_OnChangeCoreDisplay,
|
||||
I_OnNickSuspended, I_OnDelNick,
|
||||
/* ChanServ */
|
||||
I_OnAccessAdd, I_OnAccessDel, I_OnAccessClear, I_OnLevelChange,
|
||||
I_OnDelChan, I_OnChanRegistered, I_OnChanSuspend,
|
||||
I_OnAkickAdd, I_OnAkickDel, I_OnMLock, I_OnUnMLock,
|
||||
/* BotServ */
|
||||
I_OnBotCreate, I_OnBotChange, I_OnBotDelete,
|
||||
I_OnBotAssign, I_OnBotUnAssign,
|
||||
I_OnBadWordAdd, I_OnBadWordDel,
|
||||
/* MemoServ */
|
||||
I_OnMemoSend, I_OnMemoDel,
|
||||
/* OperServ */
|
||||
I_OnExceptionAdd, I_OnExceptionDel,
|
||||
I_OnAddXLine, I_OnDelXLine,
|
||||
/* HostServ */
|
||||
I_OnSetVhost, I_OnDeleteVhost
|
||||
};
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
}
|
||||
|
||||
void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms)
|
||||
{
|
||||
User *u = source.u;
|
||||
|
||||
if (command->name.find("nickserv/set/") == 0)
|
||||
{
|
||||
NickAlias *na = findnick(source.u->nick);
|
||||
if (!na)
|
||||
this->Insert(na->nc->serialize_name(), na->nc->serialize());
|
||||
|
||||
}
|
||||
else if (command->name.find("nickserv/saset/") == 0)
|
||||
{
|
||||
NickAlias *na = findnick(params[1]);
|
||||
if (!na)
|
||||
this->Insert(na->nc->serialize_name(), na->nc->serialize());
|
||||
}
|
||||
else if (command->name.find("chanserv/set") == 0 || command->name.find("chanserv/saset") == 0)
|
||||
{
|
||||
ChannelInfo *ci = params.size() > 0 ? cs_findchan(params[0]) : NULL;
|
||||
if (!ci)
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
else if (command->name == "botserv/kick" && params.size() > 2)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(params[0]);
|
||||
if (!ci)
|
||||
return;
|
||||
if (!ci->AccessFor(u).HasPriv("SET") && !u->HasPriv("botserv/administration"))
|
||||
return;
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
else if (command->name == "botserv/set" && params.size() > 1)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(params[0]);
|
||||
BotInfo *bi = NULL;
|
||||
if (!ci)
|
||||
bi = findbot(params[0]);
|
||||
if (bi && params[1].equals_ci("PRIVATE") && u->HasPriv("botserv/set/private"))
|
||||
this->Insert(bi->serialize_name(), bi->serialize());
|
||||
else if (ci && !ci->AccessFor(u).HasPriv("SET") && !u->HasPriv("botserv/administration"))
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
else if (command->name == "memoserv/ignore" && params.size() > 0)
|
||||
{
|
||||
Anope::string target = params[0];
|
||||
if (target[0] != '#')
|
||||
{
|
||||
NickCore *nc = u->Account();
|
||||
if (nc)
|
||||
this->Insert(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
else
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(target);
|
||||
if (ci && ci->AccessFor(u).HasPriv("MEMO"))
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnNickAddAccess(NickCore *nc, const Anope::string &entry)
|
||||
{
|
||||
this->Insert(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
|
||||
void OnNickEraseAccess(NickCore *nc, const Anope::string &entry)
|
||||
{
|
||||
this->Insert(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
|
||||
void OnNickClearAccess(NickCore *nc)
|
||||
{
|
||||
this->Insert(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
|
||||
void OnDelCore(NickCore *nc)
|
||||
{
|
||||
this->Delete(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
|
||||
void OnNickForbidden(NickAlias *na)
|
||||
{
|
||||
this->Insert(na->serialize_name(), na->serialize());
|
||||
}
|
||||
|
||||
void OnNickGroup(User *u, NickAlias *)
|
||||
{
|
||||
OnNickRegister(findnick(u->nick));
|
||||
}
|
||||
|
||||
void InsertAlias(NickAlias *na)
|
||||
{
|
||||
this->Insert(na->serialize_name(), na->serialize());
|
||||
}
|
||||
|
||||
void InsertCore(NickCore *nc)
|
||||
{
|
||||
this->Insert(nc->serialize_name(), nc->serialize());
|
||||
}
|
||||
|
||||
void OnNickRegister(NickAlias *na)
|
||||
{
|
||||
this->InsertCore(na->nc);
|
||||
this->InsertAlias(na);
|
||||
}
|
||||
|
||||
void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay)
|
||||
{
|
||||
SerializableBase::serialized_data data = nc->serialize();
|
||||
this->Delete(nc->serialize_name(), data);
|
||||
data.erase("display");
|
||||
data["display"] << newdisplay;
|
||||
this->Insert(nc->serialize_name(), data);
|
||||
|
||||
for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it)
|
||||
{
|
||||
NickAlias *na = *it;
|
||||
data = na->serialize();
|
||||
|
||||
this->Delete(na->serialize_name(), data);
|
||||
data.erase("nc");
|
||||
data["nc"] << newdisplay;
|
||||
this->Insert(na->serialize_name(), data);
|
||||
}
|
||||
}
|
||||
|
||||
void OnNickSuspend(NickAlias *na)
|
||||
{
|
||||
this->Insert(na->serialize_name(), na->serialize());
|
||||
}
|
||||
|
||||
void OnDelNick(NickAlias *na)
|
||||
{
|
||||
this->Delete(na->serialize_name(), na->serialize());
|
||||
}
|
||||
|
||||
void OnAccessAdd(ChannelInfo *ci, User *, ChanAccess *access)
|
||||
{
|
||||
this->Insert(access->serialize_name(), access->serialize());
|
||||
}
|
||||
|
||||
void OnAccessDel(ChannelInfo *ci, User *u, ChanAccess *access)
|
||||
{
|
||||
this->Delete(access->serialize_name(), access->serialize());
|
||||
}
|
||||
|
||||
void OnAccessClear(ChannelInfo *ci, User *u)
|
||||
{
|
||||
for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
|
||||
this->OnAccessDel(ci, NULL, ci->GetAccess(i));
|
||||
}
|
||||
|
||||
void OnLevelChange(User *u, ChannelInfo *ci, const Anope::string &priv, int16 what)
|
||||
{
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
|
||||
void OnDelChan(ChannelInfo *ci)
|
||||
{
|
||||
this->Delete(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
|
||||
void OnChanRegistered(ChannelInfo *ci)
|
||||
{
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
|
||||
void OnChanSuspend(ChannelInfo *ci)
|
||||
{
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
}
|
||||
|
||||
void OnAkickAdd(ChannelInfo *ci, AutoKick *ak)
|
||||
{
|
||||
this->Insert(ak->serialize_name(), ak->serialize());
|
||||
}
|
||||
|
||||
void OnAkickDel(ChannelInfo *ci, AutoKick *ak)
|
||||
{
|
||||
this->Delete(ak->serialize_name(), ak->serialize());
|
||||
}
|
||||
|
||||
EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock)
|
||||
{
|
||||
this->Insert(lock->serialize_name(), lock->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock)
|
||||
{
|
||||
this->Delete(lock->serialize_name(), lock->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnBotCreate(BotInfo *bi)
|
||||
{
|
||||
this->Insert(bi->serialize_name(), bi->serialize());
|
||||
}
|
||||
|
||||
void OnBotChange(BotInfo *bi)
|
||||
{
|
||||
OnBotCreate(bi);
|
||||
}
|
||||
|
||||
void OnBotDelete(BotInfo *bi)
|
||||
{
|
||||
this->Delete(bi->serialize_name(), bi->serialize());
|
||||
}
|
||||
|
||||
EventReturn OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi)
|
||||
{
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci)
|
||||
{
|
||||
this->Insert(ci->serialize_name(), ci->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnBadWordAdd(ChannelInfo *ci, BadWord *bw)
|
||||
{
|
||||
this->Insert(bw->serialize_name(), bw->serialize());
|
||||
}
|
||||
|
||||
void OnBadWordDel(ChannelInfo *ci, BadWord *bw)
|
||||
{
|
||||
this->Delete(bw->serialize_name(), bw->serialize());
|
||||
}
|
||||
|
||||
void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m)
|
||||
{
|
||||
this->Insert(m->serialize_name(), m->serialize());
|
||||
}
|
||||
|
||||
void OnMemoDel(const NickCore *nc, MemoInfo *mi, Memo *m)
|
||||
{
|
||||
this->Delete(m->serialize_name(), m->serialize());
|
||||
}
|
||||
|
||||
void OnMemoDel(ChannelInfo *ci, MemoInfo *mi, Memo *m)
|
||||
{
|
||||
this->Delete(m->serialize_name(), m->serialize());
|
||||
}
|
||||
|
||||
EventReturn OnExceptionAdd(Exception *ex)
|
||||
{
|
||||
this->Insert(ex->serialize_name(), ex->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnExceptionDel(User *, Exception *ex)
|
||||
{
|
||||
this->Delete(ex->serialize_name(), ex->serialize());
|
||||
}
|
||||
|
||||
EventReturn OnAddXLine(XLine *x, XLineManager *xlm)
|
||||
{
|
||||
this->Insert(x->serialize_name(), x->serialize());
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
|
||||
void OnDelXLine(User *, XLine *x, XLineManager *xlm)
|
||||
{
|
||||
this->Delete(x->serialize_name(), x->serialize());
|
||||
}
|
||||
|
||||
void OnDeleteVhost(NickAlias *na)
|
||||
{
|
||||
this->Insert(na->serialize_name(), na->serialize());
|
||||
}
|
||||
|
||||
void OnSetVhost(NickAlias *na)
|
||||
{
|
||||
this->Insert(na->serialize_name(), na->serialize());
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBMySQL)
|
||||
|
||||
@@ -32,19 +32,25 @@ class SQLCache : public Timer
|
||||
}
|
||||
};
|
||||
|
||||
static void ChanInfoUpdate(const SQLResult &res)
|
||||
static void ChanInfoUpdate(const Anope::string &name, const SQLResult &res)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(name);
|
||||
if (res.Rows() == 0)
|
||||
{
|
||||
delete ci;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(res.Get(0, "name"));
|
||||
if (!ci)
|
||||
ci = new ChannelInfo(res.Get(0, "name"));
|
||||
ci = new ChannelInfo(name);
|
||||
ci->SetFounder(findcore(res.Get(0, "founder")));
|
||||
ci->successor = findcore(res.Get(0, "successor"));
|
||||
ci->desc = res.Get(0, "descr");
|
||||
ci->time_registered = convertTo<time_t>(res.Get(0, "time_registered"));
|
||||
ci->ClearFlags();
|
||||
ci->FromString(BuildStringVector(res.Get(0, "flags")));
|
||||
ci->FromString(res.Get(0, "flags"));
|
||||
ci->bantype = convertTo<int>(res.Get(0, "bantype"));
|
||||
ci->memos.memomax = convertTo<unsigned>(res.Get(0, "memomax"));
|
||||
|
||||
@@ -68,21 +74,27 @@ static void ChanInfoUpdate(const SQLResult &res)
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
Log() << ex.GetReason();
|
||||
}
|
||||
catch (const ConvertException &) { }
|
||||
}
|
||||
|
||||
static void NickInfoUpdate(const SQLResult &res)
|
||||
static void NickInfoUpdate(const Anope::string &name, const SQLResult &res)
|
||||
{
|
||||
NickAlias *na = findnick(name);
|
||||
if (res.Rows() == 0)
|
||||
{
|
||||
delete na;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NickCore *nc = findcore(res.Get(0, "display"));
|
||||
if (!nc)
|
||||
return;
|
||||
NickAlias *na = findnick(res.Get(0, "nick"));
|
||||
if (!na)
|
||||
na = new NickAlias(res.Get(0, "nick"), nc);
|
||||
na = new NickAlias(name, nc);
|
||||
|
||||
na->last_quit = res.Get(0, "last_quit");
|
||||
na->last_realname = res.Get(0, "last_realname");
|
||||
@@ -91,7 +103,7 @@ static void NickInfoUpdate(const SQLResult &res)
|
||||
na->time_registered = convertTo<time_t>(res.Get(0, "time_registered"));
|
||||
na->last_seen = convertTo<time_t>(res.Get(0, "last_seen"));
|
||||
na->ClearFlags();
|
||||
na->FromString(BuildStringVector(res.Get(0, "flags")));
|
||||
na->FromString(res.Get(0, "flags"));
|
||||
|
||||
if (na->nc != nc)
|
||||
{
|
||||
@@ -105,29 +117,35 @@ static void NickInfoUpdate(const SQLResult &res)
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
Log() << ex.GetReason();
|
||||
}
|
||||
catch (const ConvertException &) { }
|
||||
}
|
||||
|
||||
static void NickCoreUpdate(const SQLResult &res)
|
||||
static void NickCoreUpdate(const Anope::string &name, const SQLResult &res)
|
||||
{
|
||||
NickCore *nc = findcore(name);
|
||||
if (res.Rows() == 0)
|
||||
{
|
||||
delete nc;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NickCore *nc = findcore(res.Get(0, "display"));
|
||||
if (!nc)
|
||||
nc = new NickCore(res.Get(0, "display"));
|
||||
nc = new NickCore(name);
|
||||
|
||||
nc->pass = res.Get(0, "pass");
|
||||
nc->email = res.Get(0, "email");
|
||||
nc->greet = res.Get(0, "greet");
|
||||
nc->ClearFlags();
|
||||
nc->FromString(BuildStringVector(res.Get(0, "flags")));
|
||||
nc->FromString(res.Get(0, "flags"));
|
||||
nc->language = res.Get(0, "language");
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
Log(LOG_DEBUG) << ex.GetReason();
|
||||
Log() << ex.GetReason();
|
||||
}
|
||||
catch (const ConvertException &) { }
|
||||
}
|
||||
@@ -141,7 +159,7 @@ class MySQLLiveModule : public Module
|
||||
SQLResult RunQuery(const SQLQuery &query)
|
||||
{
|
||||
if (!this->SQL)
|
||||
throw SQLException("Unable to locate SQL reference, is m_mysql loaded and configured correctly?");
|
||||
throw SQLException("Unable to locate SQL reference, is db_sql loaded and configured correctly?");
|
||||
|
||||
SQLResult res = SQL->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
@@ -151,12 +169,19 @@ class MySQLLiveModule : public Module
|
||||
|
||||
public:
|
||||
MySQLLiveModule(const Anope::string &modname, const Anope::string &creator) :
|
||||
Module(modname, creator, DATABASE), SQL("mysql/main")
|
||||
Module(modname, creator, DATABASE), SQL("")
|
||||
{
|
||||
Implementation i[] = { I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnShutdown };
|
||||
Implementation i[] = { I_OnReload, I_OnFindChan, I_OnFindNick, I_OnFindCore, I_OnShutdown };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
Anope::string engine = config.ReadValue("db_sql", "engine", "", 0);
|
||||
this->SQL = engine;
|
||||
}
|
||||
|
||||
void OnShutdown()
|
||||
{
|
||||
Implementation i[] = { I_OnFindChan, I_OnFindNick, I_OnFindCore };
|
||||
@@ -171,10 +196,10 @@ class MySQLLiveModule : public Module
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query("SELECT * FROM `anope_cs_info` WHERE `name` = @name");
|
||||
SQLQuery query("SELECT * FROM `ChannelInfo` WHERE `name` = @name@");
|
||||
query.setValue("name", chname);
|
||||
SQLResult res = this->RunQuery(query);
|
||||
ChanInfoUpdate(res);
|
||||
ChanInfoUpdate(chname, res);
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
@@ -189,10 +214,10 @@ class MySQLLiveModule : public Module
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query("SELECT * FROM `anope_ns_alias` WHERE `nick` = @nick");
|
||||
SQLQuery query("SELECT * FROM `NickAlias` WHERE `nick` = @nick@");
|
||||
query.setValue("nick", nick);
|
||||
SQLResult res = this->RunQuery(query);
|
||||
NickInfoUpdate(res);
|
||||
NickInfoUpdate(nick, res);
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
@@ -207,10 +232,10 @@ class MySQLLiveModule : public Module
|
||||
|
||||
try
|
||||
{
|
||||
SQLQuery query("SELECT * FROM `anope_ns_core` WHERE `display` = @display");
|
||||
SQLQuery query("SELECT * FROM `NickCore` WHERE `display` = @display@");
|
||||
query.setValue("display", nick);
|
||||
SQLResult res = this->RunQuery(query);
|
||||
NickCoreUpdate(res);
|
||||
NickCoreUpdate(nick, res);
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
@@ -30,7 +30,7 @@ class DNSBLResolver : public DNSRequest
|
||||
|
||||
void OnLookupComplete(const DNSQuery *record)
|
||||
{
|
||||
if (!user || user->GetExt("m_dnsbl_akilled"))
|
||||
if (!user || user->HasExt("m_dnsbl_akilled"))
|
||||
return;
|
||||
|
||||
const ResourceRecord &ans_record = record->answers[0];
|
||||
@@ -50,7 +50,7 @@ class DNSBLResolver : public DNSRequest
|
||||
record_reason = this->blacklist.replies[result];
|
||||
}
|
||||
|
||||
user->Extend("m_dnsbl_akilled");
|
||||
user->Extend("m_dnsbl_akilled", NULL);
|
||||
|
||||
Anope::string reason = this->blacklist.reason;
|
||||
reason = reason.replace_all_cs("%n", user->nick);
|
||||
|
||||
@@ -49,7 +49,7 @@ class IdentifyInterface : public LDAPInterface
|
||||
User *u = ii->user;
|
||||
Command *c = ii->command;
|
||||
|
||||
u->Extend("m_ldap_authentication_authenticated");
|
||||
u->Extend("m_ldap_authentication_authenticated", NULL);
|
||||
|
||||
NickAlias *na = findnick(ii->account);
|
||||
if (na == NULL)
|
||||
@@ -87,7 +87,7 @@ class IdentifyInterface : public LDAPInterface
|
||||
User *u = ii->user;
|
||||
Command *c = ii->command;
|
||||
|
||||
u->Extend("m_ldap_authentication_error");
|
||||
u->Extend("m_ldap_authentication_error", NULL);
|
||||
|
||||
c->Execute(ii->source, ii->params);
|
||||
|
||||
@@ -218,12 +218,12 @@ class NSIdentifyLDAP : public Module
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
User *u = source->u;
|
||||
if (u->GetExt("m_ldap_authentication_authenticated"))
|
||||
if (u->HasExt("m_ldap_authentication_authenticated"))
|
||||
{
|
||||
u->Shrink("m_ldap_authentication_authenticated");
|
||||
return EVENT_ALLOW;
|
||||
}
|
||||
else if (u->GetExt("m_ldap_authentication_error"))
|
||||
else if (u->HasExt("m_ldap_authentication_error"))
|
||||
{
|
||||
u->Shrink("m_ldap_authentication_error");
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
+40
-15
@@ -82,8 +82,6 @@ class MySQLResult : public SQLResult
|
||||
|
||||
MySQLResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(q, fq, err), res(NULL)
|
||||
{
|
||||
if (this->finished_query.empty())
|
||||
this->finished_query = q.query;
|
||||
}
|
||||
|
||||
~MySQLResult()
|
||||
@@ -125,6 +123,8 @@ class MySQLService : public SQLProvider
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query);
|
||||
|
||||
SQLQuery CreateTable(const Anope::string &table, const SerializableBase::serialized_data &data);
|
||||
|
||||
void Connect();
|
||||
|
||||
bool CheckConnection();
|
||||
@@ -211,7 +211,7 @@ class ModuleSQL : public Module, public Pipe
|
||||
|
||||
for (i = 0, num = config.Enumerate("mysql"); i < num; ++i)
|
||||
{
|
||||
Anope::string connname = config.ReadValue("mysql", "name", "main", i);
|
||||
Anope::string connname = config.ReadValue("mysql", "name", "mysql/main", i);
|
||||
|
||||
if (this->MySQLServices.find(connname) == this->MySQLServices.end())
|
||||
{
|
||||
@@ -284,7 +284,7 @@ class ModuleSQL : public Module, public Pipe
|
||||
};
|
||||
|
||||
MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, int po)
|
||||
: SQLProvider(o, "mysql/" + n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
|
||||
: SQLProvider(o, n), database(d), server(s), user(u), password(p), port(po), sql(NULL)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
@@ -323,16 +323,7 @@ SQLResult MySQLService::RunQuery(const SQLQuery &query)
|
||||
{
|
||||
this->Lock.Lock();
|
||||
|
||||
Anope::string real_query;
|
||||
try
|
||||
{
|
||||
real_query = this->BuildQuery(query);
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
this->Lock.Unlock();
|
||||
return MySQLResult(query, real_query, ex.GetReason());
|
||||
}
|
||||
Anope::string real_query = this->BuildQuery(query);
|
||||
|
||||
if (this->CheckConnection() && !mysql_real_query(this->sql, real_query.c_str(), real_query.length()))
|
||||
{
|
||||
@@ -349,6 +340,40 @@ SQLResult MySQLService::RunQuery(const SQLQuery &query)
|
||||
}
|
||||
}
|
||||
|
||||
SQLQuery MySQLService::CreateTable(const Anope::string &table, const SerializableBase::serialized_data &data)
|
||||
{
|
||||
Anope::string query_text = "CREATE TABLE `" + table + "` (", key_buf;
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
{
|
||||
query_text += "`" + it->first + "` ";
|
||||
if (it->second.getType() == Serialize::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else if (it->second.getMax() > 0)
|
||||
query_text += "varchar(" + stringify(it->second.getMax()) + ")";
|
||||
else
|
||||
query_text += "text";
|
||||
query_text += ",";
|
||||
|
||||
if (it->second.getKey())
|
||||
{
|
||||
if (key_buf.empty())
|
||||
key_buf = "UNIQUE KEY `ukey` (";
|
||||
key_buf += "`" + it->first + "`,";
|
||||
}
|
||||
}
|
||||
if (!key_buf.empty())
|
||||
{
|
||||
key_buf.erase(key_buf.end() - 1);
|
||||
key_buf += ")";
|
||||
query_text += " " + key_buf;
|
||||
}
|
||||
else
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ")";
|
||||
|
||||
return SQLQuery(query_text);
|
||||
}
|
||||
|
||||
void MySQLService::Connect()
|
||||
{
|
||||
this->sql = mysql_init(this->sql);
|
||||
@@ -392,7 +417,7 @@ Anope::string MySQLService::BuildQuery(const SQLQuery &q)
|
||||
Anope::string real_query = q.query;
|
||||
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator it = q.parameters.begin(), it_end = q.parameters.end(); it != it_end; ++it)
|
||||
real_query = real_query.replace_all_cs("@" + it->first, "'" + this->Escape(it->second) + "'");
|
||||
real_query = real_query.replace_all_cs("@" + it->first + "@", "'" + this->Escape(it->second) + "'");
|
||||
|
||||
return real_query;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/* RequiredLibraries: sqlite3 */
|
||||
|
||||
#include "module.h"
|
||||
#include <sqlite3.h>
|
||||
#include "sql.h"
|
||||
|
||||
/* SQLite3 API, based from InspiRCd */
|
||||
|
||||
/** A SQLite result
|
||||
*/
|
||||
class SQLiteResult : public SQLResult
|
||||
{
|
||||
public:
|
||||
SQLiteResult(const SQLQuery &q, const Anope::string &fq) : SQLResult(q, fq)
|
||||
{
|
||||
}
|
||||
|
||||
SQLiteResult(const SQLQuery &q, const Anope::string &fq, const Anope::string &err) : SQLResult(q, fq, err)
|
||||
{
|
||||
}
|
||||
|
||||
void addRow(const std::map<Anope::string, Anope::string> &data)
|
||||
{
|
||||
this->entries.push_back(data);
|
||||
}
|
||||
};
|
||||
|
||||
/** A SQLite database, there can be multiple
|
||||
*/
|
||||
class SQLiteService : public SQLProvider
|
||||
{
|
||||
Anope::string database;
|
||||
|
||||
sqlite3 *sql;
|
||||
|
||||
Anope::string Escape(const Anope::string &query);
|
||||
|
||||
public:
|
||||
SQLiteService(Module *o, const Anope::string &n, const Anope::string &d);
|
||||
|
||||
~SQLiteService();
|
||||
|
||||
void Run(SQLInterface *i, const SQLQuery &query);
|
||||
|
||||
SQLResult RunQuery(const SQLQuery &query);
|
||||
|
||||
SQLQuery CreateTable(const Anope::string &table, const SerializableBase::serialized_data &data);
|
||||
|
||||
Anope::string BuildQuery(const SQLQuery &q);
|
||||
};
|
||||
|
||||
class ModuleSQLite : public Module
|
||||
{
|
||||
/* SQL connections */
|
||||
std::map<Anope::string, SQLiteService *> SQLiteServices;
|
||||
public:
|
||||
ModuleSQLite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED)
|
||||
{
|
||||
Implementation i[] = { I_OnReload };
|
||||
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
|
||||
|
||||
OnReload();
|
||||
}
|
||||
|
||||
~ModuleSQLite()
|
||||
{
|
||||
for (std::map<Anope::string, SQLiteService *>::iterator it = this->SQLiteServices.begin(); it != this->SQLiteServices.end(); ++it)
|
||||
delete it->second;
|
||||
SQLiteServices.clear();
|
||||
}
|
||||
|
||||
void OnReload()
|
||||
{
|
||||
ConfigReader config;
|
||||
int i, num;
|
||||
|
||||
for (std::map<Anope::string, SQLiteService *>::iterator it = this->SQLiteServices.begin(); it != this->SQLiteServices.end();)
|
||||
{
|
||||
const Anope::string &cname = it->first;
|
||||
SQLiteService *s = it->second;
|
||||
++it;
|
||||
|
||||
for (i = 0, num = config.Enumerate("sqlite"); i < num; ++i)
|
||||
if (config.ReadValue("sqlite", "name", "sqlite/main", i) == cname)
|
||||
break;
|
||||
|
||||
if (i == num)
|
||||
{
|
||||
Log(LOG_NORMAL, "sqlite") << "SQLite: Removing server connection " << cname;
|
||||
|
||||
delete s;
|
||||
this->SQLiteServices.erase(cname);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, num = config.Enumerate("sqlite"); i < num; ++i)
|
||||
{
|
||||
Anope::string connname = config.ReadValue("sqlite", "name", "sqlite/main", i);
|
||||
|
||||
if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
|
||||
{
|
||||
Anope::string database = config.ReadValue("sqlite", "database", "anope", i);
|
||||
|
||||
try
|
||||
{
|
||||
SQLiteService *ss = new SQLiteService(this, connname, database);
|
||||
this->SQLiteServices[connname] = ss;
|
||||
|
||||
Log(LOG_NORMAL, "sqlite") << "SQLite: Successfully added database " << database;
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
Log(LOG_NORMAL, "sqlite") << "SQLite: " << ex.GetReason();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SQLiteService::SQLiteService(Module *o, const Anope::string &n, const Anope::string &d)
|
||||
: SQLProvider(o, n), database(d), sql(NULL)
|
||||
{
|
||||
int db = sqlite3_open_v2(database.c_str(), &this->sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
|
||||
if (db != SQLITE_OK)
|
||||
throw SQLException("Unable to open SQLite database " + database + ": " + sqlite3_errmsg(this->sql));
|
||||
}
|
||||
|
||||
SQLiteService::~SQLiteService()
|
||||
{
|
||||
sqlite3_interrupt(this->sql);
|
||||
sqlite3_close(this->sql);
|
||||
}
|
||||
|
||||
void SQLiteService::Run(SQLInterface *i, const SQLQuery &query)
|
||||
{
|
||||
SQLResult res = this->RunQuery(query);
|
||||
if (!res.GetError().empty())
|
||||
i->OnError(res);
|
||||
else
|
||||
i->OnResult(res);
|
||||
}
|
||||
|
||||
SQLResult SQLiteService::RunQuery(const SQLQuery &query)
|
||||
{
|
||||
Anope::string real_query = this->BuildQuery(query);
|
||||
sqlite3_stmt *stmt;
|
||||
int err = sqlite3_prepare_v2(this->sql, real_query.c_str(), real_query.length(), &stmt, NULL);
|
||||
if (err != SQLITE_OK)
|
||||
return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
|
||||
|
||||
std::vector<Anope::string> columns;
|
||||
int cols = sqlite3_column_count(stmt);
|
||||
columns.resize(cols);
|
||||
for (int i = 0; i < cols; ++i)
|
||||
columns[i] = sqlite3_column_name(stmt, i);
|
||||
|
||||
SQLiteResult result(query, real_query);
|
||||
|
||||
do
|
||||
{
|
||||
err = sqlite3_step(stmt);
|
||||
if (err == SQLITE_ROW)
|
||||
{
|
||||
std::map<Anope::string, Anope::string> items;
|
||||
for (int i = 0; i < cols; ++i)
|
||||
{
|
||||
const char *data = reinterpret_cast<const char *>(sqlite3_column_text(stmt, i));
|
||||
if (data && *data)
|
||||
items[columns[i]] = data;
|
||||
}
|
||||
result.addRow(items);
|
||||
}
|
||||
}
|
||||
while (err == SQLITE_ROW);
|
||||
|
||||
if (err != SQLITE_DONE)
|
||||
return SQLiteResult(query, real_query, sqlite3_errmsg(this->sql));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLQuery SQLiteService::CreateTable(const Anope::string &table, const SerializableBase::serialized_data &data)
|
||||
{
|
||||
Anope::string query_text = "CREATE TABLE `" + table + "` (", key_buf;
|
||||
for (SerializableBase::serialized_data::const_iterator it = data.begin(), it_end = data.end(); it != it_end; ++it)
|
||||
{
|
||||
query_text += "`" + it->first + "` ";
|
||||
if (it->second.getType() == Serialize::DT_INT)
|
||||
query_text += "int(11)";
|
||||
else if (it->second.getMax() > 0)
|
||||
query_text += "varchar(" + stringify(it->second.getMax()) + ")";
|
||||
else
|
||||
query_text += "text";
|
||||
query_text += ",";
|
||||
|
||||
if (it->second.getKey())
|
||||
{
|
||||
if (key_buf.empty())
|
||||
key_buf = "UNIQUE (";
|
||||
key_buf += "`" + it->first + "`,";
|
||||
}
|
||||
}
|
||||
if (!key_buf.empty())
|
||||
{
|
||||
key_buf.erase(key_buf.end() - 1);
|
||||
key_buf += ")";
|
||||
query_text += " " + key_buf;
|
||||
}
|
||||
else
|
||||
query_text.erase(query_text.end() - 1);
|
||||
query_text += ")";
|
||||
|
||||
return SQLQuery(query_text);
|
||||
}
|
||||
|
||||
Anope::string SQLiteService::Escape(const Anope::string &query)
|
||||
{
|
||||
char *e = sqlite3_mprintf("%q", query.c_str());
|
||||
Anope::string buffer = e;
|
||||
sqlite3_free(e);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Anope::string SQLiteService::BuildQuery(const SQLQuery &q)
|
||||
{
|
||||
Anope::string real_query = q.query;
|
||||
|
||||
for (std::map<Anope::string, Anope::string>::const_iterator it = q.parameters.begin(), it_end = q.parameters.end(); it != it_end; ++it)
|
||||
real_query = real_query.replace_all_cs("@" + it->first + "@", "'" + this->Escape(it->second) + "'");
|
||||
|
||||
return real_query;
|
||||
}
|
||||
|
||||
MODULE_INIT(ModuleSQLite)
|
||||
|
||||
@@ -116,5 +116,7 @@ class SQLProvider : public Service<Base>
|
||||
virtual void Run(SQLInterface *i, const SQLQuery &query) = 0;
|
||||
|
||||
virtual SQLResult RunQuery(const SQLQuery &query) = 0;
|
||||
|
||||
virtual SQLQuery CreateTable(const Anope::string &table, const SerializableBase::serialized_data &data) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -268,8 +268,7 @@ class InspIRCdProto : public IRCDProto
|
||||
|
||||
Anope::string svidbuf = stringify(u->timestamp);
|
||||
|
||||
u->Account()->Shrink("authenticationtoken");
|
||||
u->Account()->Extend("authenticationtoken", new ExtensibleItemRegular<Anope::string>(svidbuf));
|
||||
u->Account()->Extend("authenticationtoken", new ExtensibleString(svidbuf));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -321,8 +320,8 @@ class InspircdIRCdMessage : public IRCdMessage
|
||||
user->SetCloakedHost(params[3]);
|
||||
|
||||
NickAlias *na = findnick(user->nick);
|
||||
Anope::string svidbuf;
|
||||
if (na && na->nc->GetExtRegular("authenticationtoken", svidbuf) && svidbuf == params[0])
|
||||
Anope::string *svidbuf = na ? na->nc->GetExt<Anope::string *>("authenticationtoken") : NULL;
|
||||
if (na && svidbuf && *svidbuf == params[0])
|
||||
{
|
||||
user->Login(na->nc);
|
||||
if (na->nc->HasFlag(NI_UNCONFIRMED))
|
||||
|
||||
@@ -85,6 +85,7 @@ class MyMemoServService : public MemoServService
|
||||
|
||||
Memo *m = new Memo();
|
||||
mi->memos.push_back(m);
|
||||
m->owner = target;
|
||||
m->sender = source;
|
||||
m->time = Anope::CurTime;
|
||||
m->text = message;
|
||||
|
||||
@@ -273,6 +273,19 @@ class OperServCore : public Module
|
||||
XLineManager::RegisterXLineManager(&sglines);
|
||||
XLineManager::RegisterXLineManager(&sqlines);
|
||||
XLineManager::RegisterXLineManager(&snlines);
|
||||
|
||||
Serializable<XLine>::Alloc.Register("XLine");
|
||||
}
|
||||
|
||||
~OperServCore()
|
||||
{
|
||||
this->sglines.Clear();
|
||||
this->sqlines.Clear();
|
||||
this->snlines.Clear();
|
||||
|
||||
XLineManager::UnregisterXLineManager(&sglines);
|
||||
XLineManager::UnregisterXLineManager(&sqlines);
|
||||
XLineManager::UnregisterXLineManager(&snlines);
|
||||
}
|
||||
|
||||
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message)
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "services.h"
|
||||
#include "modules.h"
|
||||
#include "access.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
#include "services.h"
|
||||
#include "modules.h"
|
||||
|
||||
std::vector<SerializableBase *> serialized_types;
|
||||
std::list<SerializableBase *> serialized_items;
|
||||
|
||||
void RegisterTypes()
|
||||
{
|
||||
Serializable<NickCore>::Alloc.Register("NickCore");
|
||||
Serializable<NickAlias>::Alloc.Register("NickAlias");
|
||||
Serializable<BotInfo>::Alloc.Register("BotInfo");
|
||||
Serializable<ChannelInfo>::Alloc.Register("ChannelInfo");
|
||||
Serializable<LogSetting>::Alloc.Register("LogSetting");
|
||||
Serializable<ModeLock>::Alloc.Register("ModeLock");
|
||||
Serializable<AutoKick>::Alloc.Register("AutoKick");
|
||||
Serializable<BadWord>::Alloc.Register("BadWord");
|
||||
Serializable<Memo>::Alloc.Register("Memo");
|
||||
}
|
||||
|
||||
Base::Base()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# If not on Windows, generate anoperc and install it along with mydbgen
|
||||
if(NOT WIN32)
|
||||
configure_file(${Anope_SOURCE_DIR}/src/bin/anoperc.in ${Anope_BINARY_DIR}/src/bin/anoperc)
|
||||
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/anoperc ${CMAKE_CURRENT_SOURCE_DIR}/mydbgen
|
||||
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/anoperc
|
||||
DESTINATION bin
|
||||
)
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $1 = "-t" ] ; then
|
||||
shift
|
||||
fi
|
||||
if [ ! "$2" ] ; then
|
||||
echo >&2 Usage: $0 '<sourcedir> <targetdir>'
|
||||
exit 1
|
||||
fi
|
||||
if [ -d "$1" ] ; then
|
||||
dir="$1"
|
||||
else
|
||||
dir="`echo $1 | sed 's#\(.*\)/.*#\1#'`"
|
||||
fi
|
||||
while [ "$2" ] ; do
|
||||
shift
|
||||
done
|
||||
if [ ! -d $1 ] ; then
|
||||
mkdir -p $1 || exit 1
|
||||
fi
|
||||
/bin/tar -Ccf $dir - . | /bin/tar -Cxf $1 -
|
||||
@@ -1,239 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Ribosome's all in one language tool
|
||||
# 1) Compares to check for missing lines
|
||||
# 2) Compares to check for equal lines
|
||||
# 3) Fixes (on request) missing lines
|
||||
# 4) Checks for errors in lines
|
||||
# 5) Checks for long lines (>60 characters)
|
||||
#
|
||||
|
||||
# Check to see if we have received arguments
|
||||
if (!$ARGV[0]) {
|
||||
print "Usage: $0 [language file]\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# If yes, set $sourcefile to the language filename
|
||||
$testagainst = $ARGV[0];
|
||||
|
||||
# Set $sourcefile to en_us language file
|
||||
$sourcefile = "en_us.l";
|
||||
|
||||
# Number of Keys in File, Number of Equal Lines, Number of Missing Lines
|
||||
# Fixed Lines (optional) and Number of Format Error Lines, Number of Long Lines
|
||||
my $numberlines = 0;
|
||||
my $equallines = 0;
|
||||
my $missinglines = 0;
|
||||
my $fixedlines = 0;
|
||||
my $errorline = 0;
|
||||
my $longlines = 0;
|
||||
|
||||
# Array to hold the lines from the source file and explosion array for long line check
|
||||
|
||||
my @sourcearray;
|
||||
my @explosion;
|
||||
|
||||
# Create associative arrays which will contain keys and definitions
|
||||
# One for the control source and one for what is being tested against
|
||||
|
||||
my %sourcehash= ();
|
||||
my %testhash= ();
|
||||
|
||||
# Check if Files Exist
|
||||
|
||||
if (! -f $sourcefile) {
|
||||
print "Critical Error: The source file does not exist or is unreadable.\nNote: This tool must be run from the language directory.\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
if (! -f $testagainst) {
|
||||
print "Critical Error: The language file does not exist or is unreadable\n";
|
||||
exit;
|
||||
}
|
||||
###########################################
|
||||
# Function to load sourcefile into memory #
|
||||
###########################################
|
||||
|
||||
sub load_sourcefile {
|
||||
|
||||
my $_key; # This variable will hold the key
|
||||
my $_def; # This variable will hold the definition
|
||||
my $line; # This variable will hold the current line
|
||||
|
||||
open (SOURCEFILE, "< $sourcefile"); # Open the source file
|
||||
while (<SOURCEFILE>) { # For each line the source file
|
||||
$line = $_; # $line is set to the line in the source file
|
||||
|
||||
# Skip comments
|
||||
if (/^#/) { # This checks for # which indicates comment
|
||||
next; # If detected, the next line is skipped to
|
||||
}
|
||||
|
||||
# Start of a key
|
||||
if (/^[A-Z]/) { # Checks to see if the line is a key
|
||||
chomp($line); # Removes things that shouldn't be at the end
|
||||
push (@sourcearray, $line); # Puts the line into the source array
|
||||
# If a key is defined, load definition into the hash
|
||||
if ($_key ne undef) { # If the key is defined
|
||||
$sourcehash{$_key} = $_def; # Add the definition to the associative array
|
||||
}
|
||||
$_key=$line; # Set the key to the line
|
||||
$_def=""; # Reset the definition
|
||||
next; # Move onto the next line
|
||||
}
|
||||
|
||||
if ($_key ne undef) { # If the key is set already
|
||||
$_def.=$line; # The definition is the current line
|
||||
}
|
||||
|
||||
$sourcehash{$_key} = $_def; # Load the definition into the associative array
|
||||
} # End of while which reads lines
|
||||
|
||||
close (SOURCEFILE); # Close the source file
|
||||
|
||||
} # End of load_sourcefile function
|
||||
|
||||
#################################################
|
||||
# Function to load testagainst file into memory #
|
||||
#################################################
|
||||
|
||||
sub load_testagainst {
|
||||
|
||||
my $_key; # This variable will hold the key
|
||||
my $_def; # This variable will hold the definition
|
||||
my $line; # This variable will hold the current line
|
||||
|
||||
open (TESTAGAINSTFILE, "< $testagainst"); # Open the file containing the control lines
|
||||
while (<TESTAGAINSTFILE>) { # For each line in the file
|
||||
$line = $_; # $line is set to the lines value
|
||||
|
||||
|
||||
# Skip comments
|
||||
if (/^#/) { # This checks for # which indicates comment
|
||||
next; # If detected, the next line is skipped to
|
||||
}
|
||||
|
||||
# Start of a key
|
||||
if (/^[A-Z]/) { # Checks to see if the line is a key
|
||||
chomp($line); # Removes things that shouldn't be at the end
|
||||
|
||||
|
||||
if ($_key ne undef) { # If the key is defined
|
||||
$testhash{$_key} = $_def; # Add the definition to the associative array
|
||||
}
|
||||
$_key=$line; # Set the key to the line
|
||||
$_def=""; # Reset the definition
|
||||
next; # Move onto the next line
|
||||
}
|
||||
|
||||
if ($_key ne undef) { # If the key is set already
|
||||
$_def.=$line; # The definition is the current line
|
||||
}
|
||||
|
||||
$testhash{$_key} = $_def; # Load the definition into the associative array
|
||||
} # End of while which reads lines
|
||||
close (TESTAGAINSTFILE); # Close the source file
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub get_format { # Function to get the formatting from a string
|
||||
my $fmt="";
|
||||
my $str=shift; # Get the input
|
||||
|
||||
while ($str =~ m/%\w/g) {
|
||||
$fmt .= $&;
|
||||
}
|
||||
|
||||
return $fmt; # Return the formatting
|
||||
}
|
||||
|
||||
|
||||
load_sourcefile; # Call function to load the source file
|
||||
load_testagainst; # Call function to load the test file
|
||||
|
||||
if (!grep(/^LANG_NAME/,%testhash)) {
|
||||
print "Critical Error: $ARGV[0] is not a valid language file!\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
open (LOG,"> langcheck.log"); # Open logfile for writing
|
||||
|
||||
foreach $sourcearray (@sourcearray) { # For each key stored in the source array
|
||||
my $_key=$_; # Store key from source array in $_key
|
||||
|
||||
if ((get_format($sourcehash{$sourcearray})) ne (get_format($testhash{$sourcearray}))) {
|
||||
if ($sourcearray !~ STRFTIME ) {
|
||||
$errorline++;
|
||||
print LOG "FORMAT: $sourcearray - (expecting '".get_format($sourcehash{$sourcearray})."' and got '".get_format($testhash{$sourcearray})."')\n";
|
||||
} }
|
||||
|
||||
if ($testhash{$sourcearray} eq $sourcehash{$sourcearray} ) {
|
||||
# If the definitions between the source and the test are equal
|
||||
$equallines++; # Number of equal lines increases
|
||||
print LOG "EQUAL: $sourcearray\n"; # Line is written to logfile
|
||||
}
|
||||
|
||||
if (!grep(/^$sourcearray/,%testhash)) { # If the key is found in the testhash associative array
|
||||
$missinglines++; # Increase missing lines
|
||||
print LOG "MISSING: $sourcearray\n"; # Line is written to logfile
|
||||
}
|
||||
|
||||
@explosion = split(/\n/, $testhash{$sourcearray});
|
||||
foreach $explosion (@explosion) {
|
||||
$explosion =~ s/\002//g;
|
||||
$explosion =~ s/\037//g;
|
||||
if (length($explosion) > 61) {
|
||||
print LOG "LONGLINE: $sourcearray (".substr($explosion,1,30)."...)\n";
|
||||
$longlines++;
|
||||
}
|
||||
}
|
||||
|
||||
$numberlines++; # Increase the number of lines tested by 1
|
||||
}
|
||||
close (LOG); # Close the logfile
|
||||
|
||||
|
||||
#########################
|
||||
# Show the test results #
|
||||
#########################
|
||||
|
||||
print "Calculation Results:\n";
|
||||
print "----------------------------------\n";
|
||||
print "[$numberlines] line(s) were compared\n";
|
||||
print "[$equallines] line(s) were found to equal their $sourcefile counterpart(s)\n";
|
||||
print "[$missinglines] line(s) were found to be missing\n";
|
||||
print "[$longlines] line(s) were found to be long (>60 chars)\n";
|
||||
print "[$errorline] line(s) were found to have formatting errors\n";
|
||||
print "The specific details of the test have been saved in langcheck.log\n";
|
||||
|
||||
if ($missinglines) { # If missing lines exist
|
||||
print "----------------------------------\n";
|
||||
print "Missing line(s) have been detected in this test, would you like to fix the file?\n";
|
||||
print "This automatically inserts values from the control file ($sourcefile) for the missing values\n";
|
||||
print "y/N? (Default: No) ";
|
||||
|
||||
my $input = <STDIN>; # Ask if the file should be fixed
|
||||
if ((substr($input,0,1) eq "y") || (substr($input,0,1) eq "Y")) { # If Yes...
|
||||
|
||||
open (FIX, ">> $testagainst"); # Open the file and append changes
|
||||
|
||||
foreach $sourcearray (@sourcearray) { # For each key stored in the source array
|
||||
my $_key=$_; # Store key from source array in $_key
|
||||
|
||||
if (!grep(/^$sourcearray/,%testhash)) { # If the key is not found in the testhash associative array
|
||||
print FIX "$sourcearray\n$sourcehash{$sourcearray}"; # Add the line(s) to the language file
|
||||
$fixedlines++; # Increase the fixed line count
|
||||
}
|
||||
}
|
||||
|
||||
close (FIX); # Close file after fixing
|
||||
|
||||
print "Fixing Compete. [$fixedlines] line(s) fixed.\n";
|
||||
exit; # And Exit!
|
||||
}
|
||||
# Otherwise, quit without fixing
|
||||
print "Exiting. The language file has NOT been fixed.\n";
|
||||
|
||||
}
|
||||
-148
@@ -1,148 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
|
||||
# Location of the .sql file with the schema
|
||||
DBSQL="tables.sql"
|
||||
|
||||
# Schema Version
|
||||
SVER="2"
|
||||
|
||||
# Local Version, defaults to 0
|
||||
LVER="0"
|
||||
|
||||
TFILE="/tmp/.anopedb.$$"
|
||||
|
||||
if [ "`eval echo -n 'a'`" = "-n a" ] ; then
|
||||
c="\c"
|
||||
else
|
||||
n="-n"
|
||||
fi
|
||||
|
||||
DBFILE=../data/$DBSQL
|
||||
|
||||
if [ ! -f "./$DBFILE" ] ; then
|
||||
echo "Error: Required file $DBSQL was not found!";
|
||||
exit
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "This script will guide you through the process of configuring your Anope"
|
||||
echo "installation to make use of MySQL support. This script must be used for both"
|
||||
echo "new installs as well as for upgrading for users who have a previous version"
|
||||
echo "of Anope installed"
|
||||
|
||||
while [ -z "$SQLHOST" ] ; do
|
||||
echo ""
|
||||
echo "What is the hostname of your MySQL server?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLHOST=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
while [ -z "$SQLUSER" ] ; do
|
||||
echo ""
|
||||
echo "What is your MySQL username?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLUSER=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
OLD_TTY=`stty -g`
|
||||
|
||||
echo ""
|
||||
echo "What is your MySQL password?"
|
||||
echo $n "-> $c"
|
||||
stty -echo echonl
|
||||
read cc
|
||||
SQLPASS_PREFIX=""
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLPASS_PREFIX="-p"
|
||||
SQLPASS=$cc
|
||||
fi
|
||||
stty $OLD_TTY
|
||||
|
||||
mysqlshow -h$SQLHOST -u$SQLUSER $SQLPASS_PREFIX$SQLPASS >/dev/null 2>&1
|
||||
if test "$?" = "1" ; then
|
||||
echo "Error: Unable to login, verify your login/password and hostname"
|
||||
exit
|
||||
fi
|
||||
|
||||
while [ -z "$SQLDB" ] ; do
|
||||
echo ""
|
||||
echo "What is the name of the Anope SQL database?"
|
||||
echo $n "-> $c"
|
||||
read cc
|
||||
if [ ! -z "$cc" ] ; then
|
||||
SQLDB=$cc
|
||||
fi
|
||||
done
|
||||
|
||||
MYSQLDUMP="mysqldump -h$SQLHOST -u$SQLUSER $SQLPASS_PREFIX$SQLPASS $SQLDB"
|
||||
MYSQLSHOW="mysqlshow -h$SQLHOST -u$SQLUSER $SQLPASS_PREFIX$SQLPASS $SQLDB"
|
||||
MYSQL="mysql -h$SQLHOST -u$SQLUSER $SQLPASS_PREFIX$SQLPASS $SQLDB"
|
||||
|
||||
echo ""
|
||||
|
||||
$MYSQLSHOW | grep -q $SQLDB
|
||||
if test "$?" = "1" ; then
|
||||
echo -n "Unable to find databse, creating... "
|
||||
mysql -h$SQLHOST -u$SQLUSER $SQLPASS_PREFIX$SQLPASS -Bs -e "create database $SQLDB" >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'database creation'"
|
||||
fi
|
||||
fi
|
||||
|
||||
$MYSQL -Bs -e "show tables like 'anope_os_core'" | grep -q anope_os_core
|
||||
if test "$?" = "1" ; then
|
||||
echo -n "Unable to find Anope schema, creating... "
|
||||
$MYSQL < $DBFILE
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'schema creation'"
|
||||
fi
|
||||
else
|
||||
echo "done!"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
if [ $LVER -ne $SVER ]; then
|
||||
echo -n "Inserting initial version number... "
|
||||
$MYSQL -Bs -e "delete from anope_info"
|
||||
echo "INSERT INTO anope_info (version, date) VALUES ($SVER, now())" > $TFILE
|
||||
$MYSQL < $TFILE >/dev/null 2>&1
|
||||
if test "$?" = "0" ; then
|
||||
echo "done!"
|
||||
else
|
||||
echo "failed!"
|
||||
FAILED="$FAILED 'version insert'"
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f $TFILE
|
||||
if test "x$FAILED" = "x" ; then
|
||||
# Try to find out more about this installation
|
||||
SQLPORT="$(mysql_config --port 2> /dev/null)"
|
||||
if test "$SQLPORT" = "0" ; then
|
||||
SQLPORT=3306
|
||||
fi
|
||||
echo ""
|
||||
echo "Your MySQL setup is complete and your Anope schema is up to date. Make"
|
||||
echo "sure you configure MySQL on your services.conf file prior to launching"
|
||||
echo "Anope with MySQL support."
|
||||
echo ""
|
||||
else
|
||||
echo "The following operations failed:"
|
||||
echo "$FAILED"
|
||||
fi
|
||||
|
||||
exit
|
||||
@@ -64,6 +64,29 @@ BotInfo::~BotInfo()
|
||||
BotListByUID.erase(this->uid);
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data BotInfo::serialize()
|
||||
{
|
||||
SerializableBase::serialized_data data;
|
||||
|
||||
data["nick"] << this->nick;
|
||||
data["user"] << this->ident;
|
||||
data["host"] << this->host;
|
||||
data["realname"] << this->realname;
|
||||
data["created"] << this->created;
|
||||
data["chancount"] << this->chancount;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void BotInfo::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
BotInfo *bi = findbot(data["nick"].astr());
|
||||
if (bi == NULL)
|
||||
bi = new BotInfo(data["nick"].astr(), data["user"].astr(), data["host"].astr(), data["realname"].astr());
|
||||
data["created"] >> bi->created;
|
||||
data["chancount"] >> bi->chancount;
|
||||
}
|
||||
|
||||
void BotInfo::GenerateUID()
|
||||
{
|
||||
if (!this->uid.empty())
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ const Anope::string &HostInfo::GetCreator() const
|
||||
/** Retrieve when the vhost was crated
|
||||
* @return the time it was created
|
||||
*/
|
||||
const time_t HostInfo::GetTime() const
|
||||
time_t HostInfo::GetTime() const
|
||||
{
|
||||
return Time;
|
||||
}
|
||||
|
||||
+2
-2
@@ -241,6 +241,8 @@ void Init(int ac, char **av)
|
||||
#endif
|
||||
if (set_group() < 0)
|
||||
throw FatalException("set_group() fail");
|
||||
|
||||
RegisterTypes();
|
||||
|
||||
/* Parse command line arguments */
|
||||
ParseCommandLineArguments(ac, av);
|
||||
@@ -442,8 +444,6 @@ void Init(int ac, char **av)
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnLoadDatabase, OnLoadDatabase());
|
||||
Log() << "Databases loaded";
|
||||
|
||||
FOREACH_MOD(I_OnPostLoadDatabases, OnPostLoadDatabases());
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
@@ -375,6 +375,7 @@ int main(int ac, char **av, char **envp)
|
||||
ModuleManager::UnloadModule(m, NULL);
|
||||
|
||||
ModuleManager::CleanupRuntimeDirectory();
|
||||
serialized_items.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
OnShutdown();
|
||||
|
||||
@@ -11,9 +11,41 @@
|
||||
|
||||
#include "services.h"
|
||||
#include "modules.h"
|
||||
#include "memoserv.h"
|
||||
|
||||
Memo::Memo() : Flags<MemoFlag>(MemoFlagStrings) { }
|
||||
|
||||
SerializableBase::serialized_data Memo::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["owner"] << this->owner;
|
||||
data["time"] << this->time;
|
||||
data["sender"] << this->sender;
|
||||
data["text"] << this->text;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Memo::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
if (!memoserv)
|
||||
return;
|
||||
|
||||
bool ischan;
|
||||
MemoInfo *mi = memoserv->GetMemoInfo(data["owner"].astr(), ischan);
|
||||
if (!mi)
|
||||
return;
|
||||
|
||||
Memo *m = new Memo();
|
||||
data["owner"] >> m->owner;
|
||||
data["time"] >> m->time;
|
||||
data["sender"] >> m->sender;
|
||||
data["text"] >> m->text;
|
||||
|
||||
mi->memos.push_back(m);
|
||||
}
|
||||
|
||||
unsigned MemoInfo::GetIndex(Memo *m) const
|
||||
{
|
||||
for (unsigned i = 0; i < this->memos.size(); ++i)
|
||||
|
||||
@@ -14,6 +14,19 @@
|
||||
#include "version.h"
|
||||
#include "modules.h"
|
||||
|
||||
ExtensibleItem::ExtensibleItem()
|
||||
{
|
||||
}
|
||||
|
||||
ExtensibleItem::~ExtensibleItem()
|
||||
{
|
||||
}
|
||||
|
||||
void ExtensibleItem::OnDelete()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
struct arc4_stream
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ void SetDefaultMLock(ServerConfig *config)
|
||||
|
||||
if (cm->Type != MODE_LIST) // Only MODE_LIST can have duplicates
|
||||
def_mode_locks.erase(cm->Name);
|
||||
def_mode_locks.insert(std::make_pair(cm->Name, ModeLock(adding == 1, cm->Name, param)));
|
||||
def_mode_locks.insert(std::make_pair(cm->Name, ModeLock(NULL, adding == 1, cm->Name, param)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,3 +102,47 @@ void NickAlias::OnCancel(User *)
|
||||
new NickServRelease(this, Config->NSReleaseTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data NickAlias::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["nick"].setKey().setMax(Config->NickLen) << this->nick;
|
||||
data["last_quit"] << this->last_quit;
|
||||
data["last_realname"] << this->last_realname;
|
||||
data["last_usermask"] << this->last_usermask;
|
||||
data["last_realhost"] << this->last_realhost;
|
||||
data["time_registered"].setType(Serialize::DT_INT) << this->time_registered;
|
||||
data["last_seen"].setType(Serialize::DT_INT) << this->last_seen;
|
||||
data["nc"] << this->nc->display;
|
||||
|
||||
if (this->hostinfo.HasVhost())
|
||||
{
|
||||
data["vhost_ident"] << this->hostinfo.GetIdent();
|
||||
data["vhost_host"] << this->hostinfo.GetHost();
|
||||
data["vhost_creator"] << this->hostinfo.GetCreator();
|
||||
data["vhost_time"] << this->hostinfo.GetTime();
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void NickAlias::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
NickCore *core = findcore(data["nc"].astr());
|
||||
if (core == NULL)
|
||||
return;
|
||||
|
||||
NickAlias *na = new NickAlias(data["nick"].astr(), core);
|
||||
data["last_quit"] >> na->last_quit;
|
||||
data["last_realname"] >> na->last_realname;
|
||||
data["last_usermask"] >> na->last_usermask;
|
||||
data["last_realhost"] >> na->last_realhost;
|
||||
data["time_registered"] >> na->time_registered;
|
||||
data["last_seen"] >> na->last_seen;
|
||||
|
||||
time_t vhost_time;
|
||||
data["vhost_time"] >> vhost_time;
|
||||
na->hostinfo.SetVhost(data["vhost_ident"].astr(), data["vhost_host"].astr(), data["vhost_creator"].astr(), vhost_time);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,57 @@ NickCore::~NickCore()
|
||||
}
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data NickCore::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["display"].setKey().setMax(Config->NickLen) << this->display;
|
||||
data["pass"] << this->pass;
|
||||
data["email"] << this->email;
|
||||
data["greet"] << this->greet;
|
||||
data["language"] << this->language;
|
||||
for (unsigned i = 0; i < this->access.size(); ++i)
|
||||
data["access"] << this->access[i] << " ";
|
||||
for (unsigned i = 0; i < this->cert.size(); ++i)
|
||||
data["cert"] << this->cert[i] << " ";
|
||||
data["memomax"] << this->memos.memomax;
|
||||
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
|
||||
data["memoignores"] << this->memos.ignores[i] << " ";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void NickCore::unserialize(serialized_data &data)
|
||||
{
|
||||
NickCore *nc = new NickCore(data["display"].astr());
|
||||
data["pass"] >> nc->pass;
|
||||
data["email"] >> nc->email;
|
||||
data["greet"] >> nc->greet;
|
||||
data["language"] >> nc->language;
|
||||
{
|
||||
Anope::string buf;
|
||||
data["access"] >> buf;
|
||||
spacesepstream sep(buf);
|
||||
while (sep.GetToken(buf))
|
||||
nc->access.push_back(buf);
|
||||
}
|
||||
{
|
||||
Anope::string buf;
|
||||
data["cert"] >> buf;
|
||||
spacesepstream sep(buf);
|
||||
while (sep.GetToken(buf))
|
||||
nc->access.push_back(buf);
|
||||
}
|
||||
data["memomax"] >> nc->memos.memomax;
|
||||
{
|
||||
Anope::string buf;
|
||||
data["memoignores"] >> buf;
|
||||
spacesepstream sep(buf);
|
||||
while (sep.GetToken(buf))
|
||||
nc->memos.ignores.push_back(buf);
|
||||
}
|
||||
}
|
||||
|
||||
bool NickCore::IsServicesOper() const
|
||||
{
|
||||
return this->o != NULL;
|
||||
|
||||
+39
-2
@@ -16,6 +16,10 @@
|
||||
/* List of XLine managers we check users against in XLineManager::CheckAll */
|
||||
std::list<XLineManager *> XLineManager::XLineManagers;
|
||||
|
||||
XLine::XLine()
|
||||
{
|
||||
}
|
||||
|
||||
XLine::XLine(const Anope::string &mask, const Anope::string &reason) : Mask(mask), Created(0), Expires(0), Reason(reason)
|
||||
{
|
||||
}
|
||||
@@ -66,6 +70,37 @@ sockaddrs XLine::GetIP() const
|
||||
return addr;
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data XLine::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["mask"] << this->Mask;
|
||||
data["by"] << this->By;
|
||||
data["created"] << this->Created;
|
||||
data["expires"] << this->Expires;
|
||||
data["reason"] << this->Reason;
|
||||
data["manager"] << this->Manager;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void XLine::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
service_reference<XLineManager> xlm(data["manager"].astr());
|
||||
if (!xlm)
|
||||
return;
|
||||
|
||||
XLine *xl = new XLine();
|
||||
|
||||
data["mask"] >> xl->Mask;
|
||||
data["by"] >> xl->By;
|
||||
data["created"] >> xl->Created;
|
||||
data["expires"] >> xl->Expires;
|
||||
data["reason"] >> xl->Reason;
|
||||
|
||||
xlm->AddXLine(xl);
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
XLineManager::XLineManager(Module *creator, const Anope::string &xname, char t) : Service<XLineManager>(creator, xname), type(t)
|
||||
@@ -159,6 +194,7 @@ const std::vector<XLine *> &XLineManager::GetList() const
|
||||
*/
|
||||
void XLineManager::AddXLine(XLine *x)
|
||||
{
|
||||
x->Manager = this->name;
|
||||
this->XLines.push_back(x);
|
||||
}
|
||||
|
||||
@@ -199,8 +235,9 @@ XLine *XLineManager::GetEntry(unsigned index)
|
||||
*/
|
||||
void XLineManager::Clear()
|
||||
{
|
||||
while (!this->XLines.empty())
|
||||
this->DelXLine(this->XLines.front());
|
||||
for (unsigned i = 0; i < this->XLines.size(); ++i)
|
||||
delete this->XLines[i];
|
||||
this->XLines.clear();
|
||||
}
|
||||
|
||||
/** Add an entry to this XLine Manager
|
||||
|
||||
+214
-7
@@ -12,6 +12,124 @@
|
||||
#include "services.h"
|
||||
#include "modules.h"
|
||||
|
||||
SerializableBase::serialized_data BadWord::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["word"] << this->word;
|
||||
data["type"].setType(Serialize::DT_INT) << this->type;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void BadWord::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
BadWord *bw = new BadWord();
|
||||
data["word"] >> bw->word;
|
||||
unsigned int n;
|
||||
data["type"] >> n;
|
||||
bw->type = static_cast<BadWordType>(n);
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data AutoKick::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
if (this->HasFlag(AK_ISNICK) && this->nc)
|
||||
data["nc"] << this->nc->display;
|
||||
else
|
||||
data["mask"] << this->mask;
|
||||
data["reason"] << this->reason;
|
||||
data["creator"] << this->creator;
|
||||
data["addtime"].setType(Serialize::DT_INT) << this->addtime;
|
||||
data["last_used"].setType(Serialize::DT_INT) << this->last_used;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void AutoKick::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
AutoKick *ak = new AutoKick();
|
||||
|
||||
data["mask"] >> ak->mask;
|
||||
ak->nc = findcore(data["nc"].astr());
|
||||
data["reason"] >> ak->reason;
|
||||
data["creator"] >> ak->creator;
|
||||
data["addtime"] >> ak->addtime;
|
||||
data["last_used"] >> ak->last_used;
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data ModeLock::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
if (this->ci == NULL)
|
||||
return data;
|
||||
|
||||
data["ci"] << this->ci->name;
|
||||
data["set"] << this->set;
|
||||
data["name"] << ChannelModeNameStrings[this->name];
|
||||
data["param"] << this->param;
|
||||
data["setter"] << this->setter;
|
||||
data["created"].setType(Serialize::DT_INT) << this->created;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ModeLock::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(data["ci"].astr());
|
||||
if (ci == NULL)
|
||||
return;
|
||||
|
||||
ModeLock ml;
|
||||
|
||||
ml.ci = ci;
|
||||
|
||||
data["set"] >> ml.set;
|
||||
Anope::string n;
|
||||
data["name"] >> n;
|
||||
for (unsigned i = 0; !ChannelModeNameStrings[i].empty(); ++i)
|
||||
if (n == ChannelModeNameStrings[i])
|
||||
{
|
||||
ml.name = static_cast<ChannelModeName>(i);
|
||||
break;
|
||||
}
|
||||
data["param"] >> ml.param;
|
||||
data["setter"] >> ml.setter;
|
||||
data["created"] >> ml.created;
|
||||
|
||||
ci->mode_locks.insert(std::make_pair(ml.name, ml));
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data LogSetting::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["service_name"] << service_name;
|
||||
data["command_service"] << command_service;
|
||||
data["command_name"] << command_name;
|
||||
data["method"] << method;
|
||||
data["extra"] << extra;
|
||||
data["creator"] << creator;
|
||||
data["created"].setType(Serialize::DT_INT) << created;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void LogSetting::unserialize(serialized_data &data)
|
||||
{
|
||||
LogSetting ls;
|
||||
|
||||
data["service_name"] >> ls.service_name;
|
||||
data["command_service"] >> ls.command_service;
|
||||
data["command_name"] >> ls.command_name;
|
||||
data["method"] >> ls.method;
|
||||
data["extra"] >> ls.extra;
|
||||
data["creator"] >> ls.creator;
|
||||
data["created"] >> ls.created;
|
||||
}
|
||||
|
||||
/** Default constructor
|
||||
* @param chname The channel name
|
||||
*/
|
||||
@@ -142,6 +260,83 @@ ChannelInfo::~ChannelInfo()
|
||||
--this->founder->channelcount;
|
||||
}
|
||||
|
||||
SerializableBase::serialized_data ChannelInfo::serialize()
|
||||
{
|
||||
serialized_data data;
|
||||
|
||||
data["name"].setKey().setMax(255) << this->name;
|
||||
if (this->founder)
|
||||
data["founder"] << this->founder->display;
|
||||
if (this->successor)
|
||||
data["successor"] << this->successor->display;
|
||||
data["description"] << this->desc;
|
||||
data["time_registered"].setType(Serialize::DT_INT) << this->time_registered;
|
||||
data["last_used"].setType(Serialize::DT_INT) << this->last_used;
|
||||
data["last_topic"] << this->last_topic;
|
||||
data["last_topic_setter"] << this->last_topic_setter;
|
||||
data["last_topic_time"].setType(Serialize::DT_INT) << this->last_topic_time;
|
||||
data["bantype"].setType(Serialize::DT_INT) << this->bantype;
|
||||
data["botflags"] << this->botflags.ToString();
|
||||
{
|
||||
Anope::string levels_buffer;
|
||||
for (std::map<Anope::string, int16>::iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
|
||||
levels_buffer += it->first + " " + stringify(it->second) + " ";
|
||||
data["levels"] << levels_buffer;
|
||||
}
|
||||
if (this->bi)
|
||||
data["bi"] << this->bi->nick;
|
||||
for (int i = 0; i < TTB_SIZE; ++i)
|
||||
data["ttb"] << this->ttb[i] << " ";
|
||||
data["capsmin"].setType(Serialize::DT_INT) << this->capsmin;
|
||||
data["capspercent"].setType(Serialize::DT_INT) << this->capspercent;
|
||||
data["floodlines"].setType(Serialize::DT_INT) << this->floodlines;
|
||||
data["floodsecs"].setType(Serialize::DT_INT) << this->floodsecs;
|
||||
data["repeattimes"].setType(Serialize::DT_INT) << this->repeattimes;
|
||||
data["memomax"] << this->memos.memomax;
|
||||
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
|
||||
data["memoignores"] << this->memos.ignores[i] << " ";
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void ChannelInfo::unserialize(SerializableBase::serialized_data &data)
|
||||
{
|
||||
ChannelInfo *ci = new ChannelInfo(data["name"].astr());
|
||||
if (data.count("founder") > 0)
|
||||
ci->founder = findcore(data["founder"].astr());
|
||||
if (data.count("successor") > 0)
|
||||
ci->successor = findcore(data["successor"].astr());
|
||||
data["description"] >> ci->desc;
|
||||
data["time_registered"] >> ci->time_registered;
|
||||
data["last_used"] >> ci->last_used;
|
||||
data["last_topic"] >> ci->last_topic;
|
||||
data["last_topic_setter"] >> ci->last_topic_setter;
|
||||
data["last_topic_time"] >> ci->last_topic_time;
|
||||
data["bantype"] >> ci->bantype;
|
||||
ci->botflags.FromString(data["botflags"].astr());
|
||||
{
|
||||
std::vector<Anope::string> v = BuildStringVector(data["levels"].astr());
|
||||
for (unsigned i = 0; i + 1 < v.size(); i += 2)
|
||||
ci->levels[v[i]] = convertTo<int16>(v[i + 1]);
|
||||
}
|
||||
if (data.count("bi") > 0)
|
||||
ci->bi = findbot(data["bi"].astr());
|
||||
data["capsmin"] >> ci->capsmin;
|
||||
data["capspercent"] >> ci->capspercent;
|
||||
data["floodlines"] >> ci->floodlines;
|
||||
data["floodsecs"] >> ci->floodsecs;
|
||||
data["repeattimes"] >> ci->repeattimes;
|
||||
data["memomax"] >> ci->memos.memomax;
|
||||
{
|
||||
Anope::string buf;
|
||||
data["memoignores"] >> buf;
|
||||
spacesepstream sep(buf);
|
||||
while (sep.GetToken(buf))
|
||||
ci->memos.ignores.push_back(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Change the founder of the channek
|
||||
* @params nc The new founder
|
||||
*/
|
||||
@@ -338,6 +533,7 @@ AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &
|
||||
{
|
||||
AutoKick *autokick = new AutoKick();
|
||||
autokick->mask = mask;
|
||||
autokick->nc = NULL;
|
||||
autokick->reason = reason;
|
||||
autokick->creator = user;
|
||||
autokick->addtime = t;
|
||||
@@ -484,7 +680,7 @@ bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string &
|
||||
{
|
||||
if (setter.empty())
|
||||
setter = this->founder ? this->founder->display : "Unknown";
|
||||
std::pair<ChannelModeName, ModeLock> ml = std::make_pair(mode->Name, ModeLock(status, mode->Name, param, setter, created));
|
||||
std::pair<ChannelModeName, ModeLock> ml = std::make_pair(mode->Name, ModeLock(this, status, mode->Name, param, setter, created));
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnMLock, OnMLock(this, &ml.second));
|
||||
@@ -525,13 +721,20 @@ bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string &
|
||||
*/
|
||||
bool ChannelInfo::RemoveMLock(ChannelMode *mode, const Anope::string ¶m)
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, mode, param));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return false;
|
||||
|
||||
if (mode->Type == MODE_REGULAR || mode->Type == MODE_PARAM)
|
||||
return this->mode_locks.erase(mode->Name) > 0;
|
||||
{
|
||||
std::multimap<ChannelModeName, ModeLock>::iterator it = this->mode_locks.find(mode->Name), it_end = this->mode_locks.upper_bound(mode->Name), it_next = it;
|
||||
if (it != this->mode_locks.end())
|
||||
for (; it != it_end; it = it_next)
|
||||
{
|
||||
++it_next;
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, &it->second));
|
||||
if (MOD_RESULT != EVENT_STOP)
|
||||
this->mode_locks.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For list or status modes, we must check the parameter
|
||||
@@ -544,6 +747,10 @@ bool ChannelInfo::RemoveMLock(ChannelMode *mode, const Anope::string ¶m)
|
||||
const ModeLock &ml = it->second;
|
||||
if (ml.param == param)
|
||||
{
|
||||
EventReturn MOD_RESULT;
|
||||
FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, &it->second));
|
||||
if (MOD_RESULT == EVENT_STOP)
|
||||
return false;
|
||||
this->mode_locks.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,975 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2011 Anope Team <team@anope.org>
|
||||
* Copyright (C) 2005-2006 Florian Schulze <certus@anope.org>
|
||||
* Copyright (C) 2008-2011 Robin Burchell <w00t@inspircd.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (see it online
|
||||
* at http://www.gnu.org/copyleft/gpl.html) as published by the Free
|
||||
* Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef DB_CONVERT_H
|
||||
#define DB_CONVERT_H
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "sysconf.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#define C_LBLUE "\033[1;34m"
|
||||
#define C_NONE "\033[m"
|
||||
#else
|
||||
#define C_LBLUE ""
|
||||
#define C_NONE ""
|
||||
#endif
|
||||
|
||||
#define getc_db(f) (fgetc((f)->fp))
|
||||
#define HASH(nick) ((tolower((nick)[0]) & 31)<<5 | (tolower((nick)[1]) & 31))
|
||||
#define HASH2(chan) ((chan)[1] ? ((chan)[1] & 31)<<5 | ((chan)[2] & 31) : 0)
|
||||
#define read_buffer(buf, f) (read_db((f), (buf), sizeof(buf)) == sizeof(buf))
|
||||
#define write_buffer(buf, f) (write_db((f), (buf), sizeof(buf)) == sizeof(buf))
|
||||
#define read_db(f, buf, len) (fread((buf), 1, (len), (f)->fp))
|
||||
#define write_db(f, buf, len) (fwrite((buf), 1, (len), (f)->fp))
|
||||
#define read_int8(ret, f) ((*(ret) = fgetc((f)->fp)) == EOF ? -1 : 0)
|
||||
#define write_int8(val, f) (fputc((val), (f)->fp) == EOF ? -1 : 0)
|
||||
#define SAFE(x) \
|
||||
if (true) \
|
||||
{ \
|
||||
if ((x) < 0) \
|
||||
printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
|
||||
} \
|
||||
else \
|
||||
static_cast<void>(0)
|
||||
#define READ(x) \
|
||||
if (true) \
|
||||
{ \
|
||||
if ((x) < 0) \
|
||||
{ \
|
||||
printf("Error, the database is broken, trying to continue... no guarantee.\n"); \
|
||||
exit(0); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
static_cast<void>(0)
|
||||
|
||||
struct Memo
|
||||
{
|
||||
uint32 number; /* Index number -- not necessarily array position! */
|
||||
uint16 flags; /* Flags */
|
||||
time_t time; /* When was it sent? */
|
||||
char sender[32]; /* Name of the sender */
|
||||
char *text;
|
||||
};
|
||||
|
||||
struct dbFILE
|
||||
{
|
||||
int mode; /* 'r' for reading, 'w' for writing */
|
||||
FILE *fp; /* The normal file descriptor */
|
||||
char filename[1024]; /* Name of the database file */
|
||||
};
|
||||
|
||||
struct MemoInfo
|
||||
{
|
||||
int16 memocount; /* Current # of memos */
|
||||
int16 memomax; /* Max # of memos one can hold*/
|
||||
Memo *memos; /* Pointer to original memos */
|
||||
};
|
||||
|
||||
struct NickCore
|
||||
{
|
||||
NickCore *next, *prev;
|
||||
|
||||
char *display; /* How the nick is displayed */
|
||||
char pass[32]; /* Password of the nicks */
|
||||
char *email; /* E-mail associated to the nick */
|
||||
char *greet; /* Greet associated to the nick */
|
||||
uint32 icq; /* ICQ # associated to the nick */
|
||||
char *url; /* URL associated to the nick */
|
||||
uint32 flags; /* See NI_* below */
|
||||
uint16 language; /* Language selected by nickname owner (LANG_*) */
|
||||
uint16 accesscount; /* # of entries */
|
||||
char **access; /* Array of strings */
|
||||
MemoInfo memos; /* Memo information */
|
||||
uint16 channelcount; /* Number of channels currently registered */
|
||||
int unused; /* Used for nick collisions */
|
||||
int aliascount; /* How many aliases link to us? Remove the core if 0 */
|
||||
};
|
||||
|
||||
struct NickAlias
|
||||
{
|
||||
NickAlias *next, *prev;
|
||||
char *nick; /* Nickname */
|
||||
time_t time_registered; /* When the nick was registered */
|
||||
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 ChanAccess
|
||||
{
|
||||
uint16 in_use; /* 1 if this entry is in use, else 0 */
|
||||
int16 level;
|
||||
NickCore *nc; /* Guaranteed to be non-NULL if in use, NULL if not */
|
||||
time_t last_seen;
|
||||
};
|
||||
|
||||
struct AutoKick
|
||||
{
|
||||
int16 in_use; /* Always 0 if not in use */
|
||||
int16 is_nick; /* 1 if a regged nickname, 0 if a nick!user@host mask */
|
||||
uint16 flags;
|
||||
union
|
||||
{
|
||||
char *mask; /* Guaranteed to be non-NULL if in use, NULL if not */
|
||||
NickCore *nc; /* Same */
|
||||
} u;
|
||||
char *reason;
|
||||
char *creator;
|
||||
time_t addtime;
|
||||
};
|
||||
|
||||
struct BadWord
|
||||
{
|
||||
uint16 in_use;
|
||||
char *word;
|
||||
uint16 type;
|
||||
};
|
||||
|
||||
struct ChannelInfo
|
||||
{
|
||||
ChannelInfo *next, *prev;
|
||||
|
||||
char name[64]; /* Channel name */
|
||||
char *founder; /* Who registered the channel */
|
||||
char *successor; /* Who gets the channel if the founder nick is dropped or expires */
|
||||
char founderpass[32]; /* Channel password */
|
||||
char *desc; /* Description */
|
||||
char *url; /* URL */
|
||||
char *email; /* Email address */
|
||||
time_t time_registered; /* When was it registered */
|
||||
time_t last_used; /* When was it used hte last time */
|
||||
char *last_topic; /* Last topic on the channel */
|
||||
char last_topic_setter[32]; /* Who set the last topic */
|
||||
time_t last_topic_time; /* When the last topic was set */
|
||||
uint32 flags; /* Flags */
|
||||
char *forbidby; /* if forbidden: who did it */
|
||||
char *forbidreason; /* if forbidden: why */
|
||||
int16 bantype; /* Bantype */
|
||||
int16 *levels; /* Access levels for commands */
|
||||
uint16 accesscount; /* # of pple with access */
|
||||
ChanAccess *access; /* List of authorized users */
|
||||
uint16 akickcount; /* # of akicked pple */
|
||||
AutoKick *akick; /* List of users to kickban */
|
||||
uint32 mlock_on, mlock_off; /* See channel modes below */
|
||||
uint32 mlock_limit; /* 0 if no limit */
|
||||
char *mlock_key; /* NULL if no key */
|
||||
char *mlock_flood; /* NULL if no +f */
|
||||
char *mlock_redirect; /* NULL if no +L */
|
||||
char *entry_message; /* Notice sent on entering channel */
|
||||
MemoInfo memos; /* Memos */
|
||||
char *bi; /* Bot used on this channel */
|
||||
uint32 botflags; /* BS_* below */
|
||||
int16 *ttb; /* Times to ban for each kicker */
|
||||
uint16 bwcount; /* Badword count */
|
||||
BadWord *badwords; /* For BADWORDS kicker */
|
||||
int16 capsmin, capspercent; /* For CAPS kicker */
|
||||
int16 floodlines, floodsecs; /* For FLOOD kicker */
|
||||
int16 repeattimes; /* For REPEAT kicker */
|
||||
};
|
||||
|
||||
struct HostCore
|
||||
{
|
||||
HostCore *next;
|
||||
char *nick;
|
||||
char *vIdent;
|
||||
char *vHost;
|
||||
char *creator;
|
||||
int32 time;
|
||||
};
|
||||
|
||||
dbFILE *open_db_read(const char *service, const char *filename, int version);
|
||||
NickCore *findcore(const char *nick, int version);
|
||||
NickAlias *findnick(const char *nick);
|
||||
ChannelInfo *cs_findchan(const char *chan);
|
||||
char *strscpy(char *d, const char *s, size_t len);
|
||||
int write_file_version(dbFILE * f, uint32 version);
|
||||
int mystricmp(const char *s1, const char *s2);
|
||||
int delnick(NickAlias *na, int donttouchthelist);
|
||||
int write_string(const char *s, dbFILE * f);
|
||||
int write_ptr(const void *ptr, dbFILE * f);
|
||||
int read_int16(int16 * ret, dbFILE * f);
|
||||
int read_int32(int32 * ret, dbFILE * f);
|
||||
int read_uint16(uint16 * ret, dbFILE * f);
|
||||
int read_uint32(uint32 * ret, dbFILE * f);
|
||||
int read_string(char **ret, dbFILE * f);
|
||||
int write_int16(uint16 val, dbFILE * f);
|
||||
int write_int32(uint32 val, dbFILE * f);
|
||||
int read_ptr(void **ret, dbFILE * f);
|
||||
int delcore(NickCore *nc);
|
||||
void alpha_insert_chan(ChannelInfo * ci);
|
||||
void close_db(dbFILE * f);
|
||||
|
||||
ChannelInfo *chanlists[256];
|
||||
NickAlias *nalists[1024];
|
||||
NickCore *nclists[1024];
|
||||
HostCore *head = NULL;
|
||||
|
||||
void b64_encode(const std::string &src, std::string &target);
|
||||
|
||||
/* Memo Flags */
|
||||
#define MF_UNREAD 0x0001 /* Memo has not yet been read */
|
||||
#define MF_RECEIPT 0x0002 /* Sender requested receipt */
|
||||
#define MF_NOTIFYS 0x0004 /* Memo is a notification of receitp */
|
||||
|
||||
/* Nickname status flags: */
|
||||
#define NS_FORBIDDEN 0x0002 /* Nick may not be registered or used */
|
||||
#define NS_NO_EXPIRE 0x0004 /* Nick never expires */
|
||||
|
||||
/* Nickname setting flags: */
|
||||
#define NI_KILLPROTECT 0x00000001 /* Kill others who take this nick */
|
||||
#define NI_SECURE 0x00000002 /* Don't recognize unless IDENTIFY'd */
|
||||
#define NI_MSG 0x00000004 /* Use PRIVMSGs instead of NOTICEs */
|
||||
#define NI_MEMO_HARDMAX 0x00000008 /* Don't allow user to change memo limit */
|
||||
#define NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */
|
||||
#define NI_MEMO_RECEIVE 0x00000020 /* Notify of new memos when sent */
|
||||
#define NI_PRIVATE 0x00000040 /* Don't show in LIST to non-servadmins */
|
||||
#define NI_HIDE_EMAIL 0x00000080 /* Don't show E-mail in INFO */
|
||||
#define NI_HIDE_MASK 0x00000100 /* Don't show last seen address in INFO */
|
||||
#define NI_HIDE_QUIT 0x00000200 /* Don't show last quit message in INFO */
|
||||
#define NI_KILL_QUICK 0x00000400 /* Kill in 20 seconds instead of 60 */
|
||||
#define NI_KILL_IMMED 0x00000800 /* Kill immediately instead of in 60 sec */
|
||||
#define NI_ENCRYPTEDPW 0x00004000 /* Nickname password is encrypted */
|
||||
#define NI_MEMO_MAIL 0x00010000 /* User gets email on memo */
|
||||
#define NI_HIDE_STATUS 0x00020000 /* Don't show services access status */
|
||||
#define NI_SUSPENDED 0x00040000 /* Nickname is suspended */
|
||||
#define NI_AUTOOP 0x00080000 /* Autoop nickname in channels */
|
||||
#define NI_NOEXPIRE 0x00100000 /* nicks in this group won't expire */
|
||||
|
||||
// Old NS_FORBIDDEN, very fucking temporary.
|
||||
#define NI_FORBIDDEN 0x80000000
|
||||
|
||||
/* Retain topic even after last person leaves channel */
|
||||
#define CI_KEEPTOPIC 0x00000001
|
||||
/* Don't allow non-authorized users to be opped */
|
||||
#define CI_SECUREOPS 0x00000002
|
||||
/* Hide channel from ChanServ LIST command */
|
||||
#define CI_PRIVATE 0x00000004
|
||||
/* Topic can only be changed by SET TOPIC */
|
||||
#define CI_TOPICLOCK 0x00000008
|
||||
/* Those not allowed ops are kickbanned */
|
||||
#define CI_RESTRICTED 0x00000010
|
||||
/* Don't allow ChanServ and BotServ commands to do bad things to bigger levels */
|
||||
#define CI_PEACE 0x00000020
|
||||
/* Don't allow any privileges unless a user is IDENTIFY'd with NickServ */
|
||||
#define CI_SECURE 0x00000040
|
||||
/* Don't allow the channel to be registered or used */
|
||||
#define CI_FORBIDDEN 0x00000080
|
||||
/* Channel password is encrypted */
|
||||
#define CI_ENCRYPTEDPW 0x00000100
|
||||
/* Channel does not expire */
|
||||
#define CI_NO_EXPIRE 0x00000200
|
||||
/* Channel memo limit may not be changed */
|
||||
#define CI_MEMO_HARDMAX 0x00000400
|
||||
/* Send notice to channel on use of OP/DEOP */
|
||||
#define CI_OPNOTICE 0x00000800
|
||||
/* Stricter control of channel founder status */
|
||||
#define CI_SECUREFOUNDER 0x00001000
|
||||
/* Always sign kicks */
|
||||
#define CI_SIGNKICK 0x00002000
|
||||
/* Sign kicks if level is < than the one defined by the SIGNKICK level */
|
||||
#define CI_SIGNKICK_LEVEL 0x00004000
|
||||
/* Use the xOP lists */
|
||||
#define CI_XOP 0x00008000
|
||||
/* Channel is suspended */
|
||||
#define CI_SUSPENDED 0x00010000
|
||||
|
||||
/* akick */
|
||||
#define AK_USED 0x0001
|
||||
#define AK_ISNICK 0x0002
|
||||
#define AK_STUCK 0x0004
|
||||
|
||||
/* botflags */
|
||||
#define BI_PRIVATE 0x0001
|
||||
#define BI_CHANSERV 0x0002
|
||||
#define BI_BOTSERV 0x0004
|
||||
#define BI_HOSTSERV 0x0008
|
||||
#define BI_OPERSERV 0x0010
|
||||
#define BI_MEMOSERV 0x0020
|
||||
#define BI_NICKSERV 0x0040
|
||||
#define BI_GLOBAL 0x0080
|
||||
|
||||
/* BotServ SET flags */
|
||||
#define BS_DONTKICKOPS 0x00000001
|
||||
#define BS_DONTKICKVOICES 0x00000002
|
||||
#define BS_FANTASY 0x00000004
|
||||
#define BS_SYMBIOSIS 0x00000008
|
||||
#define BS_GREET 0x00000010
|
||||
#define BS_NOBOT 0x00000020
|
||||
|
||||
/* BotServ Kickers flags */
|
||||
#define BS_KICK_BOLDS 0x80000000
|
||||
#define BS_KICK_COLORS 0x40000000
|
||||
#define BS_KICK_REVERSES 0x20000000
|
||||
#define BS_KICK_UNDERLINES 0x10000000
|
||||
#define BS_KICK_BADWORDS 0x08000000
|
||||
#define BS_KICK_CAPS 0x04000000
|
||||
#define BS_KICK_FLOOD 0x02000000
|
||||
#define BS_KICK_REPEAT 0x01000000
|
||||
|
||||
/* Indices for TTB (Times To Ban) */
|
||||
enum
|
||||
{
|
||||
TTB_BOLDS,
|
||||
TTB_COLORS,
|
||||
TTB_REVERSES,
|
||||
TTB_UNDERLINES,
|
||||
TTB_BADWORDS,
|
||||
TTB_CAPS,
|
||||
TTB_FLOOD,
|
||||
TTB_REPEAT,
|
||||
TTB_SIZE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
LANG_EN_US, /* United States English */
|
||||
LANG_JA_JIS, /* Japanese (JIS encoding) */
|
||||
LANG_JA_EUC, /* Japanese (EUC encoding) */
|
||||
LANG_JA_SJIS, /* Japanese (SJIS encoding) */
|
||||
LANG_ES, /* Spanish */
|
||||
LANG_PT, /* Portugese */
|
||||
LANG_FR, /* French */
|
||||
LANG_TR, /* Turkish */
|
||||
LANG_IT, /* Italian */
|
||||
LANG_DE, /* German */
|
||||
LANG_CAT, /* Catalan */
|
||||
LANG_GR, /* Greek */
|
||||
LANG_NL, /* Dutch */
|
||||
LANG_RU, /* Russian */
|
||||
LANG_HUN, /* Hungarian */
|
||||
LANG_PL /* Polish */
|
||||
};
|
||||
|
||||
const std::string GetLanguageID(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case LANG_EN_US:
|
||||
return "en_US";
|
||||
break;
|
||||
case LANG_JA_JIS:
|
||||
case LANG_JA_EUC:
|
||||
case LANG_JA_SJIS: // these seem to be unused
|
||||
return "en_US";
|
||||
break;
|
||||
case LANG_ES:
|
||||
return "es_ES";
|
||||
break;
|
||||
case LANG_PT:
|
||||
return "pt_PT";
|
||||
break;
|
||||
case LANG_FR:
|
||||
return "fr_FR";
|
||||
break;
|
||||
case LANG_TR:
|
||||
return "tr_TR";
|
||||
break;
|
||||
case LANG_IT:
|
||||
return "it_IT";
|
||||
break;
|
||||
case LANG_DE:
|
||||
return "de_DE";
|
||||
break;
|
||||
case LANG_CAT:
|
||||
return "ca_ES"; // yes, iso639 defines catalan as CA
|
||||
break;
|
||||
case LANG_GR:
|
||||
return "el_GR";
|
||||
break;
|
||||
case LANG_NL:
|
||||
return "nl_NL";
|
||||
break;
|
||||
case LANG_RU:
|
||||
return "ru_RU";
|
||||
break;
|
||||
case LANG_HUN:
|
||||
return "hu_HU";
|
||||
break;
|
||||
case LANG_PL:
|
||||
return "pl_PL";
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Open a database file for reading and check for the version */
|
||||
dbFILE *open_db_read(const char *service, const char *filename, int version)
|
||||
{
|
||||
dbFILE *f;
|
||||
FILE *fp;
|
||||
int myversion;
|
||||
|
||||
f = new dbFILE;
|
||||
if (!f)
|
||||
{
|
||||
printf("Can't allocate memory for %s database %s.\n", service, filename);
|
||||
exit(0);
|
||||
}
|
||||
strscpy(f->filename, filename, sizeof(f->filename));
|
||||
f->mode = 'r';
|
||||
fp = fopen(f->filename, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
printf("Can't read %s database %s.\n", service, f->filename);
|
||||
//free(f);
|
||||
delete f;
|
||||
return NULL;
|
||||
}
|
||||
f->fp = fp;
|
||||
myversion = fgetc(fp) << 24 | fgetc(fp) << 16 | fgetc(fp) << 8 | fgetc(fp);
|
||||
if (feof(fp))
|
||||
{
|
||||
printf("Error reading version number on %s: End of file detected.\n", f->filename);
|
||||
exit(0);
|
||||
}
|
||||
else if (myversion < version)
|
||||
{
|
||||
printf("Unsuported database version (%d) on %s.\n", myversion, f->filename);
|
||||
exit(0);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
/* Close it */
|
||||
void close_db(dbFILE *f)
|
||||
{
|
||||
fclose(f->fp);
|
||||
delete f;
|
||||
}
|
||||
|
||||
int read_int16(int16 *ret, dbFILE *f)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 8 | c2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_uint16(uint16 *ret, dbFILE *f)
|
||||
{
|
||||
int c1, c2;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 8 | c2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_int16(uint16 val, dbFILE *f)
|
||||
{
|
||||
if (fputc((val >> 8) & 0xFF, f->fp) == EOF || fputc(val & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_int32(int32 *ret, dbFILE *f)
|
||||
{
|
||||
int c1, c2, c3, c4;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
c3 = fgetc(f->fp);
|
||||
c4 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_uint32(uint32 *ret, dbFILE *f)
|
||||
{
|
||||
int c1, c2, c3, c4;
|
||||
|
||||
c1 = fgetc(f->fp);
|
||||
c2 = fgetc(f->fp);
|
||||
c3 = fgetc(f->fp);
|
||||
c4 = fgetc(f->fp);
|
||||
if (c1 == EOF || c2 == EOF || c3 == EOF || c4 == EOF)
|
||||
return -1;
|
||||
*ret = c1 << 24 | c2 << 16 | c3 << 8 | c4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_int32(uint32 val, dbFILE *f)
|
||||
{
|
||||
if (fputc((val >> 24) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val >> 16) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val >> 8) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
if (fputc((val) & 0xFF, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_ptr(void **ret, dbFILE *f)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = fgetc(f->fp);
|
||||
if (c == EOF)
|
||||
return -1;
|
||||
*ret = c ? reinterpret_cast<void *>(1) : reinterpret_cast<void *>(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_ptr(const void *ptr, dbFILE * f)
|
||||
{
|
||||
if (fputc(ptr ? 1 : 0, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_string(char **ret, dbFILE *f)
|
||||
{
|
||||
char *s;
|
||||
uint16 len;
|
||||
|
||||
if (read_uint16(&len, f) < 0)
|
||||
return -1;
|
||||
if (len == 0)
|
||||
{
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
s = new char[len];
|
||||
if (len != fread(s, 1, len, f->fp))
|
||||
{
|
||||
delete [] s;
|
||||
return -1;
|
||||
}
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int write_string(const char *s, dbFILE *f)
|
||||
{
|
||||
uint32 len;
|
||||
|
||||
if (!s)
|
||||
return write_int16(0, f);
|
||||
len = strlen(s);
|
||||
if (len > 65534)
|
||||
len = 65534;
|
||||
if (write_int16(static_cast<uint16>(len + 1), f) < 0)
|
||||
return -1;
|
||||
if (len > 0 && fwrite(s, 1, len, f->fp) != len)
|
||||
return -1;
|
||||
if (fputc(0, f->fp) == EOF)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NickCore *findcore(const char *nick, int unused)
|
||||
{
|
||||
NickCore *nc;
|
||||
|
||||
for (nc = nclists[HASH(nick)]; nc; nc = nc->next)
|
||||
if (!mystricmp(nc->display, nick) && ((nc->unused && unused) || (!nc->unused && !unused)))
|
||||
return nc;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NickAlias *findnick(const char *nick)
|
||||
{
|
||||
NickAlias *na;
|
||||
|
||||
for (na = nalists[HASH(nick)]; na; na = na->next)
|
||||
if (!mystricmp(na->nick, nick))
|
||||
return na;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int write_file_version(dbFILE *f, uint32 version)
|
||||
{
|
||||
FILE *fp = f->fp;
|
||||
if (fputc(version >> 24 & 0xFF, fp) < 0 || fputc(version >> 16 & 0xFF, fp) < 0 || fputc(version >> 8 & 0xFF, fp) < 0 || fputc(version & 0xFF, fp) < 0)
|
||||
{
|
||||
printf("Error writing version number on %s.\n", f->filename);
|
||||
exit(0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* strscpy: Copy at most len-1 characters from a string to a buffer, and
|
||||
* add a null terminator after the last character copied.
|
||||
*/
|
||||
|
||||
char *strscpy(char *d, const char *s, size_t len)
|
||||
{
|
||||
char *d_orig = d;
|
||||
|
||||
if (!len)
|
||||
return d;
|
||||
while (--len && (*d++ = *s++));
|
||||
*d = '\0';
|
||||
return d_orig;
|
||||
}
|
||||
|
||||
int mystricmp(const char *s1, const char *s2)
|
||||
{
|
||||
register int c;
|
||||
|
||||
while ((c = tolower(*s1)) == tolower(*s2))
|
||||
{
|
||||
if (!c)
|
||||
return 0;
|
||||
++s1;
|
||||
++s2;
|
||||
}
|
||||
if (c < tolower(*s2))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delnick(NickAlias *na, int donttouchthelist)
|
||||
{
|
||||
if (!donttouchthelist)
|
||||
{
|
||||
/* Remove us from the aliases list */
|
||||
if (na->next)
|
||||
na->next->prev = na->prev;
|
||||
if (na->prev)
|
||||
na->prev->next = na->next;
|
||||
else
|
||||
nalists[HASH(na->nick)] = na->next;
|
||||
}
|
||||
|
||||
if (na->last_usermask)
|
||||
delete [] na->last_usermask;
|
||||
if (na->last_realname)
|
||||
delete [] na->last_realname;
|
||||
if (na->last_quit)
|
||||
delete [] na->last_quit;
|
||||
/* free() us */
|
||||
delete [] na->nick;
|
||||
delete na;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delcore(NickCore *nc)
|
||||
{
|
||||
int i;
|
||||
/* Remove the core from the list */
|
||||
if (nc->next)
|
||||
nc->next->prev = nc->prev;
|
||||
if (nc->prev)
|
||||
nc->prev->next = nc->next;
|
||||
else
|
||||
nclists[HASH(nc->display)] = nc->next;
|
||||
|
||||
delete [] nc->display;
|
||||
if (nc->email)
|
||||
delete [] nc->email;
|
||||
if (nc->greet)
|
||||
delete [] nc->greet;
|
||||
if (nc->url)
|
||||
delete [] nc->url;
|
||||
if (nc->access)
|
||||
{
|
||||
for (i = 0; i < nc->accesscount; ++i)
|
||||
if (nc->access[i])
|
||||
delete [] nc->access[i];
|
||||
delete [] nc->access;
|
||||
}
|
||||
if (nc->memos.memos)
|
||||
{
|
||||
for (i = 0; i < nc->memos.memocount; ++i)
|
||||
if (nc->memos.memos[i].text)
|
||||
delete [] nc->memos.memos[i].text;
|
||||
delete [] nc->memos.memos;
|
||||
}
|
||||
delete nc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ChannelInfo *cs_findchan(const char *chan)
|
||||
{
|
||||
ChannelInfo *ci;
|
||||
for (ci = chanlists[tolower(chan[1])]; ci; ci = ci->next)
|
||||
if (!mystricmp(ci->name, chan))
|
||||
return ci;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void alpha_insert_chan(ChannelInfo *ci)
|
||||
{
|
||||
ChannelInfo *ptr, *prev;
|
||||
char *chan = ci->name;
|
||||
|
||||
for (prev = NULL, ptr = chanlists[tolower(chan[1])]; ptr && mystricmp(ptr->name, chan) < 0; prev = ptr, ptr = ptr->next);
|
||||
ci->prev = prev;
|
||||
ci->next = ptr;
|
||||
if (!prev)
|
||||
chanlists[tolower(chan[1])] = ci;
|
||||
else
|
||||
prev->next = ci;
|
||||
if (ptr)
|
||||
ptr->prev = ci;
|
||||
}
|
||||
|
||||
HostCore *findHostCore(char *nick)
|
||||
{
|
||||
for (HostCore *hc = head; hc; hc = hc->next)
|
||||
if (nick && hc->nick && !mystricmp(hc->nick, nick))
|
||||
return hc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *int_to_base64(long);
|
||||
static long base64_to_int(char *);
|
||||
|
||||
const char *base64enc(long i)
|
||||
{
|
||||
if (i < 0)
|
||||
return "0";
|
||||
return int_to_base64(i);
|
||||
}
|
||||
|
||||
long base64dec(char *b64)
|
||||
{
|
||||
if (b64)
|
||||
return base64_to_int(b64);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string Hex(const std::string &data)
|
||||
{
|
||||
const char hextable[] = "0123456789abcdef";
|
||||
|
||||
size_t l = data.length();
|
||||
std::string rv;
|
||||
for (size_t i = 0; i < l; ++i)
|
||||
{
|
||||
unsigned char c = data[i];
|
||||
rv += hextable[c >> 4];
|
||||
rv += hextable[c & 0xF];
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||
The following encoding technique is taken from RFC 1521 by Borenstein
|
||||
and Freed. It is reproduced here in a slightly edited form for
|
||||
convenience.
|
||||
|
||||
A 65-character subset of US-ASCII is used, enabling 6 bits to be
|
||||
represented per printable character. (The extra 65th character, "=",
|
||||
is used to signify a special processing function.)
|
||||
|
||||
The encoding process represents 24-bit groups of input bits as output
|
||||
strings of 4 encoded characters. Proceeding from left to right, a
|
||||
24-bit input group is formed by concatenating 3 8-bit input groups.
|
||||
These 24 bits are then treated as 4 concatenated 6-bit groups, each
|
||||
of which is translated into a single digit in the base64 alphabet.
|
||||
|
||||
Each 6-bit group is used as an index into an array of 64 printable
|
||||
characters. The character referenced by the index is placed in the
|
||||
output string.
|
||||
|
||||
Table 1: The Base64 Alphabet
|
||||
|
||||
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
0 A 17 R 34 i 51 z
|
||||
1 B 18 S 35 j 52 0
|
||||
2 C 19 T 36 k 53 1
|
||||
3 D 20 U 37 l 54 2
|
||||
4 E 21 V 38 m 55 3
|
||||
5 F 22 W 39 n 56 4
|
||||
6 G 23 X 40 o 57 5
|
||||
7 H 24 Y 41 p 58 6
|
||||
8 I 25 Z 42 q 59 7
|
||||
9 J 26 a 43 r 60 8
|
||||
10 K 27 b 44 s 61 9
|
||||
11 L 28 c 45 t 62 +
|
||||
12 M 29 d 46 u 63 /
|
||||
13 N 30 e 47 v
|
||||
14 O 31 f 48 w (pad) =
|
||||
15 P 32 g 49 x
|
||||
16 Q 33 h 50 y
|
||||
|
||||
Special processing is performed if fewer than 24 bits are available
|
||||
at the end of the data being encoded. A full encoding quantum is
|
||||
always completed at the end of a quantity. When fewer than 24 input
|
||||
bits are available in an input group, zero bits are added (on the
|
||||
right) to form an integral number of 6-bit groups. Padding at the
|
||||
end of the data is performed using the '=' character.
|
||||
|
||||
Since all base64 input is an integral number of octets, only the
|
||||
-------------------------------------------------
|
||||
following cases can arise:
|
||||
|
||||
(1) the final quantum of encoding input is an integral
|
||||
multiple of 24 bits; here, the final unit of encoded
|
||||
output will be an integral multiple of 4 characters
|
||||
with no "=" padding,
|
||||
(2) the final quantum of encoding input is exactly 8 bits;
|
||||
here, the final unit of encoded output will be two
|
||||
characters followed by two "=" padding characters, or
|
||||
(3) the final quantum of encoding input is exactly 16 bits;
|
||||
here, the final unit of encoded output will be three
|
||||
characters followed by one "=" padding character.
|
||||
*/
|
||||
|
||||
void b64_encode(const std::string &src, std::string &target)
|
||||
{
|
||||
size_t src_pos = 0, src_len = src.length();
|
||||
unsigned char input[3];
|
||||
|
||||
target.clear();
|
||||
|
||||
while (src_len - src_pos > 2)
|
||||
{
|
||||
input[0] = src[src_pos++];
|
||||
input[1] = src[src_pos++];
|
||||
input[2] = src[src_pos++];
|
||||
|
||||
target += Base64[input[0] >> 2];
|
||||
target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)];
|
||||
target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)];
|
||||
target += Base64[input[2] & 0x3f];
|
||||
}
|
||||
|
||||
/* Now we worry about padding */
|
||||
if (src_pos != src_len)
|
||||
{
|
||||
input[0] = input[1] = input[2] = 0;
|
||||
for (size_t i = 0; i < src_len - src_pos; ++i)
|
||||
input[i] = src[src_pos + i];
|
||||
|
||||
target += Base64[input[0] >> 2];
|
||||
target += Base64[((input[0] & 0x03) << 4) + (input[1] >> 4)];
|
||||
if (src_pos == src_len - 1)
|
||||
target += Pad64;
|
||||
else
|
||||
target += Base64[((input[1] & 0x0f) << 2) + (input[2] >> 6)];
|
||||
target += Pad64;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ':' and '#' and '&' and '+' and '@' must never be in this table. */
|
||||
/* these tables must NEVER CHANGE! >) */
|
||||
char int6_to_base64_map[] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
|
||||
'E', 'F',
|
||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||
'U', 'V',
|
||||
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'{', '}'
|
||||
};
|
||||
|
||||
char base64_to_int6_map[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
||||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
|
||||
-1, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
||||
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, 63, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||
};
|
||||
|
||||
static char *int_to_base64(long val)
|
||||
{
|
||||
/* 32/6 == max 6 bytes for representation,
|
||||
* +1 for the null, +1 for byte boundaries
|
||||
*/
|
||||
static char base64buf[8];
|
||||
long i = 7;
|
||||
|
||||
base64buf[i] = '\0';
|
||||
|
||||
/* Temporary debugging code.. remove before 2038 ;p.
|
||||
* This might happen in case of 64bit longs (opteron/ia64),
|
||||
* if the value is then too large it can easily lead to
|
||||
* a buffer underflow and thus to a crash. -- Syzop
|
||||
*/
|
||||
if (val > 2147483647L)
|
||||
abort();
|
||||
|
||||
do
|
||||
{
|
||||
base64buf[--i] = int6_to_base64_map[val & 63];
|
||||
}
|
||||
while (val >>= 6);
|
||||
|
||||
return base64buf + i;
|
||||
}
|
||||
|
||||
static long base64_to_int(char *b64)
|
||||
{
|
||||
int v = base64_to_int6_map[static_cast<unsigned char>(*b64++)];
|
||||
|
||||
if (!b64)
|
||||
return 0;
|
||||
|
||||
while (*b64)
|
||||
{
|
||||
v <<= 6;
|
||||
v += base64_to_int6_map[static_cast<unsigned char>(*b64++)];
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif // DB_CONVERT_H
|
||||
Reference in New Issue
Block a user