diff options
author | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-28 22:25:43 +0000 |
---|---|---|
committer | danieldg <danieldg@e03df62e-2008-0410-955e-edbf42e46eb7> | 2009-09-28 22:25:43 +0000 |
commit | 83454575bcdc969e73fb9026dc3533dfb22c27a2 (patch) | |
tree | bc9550713de94aec291b83e4bfb33f32a3519268 /src/modules/extra | |
parent | 5e1d239f3d94bd1afd3ce64c2f47a64305f1e1f0 (diff) |
Fix compilation of some extras modules
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@11776 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/modules/extra')
-rw-r--r-- | src/modules/extra/m_ldapauth.cpp | 32 | ||||
-rw-r--r-- | src/modules/extra/m_sqlauth.cpp | 210 | ||||
-rw-r--r-- | src/modules/extra/m_sqllog.cpp | 306 | ||||
-rw-r--r-- | src/modules/extra/m_sqloper.cpp | 332 | ||||
-rw-r--r-- | src/modules/extra/m_sqlutils.cpp | 230 | ||||
-rw-r--r-- | src/modules/extra/m_sqlutils.h | 143 | ||||
-rw-r--r-- | src/modules/extra/m_sqlv2.h | 606 |
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> ¶meters, 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> ¶meters, 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 ¶ms) - : 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 |