summaryrefslogtreecommitdiff
path: root/src/modules/extra
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/extra')
-rw-r--r--src/modules/extra/m_ldapauth.cpp32
-rw-r--r--src/modules/extra/m_sqlauth.cpp210
-rw-r--r--src/modules/extra/m_sqllog.cpp306
-rw-r--r--src/modules/extra/m_sqloper.cpp332
-rw-r--r--src/modules/extra/m_sqlutils.cpp230
-rw-r--r--src/modules/extra/m_sqlutils.h143
-rw-r--r--src/modules/extra/m_sqlv2.h606
7 files changed, 12 insertions, 1847 deletions
diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp
index 6fa5abfe7..013bdd110 100644
--- a/src/modules/extra/m_ldapauth.cpp
+++ b/src/modules/extra/m_ldapauth.cpp
@@ -33,6 +33,7 @@
class ModuleLDAPAuth : public Module
{
+ LocalIntExt ldapAuthed;
std::string base;
std::string attribute;
std::string ldapserver;
@@ -46,21 +47,21 @@ class ModuleLDAPAuth : public Module
LDAP *conn;
public:
- ModuleLDAPAuth()
- {
+ ModuleLDAPAuth() : ldapAuthed("ldapauth", this)
+ {
conn = NULL;
- Implementation eventlist[] = { I_OnUserDisconnect, I_OnCheckReady, I_OnRehash, I_OnUserRegister };
+ Implementation eventlist[] = { I_OnCheckReady, I_OnRehash, I_OnUserRegister };
ServerInstance->Modules->Attach(eventlist, this, 4);
OnRehash(NULL);
}
- virtual ~ModuleLDAPAuth()
+ ~ModuleLDAPAuth()
{
if (conn)
ldap_unbind_ext(conn, NULL, NULL);
}
- virtual void OnRehash(User* user)
+ void OnRehash(User* user)
{
ConfigReader Conf;
@@ -110,11 +111,11 @@ public:
return true;
}
- virtual ModResult OnUserRegister(User* user)
+ ModResult OnUserRegister(User* user)
{
if ((!allowpattern.empty()) && (InspIRCd::Match(user->nick,allowpattern)))
{
- user->Extend("ldapauthed");
+ ldapAuthed.set(user,1);
return MOD_RES_PASSTHRU;
}
@@ -188,7 +189,6 @@ public:
{
if (verbose)
ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s!%s@%s (No password provided)", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
- user->Extend("ldapauth_failed");
return false;
}
cred.bv_val = (char*)user->password.data();
@@ -196,7 +196,7 @@ public:
if ((res = ldap_sasl_bind_s(conn, ldap_get_dn(conn, entry), LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) == LDAP_SUCCESS)
{
ldap_msgfree(msg);
- user->Extend("ldapauthed");
+ ldapAuthed.set(user,1);
return true;
}
else
@@ -204,24 +204,16 @@ public:
if (verbose)
ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s!%s@%s (%s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), ldap_err2string(res));
ldap_msgfree(msg);
- user->Extend("ldapauth_failed");
return false;
}
}
-
- virtual void OnUserDisconnect(User* user)
- {
- user->Shrink("ldapauthed");
- user->Shrink("ldapauth_failed");
- }
-
- virtual ModResult OnCheckReady(User* user)
+ ModResult OnCheckReady(User* user)
{
- return user->GetExt("ldapauthed") ? MOD_RES_PASSTHRU : MOD_RES_DENY;
+ return ldapAuthed.get(user) ? MOD_RES_PASSTHRU : MOD_RES_DENY;
}
- virtual Version GetVersion()
+ Version GetVersion()
{
return Version("Allow/Deny connections based upon answer from LDAP server", VF_VENDOR, API_VERSION);
}
diff --git a/src/modules/extra/m_sqlauth.cpp b/src/modules/extra/m_sqlauth.cpp
deleted file mode 100644
index d7c0675bb..000000000
--- a/src/modules/extra/m_sqlauth.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#include "inspircd.h"
-#include "m_sqlv2.h"
-#include "m_sqlutils.h"
-#include "m_hash.h"
-
-/* $ModDesc: Allow/Deny connections based upon an arbitary SQL table */
-/* $ModDep: m_sqlv2.h m_sqlutils.h m_hash.h */
-
-class ModuleSQLAuth : public Module
-{
- Module* SQLutils;
- Module* SQLprovider;
-
- std::string freeformquery;
- std::string killreason;
- std::string allowpattern;
- std::string databaseid;
-
- bool verbose;
-
-public:
- ModuleSQLAuth()
- {
- ServerInstance->Modules->UseInterface("SQLutils");
- ServerInstance->Modules->UseInterface("SQL");
-
- SQLutils = ServerInstance->Modules->Find("m_sqlutils.so");
- if (!SQLutils)
- throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so.");
-
- SQLprovider = ServerInstance->Modules->FindFeature("SQL");
- if (!SQLprovider)
- throw ModuleException("Can't find an SQL provider module. Please load one before attempting to load m_sqlauth.");
-
- OnRehash(NULL);
- Implementation eventlist[] = { I_OnUserDisconnect, I_OnCheckReady, I_OnRequest, I_OnRehash, I_OnUserRegister };
- ServerInstance->Modules->Attach(eventlist, this, 5);
- }
-
- virtual ~ModuleSQLAuth()
- {
- ServerInstance->Modules->DoneWithInterface("SQL");
- ServerInstance->Modules->DoneWithInterface("SQLutils");
- }
-
-
- virtual void OnRehash(User* user)
- {
- ConfigReader Conf;
-
- databaseid = Conf.ReadValue("sqlauth", "dbid", 0); /* Database ID, given to the SQL service provider */
- freeformquery = Conf.ReadValue("sqlauth", "query", 0); /* Field name where username can be found */
- killreason = Conf.ReadValue("sqlauth", "killreason", 0); /* Reason to give when access is denied to a user (put your reg details here) */
- allowpattern = Conf.ReadValue("sqlauth", "allowpattern",0 ); /* Allow nicks matching this pattern without requiring auth */
- verbose = Conf.ReadFlag("sqlauth", "verbose", 0); /* Set to true if failed connects should be reported to operators */
- }
-
- virtual ModResult OnUserRegister(User* user)
- {
- if ((!allowpattern.empty()) && (InspIRCd::Match(user->nick,allowpattern)))
- {
- user->Extend("sqlauthed");
- return MOD_RES_PASSTHRU;
- }
-
- if (!CheckCredentials(user))
- {
- ServerInstance->Users->QuitUser(user, killreason);
- return MOD_RES_DENY;
- }
- return MOD_RES_PASSTHRU;
- }
-
- bool CheckCredentials(User* user)
- {
- std::string thisquery = freeformquery;
- std::string safepass = user->password;
- std::string safegecos = user->fullname;
-
- /* Search and replace the escaped nick and escaped pass into the query */
-
- SearchAndReplace(safepass, std::string("\""), std::string("\\\""));
- SearchAndReplace(safegecos, std::string("\""), std::string("\\\""));
-
- SearchAndReplace(thisquery, std::string("$nick"), user->nick);
- SearchAndReplace(thisquery, std::string("$pass"), safepass);
- SearchAndReplace(thisquery, std::string("$host"), user->host);
- SearchAndReplace(thisquery, std::string("$ip"), std::string(user->GetIPString()));
- SearchAndReplace(thisquery, std::string("$gecos"), safegecos);
- SearchAndReplace(thisquery, std::string("$ident"), user->ident);
- SearchAndReplace(thisquery, std::string("$server"), std::string(user->server));
- SearchAndReplace(thisquery, std::string("$uuid"), user->uuid);
-
- Module* HashMod = ServerInstance->Modules->Find("m_md5.so");
-
- if (HashMod)
- {
- HashResetRequest(this, HashMod).Send();
- SearchAndReplace(thisquery, std::string("$md5pass"), std::string(HashSumRequest(this, HashMod, user->password).Send()));
- }
-
- HashMod = ServerInstance->Modules->Find("m_sha256.so");
-
- if (HashMod)
- {
- HashResetRequest(this, HashMod).Send();
- SearchAndReplace(thisquery, std::string("$sha256pass"), std::string(HashSumRequest(this, HashMod, user->password).Send()));
- }
-
- /* Build the query */
- SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(thisquery));
-
- if(req.Send())
- {
- /* When we get the query response from the service provider we will be given an ID to play with,
- * just an ID number which is unique to this query. We need a way of associating that ID with a User
- * so we insert it into a map mapping the IDs to users.
- * Thankfully m_sqlutils provides this, it will associate a ID with a user or channel, and if the user quits it removes the
- * association. This means that if the user quits during a query we will just get a failed lookup from m_sqlutils - telling
- * us to discard the query.
- */
- AssociateUser(this, SQLutils, req.id, user).Send();
-
- return true;
- }
- else
- {
- if (verbose)
- ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s!%s@%s (SQL query failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), req.error.Str());
- return false;
- }
- }
-
- virtual const char* OnRequest(Request* request)
- {
- if(strcmp(SQLRESID, request->GetId()) == 0)
- {
- SQLresult* res = static_cast<SQLresult*>(request);
-
- User* user = GetAssocUser(this, SQLutils, res->id).S().user;
- UnAssociate(this, SQLutils, res->id).S();
-
- if(user)
- {
- if(res->error.Id() == SQL_NO_ERROR)
- {
- if(res->Rows())
- {
- /* We got a row in the result, this is enough really */
- user->Extend("sqlauthed");
- }
- else if (verbose)
- {
- /* No rows in result, this means there was no record matching the user */
- ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s!%s@%s (SQL query returned no matches)", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
- user->Extend("sqlauth_failed");
- }
- }
- else if (verbose)
- {
- ServerInstance->SNO->WriteGlobalSno('a', "Forbidden connection from %s!%s@%s (SQL query failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), res->error.Str());
- user->Extend("sqlauth_failed");
- }
- }
- else
- {
- return NULL;
- }
-
- if (!user->GetExt("sqlauthed"))
- {
- ServerInstance->Users->QuitUser(user, killreason);
- }
- return SQLSUCCESS;
- }
- return NULL;
- }
-
- virtual void OnUserDisconnect(User* user)
- {
- user->Shrink("sqlauthed");
- user->Shrink("sqlauth_failed");
- }
-
- virtual ModResult OnCheckReady(User* user)
- {
- return user->GetExt("sqlauthed") ? MOD_RES_PASSTHRU : MOD_RES_DENY;
- }
-
- virtual Version GetVersion()
- {
- return Version("Allow/Deny connections based upon an arbitary SQL table", VF_VENDOR, API_VERSION);
- }
-
-};
-
-MODULE_INIT(ModuleSQLAuth)
diff --git a/src/modules/extra/m_sqllog.cpp b/src/modules/extra/m_sqllog.cpp
deleted file mode 100644
index 4713f24a9..000000000
--- a/src/modules/extra/m_sqllog.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#include "inspircd.h"
-#include "m_sqlv2.h"
-
-static Module* SQLModule;
-static Module* MyMod;
-static std::string dbid;
-
-enum LogTypes { LT_OPER = 1, LT_KILL, LT_SERVLINK, LT_XLINE, LT_CONNECT, LT_DISCONNECT, LT_FLOOD, LT_LOADMODULE };
-
-enum QueryState { FIND_SOURCE, FIND_NICK, FIND_HOST, DONE};
-
-class QueryInfo;
-
-std::map<unsigned long,QueryInfo*> active_queries;
-
-class QueryInfo
-{
-public:
- QueryState qs;
- unsigned long id;
- std::string nick;
- std::string source;
- std::string hostname;
- int sourceid;
- int nickid;
- int hostid;
- int category;
- time_t date;
- bool insert;
-
- QueryInfo(const std::string &n, const std::string &s, const std::string &h, unsigned long i, int cat)
- {
- ServerInstance = Instance;
- qs = FIND_SOURCE;
- nick = n;
- source = s;
- hostname = h;
- id = i;
- category = cat;
- sourceid = nickid = hostid = -1;
- date = ServerInstance->Time();
- insert = false;
- }
-
- void Go(SQLresult* res)
- {
- SQLrequest req = SQLrequest(MyMod, SQLModule, dbid, SQLquery(""));
- switch (qs)
- {
- case FIND_SOURCE:
- if (res->Rows() && sourceid == -1 && !insert)
- {
- sourceid = atoi(res->GetValue(0,0).d.c_str());
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % nick);
- if(req.Send())
- {
- insert = false;
- qs = FIND_NICK;
- active_queries[req.id] = this;
- }
- }
- else if (res->Rows() && sourceid == -1 && insert)
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % source);
- if(req.Send())
- {
- insert = false;
- qs = FIND_SOURCE;
- active_queries[req.id] = this;
- }
- }
- else
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_actors (actor) VALUES('?')") % source);
- if(req.Send())
- {
- insert = true;
- qs = FIND_SOURCE;
- active_queries[req.id] = this;
- }
- }
- break;
-
- case FIND_NICK:
- if (res->Rows() && nickid == -1 && !insert)
- {
- nickid = atoi(res->GetValue(0,0).d.c_str());
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'") % hostname);
- if(req.Send())
- {
- insert = false;
- qs = FIND_HOST;
- active_queries[req.id] = this;
- }
- }
- else if (res->Rows() && nickid == -1 && insert)
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % nick);
- if(req.Send())
- {
- insert = false;
- qs = FIND_NICK;
- active_queries[req.id] = this;
- }
- }
- else
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_actors (actor) VALUES('?')") % nick);
- if(req.Send())
- {
- insert = true;
- qs = FIND_NICK;
- active_queries[req.id] = this;
- }
- }
- break;
-
- case FIND_HOST:
- if (res->Rows() && hostid == -1 && !insert)
- {
- hostid = atoi(res->GetValue(0,0).d.c_str());
- req = SQLrequest(MyMod, SQLModule, dbid,
- SQLquery("INSERT INTO ircd_log (category_id,nick,host,source,dtime) VALUES('?','?','?','?','?')") % category % nickid % hostid % sourceid % date);
- if(req.Send())
- {
- insert = true;
- qs = DONE;
- active_queries[req.id] = this;
- }
- }
- else if (res->Rows() && hostid == -1 && insert)
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'") % hostname);
- if(req.Send())
- {
- insert = false;
- qs = FIND_HOST;
- active_queries[req.id] = this;
- }
- }
- else
- {
- req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_hosts (hostname) VALUES('?')") % hostname);
- if(req.Send())
- {
- insert = true;
- qs = FIND_HOST;
- active_queries[req.id] = this;
- }
- }
- break;
-
- case DONE:
- std::map<unsigned long,QueryInfo*>::iterator x = active_queries.find(req.id);
- if (x != active_queries.end())
- {
- delete x->second;
- active_queries.erase(x);
- }
- break;
- }
- }
-};
-
-/* $ModDesc: Logs network-wide data to an SQL database */
-
-class ModuleSQLLog : public Module
-{
-
- public:
- ModuleSQLLog()
- {
- ServerInstance->Modules->UseInterface("SQLutils");
- ServerInstance->Modules->UseInterface("SQL");
-
- Module* SQLutils = ServerInstance->Modules->Find("m_sqlutils.so");
- if (!SQLutils)
- throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so.");
-
- SQLModule = ServerInstance->Modules->FindFeature("SQL");
-
- OnRehash(NULL);
- MyMod = this;
- active_queries.clear();
-
- Implementation eventlist[] = { I_OnRehash, I_OnOper, I_OnGlobalOper, I_OnKill,
- I_OnPreCommand, I_OnUserConnect, I_OnUserQuit, I_OnLoadModule, I_OnRequest };
- ServerInstance->Modules->Attach(eventlist, this, 9);
- }
-
- virtual ~ModuleSQLLog()
- {
- ServerInstance->Modules->DoneWithInterface("SQL");
- ServerInstance->Modules->DoneWithInterface("SQLutils");
- }
-
-
- void ReadConfig()
- {
- ConfigReader Conf;
- dbid = Conf.ReadValue("sqllog","dbid",0); // database id of a database configured in sql module
- }
-
- virtual void OnRehash(User* user)
- {
- ReadConfig();
- }
-
- virtual const char* OnRequest(Request* request)
- {
- if(strcmp(SQLRESID, request->GetId()) == 0)
- {
- SQLresult* res;
- std::map<unsigned long, QueryInfo*>::iterator n;
-
- res = static_cast<SQLresult*>(request);
- n = active_queries.find(res->id);
-
- if (n != active_queries.end())
- {
- n->second->Go(res);
- active_queries.erase(n);
- }
-
- return SQLSUCCESS;
- }
-
- return NULL;
- }
-
- void AddLogEntry(int category, const std::string &nick, const std::string &host, const std::string &source)
- {
- // is the sql module loaded? If not, we don't attempt to do anything.
- if (!SQLModule)
- return;
-
- SQLrequest req = SQLrequest(this, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % source);
- if(req.Send())
- {
- QueryInfo* i = new QueryInfo(nick, source, host, req.id, category);
- i->qs = FIND_SOURCE;
- active_queries[req.id] = i;
- }
- }
-
- virtual void OnOper(User* user, const std::string &opertype)
- {
- AddLogEntry(LT_OPER,user->nick,user->host,user->server);
- }
-
- virtual void OnGlobalOper(User* user)
- {
- AddLogEntry(LT_OPER,user->nick,user->host,user->server);
- }
-
- virtual ModResult OnKill(User* source, User* dest, const std::string &reason)
- {
- AddLogEntry(LT_KILL,dest->nick,dest->host,source->nick);
- return MOD_RES_PASSTHRU;
- }
-
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, User *user, bool validated, const std::string &original_line)
- {
- if ((command == "GLINE" || command == "KLINE" || command == "ELINE" || command == "ZLINE") && validated)
- {
- AddLogEntry(LT_XLINE,user->nick,command[0]+std::string(":")+parameters[0],user->server);
- }
- return MOD_RES_PASSTHRU;
- }
-
- virtual void OnUserConnect(User* user)
- {
- AddLogEntry(LT_CONNECT,user->nick,user->host,user->server);
- }
-
- virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
- {
- AddLogEntry(LT_DISCONNECT,user->nick,user->host,user->server);
- }
-
- virtual void OnLoadModule(Module* mod, const std::string &name)
- {
- AddLogEntry(LT_LOADMODULE,name,ServerInstance->Config->ServerName, ServerInstance->Config->ServerName);
- }
-
- virtual Version GetVersion()
- {
- return Version("Logs network-wide data to an SQL database", VF_VENDOR, API_VERSION);
- }
-
-};
-
-MODULE_INIT(ModuleSQLLog)
diff --git a/src/modules/extra/m_sqloper.cpp b/src/modules/extra/m_sqloper.cpp
deleted file mode 100644
index 47aa8d1fd..000000000
--- a/src/modules/extra/m_sqloper.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#include "inspircd.h"
-#include "m_sqlv2.h"
-#include "m_sqlutils.h"
-#include "m_hash.h"
-#include "commands/cmd_oper.h"
-
-/* $ModDesc: Allows storage of oper credentials in an SQL table */
-/* $ModDep: m_sqlv2.h m_sqlutils.h m_hash.h */
-
-typedef std::map<irc::string, Module*> hashymodules;
-
-class ModuleSQLOper : public Module
-{
- Module* SQLutils;
- std::string databaseid;
- irc::string hashtype;
- hashymodules hashers;
- bool diduseiface;
- parameterlist names;
-
-public:
- ModuleSQLOper()
- {
- ServerInstance->Modules->UseInterface("SQLutils");
- ServerInstance->Modules->UseInterface("SQL");
- ServerInstance->Modules->UseInterface("HashRequest");
-
- OnRehash(NULL);
-
- diduseiface = false;
-
- /* Find all modules which implement the interface 'HashRequest' */
- modulelist* ml = ServerInstance->Modules->FindInterface("HashRequest");
-
- /* Did we find any modules? */
- if (ml)
- {
- /* Yes, enumerate them all to find out the hashing algorithm name */
- for (modulelist::iterator m = ml->begin(); m != ml->end(); m++)
- {
- /* Make a request to it for its name, its implementing
- * HashRequest so we know its safe to do this
- */
- std::string name = HashNameRequest(this, *m).Send();
- /* Build a map of them */
- hashers[name.c_str()] = *m;
- names.push_back(name);
- }
- /* UseInterface doesn't do anything if there are no providers, so we'll have to call it later if a module gets loaded later on. */
- diduseiface = true;
- ServerInstance->Modules->UseInterface("HashRequest");
- }
-
- SQLutils = ServerInstance->Modules->Find("m_sqlutils.so");
- if (!SQLutils)
- throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqloper.so.");
-
- Implementation eventlist[] = { I_OnRequest, I_OnRehash, I_OnPreCommand, I_OnLoadModule };
- ServerInstance->Modules->Attach(eventlist, this, 3);
- }
-
- bool OneOfMatches(const char* host, const char* ip, const char* hostlist)
- {
- std::stringstream hl(hostlist);
- std::string xhost;
- while (hl >> xhost)
- {
- if (InspIRCd::Match(host, xhost, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(ip, xhost, ascii_case_insensitive_map))
- {
- return true;
- }
- }
- return false;
- }
-
- virtual void OnLoadModule(Module* mod, const std::string& name)
- {
- if (ServerInstance->Modules->ModuleHasInterface(mod, "HashRequest"))
- {
- ServerInstance->Logs->Log("m_sqloper",DEBUG, "Post-load registering hasher: %s", name.c_str());
- std::string sname = HashNameRequest(this, mod).Send();
- hashers[sname.c_str()] = mod;
- names.push_back(sname);
- if (!diduseiface)
- {
- ServerInstance->Modules->UseInterface("HashRequest");
- diduseiface = true;
- }
- }
- }
-
- virtual ~ModuleSQLOper()
- {
- ServerInstance->Modules->DoneWithInterface("SQL");
- ServerInstance->Modules->DoneWithInterface("SQLutils");
- if (diduseiface)
- ServerInstance->Modules->DoneWithInterface("HashRequest");
- }
-
-
- virtual void OnRehash(User* user)
- {
- ConfigReader Conf;
-
- databaseid = Conf.ReadValue("sqloper", "dbid", 0); /* Database ID of a database configured for the service provider module */
- hashtype = assign(Conf.ReadValue("sqloper", "hash", 0));
- }
-
- virtual ModResult OnPreCommand(std::string &command, std::vector<std::string> &parameters, User *user, bool validated, const std::string &original_line)
- {
- if ((validated) && (command == "OPER"))
- {
- if (LookupOper(user, parameters[0], parameters[1]))
- {
- /* Returning true here just means the query is in progress, or on it's way to being
- * in progress. Nothing about the /oper actually being successful..
- * If the oper lookup fails later, we pass the command to the original handler
- * for /oper by calling its Handle method directly.
- */
- return MOD_RES_DENY;
- }
- }
- return MOD_RES_PASSTHRU;
- }
-
- bool LookupOper(User* user, const std::string &username, const std::string &password)
- {
- Module* target;
-
- target = ServerInstance->Modules->FindFeature("SQL");
-
- if (target)
- {
- hashymodules::iterator x = hashers.find(hashtype);
- if (x == hashers.end())
- return false;
-
- /* Reset hash module first back to MD5 standard state */
- HashResetRequest(this, x->second).Send();
- /* Make an MD5 hash of the password for using in the query */
- std::string md5_pass_hash = HashSumRequest(this, x->second, password.c_str()).Send();
-
- /* We generate our own sum here because some database providers (e.g. SQLite) dont have a builtin md5/sha256 function,
- * also hashing it in the module and only passing a remote query containing a hash is more secure.
- */
- SQLrequest req = SQLrequest(this, target, databaseid,
- SQLquery("SELECT username, password, hostname, type FROM ircd_opers WHERE username = '?' AND password='?'") % username % md5_pass_hash);
-
- if (req.Send())
- {
- /* When we get the query response from the service provider we will be given an ID to play with,
- * just an ID number which is unique to this query. We need a way of associating that ID with a User
- * so we insert it into a map mapping the IDs to users.
- * Thankfully m_sqlutils provides this, it will associate a ID with a user or channel, and if the user quits it removes the
- * association. This means that if the user quits during a query we will just get a failed lookup from m_sqlutils - telling
- * us to discard the query.
- */
- AssociateUser(this, SQLutils, req.id, user).Send();
-
- user->Extend("oper_user", strdup(username.c_str()));
- user->Extend("oper_pass", strdup(password.c_str()));
-
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- ServerInstance->Logs->Log("m_sqloper",SPARSE, "WARNING: Couldn't find SQL provider module. NOBODY will be able to oper up unless their o:line is statically configured");
- return false;
- }
- }
-
- virtual const char* OnRequest(Request* request)
- {
- if (strcmp(SQLRESID, request->GetId()) == 0)
- {
- SQLresult* res = static_cast<SQLresult*>(request);
-
- User* user = GetAssocUser(this, SQLutils, res->id).S().user;
- UnAssociate(this, SQLutils, res->id).S();
-
- char* tried_user = NULL;
- char* tried_pass = NULL;
-
- user->GetExt("oper_user", tried_user);
- user->GetExt("oper_pass", tried_pass);
-
- if (user)
- {
- if (res->error.Id() == SQL_NO_ERROR)
- {
- if (res->Rows())
- {
- /* We got a row in the result, this means there was a record for the oper..
- * now we just need to check if their host matches, and if it does then
- * oper them up.
- *
- * We now (previous versions of the module didn't) support multiple SQL
- * rows per-oper in the same way the config file does, all rows will be tried
- * until one is found which matches. This is useful to define several different
- * hosts for a single oper.
- *
- * The for() loop works as SQLresult::GetRowMap() returns an empty map when there
- * are no more rows to return.
- */
-
- for (SQLfieldMap& row = res->GetRowMap(); row.size(); row = res->GetRowMap())
- {
- if (OperUser(user, row["hostname"].d, row["type"].d))
- {
- /* If/when one of the rows matches, stop checking and return */
- return SQLSUCCESS;
- }
- if (tried_user && tried_pass)
- {
- LoginFail(user, tried_user, tried_pass);
- free(tried_user);
- free(tried_pass);
- user->Shrink("oper_user");
- user->Shrink("oper_pass");
- }
- }
- }
- else
- {
- /* No rows in result, this means there was no oper line for the user,
- * we should have already checked the o:lines so now we need an
- * "insufficient awesomeness" (invalid credentials) error
- */
- if (tried_user && tried_pass)
- {
- LoginFail(user, tried_user, tried_pass);
- free(tried_user);
- free(tried_pass);
- user->Shrink("oper_user");
- user->Shrink("oper_pass");
- }
- }
- }
- else
- {
- /* This one shouldn't happen, the query failed for some reason.
- * We have to fail the /oper request and give them the same error
- * as above.
- */
- if (tried_user && tried_pass)
- {
- LoginFail(user, tried_user, tried_pass);
- free(tried_user);
- free(tried_pass);
- user->Shrink("oper_user");
- user->Shrink("oper_pass");
- }
-
- }
- }
-
- return SQLSUCCESS;
- }
-
- return NULL;
- }
-
- void LoginFail(User* user, const std::string &username, const std::string &pass)
- {
- Command* oper_command = ServerInstance->Parser->GetHandler("OPER");
-
- if (oper_command)
- {
- std::vector<std::string> params;
- params.push_back(username);
- params.push_back(pass);
- oper_command->Handle(params, user);
- }
- else
- {
- ServerInstance->Logs->Log("m_sqloper",DEBUG, "BUG: WHAT?! Why do we have no OPER command?!");
- }
- }
-
- bool OperUser(User* user, const std::string &pattern, const std::string &type)
- {
- ConfigReader Conf;
-
- for (int j = 0; j < Conf.Enumerate("type"); j++)
- {
- std::string tname = Conf.ReadValue("type","name",j);
- std::string hostname(user->ident);
-
- hostname.append("@").append(user->host);
-
- if ((tname == type) && OneOfMatches(hostname.c_str(), user->GetIPString(), pattern.c_str()))
- {
- /* Opertype and host match, looks like this is it. */
- std::string operhost = Conf.ReadValue("type", "host", j);
-
- if (operhost.size())
- user->ChangeDisplayedHost(operhost.c_str());
-
- user->Oper(type, tname);
- return true;
- }
- }
-
- return false;
- }
-
- virtual Version GetVersion()
- {
- return Version("Allows storage of oper credentials in an SQL table", VF_VENDOR, API_VERSION);
- }
-
-};
-
-MODULE_INIT(ModuleSQLOper)
diff --git a/src/modules/extra/m_sqlutils.cpp b/src/modules/extra/m_sqlutils.cpp
deleted file mode 100644
index 6d40ee22c..000000000
--- a/src/modules/extra/m_sqlutils.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#include "inspircd.h"
-#include <sstream>
-#include <list>
-#include "m_sqlutils.h"
-
-/* $ModDesc: Provides some utilities to SQL client modules, such as mapping queries to users and channels */
-/* $ModDep: m_sqlutils.h */
-
-typedef std::map<unsigned long, User*> IdUserMap;
-typedef std::map<unsigned long, Channel*> IdChanMap;
-typedef std::list<unsigned long> AssocIdList;
-
-class ModuleSQLutils : public Module
-{
-private:
- IdUserMap iduser;
- IdChanMap idchan;
-
-public:
- ModuleSQLutils()
- {
- ServerInstance->Modules->PublishInterface("SQLutils", this);
- Implementation eventlist[] = { I_OnChannelDelete, I_OnUnloadModule, I_OnRequest, I_OnUserDisconnect };
- ServerInstance->Modules->Attach(eventlist, this, 4);
- }
-
- virtual ~ModuleSQLutils()
- {
- ServerInstance->Modules->UnpublishInterface("SQLutils", this);
- }
-
-
- virtual const char* OnRequest(Request* request)
- {
- if(strcmp(SQLUTILAU, request->GetId()) == 0)
- {
- AssociateUser* req = (AssociateUser*)request;
-
- iduser.insert(std::make_pair(req->id, req->user));
-
- AttachList(req->user, req->id);
- }
- else if(strcmp(SQLUTILAC, request->GetId()) == 0)
- {
- AssociateChan* req = (AssociateChan*)request;
-
- idchan.insert(std::make_pair(req->id, req->chan));
-
- AttachList(req->chan, req->id);
- }
- else if(strcmp(SQLUTILUA, request->GetId()) == 0)
- {
- UnAssociate* req = (UnAssociate*)request;
-
- /* Unassociate a given query ID with all users and channels
- * it is associated with.
- */
-
- DoUnAssociate(iduser, req->id);
- DoUnAssociate(idchan, req->id);
- }
- else if(strcmp(SQLUTILGU, request->GetId()) == 0)
- {
- GetAssocUser* req = (GetAssocUser*)request;
-
- IdUserMap::iterator iter = iduser.find(req->id);
-
- if(iter != iduser.end())
- {
- req->user = iter->second;
- }
- }
- else if(strcmp(SQLUTILGC, request->GetId()) == 0)
- {
- GetAssocChan* req = (GetAssocChan*)request;
-
- IdChanMap::iterator iter = idchan.find(req->id);
-
- if(iter != idchan.end())
- {
- req->chan = iter->second;
- }
- }
-
- return SQLUTILSUCCESS;
- }
-
- virtual void OnUserDisconnect(User* user)
- {
- /* A user is disconnecting, first we need to check if they have a list of queries associated with them.
- * Then, if they do, we need to erase each of them from our IdUserMap (iduser) so when the module that
- * associated them asks to look them up then it gets a NULL result and knows to discard the query.
- */
- AssocIdList* il;
-
- if(user->GetExt("sqlutils_queryids", il))
- {
- for(AssocIdList::iterator listiter = il->begin(); listiter != il->end(); listiter++)
- {
- IdUserMap::iterator iter;
-
- iter = iduser.find(*listiter);
-
- if(iter != iduser.end())
- {
- if(iter->second != user)
- {
- ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: ID associated with user %s doesn't have the same User* associated with it in the map (erasing anyway)", user->nick.c_str());
- }
-
- iduser.erase(iter);
- }
- else
- {
- ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: user %s was extended with sqlutils_queryids but there was nothing matching in the map", user->nick.c_str());
- }
- }
-
- user->Shrink("sqlutils_queryids");
- delete il;
- }
- }
-
- void AttachList(Extensible* obj, unsigned long id)
- {
- AssocIdList* il;
-
- if(!obj->GetExt("sqlutils_queryids", il))
- {
- /* Doesn't already exist, create a new list and attach it. */
- il = new AssocIdList;
- obj->Extend("sqlutils_queryids", il);
- }
-
- /* Now either way we have a valid list in il, attached. */
- il->push_back(id);
- }
-
- void RemoveFromList(Extensible* obj, unsigned long id)
- {
- AssocIdList* il;
-
- if(obj->GetExt("sqlutils_queryids", il))
- {
- /* Only do anything if the list exists... (which it ought to) */
- il->remove(id);
-
- if(il->empty())
- {
- /* If we just emptied it.. */
- delete il;
- obj->Shrink("sqlutils_queryids");
- }
- }
- }
-
- template <class T> void DoUnAssociate(T &map, unsigned long id)
- {
- /* For each occurence of 'id' (well, only one..it's not a multimap) in 'map'
- * remove it from the map, take an Extensible* value from the map and remove
- * 'id' from the list of query IDs attached to it.
- */
- typename T::iterator iter = map.find(id);
-
- if(iter != map.end())
- {
- /* Found a value indexed by 'id', call RemoveFromList()
- * on it with 'id' to remove 'id' from the list attached
- * to the value.
- */
- RemoveFromList(iter->second, id);
- }
- }
-
- virtual void OnChannelDelete(Channel* chan)
- {
- /* A channel is being destroyed, first we need to check if it has a list of queries associated with it.
- * Then, if it does, we need to erase each of them from our IdChanMap (idchan) so when the module that
- * associated them asks to look them up then it gets a NULL result and knows to discard the query.
- */
- AssocIdList* il;
-
- if(chan->GetExt("sqlutils_queryids", il))
- {
- for(AssocIdList::iterator listiter = il->begin(); listiter != il->end(); listiter++)
- {
- IdChanMap::iterator iter;
-
- iter = idchan.find(*listiter);
-
- if(iter != idchan.end())
- {
- if(iter->second != chan)
- {
- ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: ID associated with channel %s doesn't have the same Channel* associated with it in the map (erasing anyway)", chan->name.c_str());
- }
- idchan.erase(iter);
- }
- else
- {
- ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: channel %s was extended with sqlutils_queryids but there was nothing matching in the map", chan->name.c_str());
- }
- }
-
- chan->Shrink("sqlutils_queryids");
- delete il;
- }
- }
-
- virtual Version GetVersion()
- {
- return Version("Provides some utilities to SQL client modules, such as mapping queries to users and channels", VF_VENDOR | VF_SERVICEPROVIDER, API_VERSION);
- }
-
-};
-
-MODULE_INIT(ModuleSQLutils)
diff --git a/src/modules/extra/m_sqlutils.h b/src/modules/extra/m_sqlutils.h
deleted file mode 100644
index ce43be8cc..000000000
--- a/src/modules/extra/m_sqlutils.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#ifndef INSPIRCD_SQLUTILS
-#define INSPIRCD_SQLUTILS
-
-#include "modules.h"
-
-#define SQLUTILAU "SQLutil AssociateUser"
-#define SQLUTILAC "SQLutil AssociateChan"
-#define SQLUTILUA "SQLutil UnAssociate"
-#define SQLUTILGU "SQLutil GetAssocUser"
-#define SQLUTILGC "SQLutil GetAssocChan"
-#define SQLUTILSUCCESS "You shouldn't be reading this (success)"
-
-/** Used to associate an SQL query with a user
- */
-class AssociateUser : public Request
-{
-public:
- /** Query ID
- */
- unsigned long id;
- /** User
- */
- User* user;
-
- AssociateUser(Module* s, Module* d, unsigned long i, User* u)
- : Request(s, d, SQLUTILAU), id(i), user(u)
- {
- }
-
- AssociateUser& S()
- {
- Send();
- return *this;
- }
-};
-
-/** Used to associate an SQL query with a channel
- */
-class AssociateChan : public Request
-{
-public:
- /** Query ID
- */
- unsigned long id;
- /** Channel
- */
- Channel* chan;
-
- AssociateChan(Module* s, Module* d, unsigned long i, Channel* u)
- : Request(s, d, SQLUTILAC), id(i), chan(u)
- {
- }
-
- AssociateChan& S()
- {
- Send();
- return *this;
- }
-};
-
-/** Unassociate a user or class from an SQL query
- */
-class UnAssociate : public Request
-{
-public:
- /** The query ID
- */
- unsigned long id;
-
- UnAssociate(Module* s, Module* d, unsigned long i)
- : Request(s, d, SQLUTILUA), id(i)
- {
- }
-
- UnAssociate& S()
- {
- Send();
- return *this;
- }
-};
-
-/** Get the user associated with an SQL query ID
- */
-class GetAssocUser : public Request
-{
-public:
- /** The query id
- */
- unsigned long id;
- /** The user
- */
- User* user;
-
- GetAssocUser(Module* s, Module* d, unsigned long i)
- : Request(s, d, SQLUTILGU), id(i), user(NULL)
- {
- }
-
- GetAssocUser& S()
- {
- Send();
- return *this;
- }
-};
-
-/** Get the channel associated with an SQL query ID
- */
-class GetAssocChan : public Request
-{
-public:
- /** The query id
- */
- unsigned long id;
- /** The channel
- */
- Channel* chan;
-
- GetAssocChan(Module* s, Module* d, unsigned long i)
- : Request(s, d, SQLUTILGC), id(i), chan(NULL)
- {
- }
-
- GetAssocChan& S()
- {
- Send();
- return *this;
- }
-};
-
-#endif
diff --git a/src/modules/extra/m_sqlv2.h b/src/modules/extra/m_sqlv2.h
deleted file mode 100644
index a9297bd80..000000000
--- a/src/modules/extra/m_sqlv2.h
+++ /dev/null
@@ -1,606 +0,0 @@
-/* +------------------------------------+
- * | Inspire Internet Relay Chat Daemon |
- * +------------------------------------+
- *
- * InspIRCd: (C) 2002-2009 InspIRCd Development Team
- * See: http://wiki.inspircd.org/Credits
- *
- * This program is free but copyrighted software; see
- * the file COPYING for details.
- *
- * ---------------------------------------------------
- */
-
-#ifndef INSPIRCD_SQLAPI_2
-#define INSPIRCD_SQLAPI_2
-
-#include <string>
-#include <deque>
-#include <map>
-#include "modules.h"
-
-/** Identifiers used to identify Request types
- */
-#define SQLREQID "SQLv2 Request"
-#define SQLRESID "SQLv2 Result"
-#define SQLSUCCESS "You shouldn't be reading this (success)"
-
-/** Defines the error types which SQLerror may be set to
- */
-enum SQLerrorNum { SQL_NO_ERROR, SQL_BAD_DBID, SQL_BAD_CONN, SQL_QSEND_FAIL, SQL_QREPLY_FAIL };
-
-/** A list of format parameters for an SQLquery object.
- */
-typedef std::deque<std::string> ParamL;
-
-/** The base class of SQL exceptions
- */
-class SQLexception : public ModuleException
-{
- public:
- SQLexception(const std::string &reason) : ModuleException(reason)
- {
- }
-
- SQLexception() : ModuleException("SQLv2: Undefined exception")
- {
- }
-};
-
-/** An exception thrown when a bad column or row name or id is requested
- */
-class SQLbadColName : public SQLexception
-{
-public:
- SQLbadColName() : SQLexception("SQLv2: Bad column name")
- {
- }
-};
-
-/** SQLerror holds the error state of any SQLrequest or SQLresult.
- * The error string varies from database software to database software
- * and should be used to display informational error messages to users.
- */
-class SQLerror : public classbase
-{
- /** The error id
- */
- SQLerrorNum id;
- /** The error string
- */
- std::string str;
-public:
- /** Initialize an SQLerror
- * @param i The error ID to set
- * @param s The (optional) error string to set
- */
- SQLerror(SQLerrorNum i = SQL_NO_ERROR, const std::string &s = "")
- : id(i), str(s)
- {
- }
-
- /** Return the ID of the error
- */
- SQLerrorNum Id()
- {
- return id;
- }
-
- /** Set the ID of an error
- * @param i The new error ID to set
- * @return the ID which was set
- */
- SQLerrorNum Id(SQLerrorNum i)
- {
- id = i;
- return id;
- }
-
- /** Set the error string for an error
- * @param s The new error string to set
- */
- void Str(const std::string &s)
- {
- str = s;
- }
-
- /** Return the error string for an error
- */
- const char* Str()
- {
- if(str.length())
- return str.c_str();
-
- switch(id)
- {
- case SQL_NO_ERROR:
- return "No error";
- case SQL_BAD_DBID:
- return "Invalid database ID";
- case SQL_BAD_CONN:
- return "Invalid connection";
- case SQL_QSEND_FAIL:
- return "Sending query failed";
- case SQL_QREPLY_FAIL:
- return "Getting query result failed";
- default:
- return "Unknown error";
- }
- }
-};
-
-/** SQLquery provides a way to represent a query string, and its parameters in a type-safe way.
- * C++ has no native type-safe way of having a variable number of arguments to a function,
- * the workaround for this isn't easy to describe simply, but in a nutshell what's really
- * happening when - from the above example - you do this:
- *
- * SQLrequest foo = SQLrequest(this, target, "databaseid", SQLquery("SELECT (foo, bar) FROM rawr WHERE foo = '?' AND bar = ?", "Hello", "42"));
- *
- * what's actually happening is functionally this:
- *
- * SQLrequest foo = SQLrequest(this, target, "databaseid", query("SELECT (foo, bar) FROM rawr WHERE foo = '?' AND bar = ?").addparam("Hello").addparam("42"));
- *
- * with 'query()' returning a reference to an object with a 'addparam()' member function which
- * in turn returns a reference to that object. There are actually four ways you can create a
- * SQLrequest..all have their disadvantages and advantages. In the real implementations the
- * 'query()' function is replaced by the constructor of another class 'SQLquery' which holds
- * the query string and a ParamL (std::deque<std::string>) of query parameters.
- * This is essentially the same as the above example except 'addparam()' is replaced by operator,(). The full syntax for this method is:
- *
- * SQLrequest foo = SQLrequest(this, target, "databaseid", (SQLquery("SELECT.. ?"), parameter, parameter));
- */
-class SQLquery : public classbase
-{
-public:
- /** The query 'format string'
- */
- std::string q;
- /** The query parameter list
- * There should be one parameter for every ? character
- * within the format string shown above.
- */
- ParamL p;
-
- /** Initialize an SQLquery with a given format string only
- */
- SQLquery(const std::string &query)
- : q(query)
- {
- }
-
- /** Initialize an SQLquery with a format string and parameters.
- * If you provide parameters, you must initialize the list yourself
- * if you choose to do it via this method, using std::deque::push_back().
- */
- SQLquery(const std::string &query, const ParamL &params)
- : q(query), p(params)
- {
- }
-
- /** An overloaded operator for pushing parameters onto the parameter list
- */
- template<typename T> SQLquery& operator,(const T &foo)
- {
- p.push_back(ConvToStr(foo));
- return *this;
- }
-
- /** An overloaded operator for pushing parameters onto the parameter list.
- * This has higher precedence than 'operator,' and can save on parenthesis.
- */
- template<typename T> SQLquery& operator%(const T &foo)
- {
- p.push_back(ConvToStr(foo));
- return *this;
- }
-};
-
-/** SQLrequest is sent to the SQL API to command it to run a query and return the result.
- * You must instantiate this object with a valid SQLquery object and its parameters, then
- * send it using its Send() method to the module providing the 'SQL' feature. To find this
- * module, use Server::FindFeature().
- */
-class SQLrequest : public Request
-{
-public:
- /** The fully parsed and expanded query string
- * This is initialized from the SQLquery parameter given in the constructor.
- */
- SQLquery query;
- /** The database ID to apply the request to
- */
- std::string dbid;
- /** True if this is a priority query.
- * Priority queries may 'queue jump' in the request queue.
- */
- bool pri;
- /** The query ID, assigned by the SQL api.
- * After your request is processed, this will
- * be initialized for you by the API to a valid request ID,
- * except in the case of an error.
- */
- unsigned long id;
- /** If an error occured, error.id will be any other value than SQL_NO_ERROR.
- */
- SQLerror error;
-
- /** Initialize an SQLrequest.
- * For example:
- *
- * SQLrequest req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_actors VALUES('','?')" % nick));
- *
- * @param s A pointer to the sending module, where the result should be routed
- * @param d A pointer to the receiving module, identified as implementing the 'SQL' feature
- * @param databaseid The database ID to perform the query on. This must match a valid
- * database ID from the configuration of the SQL module.
- * @param q A properly initialized SQLquery object.
- */
- SQLrequest(Module* s, Module* d, const std::string &databaseid, const SQLquery &q)
- : Request(s, d, SQLREQID), query(q), dbid(databaseid), pri(false), id(0)
- {
- }
-
- /** Set the priority of a request.
- */
- void Priority(bool p = true)
- {
- pri = p;
- }
-
- /** Set the source of a request. You should not need to use this method.
- */
- void SetSource(Module* mod)
- {
- source = mod;
- }
-};
-
-/**
- * This class contains a field's data plus a way to determine if the field
- * is NULL or not without having to mess around with NULL pointers.
- */
-class SQLfield
-{
-public:
- /**
- * The data itself
- */
- std::string d;
-
- /**
- * If the field was null
- */
- bool null;
-
- /** Initialize an SQLfield
- */
- SQLfield(const std::string &data = "", bool n = false)
- : d(data), null(n)
- {
-
- }
-};
-
-/** A list of items which make up a row of a result or table (tuple)
- * This does not include field names.
- */
-typedef std::vector<SQLfield> SQLfieldList;
-/** A list of items which make up a row of a result or table (tuple)
- * This also includes the field names.
- */
-typedef std::map<std::string, SQLfield> SQLfieldMap;
-
-/** SQLresult is a reply to a previous query.
- * If you send a query to the SQL api, the response will arrive at your
- * OnRequest method of your module at some later time, depending on the
- * congestion of the SQL server and complexity of the query. The ID of
- * this result will match the ID assigned to your original request.
- * SQLresult contains its own internal cursor (row counter) which is
- * incremented with each method call which retrieves a single row.
- */
-class SQLresult : public Request
-{
-public:
- /** The original query string passed initially to the SQL API
- */
- std::string query;
- /** The database ID the query was executed on
- */
- std::string dbid;
- /**
- * The error (if any) which occured.
- * If an error occured the value of error.id will be any
- * other value than SQL_NO_ERROR.
- */
- SQLerror error;
- /**
- * This will match query ID you were given when sending
- * the request at an earlier time.
- */
- unsigned long id;
-
- /** Used by the SQL API to instantiate an SQLrequest
- */
- SQLresult(Module* s, Module* d, unsigned long i)
- : Request(s, d, SQLRESID), id(i)
- {
- }
-
- /**
- * Return the number of rows in the result
- * Note that if you have perfomed an INSERT
- * or UPDATE query or other query which will
- * not return rows, this will return the
- * number of affected rows, and SQLresult::Cols()
- * will contain 0. In this case you SHOULD NEVER
- * access any of the result set rows, as there arent any!
- * @returns Number of rows in the result set.
- */
- virtual int Rows() = 0;
-
- /**
- * Return the number of columns in the result.
- * If you performed an UPDATE or INSERT which
- * does not return a dataset, this value will
- * be 0.
- * @returns Number of columns in the result set.
- */
- virtual int Cols() = 0;
-
- /**
- * Get a string name of the column by an index number
- * @param column The id number of a column
- * @returns The column name associated with the given ID
- */
- virtual std::string ColName(int column) = 0;
-
- /**
- * Get an index number for a column from a string name.
- * An exception of type SQLbadColName will be thrown if
- * the name given is invalid.
- * @param column The column name to get the ID of
- * @returns The ID number of the column provided
- */
- virtual int ColNum(const std::string &column) = 0;
-
- /**
- * Get a string value in a given row and column
- * This does not effect the internal cursor.
- * @returns The value stored at [row,column] in the table
- */
- virtual SQLfield GetValue(int row, int column) = 0;
-
- /**
- * Return a list of values in a row, this should
- * increment an internal counter so you can repeatedly
- * call it until it returns an empty vector.
- * This returns a reference to an internal object,
- * the same object is used for all calls to this function
- * and therefore the return value is only valid until
- * you call this function again. It is also invalid if
- * the SQLresult object is destroyed.
- * The internal cursor (row counter) is incremented by one.
- * @returns A reference to the current row's SQLfieldList
- */
- virtual SQLfieldList& GetRow() = 0;
-
- /**
- * As above, but return a map indexed by key name.
- * The internal cursor (row counter) is incremented by one.
- * @returns A reference to the current row's SQLfieldMap
- */
- virtual SQLfieldMap& GetRowMap() = 0;
-
- /**
- * Like GetRow(), but returns a pointer to a dynamically
- * allocated object which must be explicitly freed. For
- * portability reasons this must be freed with SQLresult::Free()
- * The internal cursor (row counter) is incremented by one.
- * @returns A newly-allocated SQLfieldList
- */
- virtual SQLfieldList* GetRowPtr() = 0;
-
- /**
- * As above, but return a map indexed by key name
- * The internal cursor (row counter) is incremented by one.
- * @returns A newly-allocated SQLfieldMap
- */
- virtual SQLfieldMap* GetRowMapPtr() = 0;
-
- /**
- * Overloaded function for freeing the lists and maps
- * returned by GetRowPtr or GetRowMapPtr.
- * @param fm The SQLfieldMap to free
- */
- virtual void Free(SQLfieldMap* fm) = 0;
-
- /**
- * Overloaded function for freeing the lists and maps
- * returned by GetRowPtr or GetRowMapPtr.
- * @param fl The SQLfieldList to free
- */
- virtual void Free(SQLfieldList* fl) = 0;
-};
-
-
-/** SQLHost represents a <database> config line and is useful
- * for storing in a map and iterating on rehash to see which
- * <database> tags was added/removed/unchanged.
- */
-class SQLhost
-{
- public:
- std::string id; /* Database handle id */
- std::string host; /* Database server hostname */
- std::string ip; /* resolved IP, needed for at least pgsql.so */
- unsigned int port; /* Database server port */
- std::string name; /* Database name */
- std::string user; /* Database username */
- std::string pass; /* Database password */
- bool ssl; /* If we should require SSL */
-
- SQLhost()
- : id(""), host(""), ip(""), port(0), name(""), user(""), pass(""), ssl(0)
- {
- }
-
- SQLhost(const std::string& i, const std::string& h, unsigned int p, const std::string& n, const std::string& u, const std::string& pa, bool s)
- : id(i), host(h), ip(""), port(p), name(n), user(u), pass(pa), ssl(s)
- {
- }
-
- /** Overload this to return a correct Data source Name (DSN) for
- * the current SQL module.
- */
- std::string GetDSN();
-};
-
-/** Overload operator== for two SQLhost objects for easy comparison.
- */
-bool operator== (const SQLhost& l, const SQLhost& r)
-{
- return (l.id == r.id && l.host == r.host && l.port == r.port && l.name == r.name && l.user == r.user && l.pass == r.pass && l.ssl == r.ssl);
-}
-/** Overload operator!= for two SQLhost objects for easy comparison.
- */
-bool operator!= (const SQLhost& l, const SQLhost& r)
-{
- return (l.id != r.id || l.host != r.host || l.port != r.port || l.name != r.name || l.user != r.user || l.pass != r.pass || l.ssl != r.ssl);
-}
-
-
-/** QueryQueue, a queue of queries waiting to be executed.
- * This maintains two queues internally, one for 'priority'
- * queries and one for less important ones. Each queue has
- * new queries appended to it and ones to execute are popped
- * off the front. This keeps them flowing round nicely and no
- * query should ever get 'stuck' for too long. If there are
- * queries in the priority queue they will be executed first,
- * 'unimportant' queries will only be executed when the
- * priority queue is empty.
- *
- * We store lists of SQLrequest's here, by value as we want to avoid storing
- * any data allocated inside the client module (in case that module is unloaded
- * while the query is in progress).
- *
- * Because we want to work on the current SQLrequest in-situ, we need a way
- * of accessing the request we are currently processing, QueryQueue::front(),
- * but that call needs to always return the same request until that request
- * is removed from the queue, this is what the 'which' variable is. New queries are
- * always added to the back of one of the two queues, but if when front()
- * is first called then the priority queue is empty then front() will return
- * a query from the normal queue, but if a query is then added to the priority
- * queue then front() must continue to return the front of the *normal* queue
- * until pop() is called.
- */
-
-class QueryQueue : public classbase
-{
-private:
- typedef std::deque<SQLrequest> ReqDeque;
-
- ReqDeque priority; /* The priority queue */
- ReqDeque normal; /* The 'normal' queue */
- enum { PRI, NOR, NON } which; /* Which queue the currently active element is at the front of */
-
-public:
- QueryQueue()
- : which(NON)
- {
- }
-
- void push(const SQLrequest &q)
- {
- if(q.pri)
- priority.push_back(q);
- else
- normal.push_back(q);
- }
-
- void pop()
- {
- if((which == PRI) && priority.size())
- {
- priority.pop_front();
- }
- else if((which == NOR) && normal.size())
- {
- normal.pop_front();
- }
-
- /* Reset this */
- which = NON;
-
- /* Silently do nothing if there was no element to pop() */
- }
-
- SQLrequest& front()
- {
- switch(which)
- {
- case PRI:
- return priority.front();
- case NOR:
- return normal.front();
- default:
- if(priority.size())
- {
- which = PRI;
- return priority.front();
- }
-
- if(normal.size())
- {
- which = NOR;
- return normal.front();
- }
-
- /* This will probably result in a segfault,
- * but the caller should have checked totalsize()
- * first so..meh - moron :p
- */
-
- return priority.front();
- }
- }
-
- std::pair<int, int> size()
- {
- return std::make_pair(priority.size(), normal.size());
- }
-
- int totalsize()
- {
- return priority.size() + normal.size();
- }
-
- void PurgeModule(Module* mod)
- {
- DoPurgeModule(mod, priority);
- DoPurgeModule(mod, normal);
- }
-
-private:
- void DoPurgeModule(Module* mod, ReqDeque& q)
- {
- for(ReqDeque::iterator iter = q.begin(); iter != q.end(); iter++)
- {
- if(iter->GetSource() == mod)
- {
- if(iter->id == front().id)
- {
- /* It's the currently active query.. :x */
- iter->SetSource(NULL);
- }
- else
- {
- /* It hasn't been executed yet..just remove it */
- iter = q.erase(iter);
- }
- }
- }
- }
-};
-
-
-#endif