1
0
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:
Adam
2010-08-15 01:45:38 -04:00
parent 4d0a1aaabd
commit a950ed8cab
28 changed files with 2805 additions and 2459 deletions
+1
View File
@@ -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
View File
@@ -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
View File
@@ -292,9 +292,7 @@ options
*
* Supported:
* - db_plain
* - db_mysql_write
* - db_mysql_read
* - db_mysql_execute
* - db_mysql
*/
database = "db_plain"
+354
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -30,6 +30,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdexcept>
#include <string.h>
#include <signal.h>
+24
View File
@@ -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:
-1
View File
@@ -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
+414
View File
@@ -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)
-212
View File
@@ -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
-159
View File
@@ -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)
-618
View File
@@ -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
+82
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+11
View File
@@ -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);
}
+34
View File
@@ -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;
}
+16
View File
@@ -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()
{
}
+50
View File
@@ -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()
{
}
+76
View File
@@ -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()
{
}
+7
View File
@@ -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?