mirror of
https://github.com/anope/anope.git
synced 2026-06-12 19:14:47 +02:00
Rewrote the MySQL API to use threads. This acts similar to before, but is faster. Removed db_mysql_execute for now.
This commit is contained in:
@@ -330,6 +330,7 @@ check_function_exists(strlcat HAVE_STRLCAT)
|
||||
check_function_exists(strlcpy HAVE_STRLCPY)
|
||||
check_function_exists(umask HAVE_UMASK)
|
||||
check_function_exists(backtrace HAVE_BACKTRACE)
|
||||
check_function_exists(eventfd HAVE_EVENTFD)
|
||||
|
||||
# Check for the existance of the following types
|
||||
check_type_size(uint8_t UINT8_T)
|
||||
|
||||
+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 example.conf tables.sql)
|
||||
set(DATA example.chk example.conf mysql/tables.sql)
|
||||
install(FILES ${DATA}
|
||||
DESTINATION data
|
||||
)
|
||||
|
||||
+1
-3
@@ -292,9 +292,7 @@ options
|
||||
*
|
||||
* Supported:
|
||||
* - db_plain
|
||||
* - db_mysql_write
|
||||
* - db_mysql_read
|
||||
* - db_mysql_execute
|
||||
* - db_mysql
|
||||
*/
|
||||
database = "db_plain"
|
||||
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_bs_badwords`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_bs_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_bs_info_metadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_access`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_cs_access`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_cs_access` (
|
||||
`level` int(11) NOT NULL default '0',
|
||||
`display` 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 '',
|
||||
UNIQUE KEY `channel` (`channel`,`display`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_akick`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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,
|
||||
`forbidby` text NOT NULL,
|
||||
`forbidreason` text NOT NULL,
|
||||
`bantype` smallint(6) NOT NULL default '0',
|
||||
`mlock_on` text NOT NULL,
|
||||
`mlock_off` text NOT NULL,
|
||||
`mlock_params` text NOT NULL,
|
||||
`entry_message` text NOT NULL,
|
||||
`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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_info_metadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_levels`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_cs_levels`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_cs_levels` (
|
||||
`channel` varchar(255) NOT NULL default '',
|
||||
`position` int(11) NOT NULL default '0',
|
||||
`level` int(11) NOT NULL default '0',
|
||||
UNIQUE KEY `channel` (`channel`,`position`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_cs_ttb`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_extra`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_extra`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_extra` (
|
||||
`data` text NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_info`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_info` (
|
||||
`version` int(11) default NULL,
|
||||
`date` datetime default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ms_info`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_ms_info`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_ms_info` (
|
||||
`receiver` varchar(255) NOT NULL,
|
||||
`number` int(11) NOT NULL default '0',
|
||||
`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'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_access`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_ns_access`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_ns_access` (
|
||||
`display` varchar(255) NOT NULL default '',
|
||||
`access` varchar(160) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_alias`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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,
|
||||
`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`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_alias_metadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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,
|
||||
PRIMARY KEY (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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` smallint(5) unsigned NOT NULL default '0',
|
||||
`channelcount` smallint(5) unsigned NOT NULL default '0',
|
||||
`memomax` smallint(5) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`display`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_core_metadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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,
|
||||
PRIMARY KEY (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_ns_request`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_ns_request`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_ns_request` (
|
||||
`nick` varchar(255) NOT NULL default '',
|
||||
`passcode` text NOT NULL,
|
||||
`password` text NOT NULL,
|
||||
`email` text NOT NULL,
|
||||
`requested` int(10) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`nick`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_akills`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_os_akills`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_os_akills` (
|
||||
`user` varchar(255) NOT NULL,
|
||||
`host` 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_core`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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',
|
||||
`akills_count` int(11) NOT NULL default '0',
|
||||
`snlines_count` int(11) NOT NULL default '0',
|
||||
`sqlines_count` int(11) NOT NULL default '0',
|
||||
`szlines_count` int(11) NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_exceptions`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table `anope_os_xlines`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `anope_os_xlines`;
|
||||
CREATE TABLE IF NOT EXISTS `anope_os_xlines` (
|
||||
`type` varchar(20) 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-386
@@ -1,386 +0,0 @@
|
||||
|
||||
-- If you need to create your db, uncomment the following lines.
|
||||
--
|
||||
-- CREATE DATABASE anope;
|
||||
-- USE anope;
|
||||
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_extra'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_extra;
|
||||
CREATE TABLE anope_extra (
|
||||
data text NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_commands'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_commands;
|
||||
CREATE TABLE anope_commands (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
service varchar(255) NOT NULL default '',
|
||||
command text NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ns_core'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_core;
|
||||
CREATE TABLE anope_ns_core (
|
||||
display varchar(255) NOT NULL default '',
|
||||
pass text NOT NULL,
|
||||
email text NOT NULL default '',
|
||||
greet text NOT NULL default '',
|
||||
icq int(10) unsigned NOT NULL default '0',
|
||||
url text NOT NULL default '',
|
||||
flags text NOT NULL default '',
|
||||
language smallint(5) unsigned NOT NULL default '0',
|
||||
channelcount smallint(5) unsigned NOT NULL default '0',
|
||||
memomax smallint(5) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (display)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ns_core_metadata'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_core_metadata;
|
||||
CREATE TABLE anope_ns_core_metadata (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
name varchar(255) NOT NULL default '',
|
||||
value text NOT NULL default '',
|
||||
PRIMARY KEY (name)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
--
|
||||
-- Table structure for table 'anope_ns_alias'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_alias;
|
||||
CREATE TABLE anope_ns_alias (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
last_quit text NOT NULL,
|
||||
last_realname text NOT NULL,
|
||||
last_usermask 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 default '',
|
||||
display varchar(255) NOT NULL default '',
|
||||
PRIMARY KEY (nick)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ns_alias_metadata'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_alias_metadata;
|
||||
CREATE TABLE anope_ns_alias_metadata (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
name varchar(255) NOT NULL default '',
|
||||
value text NOT NULL default '',
|
||||
PRIMARY KEY (name)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ns_access'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_access;
|
||||
CREATE TABLE anope_ns_access (
|
||||
display varchar(255) NOT NULL default '',
|
||||
access varchar(160) NOT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- ---------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ns_request'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ns_request;
|
||||
CREATE TABLE anope_ns_request (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
passcode text NOT NULL,
|
||||
password text NOT NULL,
|
||||
email text NOT NULL,
|
||||
requested int(10) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (nick)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_access'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_access;
|
||||
CREATE TABLE anope_cs_access (
|
||||
level int(11) NOT NULL default '0',
|
||||
display 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 '',
|
||||
UNIQUE KEY (channel,display)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_akick'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_akick;
|
||||
CREATE TABLE 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 default '',
|
||||
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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_bs_badwords'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_bs_badwords;
|
||||
CREATE TABLE 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_info'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_info;
|
||||
CREATE TABLE anope_cs_info (
|
||||
name varchar(255) NOT NULL default '',
|
||||
founder text NOT NULL,
|
||||
successor text NOT NULL,
|
||||
descr text NOT NULL,
|
||||
url text NOT NULL,
|
||||
email 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 default '',
|
||||
forbidby text NOT NULL,
|
||||
forbidreason text NOT NULL,
|
||||
bantype smallint(6) NOT NULL default '0',
|
||||
mlock_on text NOT NULL default '',
|
||||
mlock_off text NOT NULL default '',
|
||||
mlock_params text NOT NULL default '',
|
||||
entry_message text NOT NULL,
|
||||
memomax smallint(5) unsigned NOT NULL default '0',
|
||||
botnick varchar(255) NOT NULL default '',
|
||||
botflags text NOT NULL default '',
|
||||
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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_info_metadata'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_info_metadata;
|
||||
CREATE TABLE anope_cs_info_metadata (
|
||||
channel varchar(255) NOT NULL default '',
|
||||
name varchar(255) NOT NULL default '',
|
||||
value text NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_levels'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_levels;
|
||||
CREATE TABLE anope_cs_levels (
|
||||
channel varchar(255) NOT NULL default '',
|
||||
position int(11) NOT NULL default '0',
|
||||
level int(11) NOT NULL default '0',
|
||||
UNIQUE KEY channel (channel,position)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_cs_ttb'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_cs_ttb;
|
||||
CREATE TABLE 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_bs_core'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_bs_core;
|
||||
CREATE TABLE anope_bs_core (
|
||||
nick varchar(255) NOT NULL default '',
|
||||
user varchar(255) NOT NULL default '',
|
||||
host text NOT NULL default '',
|
||||
rname text NOT NULL default '',
|
||||
flags text NOT NULL default '',
|
||||
created int(10) unsigned NOT NULL default '0',
|
||||
chancount int(11) NOT NULL default '0',
|
||||
PRIMARY KEY (nick)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_bs_info_metadata'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_bs_info_metadata;
|
||||
CREATE TABLE anope_bs_info_metadata (
|
||||
botname varchar(255) NOT NULL default '',
|
||||
name varchar(255) NOT NULL default '',
|
||||
value text NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_ms_info'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_ms_info;
|
||||
CREATE TABLE anope_ms_info (
|
||||
receiver varchar(255) NOT NULL,
|
||||
number int(11) NOT NULL default '0',
|
||||
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'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_os_akills'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_akills;
|
||||
CREATE TABLE anope_os_akills (
|
||||
user varchar(255) NOT NULL,
|
||||
host 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_os_core'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_core;
|
||||
CREATE TABLE anope_os_core (
|
||||
maxusercnt int(11) NOT NULL default '0',
|
||||
maxusertime int(10) unsigned NOT NULL default '0',
|
||||
akills_count int(11) NOT NULL default '0',
|
||||
snlines_count int(11) NOT NULL default '0',
|
||||
sqlines_count int(11) NOT NULL default '0',
|
||||
szlines_count int(11) NOT NULL default '0'
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_os_exceptions'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_exceptions;
|
||||
CREATE TABLE 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_os_xlines'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_os_xlines;
|
||||
CREATE TABLE anope_os_xlines (
|
||||
type varchar(20) 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=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_metadata'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_metadata;
|
||||
CREATE TABLE anope_metadata (
|
||||
name varchar(255) NOT NULL default '',
|
||||
value text NOT NULL default '',
|
||||
PRIMARY KEY (name)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Table structure for table 'anope_info'
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS anope_info;
|
||||
CREATE TABLE anope_info (
|
||||
version int(11) default NULL,
|
||||
date datetime default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
Anope MySQL Support
|
||||
-------------------
|
||||
|
||||
MySQL support was readded in version 1.9.2 In the form of three modules.
|
||||
|
||||
db_mysql_read - Allows you to load your databases from MySQL.
|
||||
db_mysql_write - Allows live updating of SQL tables whenever something is executed in Anope.
|
||||
db_mysql_execute - Allows executing of Anope commands via SQL.
|
||||
|
||||
To execute commands via SQL, you must insert the command into the anope_commands table, an example is as follows:
|
||||
|
||||
INSERT INTO `anope_commands` (nick, service, command) VALUES('Adam', 'NickServ', 'REGISTER qwerty Adam@anope.org');
|
||||
|
||||
By default, every 60 seconds Anope checks this table for commands to execute. When Anope sees a new command to execute, it checks the following.
|
||||
|
||||
If the nick given is -SQLUser, then the command gets executed by a special fake user within Anope called -SQLUser. -SQLUser has every permission and command available, there are no permission checks at all for this user, it can do anything.
|
||||
|
||||
If the nick is not -SQLUser, it checks to see if it is a registered nick. If it is, it sees if there are any users online using the NickCore of that nick.
|
||||
If there is a user online with that core the command gets executed as if that user executed it, and the reply goes to that user.
|
||||
If there isn't a user online with the core, it creates a fake user as the nick given to it, and gives to it the permissions the user would have if they were online and identified.
|
||||
If the nick is not registered, it checks to see if there is a user currently on that nick. If there is, it executes the command as that user, and the reply goes to that user.
|
||||
If the nick is not registered and no one is using the nick, it creates a fake user of the nick given to it, and gives it regular nonidentified user access.
|
||||
|
||||
Currently there is no way to check to see if a command was executed successfully within Anope from SQL (even if there was, the possibly update delay would be a problem).
|
||||
|
||||
IMPORTANT: When using db_mysql_write when you already have a database, you need to do an initial import of the data to SQL (as db_mysql_write only updates it when it is changed, it never actually mass-dumps all of your data into SQL). To do this, start Anope and execute /OperServ SQLSYNC.
|
||||
|
||||
+116
-3
@@ -160,9 +160,6 @@ extern CoreExport message_map MessageMap;
|
||||
class Module;
|
||||
extern CoreExport std::list<Module *> Modules;
|
||||
|
||||
/*************************************************************************/
|
||||
/* Structure for information about a *Serv command. */
|
||||
|
||||
class Version
|
||||
{
|
||||
private:
|
||||
@@ -1109,11 +1106,16 @@ enum Implementation
|
||||
I_END
|
||||
};
|
||||
|
||||
class Service;
|
||||
|
||||
/** Used to manage modules.
|
||||
*/
|
||||
class CoreExport ModuleManager
|
||||
{
|
||||
private:
|
||||
/** A map of service providers
|
||||
*/
|
||||
static std::map<Anope::string, Service *> ServiceProviders;
|
||||
public:
|
||||
/** Event handler hooks.
|
||||
* This needs to be public to be used by FOREACH_MOD and friends.
|
||||
@@ -1202,6 +1204,24 @@ class CoreExport ModuleManager
|
||||
*/
|
||||
static void UnloadAll(bool unload_proto);
|
||||
|
||||
/** Register a service
|
||||
* @param s The service
|
||||
* @return true if it was successfully registeed, else false (service name colision)
|
||||
*/
|
||||
static bool RegisterService(Service *s);
|
||||
|
||||
/** Unregister a service
|
||||
* @param s The service
|
||||
* @return true if it was unregistered successfully
|
||||
*/
|
||||
static bool UnregisterService(Service *s);
|
||||
|
||||
/** Get a service
|
||||
* @param name The service name
|
||||
* @return The services, or NULL
|
||||
*/
|
||||
static Service *GetService(const Anope::string &name);
|
||||
|
||||
private:
|
||||
/** Call the module_delete function to safely delete the module
|
||||
* @param m the module to delete
|
||||
@@ -1229,6 +1249,99 @@ class CallBack : public Timer
|
||||
}
|
||||
};
|
||||
|
||||
class Service
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
Anope::string name;
|
||||
|
||||
Service(Module *o, const Anope::string &n);
|
||||
|
||||
virtual ~Service();
|
||||
};
|
||||
|
||||
class dynamic_reference_base
|
||||
{
|
||||
public:
|
||||
dynamic_reference_base();
|
||||
|
||||
virtual ~dynamic_reference_base();
|
||||
};
|
||||
|
||||
extern std::list<dynamic_reference_base *> dyn_references;
|
||||
|
||||
template<typename T>
|
||||
class dynamic_reference : public dynamic_reference_base
|
||||
{
|
||||
protected:
|
||||
T *ref;
|
||||
public:
|
||||
dynamic_reference() : dynamic_reference_base(), ref(NULL) { }
|
||||
|
||||
dynamic_reference(T *obj) : dynamic_reference_base(), ref(obj) { }
|
||||
|
||||
virtual ~dynamic_reference() { }
|
||||
|
||||
virtual operator bool()
|
||||
{
|
||||
return this->ref;
|
||||
}
|
||||
|
||||
virtual inline T *operator->()
|
||||
{
|
||||
return this->ref;
|
||||
}
|
||||
|
||||
void Invalidate()
|
||||
{
|
||||
this->ref = NULL;
|
||||
}
|
||||
|
||||
static void Invalidate(T *obj)
|
||||
{
|
||||
for (std::list<dynamic_reference_base *>::iterator it = dyn_references.begin(), it_end = dyn_references.end(); it != it_end;)
|
||||
{
|
||||
dynamic_reference<void *> *d = static_cast<dynamic_reference<void *> *>(*it);
|
||||
++it;
|
||||
|
||||
if (d && d->ref == obj)
|
||||
{
|
||||
d->Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class service_reference : public dynamic_reference<T>
|
||||
{
|
||||
Module *owner;
|
||||
Anope::string name;
|
||||
|
||||
public:
|
||||
service_reference(Module *o, const Anope::string &n) : dynamic_reference<T>(), owner(o), name(n)
|
||||
{
|
||||
}
|
||||
|
||||
~service_reference()
|
||||
{
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
if (!this->ref)
|
||||
this->ref = static_cast<T *>(ModuleManager::GetService(this->name));
|
||||
return this->ref;
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
{
|
||||
if (!this->ref)
|
||||
this->ref = static_cast<T *>(ModuleManager::GetService(this->name));
|
||||
return this->ref;
|
||||
}
|
||||
};
|
||||
|
||||
struct Message
|
||||
{
|
||||
Anope::string name;
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@@ -81,6 +81,10 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
|
||||
/* Type this socket is */
|
||||
SocketType Type;
|
||||
|
||||
/** Empty constructor, used for things such as the pipe socket
|
||||
*/
|
||||
Socket();
|
||||
|
||||
/** Default constructor
|
||||
* @param nsock The socket to use, 0 if we need to create our own
|
||||
* @param nIPv6 true if using ipv6
|
||||
@@ -149,6 +153,26 @@ class CoreExport Socket : public Flags<SocketFlag, 1>
|
||||
void Write(const Anope::string &message);
|
||||
};
|
||||
|
||||
class CoreExport Pipe : public Socket
|
||||
{
|
||||
private:
|
||||
int WritePipe;
|
||||
|
||||
int RecvInternal(char *buf, size_t sz) const;
|
||||
|
||||
int SendInternal(const Anope::string &buf) const;
|
||||
public:
|
||||
Pipe();
|
||||
|
||||
bool ProcessRead();
|
||||
|
||||
bool Read(const Anope::string &);
|
||||
|
||||
void Notify();
|
||||
|
||||
virtual void OnNotify();
|
||||
};
|
||||
|
||||
class CoreExport ClientSocket : public Socket
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -86,7 +86,6 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS})
|
||||
# Get a list of ALL files and directories within this modules directory
|
||||
file(GLOB SUBMODULE_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${MODULE_FOLDER}/*")
|
||||
remove_item_from_list(SUBMODULE_DIRS "CMakeFiles")
|
||||
remove_item_from_list(SUBMODULE_DIRS "extra/mysql") # XXX till sql is fixed
|
||||
|
||||
foreach(SUBDIR ${SUBMODULE_DIRS})
|
||||
if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,414 @@
|
||||
/* RequiredLibraries: mysqlclient */
|
||||
|
||||
#include "module.h"
|
||||
#define NO_CLIENT_LONG_LONG
|
||||
#include <mysql/mysql.h>
|
||||
#include "sql.h"
|
||||
|
||||
/** Non blocking threaded MySQL API, based loosely from InspIRCd's m_mysql.cpp
|
||||
*
|
||||
* This module spawns a single thread that is used to execute blocking MySQL queries.
|
||||
* When a module requests a query to be executed it is added to a list for the thread
|
||||
* (which never stops looping and sleeing) to pick up and execute, the result of which
|
||||
* is inserted in to another queue to be picked up my the main thread. The main thread
|
||||
* uses Pipe to become notified through the socket engine when there are results waiting
|
||||
* to be sent back to the modules requesting the query
|
||||
*/
|
||||
|
||||
class MySQLService;
|
||||
|
||||
/** A query request
|
||||
*/
|
||||
struct QueryRequest
|
||||
{
|
||||
/* The connection to the database */
|
||||
MySQLService *service;
|
||||
/* The interface to use once we have the result to send the data back */
|
||||
SQLInterface *interface;
|
||||
/* The actual query */
|
||||
Anope::string query;
|
||||
|
||||
QueryRequest(MySQLService *s, SQLInterface *i, const Anope::string &q) : service(s), interface(i), query(q) { }
|
||||
};
|
||||
|
||||
struct QueryResult
|
||||
{
|
||||
/* The interface to send the data back on */
|
||||
SQLInterface *interface;
|
||||
/* The result */
|
||||
SQLResult result;
|
||||
|
||||
QueryResult(SQLInterface *i, SQLResult &r) : interface(i), result(r) { }
|
||||
};
|
||||
|
||||
/** A MySQL result
|
||||
*/
|
||||
class MySQLResult : public SQLResult
|
||||
{
|
||||
MYSQL_RES *res;
|
||||
|
||||
public:
|
||||
MySQLResult(const Anope::string &q, MYSQL_RES *r) : SQLResult(q), res(r)
|
||||
{
|
||||
if (!res)
|
||||
return;
|
||||
|
||||
unsigned num_fields = mysql_num_fields(res);
|
||||
|
||||
if (!num_fields)
|
||||
return;
|
||||
|
||||
Alog(LOG_DEBUG) << "SQL query returned " << num_fields << " fields";
|
||||
|
||||
for (MYSQL_ROW row; (row = mysql_fetch_row(res));)
|
||||
{
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(res);
|
||||
|
||||
if (fields)
|
||||
{
|
||||
std::map<Anope::string, Anope::string> items;
|
||||
|
||||
for (unsigned field_count = 0; field_count < num_fields; ++field_count)
|
||||
{
|
||||
Alog(LOG_DEBUG) << "Field count " << field_count << " name is: " << (fields[field_count].name ? fields[field_count].name : "") << ", data is: " << (row[field_count] ? row[field_count] : "");
|
||||
Anope::string column = (fields[field_count].name ? fields[field_count].name : "");
|
||||
Anope::string data = (row[field_count] ? row[field_count] : "");
|
||||
|
||||
items[column] = data;
|
||||
}
|
||||
|
||||
this->entries.push_back(items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MySQLResult(const Anope::string &q, const Anope::string &err) : SQLResult(q, err), res(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~MySQLResult()
|
||||
{
|
||||
if (this->res)
|
||||
mysql_free_result(this->res);
|
||||
}
|
||||
};
|
||||
|
||||
/** A MySQL connection, there can be multiple
|
||||
*/
|
||||
class MySQLService : public SQLProvider
|
||||
{
|
||||
Anope::string database;
|
||||
Anope::string server;
|
||||
Anope::string user;
|
||||
Anope::string password;
|
||||
int port;
|
||||
|
||||
MYSQL *sql;
|
||||
|
||||
public:
|
||||
/* Locked by the SQL thread when a query is pending on this database,
|
||||
* prevents us from deleting a connection while a query is executing
|
||||
* in the thread
|
||||
*/
|
||||
Mutex Lock;
|
||||
|
||||
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);
|
||||
|
||||
~MySQLService();
|
||||
|
||||
void Run(SQLInterface *i, const Anope::string &query);
|
||||
|
||||
SQLResult RunQuery(const Anope::string &query);
|
||||
|
||||
const Anope::string Escape(const Anope::string &buf);
|
||||
|
||||
void Connect();
|
||||
|
||||
bool CheckConnection();
|
||||
};
|
||||
|
||||
/** The SQL thread used to execute queries
|
||||
*/
|
||||
class DispatcherThread : public Thread, public Condition
|
||||
{
|
||||
public:
|
||||
DispatcherThread() : Thread() { }
|
||||
|
||||
void Run();
|
||||
};
|
||||
|
||||
/** The pipe used by the SocketEngine to notify the main thread when
|
||||
* we have results from queries
|
||||
*/
|
||||
class MySQLPipe : public Pipe
|
||||
{
|
||||
public:
|
||||
void OnNotify();
|
||||
};
|
||||
|
||||
class ModuleSQL;
|
||||
static ModuleSQL *me;
|
||||
class ModuleSQL : public Module
|
||||
{
|
||||
public:
|
||||
/* SQL connections */
|
||||
std::map<Anope::string, MySQLService *> MySQLServices;
|
||||
/* Pending query requests */
|
||||
std::deque<QueryRequest> QueryRequests;
|
||||
/* Pending finished requests with results */
|
||||
std::deque<QueryResult> FinishedRequests;
|
||||
/* The thread used to execute queries */
|
||||
DispatcherThread *DThread;
|
||||
/* Notify pipe */
|
||||
MySQLPipe *SQLPipe;
|
||||
|
||||
ModuleSQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator)
|
||||
{
|
||||
me = this;
|
||||
|
||||
Implementation i[] = { I_OnReload, I_OnModuleUnload };
|
||||
ModuleManager::Attach(i, this, 2);
|
||||
|
||||
SQLPipe = new MySQLPipe();
|
||||
|
||||
DThread = new DispatcherThread();
|
||||
threadEngine.Start(DThread);
|
||||
|
||||
OnReload(true);
|
||||
}
|
||||
|
||||
~ModuleSQL()
|
||||
{
|
||||
for (std::map<Anope::string, MySQLService *>::iterator it = this->MySQLServices.begin(); it != this->MySQLServices.end(); ++it)
|
||||
delete it->second;
|
||||
MySQLServices.clear();
|
||||
|
||||
DThread->SetExitState();
|
||||
DThread->Wakeup();
|
||||
DThread->Join();
|
||||
|
||||
if (SocketEngine)
|
||||
delete SQLPipe;
|
||||
}
|
||||
|
||||
void OnReload(bool startup)
|
||||
{
|
||||
ConfigReader config;
|
||||
int i, num;
|
||||
|
||||
for (std::map<Anope::string, MySQLService *>::iterator it = this->MySQLServices.begin(); it != this->MySQLServices.end();)
|
||||
{
|
||||
const Anope::string cname = it->first;
|
||||
MySQLService *s = it->second;
|
||||
++it;
|
||||
|
||||
for (i = 0, num = config.Enumerate("mysql"); i < num; ++i)
|
||||
{
|
||||
if (config.ReadValue("mysql", "name", "", i) == cname)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == num)
|
||||
{
|
||||
Alog() << "MySQL: Removing server connection " << cname;
|
||||
|
||||
delete s;
|
||||
this->MySQLServices.erase(cname);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, num = config.Enumerate("mysql"); i < num; ++i)
|
||||
{
|
||||
Anope::string connname = config.ReadValue("mysql", "name", "main", i);
|
||||
|
||||
if (this->MySQLServices.find(connname) == this->MySQLServices.end())
|
||||
{
|
||||
Anope::string database = config.ReadValue("mysql", "database", "anope", i);
|
||||
Anope::string server = config.ReadValue("mysql", "server", "127.0.0.1", i);
|
||||
Anope::string user = config.ReadValue("mysql", "username", "anope", i);
|
||||
Anope::string password = config.ReadValue("mysql", "password", "", i);
|
||||
int port = config.ReadInteger("mysql", "port", "3306", i, true);
|
||||
|
||||
try
|
||||
{
|
||||
MySQLService *ss = new MySQLService(this, connname, database, server, user, password, port);
|
||||
this->MySQLServices.insert(std::make_pair(connname, ss));
|
||||
|
||||
Alog() << "MySQL: Sucessfully connected to server " << connname << " (" << server << ")";
|
||||
}
|
||||
catch (const SQLException &ex)
|
||||
{
|
||||
Alog() << "MySQL: " << ex.GetReason();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnModuleUnload(User *, Module *m)
|
||||
{
|
||||
this->DThread->Lock();
|
||||
|
||||
for (unsigned i = this->QueryRequests.size(); i > 0; --i)
|
||||
{
|
||||
QueryRequest &r = this->QueryRequests[i];
|
||||
|
||||
if (r.interface && r.interface->owner == m)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
r.service->Lock.Lock();
|
||||
r.service->Lock.Unlock();
|
||||
}
|
||||
|
||||
this->QueryRequests.erase(this->QueryRequests.begin() + i);
|
||||
}
|
||||
}
|
||||
|
||||
this->DThread->Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
Connect();
|
||||
}
|
||||
|
||||
MySQLService::~MySQLService()
|
||||
{
|
||||
this->Lock.Lock();
|
||||
this->Lock.Unlock();
|
||||
mysql_close(this->sql);
|
||||
|
||||
for (unsigned i = me->QueryRequests.size(); i > 0; --i)
|
||||
{
|
||||
QueryRequest &r = me->QueryRequests[i];
|
||||
|
||||
if (r.service == this)
|
||||
{
|
||||
if (r.interface)
|
||||
r.interface->OnError(SQLResult("", "SQL Interface is going away"));
|
||||
me->QueryRequests.erase(me->QueryRequests.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MySQLService::Run(SQLInterface *i, const Anope::string &query)
|
||||
{
|
||||
me->DThread->Lock();
|
||||
me->QueryRequests.push_back(QueryRequest(this, i, query));
|
||||
me->DThread->Unlock();
|
||||
me->DThread->Wakeup();
|
||||
}
|
||||
|
||||
SQLResult MySQLService::RunQuery(const Anope::string &query)
|
||||
{
|
||||
if (this->CheckConnection() && !mysql_real_query(this->sql, query.c_str(), query.length()))
|
||||
{
|
||||
MYSQL_RES *res = mysql_use_result(this->sql);
|
||||
|
||||
return MySQLResult(query, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
return MySQLResult(query, mysql_error(this->sql));
|
||||
}
|
||||
}
|
||||
|
||||
const Anope::string MySQLService::Escape(const Anope::string &buf)
|
||||
{
|
||||
char buffer[BUFSIZE];
|
||||
mysql_escape_string(buffer, buf.c_str(), buf.length());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void MySQLService::Connect()
|
||||
{
|
||||
this->sql = mysql_init(this->sql);
|
||||
|
||||
const unsigned int timeout = 1;
|
||||
mysql_options(this->sql, MYSQL_OPT_CONNECT_TIMEOUT, reinterpret_cast<const char *>(&timeout));
|
||||
|
||||
bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, 0);
|
||||
|
||||
if (!connect)
|
||||
throw SQLException("Unable to connect to SQL service " + this->name + ": " + mysql_error(this->sql));
|
||||
}
|
||||
|
||||
|
||||
bool MySQLService::CheckConnection()
|
||||
{
|
||||
if (!this->sql || mysql_ping(this->sql))
|
||||
{
|
||||
try
|
||||
{
|
||||
this->Connect();
|
||||
}
|
||||
catch (const SQLException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DispatcherThread::Run()
|
||||
{
|
||||
this->Lock();
|
||||
|
||||
while (!this->GetExitState())
|
||||
{
|
||||
if (!me->QueryRequests.empty())
|
||||
{
|
||||
QueryRequest &r = me->QueryRequests.front();
|
||||
this->Unlock();
|
||||
|
||||
r.service->Lock.Lock();
|
||||
SQLResult sresult = r.service->RunQuery(r.query);
|
||||
r.service->Lock.Unlock();
|
||||
|
||||
this->Lock();
|
||||
if (me->QueryRequests.front().query == r.query)
|
||||
{
|
||||
if (r.interface)
|
||||
me->FinishedRequests.push_back(QueryResult(r.interface, sresult));
|
||||
me->QueryRequests.pop_front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!me->FinishedRequests.empty())
|
||||
me->SQLPipe->Notify();
|
||||
this->Wait();
|
||||
}
|
||||
}
|
||||
|
||||
this->Unlock();
|
||||
}
|
||||
|
||||
void MySQLPipe::OnNotify()
|
||||
{
|
||||
me->DThread->Lock();
|
||||
|
||||
for (std::deque<QueryResult>::const_iterator it = me->FinishedRequests.begin(), it_end = me->FinishedRequests.end(); it != it_end; ++it)
|
||||
{
|
||||
const QueryResult &qr = *it;
|
||||
|
||||
if (!qr.interface)
|
||||
throw SQLException("NULL qr.interface in MySQLPipe::OnNotify() ?");
|
||||
|
||||
if (qr.result.GetError().empty())
|
||||
qr.interface->OnResult(qr.result);
|
||||
else
|
||||
qr.interface->OnError(qr.result);
|
||||
}
|
||||
me->FinishedRequests.clear();
|
||||
|
||||
me->DThread->Unlock();
|
||||
}
|
||||
|
||||
MODULE_INIT(ModuleSQL)
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
#ifndef DB_MYSQL_H
|
||||
#define DB_MYSQL_H
|
||||
|
||||
#include "module.h"
|
||||
|
||||
struct NickAliasFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
NickNameFlag Flag;
|
||||
};
|
||||
|
||||
NickAliasFlagInfo NickAliasFlags[] = {
|
||||
{"FORBIDDEN", NS_FORBIDDEN},
|
||||
{"NOEXPIRE", NS_NO_EXPIRE},
|
||||
{"", static_cast<NickNameFlag>(-1)}
|
||||
};
|
||||
|
||||
struct NickCoreFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
NickCoreFlag Flag;
|
||||
};
|
||||
|
||||
NickCoreFlagInfo NickCoreFlags[] = {
|
||||
{"KILLPROTECT", NI_KILLPROTECT},
|
||||
{"SECURE", NI_SECURE},
|
||||
{"MSG", NI_MSG},
|
||||
{"MEMO_HARDMAX", NI_MEMO_HARDMAX},
|
||||
{"MEMO_SIGNON", NI_MEMO_SIGNON},
|
||||
{"MEMO_RECEIVE", NI_MEMO_RECEIVE},
|
||||
{"PRIVATE", NI_PRIVATE},
|
||||
{"HIDE_EMAIL", NI_HIDE_EMAIL},
|
||||
{"HIDE_MASK", NI_HIDE_MASK},
|
||||
{"HIDE_QUIT", NI_HIDE_QUIT},
|
||||
{"KILL_QUICK", NI_KILL_QUICK},
|
||||
{"KILL_IMMED", NI_KILL_IMMED},
|
||||
{"MEMO_MAIL", NI_MEMO_MAIL},
|
||||
{"HIDE_STATUS", NI_HIDE_STATUS},
|
||||
{"SUSPENDED", NI_SUSPENDED},
|
||||
{"AUTOOP", NI_AUTOOP},
|
||||
{"FORBIDDEN", NI_FORBIDDEN},
|
||||
{"", static_cast<NickCoreFlag>(-1)}
|
||||
};
|
||||
|
||||
struct BotFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
BotServFlag Flag;
|
||||
};
|
||||
|
||||
BotFlagInfo BotFlags[] = {
|
||||
{"DONTKICKOPS", BS_DONTKICKOPS},
|
||||
{"DONTKICKVOICES", BS_DONTKICKVOICES},
|
||||
{"FANTASY", BS_FANTASY},
|
||||
{"SYMBIOSIS", BS_SYMBIOSIS},
|
||||
{"GREET", BS_GREET},
|
||||
{"NOBOT", BS_NOBOT},
|
||||
{"KICK_BOLDS", BS_KICK_BOLDS},
|
||||
{"KICK_COLORS", BS_KICK_COLORS},
|
||||
{"KICK_REVERSES", BS_KICK_REVERSES},
|
||||
{"KICK_UNDERLINES", BS_KICK_UNDERLINES},
|
||||
{"KICK_BADWORDS", BS_KICK_BADWORDS},
|
||||
{"KICK_CAPS", BS_KICK_CAPS},
|
||||
{"KICK_FLOOD", BS_KICK_FLOOD},
|
||||
{"KICK_REPEAT", BS_KICK_REPEAT},
|
||||
{"KICK_ITALICS", BS_KICK_ITALICS},
|
||||
{"", static_cast<BotServFlag>(-1)}
|
||||
};
|
||||
|
||||
struct ChannelFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
ChannelInfoFlag Flag;
|
||||
};
|
||||
|
||||
ChannelFlagInfo ChannelFlags[] = {
|
||||
{"KEEPTOPIC", CI_KEEPTOPIC},
|
||||
{"SECUREOPS", CI_SECUREOPS},
|
||||
{"PRIVATE", CI_PRIVATE},
|
||||
{"TOPICLOCK", CI_TOPICLOCK},
|
||||
{"RESTRICTED", CI_RESTRICTED},
|
||||
{"PEACE", CI_PEACE},
|
||||
{"SECURE", CI_SECURE},
|
||||
{"FORBIDDEN", CI_FORBIDDEN},
|
||||
{"NO_EXPIRE", CI_NO_EXPIRE},
|
||||
{"MEMO_HARDMAX", CI_MEMO_HARDMAX},
|
||||
{"OPNOTICE", CI_OPNOTICE},
|
||||
{"SECUREFOUNDER", CI_SECUREFOUNDER},
|
||||
{"SIGNKICK", CI_SIGNKICK},
|
||||
{"SIGNKICK_LEVEL", CI_SIGNKICK_LEVEL},
|
||||
{"XOP", CI_XOP},
|
||||
{"SUSPENDED", CI_SUSPENDED},
|
||||
{"PERSIST", CI_PERSIST},
|
||||
{"", static_cast<ChannelInfoFlag>(-1)}
|
||||
};
|
||||
|
||||
struct BotServFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
BotFlag Flag;
|
||||
};
|
||||
|
||||
BotServFlagInfo BotServFlags[] = {
|
||||
{"PRIVATE", BI_PRIVATE},
|
||||
{"", static_cast<BotFlag>(-1)}
|
||||
};
|
||||
|
||||
struct MemoFlagInfo
|
||||
{
|
||||
std::string Name;
|
||||
MemoFlag Flag;
|
||||
};
|
||||
|
||||
MemoFlagInfo MemoFlags[] = {
|
||||
{"UNREAD", MF_UNREAD},
|
||||
{"RECEIPT", MF_RECEIPT},
|
||||
{"NOTIFYS", MF_NOTIFYS},
|
||||
{"", static_cast<MemoFlag>(-1)}
|
||||
};
|
||||
|
||||
#define MYSQLPP_MYSQL_HEADERS_BURIED
|
||||
#include <mysql++/mysql++.h>
|
||||
|
||||
inline std::string SQLAssign(const mysqlpp::String &s) { return s.c_str(); }
|
||||
|
||||
class DBMySQL;
|
||||
static DBMySQL *me;
|
||||
|
||||
bool ExecuteQuery(mysqlpp::Query &query)
|
||||
{
|
||||
Alog(LOG_DEBUG) << "MySQL: " << query.str();
|
||||
|
||||
if (!query.execute())
|
||||
{
|
||||
Alog() << "MySQL: error executing query: " << query.error();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
mysqlpp::StoreQueryResult StoreQuery(mysqlpp::Query &query)
|
||||
{
|
||||
Alog(LOG_DEBUG) << "MySQL: " << query.str();
|
||||
|
||||
mysqlpp::StoreQueryResult result = query.store();
|
||||
if (!result)
|
||||
Alog() << "MySQL: error executing query: " << query.error();
|
||||
return result;
|
||||
}
|
||||
|
||||
class DBMySQL : public Module
|
||||
{
|
||||
private:
|
||||
bool LoadConfig()
|
||||
{
|
||||
ConfigReader config;
|
||||
|
||||
Database = config.ReadValue("mysql", "database", "anope", 0);
|
||||
Server = config.ReadValue("mysql", "server", "127.0.0.1", 0);
|
||||
SQLUser = config.ReadValue("mysql", "username", "anope", 0);
|
||||
Password = config.ReadValue("mysql", "password", "", 0);
|
||||
Port = config.ReadInteger("mysql", "port", "3306", 0, true);
|
||||
Delay = config.ReadInteger("mysql", "updatedelay", "60", 0, true);
|
||||
|
||||
return !Password.empty();
|
||||
}
|
||||
|
||||
public:
|
||||
mysqlpp::Connection *Con;
|
||||
mysqlpp::NoExceptions *Ne;
|
||||
|
||||
std::string Database;
|
||||
std::string Server;
|
||||
std::string SQLUser;
|
||||
std::string Password;
|
||||
unsigned int Port;
|
||||
unsigned int Delay;
|
||||
|
||||
DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator)
|
||||
{
|
||||
me = this;
|
||||
|
||||
this->SetAuthor("Anope");
|
||||
this->SetType(DATABASE);
|
||||
|
||||
if (!LoadConfig())
|
||||
throw ModuleException(Anope::string("Couldn't load config"));
|
||||
|
||||
Con = new mysqlpp::Connection(false);
|
||||
Ne = new mysqlpp::NoExceptions(Con);
|
||||
if (!Con->connect(Database.c_str(), Server.c_str(), SQLUser.c_str(), Password.c_str(), Port))
|
||||
{
|
||||
std::string Error = "MySQL: Error connecting to SQL server: ";
|
||||
Error += Con->error();
|
||||
delete Con;
|
||||
throw ModuleException(Anope::string(Error));
|
||||
}
|
||||
|
||||
mysqlpp::Query query(Con);
|
||||
query << "SET NAMES 'utf8'";
|
||||
ExecuteQuery(query);
|
||||
}
|
||||
|
||||
virtual ~DBMySQL()
|
||||
{
|
||||
delete Ne;
|
||||
delete Con;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // DB_MYSQL_H
|
||||
@@ -1,159 +0,0 @@
|
||||
/* RequiredLibraries: mysqlpp */
|
||||
|
||||
#include "db_mysql.h"
|
||||
|
||||
class FakeNickCore : public NickCore
|
||||
{
|
||||
public:
|
||||
FakeNickCore() : NickCore("-SQLUser")
|
||||
{
|
||||
NickCoreList.erase(this->display);
|
||||
}
|
||||
|
||||
~FakeNickCore()
|
||||
{
|
||||
NickCoreList[this->display] = this;
|
||||
Users.clear();
|
||||
}
|
||||
|
||||
bool IsServicesOper() const { return true; }
|
||||
bool HasCommand(const std::string &) const { return true; }
|
||||
bool HasPriv(const std::string &) const { return true; }
|
||||
} SQLCore;
|
||||
|
||||
class FakeUser : public User
|
||||
{
|
||||
public:
|
||||
FakeUser() : User("-SQLUser", "")
|
||||
{
|
||||
this->SetIdent("SQL");
|
||||
this->host = sstrdup(Config.ServerName);
|
||||
this->realname = sstrdup("Fake SQL User");
|
||||
this->hostip = sstrdup("255.255.255.255");
|
||||
this->vhost = NULL;
|
||||
this->server = Me;
|
||||
|
||||
UserListByNick.erase("-SQLUser");
|
||||
--usercnt;
|
||||
}
|
||||
|
||||
~FakeUser()
|
||||
{
|
||||
UserListByNick["-SQLUser"] = this;
|
||||
++usercnt;
|
||||
|
||||
nc = NULL;
|
||||
}
|
||||
|
||||
void SetNewNick(const std::string &newnick) { this->nick = newnick; }
|
||||
|
||||
void SendMessage(const std::string &, const char *, ...) { }
|
||||
void SendMessage(const std::string &, const std::string &) { }
|
||||
|
||||
NickCore *Account() const { return nc; }
|
||||
const bool IsIdentified(bool) const { return nc ? true : false; }
|
||||
const bool IsRecognized(bool) const { return true; }
|
||||
} SQLUser;
|
||||
|
||||
class SQLTimer : public Timer
|
||||
{
|
||||
public:
|
||||
SQLTimer() : Timer(me->Delay, time(NULL), true)
|
||||
{
|
||||
mysqlpp::Query query(me->Con);
|
||||
query << "TRUNCATE TABLE `anope_commands`";
|
||||
ExecuteQuery(query);
|
||||
}
|
||||
|
||||
void Tick(time_t)
|
||||
{
|
||||
mysqlpp::Query query(me->Con);
|
||||
mysqlpp::StoreQueryResult qres;
|
||||
|
||||
query << "SELECT * FROM `anope_commands`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres && qres.num_rows())
|
||||
{
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
User *u;
|
||||
NickAlias *na = NULL;
|
||||
bool logout = false;
|
||||
|
||||
/* If they want -SQLUser to execute the command, use it */
|
||||
if (qres[i]["nick"] == "-SQLUser")
|
||||
{
|
||||
u = &SQLUser;
|
||||
u->SetNewNick("-SQLUser");
|
||||
u->Login(&SQLCore);
|
||||
logout = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* See if the nick they want to execute the command is registered */
|
||||
na = findnick(SQLAssign(qres[i]["nick"]));
|
||||
if (na)
|
||||
{
|
||||
/* If it is and someone is online using that nick, use them */
|
||||
if (!na->nc->Users.empty())
|
||||
u = na->nc->Users.front();
|
||||
/* Make a fake nick and use that logged in as the nick we want to use */
|
||||
else
|
||||
{
|
||||
u = &SQLUser;
|
||||
u->SetNewNick(SQLAssign(qres[i]["nick"]));
|
||||
u->Login(na->nc);
|
||||
logout = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if someone is online using the nick now */
|
||||
u = finduser(SQLAssign(qres[i]["nick"]));
|
||||
/* If they arent make a fake user, and use them */
|
||||
if (!u)
|
||||
{
|
||||
u = &SQLUser;
|
||||
u->SetNewNick(SQLAssign(qres[i]["nick"]));
|
||||
u->Logout();
|
||||
logout = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BotInfo *bi = findbot(SQLAssign(qres[i]["service"]));
|
||||
if (!bi)
|
||||
{
|
||||
Alog() << "Warning: SQL command for unknown service " << qres[i]["service"];
|
||||
continue;
|
||||
}
|
||||
|
||||
mod_run_cmd(bi, u, qres[i]["command"].c_str());
|
||||
|
||||
if (logout)
|
||||
u->Logout();
|
||||
}
|
||||
|
||||
query << "TRUNCATE TABLE `anope_commands`";
|
||||
ExecuteQuery(query);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class DBMySQLExecute : public DBMySQL
|
||||
{
|
||||
SQLTimer *_SQLTimer;
|
||||
public:
|
||||
DBMySQLExecute(const Anope::string &modname, const Anope::string &creator) : DBMySQL(modname, creator)
|
||||
{
|
||||
_SQLTimer = new SQLTimer();
|
||||
}
|
||||
|
||||
~DBMySQLExecute()
|
||||
{
|
||||
delete _SQLTimer;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBMySQLExecute)
|
||||
@@ -1,618 +0,0 @@
|
||||
/* RequiredLibraries: mysqlpp */
|
||||
|
||||
#include "db_mysql.h"
|
||||
|
||||
static std::vector<std::string> MakeVector(std::string buf)
|
||||
{
|
||||
std::string s;
|
||||
spacesepstream sep(buf);
|
||||
std::vector<std::string> params;
|
||||
|
||||
while (sep.GetToken(s))
|
||||
{
|
||||
if (s[0] == ':')
|
||||
{
|
||||
s.erase(s.begin());
|
||||
if (!s.empty() && !sep.StreamEnd())
|
||||
params.push_back(s + " " + sep.GetRemaining());
|
||||
else if (!s.empty())
|
||||
params.push_back(s);
|
||||
}
|
||||
else
|
||||
params.push_back(s);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
static void LoadDatabase()
|
||||
{
|
||||
mysqlpp::Query query(me->Con);
|
||||
mysqlpp::StoreQueryResult qres;
|
||||
|
||||
query << "SELECT * FROM `anope_ns_core`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc = new NickCore(SQLAssign(qres[i]["display"]));
|
||||
nc->pass = SQLAssign(qres[i]["pass"]);
|
||||
if (qres[i]["email"].size())
|
||||
nc->email = sstrdup(qres[i]["email"].c_str());
|
||||
if (qres[i]["greet"].size())
|
||||
nc->greet = sstrdup(qres[i]["greet"].c_str());
|
||||
if (qres[i]["icq"].size())
|
||||
nc->icq = atol(qres[i]["icq"].c_str());
|
||||
if (qres[i]["url"].size())
|
||||
nc->url = sstrdup(qres[i]["url"].c_str());
|
||||
|
||||
spacesepstream sep(SQLAssign(qres[i]["flags"]));
|
||||
std::string buf;
|
||||
while (sep.GetToken(buf))
|
||||
for (int j = 0; NickCoreFlags[j].Flag != -1; ++j)
|
||||
if (NickCoreFlags[j].Name == buf)
|
||||
nc->SetFlag(NickCoreFlags[j].Flag);
|
||||
|
||||
nc->language = atoi(qres[i]["language"].c_str());
|
||||
nc->channelcount = atoi(qres[i]["channelcount"].c_str());
|
||||
nc->memos.memomax = atoi(qres[i]["memomax"].c_str());
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_access`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc = findcore(qres[i]["display"].c_str());
|
||||
if (!nc)
|
||||
{
|
||||
Alog() << "MySQL: Got NickCore access entry for nonexistant core " << qres[i]["display"];
|
||||
continue;
|
||||
}
|
||||
|
||||
nc->AddAccess(SQLAssign(qres[i]["access"]));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_core_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc = findcore(qres[i]["display"].c_str());
|
||||
if (!nc)
|
||||
{
|
||||
Alog() << "MySQL: Got NickCore access entry for nonexistant core " << qres[i]["display"];
|
||||
continue;
|
||||
}
|
||||
EventReturn MOD_RESULT;
|
||||
std::vector<std::string> Params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nc, SQLAssign(qres[i]["name"]), Params));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_alias`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc = findcore(qres[i]["display"].c_str());
|
||||
if (!nc)
|
||||
{
|
||||
Alog() << "MySQL: Got NickAlias for nick " << qres[i]["nick"] << " with nonexistant core " << qres[i]["display"];
|
||||
continue;
|
||||
}
|
||||
|
||||
NickAlias *na = new NickAlias(SQLAssign(qres[i]["nick"]), nc);
|
||||
na->last_quit = sstrdup(qres[i]["last_quit"].c_str());
|
||||
na->last_realname = sstrdup(qres[i]["last_realname"].c_str());
|
||||
na->last_usermask = sstrdup(qres[i]["last_usermask"].c_str());
|
||||
na->time_registered = atol(qres[i]["time_registered"].c_str());
|
||||
na->last_seen = atol(qres[i]["last_seen"].c_str());
|
||||
|
||||
spacesepstream sep(SQLAssign(qres[i]["flags"]));
|
||||
std::string buf;
|
||||
while (sep.GetToken(buf))
|
||||
for (int j = 0; NickAliasFlags[j].Flag != -1; ++j)
|
||||
if (NickAliasFlags[j].Name == buf)
|
||||
na->SetFlag(NickAliasFlags[j].Flag);
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_alias_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickAlias *na = findnick(SQLAssign(qres[i]["nick"]));
|
||||
if (!na)
|
||||
{
|
||||
Alog() << "MySQL: Got metadata for nonexistant nick " << qres[i]["nick"];
|
||||
continue;
|
||||
}
|
||||
EventReturn MOD_RESULT;
|
||||
std::vector<std::string> Params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(na, SQLAssign(qres[i]["name"]), Params));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_bs_core`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
BotInfo *bi = findbot(SQLAssign(qres[i]["nick"]));
|
||||
if (!bi)
|
||||
bi = new BotInfo(SQLAssign(qres[i]["nick"]));
|
||||
bi->user = SQLAssign(qres[i]["user"]);
|
||||
bi->host = SQLAssign(qres[i]["host"]);
|
||||
bi->real = SQLAssign(qres[i]["rname"]);
|
||||
|
||||
if (qres[i]["flags"].size())
|
||||
{
|
||||
spacesepstream sep(SQLAssign(qres[i]["flags"]));
|
||||
std::string buf;
|
||||
while (sep.GetToken(buf))
|
||||
for (unsigned j = 0; BotServFlags[j].Flag != -1; ++j)
|
||||
if (buf == BotServFlags[j].Name)
|
||||
{
|
||||
bi->SetFlag(BotServFlags[j].Flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bi->created = atol(qres[i]["created"]);
|
||||
bi->chancount = atol(qres[i]["chancount"]);
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_bs_info_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
BotInfo *bi = findbot(SQLAssign(qres[i]["botname"]));
|
||||
if (!bi)
|
||||
{
|
||||
Alog() << "MySQL: BotInfo metadata for nonexistant bot " << qres[i]["botname"];
|
||||
continue;
|
||||
}
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
std::vector<std::string> Params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(bi, SQLAssign(qres[i]["name"]), Params));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_info`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc;
|
||||
if (qres[i]["founder"].size())
|
||||
{
|
||||
nc = findcore(qres[i]["founder"].c_str());
|
||||
if (!nc)
|
||||
{
|
||||
Alog() << "MySQL: Channel " << qres[i]["name"] << " with nonexistant founder " << qres[i]["founder"];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ChannelInfo *ci = new ChannelInfo(SQLAssign(qres[i]["name"]));
|
||||
ci->founder = nc;
|
||||
if (qres[i]["successor"].size())
|
||||
ci->successor = findcore(qres[i]["successor"].c_str());
|
||||
ci->desc = sstrdup(qres[i]["descr"].c_str());
|
||||
if (qres[i]["url"].size())
|
||||
ci->url = sstrdup(qres[i]["url"].c_str());
|
||||
if (qres[i]["email"].size())
|
||||
ci->email = sstrdup(qres[i]["email"].c_str());
|
||||
ci->time_registered = atol(qres[i]["time_registered"]);
|
||||
ci->last_used = atol(qres[i]["last_used"]);
|
||||
if (qres[i]["last_topic"].size())
|
||||
ci->last_topic = sstrdup(qres[i]["last_topic"].c_str());
|
||||
if (qres[i]["last_topic_setter"].size())
|
||||
ci->last_topic_setter = SQLAssign(qres[i]["last_topic_setter"]);
|
||||
if (qres[i]["last_topic_time"].size())
|
||||
ci->last_topic_time = atol(qres[i]["last_topic_time"].c_str());
|
||||
if (qres[i]["flags"].size())
|
||||
{
|
||||
std::string buf;
|
||||
spacesepstream sep(SQLAssign(qres[i]["flags"]));
|
||||
while (sep.GetToken(buf))
|
||||
for (int j = 0; ChannelFlags[j].Flag != -1; ++j)
|
||||
if (buf == ChannelFlags[j].Name)
|
||||
{
|
||||
ci->SetFlag(ChannelFlags[j].Flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (qres[i]["forbidby"].size())
|
||||
ci->forbidby = sstrdup(qres[i]["forbidby"].c_str());
|
||||
if (qres[i]["forbidreason"].size())
|
||||
ci->forbidreason = sstrdup(qres[i]["forbidreason"].c_str());
|
||||
ci->bantype = atoi(qres[i]["bantype"].c_str());
|
||||
if (qres[i]["mlock_on"].size())
|
||||
{
|
||||
std::vector<Anope::string> modes;
|
||||
std::string buf;
|
||||
|
||||
spacesepstream sep(SQLAssign(qres[i]["mlock_on"]));
|
||||
while (sep.GetToken(buf))
|
||||
modes.push_back(Anope::string(buf));
|
||||
|
||||
ci->Extend("db_mlock_modes_on", new ExtensibleItemRegular<std::vector<Anope::string> >(modes));
|
||||
}
|
||||
if (qres[i]["mlock_off"].size())
|
||||
{
|
||||
std::vector<Anope::string> modes;
|
||||
std::string buf;
|
||||
|
||||
spacesepstream sep(SQLAssign(qres[i]["mlock_off"]));
|
||||
while (sep.GetToken(buf))
|
||||
modes.push_back(Anope::string(buf));
|
||||
|
||||
ci->Extend("db_mlock_modes_off", new ExtensibleItemRegular<std::vector<Anope::string> >(modes));
|
||||
}
|
||||
if (qres[i]["mlock_params"].size())
|
||||
{
|
||||
std::vector<std::pair<Anope::string, Anope::string> > mlp;
|
||||
std::string buf, buf2;
|
||||
|
||||
spacesepstream sep(SQLAssign(qres[i]["mlock_params"]));
|
||||
|
||||
while (sep.GetToken(buf) && sep.GetToken(buf2))
|
||||
mlp.push_back(std::make_pair(Anope::string(buf), Anope::string(buf2)));
|
||||
|
||||
ci->Extend("db_mlp", new ExtensibleItemRegular<std::vector<std::pair<Anope::string, Anope::string> > >(mlp));
|
||||
}
|
||||
if (qres[i]["entry_message"].size())
|
||||
ci->entry_message = sstrdup(qres[i]["entry_message"].c_str());
|
||||
ci->memos.memomax = atoi(qres[i]["memomax"].c_str());
|
||||
if (qres[i]["botnick"].size())
|
||||
ci->bi = findbot(SQLAssign(qres[i]["botnick"]));
|
||||
if (ci->bi)
|
||||
{
|
||||
if (qres[i]["botflags"].size())
|
||||
{
|
||||
std::string buf;
|
||||
spacesepstream sep(SQLAssign(qres[i]["botflags"]));
|
||||
while (sep.GetToken(buf))
|
||||
for (int j = 0; BotFlags[j].Flag != -1; ++j)
|
||||
if (buf == BotFlags[j].Name)
|
||||
{
|
||||
ci->botflags.SetFlag(BotFlags[j].Flag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (qres[i]["capsmin"].size())
|
||||
ci->capsmin = atoi(qres[i]["capsmin"].c_str());
|
||||
if (qres[i]["capspercent"].size())
|
||||
ci->capspercent = atoi(qres[i]["capspercent"].c_str());
|
||||
if (qres[i]["floodlines"].size())
|
||||
ci->floodlines = atoi(qres[i]["floodlines"].c_str());
|
||||
if (qres[i]["floodsecs"].size())
|
||||
ci->floodsecs = atoi(qres[i]["floodsecs"].c_str());
|
||||
if (qres[i]["repeattimes"].size())
|
||||
ci->repeattimes = atoi(qres[i]["repeattimes"].c_str());
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_ttb";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel ttb for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
|
||||
ci->ttb[atoi(qres[i]["ttb_id"].c_str())] = atoi(qres[i]["value"].c_str());
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_bs_badwords`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel badwords entry for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
|
||||
BadWordType BWTYPE = BW_ANY;
|
||||
if (qres[i]["type"] == "SINGLE")
|
||||
BWTYPE = BW_SINGLE;
|
||||
else if (qres[i]["type"] == "START")
|
||||
BWTYPE = BW_START;
|
||||
else if (qres[i]["type"] == "END")
|
||||
BWTYPE = BW_END;
|
||||
ci->AddBadWord(SQLAssign(qres[i]["word"]), BWTYPE);
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_access`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel access entry for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
NickCore *nc = findcore(qres[i]["display"]);
|
||||
if (!nc)
|
||||
{
|
||||
Alog() << "MySQL: Channel access entry for " << ci->name << " with nonexistant nick " << qres[i]["display"];
|
||||
continue;
|
||||
}
|
||||
|
||||
ci->AddAccess(nc, atoi(qres[i]["level"]), SQLAssign(qres[i]["creator"]), atol(qres[i]["last_seen"]));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_akick`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel akick entry for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
NickCore *nc = NULL;
|
||||
spacesepstream sep(qres[i]["flags"]);
|
||||
std::string flag, mask;
|
||||
bool stuck = false;
|
||||
while (sep.GetToken(flag))
|
||||
if (flag == "ISNICK")
|
||||
nc = findcore(qres[i]["mask"]);
|
||||
else if (flag == "STUCK")
|
||||
stuck = true;
|
||||
AutoKick *ak;
|
||||
if (nc)
|
||||
ak = ci->AddAkick(SQLAssign(qres[i]["creator"]), nc, SQLAssign(qres[i]["reason"]), atol(qres[i]["created"].c_str()), atol(qres[i]["last_used"].c_str()));
|
||||
else
|
||||
ak = ci->AddAkick(SQLAssign(qres[i]["creator"]), SQLAssign(qres[i]["mask"]), SQLAssign(qres[i]["reason"]), atol(qres[i]["created"].c_str()), atol(qres[i]["last_used"].c_str()));
|
||||
if (stuck)
|
||||
ak->SetFlag(AK_STUCK);
|
||||
if (nc)
|
||||
ak->SetFlag(AK_ISNICK);
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_levels`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel level entry for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
ci->levels[atoi(qres[i]["position"])] = atoi(qres[i]["level"]);
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_info_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (!ci)
|
||||
{
|
||||
Alog() << "MySQL: Channel metadata for nonexistant channel " << qres[i]["channel"];
|
||||
continue;
|
||||
}
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
std::vector<std::string> Params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, SQLAssign(qres[i]["name"]), Params));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_request`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickRequest *nr = new NickRequest(qres[i]["nick"].c_str());
|
||||
nr->passcode = SQLAssign(qres[i]["passcode"]);
|
||||
nr->password = SQLAssign(qres[i]["password"]);
|
||||
nr->email = sstrdup(qres[i]["email"].c_str());
|
||||
nr->requested = atol(qres[i]["requested"].c_str());
|
||||
}
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
query << "SELECT * FROM `anope_extra`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
std::vector<std::string> params = MakeVector(SQLAssign(qres[i]["data"]));
|
||||
FOREACH_RESULT(I_OnDatabaseRead, OnDatabaseRead(params));
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_core_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickCore *nc = findcore(qres[i]["nick"].c_str());
|
||||
if (nc)
|
||||
{
|
||||
std::vector<std::string> params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(nc, SQLAssign(qres[i]["name"]), params));
|
||||
}
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ns_alias_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
NickAlias *na = findnick(SQLAssign(qres[i]["nick"]));
|
||||
if (na)
|
||||
{
|
||||
std::vector<std::string> params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(na, SQLAssign(qres[i]["name"]), params));
|
||||
}
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_cs_info_metadata`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["channel"]));
|
||||
if (ci)
|
||||
{
|
||||
std::vector<std::string> params = MakeVector(SQLAssign(qres[i]["value"]));
|
||||
FOREACH_RESULT(I_OnDatabaseReadMetadata, OnDatabaseReadMetadata(ci, SQLAssign(qres[i]["name"]), params));
|
||||
}
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_ms_info`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
MemoInfo *mi = NULL;
|
||||
if (qres[i]["serv"] == "NICK")
|
||||
{
|
||||
NickCore *nc = findcore(qres[i]["receiver"].c_str());
|
||||
if (nc)
|
||||
mi = &nc->memos;
|
||||
}
|
||||
else if (qres[i]["serv"] == "CHAN")
|
||||
{
|
||||
ChannelInfo *ci = cs_findchan(SQLAssign(qres[i]["receiver"]));
|
||||
if (ci)
|
||||
mi = &ci->memos;
|
||||
}
|
||||
if (mi)
|
||||
{
|
||||
Memo *m = new Memo();
|
||||
mi->memos.push_back(m);
|
||||
m->sender = SQLAssign(qres[i]["sender"]);
|
||||
if (mi->memos.size() > 1)
|
||||
{
|
||||
m->number = mi->memos[mi->memos.size() - 2]->number + 1;
|
||||
if (m->number < 1)
|
||||
{
|
||||
for (unsigned j = 0; j < mi->memos.size(); ++j)
|
||||
mi->memos[j]->number = j + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
m->number = 1;
|
||||
m->time = atol(qres[i]["time"].c_str());
|
||||
m->text = sstrdup(qres[i]["text"].c_str());
|
||||
|
||||
if (qres[i]["flags"].size())
|
||||
{
|
||||
spacesepstream sep(SQLAssign(qres[i]["flags"]));
|
||||
std::string buf;
|
||||
while (sep.GetToken(buf))
|
||||
for (unsigned j = 0; MemoFlags[j].Flag != -1; ++j)
|
||||
if (MemoFlags[j].Name == buf)
|
||||
m->SetFlag(MemoFlags[j].Flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_os_akills`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres && SGLine)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ci::string user = qres[i]["user"].c_str();
|
||||
ci::string host = qres[i]["host"].c_str();
|
||||
ci::string by = qres[i]["xby"].c_str();
|
||||
std::string reason = SQLAssign(qres[i]["reason"]);
|
||||
time_t seton = atol(qres[i]["seton"].c_str());
|
||||
time_t expires = atol(qres[i]["expire"].c_str());
|
||||
|
||||
XLine *x = SGLine->Add(NULL, NULL, user + "@" + host, expires, reason);
|
||||
if (x)
|
||||
{
|
||||
x->By = by;
|
||||
x->Created = seton;
|
||||
}
|
||||
}
|
||||
|
||||
query << "SELECT * FROM `anope_os_xlines`";
|
||||
qres = StoreQuery(query);
|
||||
|
||||
if (qres)
|
||||
for (size_t i = 0, end = qres.num_rows(); i < end; ++i)
|
||||
{
|
||||
ci::string mask = qres[i]["mask"].c_str();
|
||||
ci::string by = qres[i]["xby"].c_str();
|
||||
std::string reason = SQLAssign(qres[i]["reason"]);
|
||||
time_t seton = atol(qres[i]["seton"].c_str());
|
||||
time_t expires = atol(qres[i]["expires"].c_str());
|
||||
|
||||
XLine *x = NULL;
|
||||
if (qres[i]["type"] == "SNLINE" && SNLine)
|
||||
x = SNLine->Add(NULL, NULL, mask, expires, reason);
|
||||
else if (qres[i]["type"] == "SQLINE" && SQLine)
|
||||
x = SQLine->Add(NULL, NULL, mask, expires, reason);
|
||||
else if (qres[i]["type"] == "SZLINE" && SZLine)
|
||||
x = SZLine->Add(NULL, NULL,mask, expires, reason);
|
||||
if (x)
|
||||
{
|
||||
x->By = by;
|
||||
x->Created = seton;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DBMySQLRead : public DBMySQL
|
||||
{
|
||||
public:
|
||||
DBMySQLRead(const Anope::string &modname, const Anope::string &creator) : DBMySQL(modname, creator)
|
||||
{
|
||||
Implementation i[] = { I_OnLoadDatabase };
|
||||
ModuleManager::Attach(i, this, 1);
|
||||
}
|
||||
|
||||
~DBMySQLRead()
|
||||
{
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase()
|
||||
{
|
||||
LoadDatabase();
|
||||
|
||||
/* No need to ever reload this again, although this should never be triggered again */
|
||||
ModuleManager::Detach(I_OnLoadDatabase, this);
|
||||
|
||||
return EVENT_STOP;
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBMySQLRead)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
|
||||
/** A SQL exception, can be thrown at various points
|
||||
*/
|
||||
class SQLException : public ModuleException
|
||||
{
|
||||
public:
|
||||
SQLException(const Anope::string &reason) : ModuleException(reason) { }
|
||||
|
||||
virtual ~SQLException() throw() { }
|
||||
};
|
||||
|
||||
/** A result from a SQL query
|
||||
*/
|
||||
class SQLResult
|
||||
{
|
||||
protected:
|
||||
/* Rows, column, item */
|
||||
std::vector<std::map<Anope::string, Anope::string> > entries;
|
||||
Anope::string query;
|
||||
Anope::string error;
|
||||
public:
|
||||
SQLResult(const Anope::string &q, const Anope::string &err = "") : query(q), error(err) { }
|
||||
|
||||
inline operator bool() const { return this->error.empty(); }
|
||||
|
||||
inline const Anope::string &GetQuery() const { return this->query; }
|
||||
inline const Anope::string &GetError() const { return this->error; }
|
||||
|
||||
int Rows() const { return this->entries.size(); }
|
||||
|
||||
const std::map<Anope::string, Anope::string> &Row(size_t index) const
|
||||
{
|
||||
try
|
||||
{
|
||||
return this->entries.at(index);
|
||||
}
|
||||
catch (const std::out_of_range &)
|
||||
{
|
||||
throw SQLException("Out of bounds access to SQLResult");
|
||||
}
|
||||
}
|
||||
|
||||
const Anope::string Get(size_t index, const Anope::string &col) const
|
||||
{
|
||||
const std::map<Anope::string, Anope::string> rows = this->Row(index);
|
||||
|
||||
std::map<Anope::string, Anope::string>::const_iterator it = rows.find(col);
|
||||
if (it == rows.end())
|
||||
throw SQLException("Unknown column name in SQLResult: " + col);
|
||||
|
||||
return it->second;
|
||||
}
|
||||
};
|
||||
|
||||
/* An interface used by modules to retrieve the results
|
||||
*/
|
||||
class SQLInterface
|
||||
{
|
||||
public:
|
||||
Module *owner;
|
||||
|
||||
SQLInterface(Module *m) : owner(m) { }
|
||||
|
||||
virtual void OnResult(const SQLResult &r) { }
|
||||
|
||||
virtual void OnError(const SQLResult &r) { }
|
||||
};
|
||||
|
||||
/** Class providing the SQL service, modules call this to execute queries
|
||||
*/
|
||||
class SQLProvider : public Service
|
||||
{
|
||||
public:
|
||||
SQLProvider(Module *c, const Anope::string &n) : Service(c, n) { }
|
||||
|
||||
virtual void Run(SQLInterface *i, const Anope::string &query) = 0;
|
||||
|
||||
virtual SQLResult RunQuery(const Anope::string &query) = 0;
|
||||
|
||||
virtual const Anope::string Escape(const Anope::string &buf) { return buf; }
|
||||
};
|
||||
|
||||
@@ -121,6 +121,8 @@ class SocketEngineEPoll : public SocketEngineBase
|
||||
epoll_event *ev = &events[i];
|
||||
Socket *s = Sockets[ev->data.fd];
|
||||
|
||||
if (s->HasFlag(SF_DEAD))
|
||||
continue;
|
||||
if (ev->events & (EPOLLHUP | EPOLLERR))
|
||||
{
|
||||
s->ProcessError();
|
||||
@@ -135,10 +137,10 @@ class SocketEngineEPoll : public SocketEngineBase
|
||||
s->SetFlag(SF_DEAD);
|
||||
}
|
||||
|
||||
for (std::map<int, Socket *>::iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end; )
|
||||
for (int i = 0; i < total; ++i)
|
||||
{
|
||||
Socket *s = it->second;
|
||||
++it;
|
||||
epoll_event *ev = &events[i];
|
||||
Socket *s = Sockets[ev->data.fd];
|
||||
|
||||
if (s->HasFlag(SF_DEAD))
|
||||
delete s;
|
||||
|
||||
@@ -73,6 +73,8 @@ class SocketEngineSelect : public SocketEngineBase
|
||||
{
|
||||
Socket *s = it->second;
|
||||
|
||||
if (s->HasFlag(SF_DEAD))
|
||||
continue;
|
||||
if (FD_ISSET(s->GetSock(), &efdset))
|
||||
{
|
||||
s->ProcessError();
|
||||
|
||||
+9
-5
@@ -2,17 +2,21 @@
|
||||
file(GLOB SRC_SRCS_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
|
||||
set(SRC_SRCS ${SRC_SRCS_C} ${SRC_SRCS_CPP})
|
||||
|
||||
# If using Windows, include windows.cpp, as it's Windows-specific
|
||||
# If using Windows, add the windows.cpp, the win32 threading engine, and the socket engine to the list
|
||||
if(WIN32)
|
||||
append_to_list(SRC_SRCS win32/windows.cpp)
|
||||
endif(WIN32)
|
||||
|
||||
# If using Windows, add the win32 threading engine to the list
|
||||
if(WIN32)
|
||||
append_to_list(SRC_SRCS threadengines/threadengine_win32.cpp)
|
||||
append_to_list(SRC_SRCS socketengines/socketengine_win32.cpp)
|
||||
# If not using Windows, add the pthread threading engine to the list
|
||||
else(WIN32)
|
||||
append_to_list(SRC_SRCS threadengines/threadengine_pthread.cpp)
|
||||
# If we have eventfd, use it
|
||||
if(HAVE_EVENTFD)
|
||||
append_to_list(SRC_SRCS socketengines/socketengine_eventfd.cpp)
|
||||
# Else fall back to pipe
|
||||
else(HAVE_EVENTFD)
|
||||
append_to_list(SRC_sRCS socketengines/socketengine_pipe.cpp)
|
||||
endif(HAVE_EVENTFD)
|
||||
endif(WIN32)
|
||||
|
||||
sort_list(SRC_SRCS)
|
||||
|
||||
+4
-1
@@ -5,7 +5,7 @@
|
||||
DBSQL="tables.sql"
|
||||
|
||||
# Schema Version
|
||||
SVER="1"
|
||||
SVER="2"
|
||||
|
||||
# Local Version, defaults to 0
|
||||
LVER="0"
|
||||
@@ -132,6 +132,9 @@ 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"
|
||||
|
||||
@@ -92,3 +92,14 @@ unsigned Version::GetBuild() const
|
||||
{
|
||||
return this->Build;
|
||||
}
|
||||
|
||||
Service::Service(Module *o, const Anope::string &n) : owner(o), name(n)
|
||||
{
|
||||
ModuleManager::RegisterService(this);
|
||||
}
|
||||
|
||||
Service::~Service()
|
||||
{
|
||||
ModuleManager::UnregisterService(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "version.h"
|
||||
#include <algorithm> // std::find
|
||||
|
||||
std::map<Anope::string, Service *> ModuleManager::ServiceProviders;
|
||||
std::vector<Module *> ModuleManager::EventHandlers[I_END];
|
||||
|
||||
void ModuleManager::LoadModuleList(std::list<Anope::string> &ModuleList)
|
||||
@@ -430,3 +431,36 @@ void ModuleManager::UnloadAll(bool unload_proto)
|
||||
DeleteModule(m);
|
||||
}
|
||||
}
|
||||
|
||||
/** Register a service
|
||||
* @oaram s The service
|
||||
* @return true if it was successfully registeed, else false (service name colision)
|
||||
*/
|
||||
bool ModuleManager::RegisterService(Service *s)
|
||||
{
|
||||
return ModuleManager::ServiceProviders.insert(std::make_pair(s->name, s)).second;
|
||||
}
|
||||
|
||||
/** Unregister a service
|
||||
* @param s The service
|
||||
* @return true if it was unregistered successfully
|
||||
*/
|
||||
bool ModuleManager::UnregisterService(Service *s)
|
||||
{
|
||||
return ModuleManager::ServiceProviders.erase(s->name);
|
||||
}
|
||||
|
||||
/** Get a service
|
||||
* @param name The service name
|
||||
* @param s The service
|
||||
* @return The service
|
||||
*/
|
||||
Service *ModuleManager::GetService(const Anope::string &name)
|
||||
{
|
||||
std::map<Anope::string, Service *>::const_iterator it = ModuleManager::ServiceProviders.find(name);
|
||||
|
||||
if (it != ModuleManager::ServiceProviders.end())
|
||||
return it->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -381,3 +381,19 @@ Version Module::GetVersion() const
|
||||
{
|
||||
return Version(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);
|
||||
}
|
||||
|
||||
std::list<dynamic_reference_base *> dyn_references;
|
||||
|
||||
dynamic_reference_base::dynamic_reference_base()
|
||||
{
|
||||
dyn_references.push_back(this);
|
||||
}
|
||||
|
||||
dynamic_reference_base::~dynamic_reference_base()
|
||||
{
|
||||
std::list<dynamic_reference_base *>::iterator it = std::find(dyn_references.begin(), dyn_references.end(), this);
|
||||
|
||||
if (it != dyn_references.end())
|
||||
dyn_references.erase(it);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "services.h"
|
||||
#include <sys/eventfd.h>
|
||||
|
||||
int Pipe::RecvInternal(char *buf, size_t sz) const
|
||||
{
|
||||
static eventfd_t dummy;
|
||||
return !eventfd_read(this->Sock, &dummy);
|
||||
}
|
||||
|
||||
int Pipe::SendInternal(const Anope::string &) const
|
||||
{
|
||||
return !eventfd_write(this->Sock, 1);
|
||||
}
|
||||
|
||||
Pipe::Pipe() : Socket()
|
||||
{
|
||||
this->Sock = eventfd(0, EFD_NONBLOCK);
|
||||
if (this->Sock < 0)
|
||||
throw CoreException(Anope::string("Could not create pipe: ") + strerror(errno));
|
||||
|
||||
this->IPv6 = false;
|
||||
this->Type = SOCKTYPE_CLIENT;
|
||||
|
||||
SocketEngine->AddSocket(this);
|
||||
}
|
||||
|
||||
bool Pipe::ProcessRead()
|
||||
{
|
||||
this->RecvInternal(NULL, 0);
|
||||
return this->Read("");
|
||||
}
|
||||
|
||||
bool Pipe::Read(const Anope::string &)
|
||||
{
|
||||
this->OnNotify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pipe::Notify()
|
||||
{
|
||||
this->Write("*");
|
||||
}
|
||||
|
||||
void Pipe::OnNotify()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "services.h"
|
||||
|
||||
int Pipe::RecvInternal(char *buf, size_t sz) const
|
||||
{
|
||||
static char dummy[512];
|
||||
while (read(this->Sock, &dummy, 512) == 512);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Pipe::SendInternal(const Anope::string &) const
|
||||
{
|
||||
static const char dummy = '*';
|
||||
return write(this->WritePipe, &dummy, 1);
|
||||
}
|
||||
|
||||
Pipe::Pipe() : Socket()
|
||||
{
|
||||
int fds[2];
|
||||
if (pipe2(fds, O_NONBLOCK))
|
||||
throw CoreException(Anope::string("Could not create pipe: ") + strerror(errno));
|
||||
|
||||
this->Sock = fds[0];
|
||||
this->WritePipe = fds[1];
|
||||
this->IPv6 = false;
|
||||
this->Type = SOCKTYPE_CLIENT;
|
||||
|
||||
SocketEngine->AddSocket(this);
|
||||
}
|
||||
|
||||
bool Pipe::ProcessRead()
|
||||
{
|
||||
this->RecvInternal(NULL, 0);
|
||||
return this->Read("");
|
||||
}
|
||||
|
||||
bool Pipe::Read(const Anope::string &)
|
||||
{
|
||||
this->OnNotify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pipe::Notify()
|
||||
{
|
||||
this->SendInternal("");
|
||||
}
|
||||
|
||||
void Pipe::OnNotify()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "services.h"
|
||||
|
||||
static Socket *newsocket = NULL;
|
||||
|
||||
class LSocket : public ListenSocket
|
||||
{
|
||||
public:
|
||||
LSocket(const Anope::string &host, int port) : ListenSocket(host, port) { }
|
||||
|
||||
bool OnAccept(Socket *s)
|
||||
{
|
||||
newsocket = s;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int Pipe::RecvInternal(char *buf, size_t sz) const
|
||||
{
|
||||
static char dummy[512];
|
||||
return read(this->Sock, &dummy, 512);
|
||||
}
|
||||
|
||||
int Pipe::SendInternal(const Anope::string &) const
|
||||
{
|
||||
static const char dummy = '*';
|
||||
return write(this->WritePipe, &dummy, 1);
|
||||
}
|
||||
|
||||
Pipe::Pipe() : Socket()
|
||||
{
|
||||
LSocket lfs("127.0.0.1", 0);
|
||||
|
||||
int cfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (cfd == -1)
|
||||
throw CoreException("Error accepting new socket for Pipe");
|
||||
|
||||
sockaddr_in addr;
|
||||
socklen_t sz = sizeof(addr);
|
||||
getsockname(lfs.GetSock(), reinterpret_cast<sockaddr *>(&addr), &sz);
|
||||
|
||||
if (connect(cfd, reinterpret_cast<sockaddr *>(&addr), sz))
|
||||
throw CoreException("Error accepting new socket for Pipe");
|
||||
lfs.ProcessRead();
|
||||
if (!newsocket)
|
||||
throw CoreException("Error accepting new socket for Pipe");
|
||||
|
||||
this->Sock = cfd;
|
||||
this->WritePipe = newsocket->GetSock();
|
||||
this->IPv6 = false;
|
||||
this->Type = SOCKTYPE_CLIENT;
|
||||
|
||||
SocketEngine->AddSocket(this);
|
||||
newsocket = NULL;
|
||||
}
|
||||
|
||||
bool Pipe::ProcessRead()
|
||||
{
|
||||
this->RecvInternal(NULL, 0);
|
||||
return this->Read("");
|
||||
}
|
||||
|
||||
bool Pipe::Read(const Anope::string &)
|
||||
{
|
||||
this->OnNotify();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Pipe::Notify()
|
||||
{
|
||||
this->SendInternal("");
|
||||
}
|
||||
|
||||
void Pipe::OnNotify()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -25,11 +25,18 @@ SocketEngineBase::SocketEngineBase()
|
||||
|
||||
SocketEngineBase::~SocketEngineBase()
|
||||
{
|
||||
for (std::map<int, Socket *>::const_iterator it = this->Sockets.begin(), it_end = this->Sockets.end(); it != it_end; ++it)
|
||||
delete it->second;
|
||||
this->Sockets.clear();
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
Socket::Socket()
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructor
|
||||
* @param nsock The socket
|
||||
* @param nIPv6 IPv6?
|
||||
|
||||
Reference in New Issue
Block a user