The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

m_sqllog.cpp

Go to the documentation of this file.
00001 /*       +------------------------------------+
00002  *       | Inspire Internet Relay Chat Daemon |
00003  *       +------------------------------------+
00004  *
00005  *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
00006  * See: http://www.inspircd.org/wiki/index.php/Credits
00007  *
00008  * This program is free but copyrighted software; see
00009  *            the file COPYING for details.
00010  *
00011  * ---------------------------------------------------
00012  */
00013 
00014 #include "inspircd.h"
00015 #include "m_sqlv2.h"
00016 
00017 static Module* SQLModule;
00018 static Module* MyMod;
00019 static std::string dbid;
00020 
00021 enum LogTypes { LT_OPER = 1, LT_KILL, LT_SERVLINK, LT_XLINE, LT_CONNECT, LT_DISCONNECT, LT_FLOOD, LT_LOADMODULE };
00022 
00023 enum QueryState { FIND_SOURCE, FIND_NICK, FIND_HOST, DONE};
00024 
00025 class QueryInfo;
00026 
00027 std::map<unsigned long,QueryInfo*> active_queries;
00028 
00029 class QueryInfo
00030 {
00031 private:
00032         InspIRCd* ServerInstance;
00033 public:
00034         QueryState qs;
00035         unsigned long id;
00036         std::string nick;
00037         std::string source;
00038         std::string hostname;
00039         int sourceid;
00040         int nickid;
00041         int hostid;
00042         int category;
00043         time_t date;
00044         bool insert;
00045 
00046         QueryInfo(InspIRCd* Instance, const std::string &n, const std::string &s, const std::string &h, unsigned long i, int cat)
00047         {
00048                 ServerInstance = Instance;
00049                 qs = FIND_SOURCE;
00050                 nick = n;
00051                 source = s;
00052                 hostname = h;
00053                 id = i;
00054                 category = cat;
00055                 sourceid = nickid = hostid = -1;
00056                 date = ServerInstance->Time();
00057                 insert = false;
00058         }
00059 
00060         void Go(SQLresult* res)
00061         {
00062                 SQLrequest req = SQLrequest(MyMod, SQLModule, dbid, SQLquery(""));
00063                 switch (qs)
00064                 {
00065                         case FIND_SOURCE:
00066                                 if (res->Rows() && sourceid == -1 && !insert)
00067                                 {
00068                                         sourceid = atoi(res->GetValue(0,0).d.c_str());
00069                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % nick);
00070                                         if(req.Send())
00071                                         {
00072                                                 insert = false;
00073                                                 qs = FIND_NICK;
00074                                                 active_queries[req.id] = this;
00075                                         }
00076                                 }
00077                                 else if (res->Rows() && sourceid == -1 && insert)
00078                                 {
00079                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % source);
00080                                         if(req.Send())
00081                                         {
00082                                                 insert = false;
00083                                                 qs = FIND_SOURCE;
00084                                                 active_queries[req.id] = this;
00085                                         }
00086                                 }
00087                                 else
00088                                 {
00089                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_actors (actor) VALUES('?')") % source);
00090                                         if(req.Send())
00091                                         {
00092                                                 insert = true;
00093                                                 qs = FIND_SOURCE;
00094                                                 active_queries[req.id] = this;
00095                                         }
00096                                 }
00097                         break;
00098 
00099                         case FIND_NICK:
00100                                 if (res->Rows() && nickid == -1 && !insert)
00101                                 {
00102                                         nickid = atoi(res->GetValue(0,0).d.c_str());
00103                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'") % hostname);
00104                                         if(req.Send())
00105                                         {
00106                                                 insert = false;
00107                                                 qs = FIND_HOST;
00108                                                 active_queries[req.id] = this;
00109                                         }
00110                                 }
00111                                 else if (res->Rows() && nickid == -1 && insert)
00112                                 {
00113                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % nick);
00114                                         if(req.Send())
00115                                         {
00116                                                 insert = false;
00117                                                 qs = FIND_NICK;
00118                                                 active_queries[req.id] = this;
00119                                         }
00120                                 }
00121                                 else
00122                                 {
00123                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_actors (actor) VALUES('?')") % nick);
00124                                         if(req.Send())
00125                                         {
00126                                                 insert = true;
00127                                                 qs = FIND_NICK;
00128                                                 active_queries[req.id] = this;
00129                                         }
00130                                 }
00131                         break;
00132 
00133                         case FIND_HOST:
00134                                 if (res->Rows() && hostid == -1 && !insert)
00135                                 {
00136                                         hostid = atoi(res->GetValue(0,0).d.c_str());
00137                                         req = SQLrequest(MyMod, SQLModule, dbid,
00138                                                         SQLquery("INSERT INTO ircd_log (category_id,nick,host,source,dtime) VALUES('?','?','?','?','?')") % category % nickid % hostid % sourceid % date);
00139                                         if(req.Send())
00140                                         {
00141                                                 insert = true;
00142                                                 qs = DONE;
00143                                                 active_queries[req.id] = this;
00144                                         }
00145                                 }
00146                                 else if (res->Rows() && hostid == -1 && insert)
00147                                 {
00148                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'") % hostname);
00149                                         if(req.Send())
00150                                         {
00151                                                 insert = false;
00152                                                 qs = FIND_HOST;
00153                                                 active_queries[req.id] = this;
00154                                         }
00155                                 }
00156                                 else
00157                                 {
00158                                         req = SQLrequest(MyMod, SQLModule, dbid, SQLquery("INSERT INTO ircd_log_hosts (hostname) VALUES('?')") % hostname);
00159                                         if(req.Send())
00160                                         {
00161                                                 insert = true;
00162                                                 qs = FIND_HOST;
00163                                                 active_queries[req.id] = this;
00164                                         }
00165                                 }
00166                         break;
00167 
00168                         case DONE:
00169                                 std::map<unsigned long,QueryInfo*>::iterator x = active_queries.find(req.id);
00170                                 if (x != active_queries.end())
00171                                 {
00172                                         delete x->second;
00173                                         active_queries.erase(x);
00174                                 }
00175                         break;
00176                 }
00177         }
00178 };
00179 
00180 /* $ModDesc: Logs network-wide data to an SQL database */
00181 
00182 class ModuleSQLLog : public Module
00183 {
00184 
00185  public:
00186         ModuleSQLLog(InspIRCd* Me)
00187         : Module(Me)
00188         {
00189                 ServerInstance->Modules->UseInterface("SQLutils");
00190                 ServerInstance->Modules->UseInterface("SQL");
00191 
00192                 Module* SQLutils = ServerInstance->Modules->Find("m_sqlutils.so");
00193                 if (!SQLutils)
00194                         throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so.");
00195 
00196                 SQLModule = ServerInstance->Modules->FindFeature("SQL");
00197 
00198                 OnRehash(NULL,"");
00199                 MyMod = this;
00200                 active_queries.clear();
00201 
00202                 Implementation eventlist[] = { I_OnRehash, I_OnOper, I_OnGlobalOper, I_OnKill,
00203                         I_OnPreCommand, I_OnUserConnect, I_OnUserQuit, I_OnLoadModule, I_OnRequest };
00204                 ServerInstance->Modules->Attach(eventlist, this, 9);
00205         }
00206 
00207         virtual ~ModuleSQLLog()
00208         {
00209                 ServerInstance->Modules->DoneWithInterface("SQL");
00210                 ServerInstance->Modules->DoneWithInterface("SQLutils");
00211         }
00212 
00213 
00214         void ReadConfig()
00215         {
00216                 ConfigReader Conf(ServerInstance);
00217                 dbid = Conf.ReadValue("sqllog","dbid",0);       // database id of a database configured in sql module
00218         }
00219 
00220         virtual void OnRehash(User* user, const std::string &parameter)
00221         {
00222                 ReadConfig();
00223         }
00224 
00225         virtual const char* OnRequest(Request* request)
00226         {
00227                 if(strcmp(SQLRESID, request->GetId()) == 0)
00228                 {
00229                         SQLresult* res;
00230                         std::map<unsigned long, QueryInfo*>::iterator n;
00231 
00232                         res = static_cast<SQLresult*>(request);
00233                         n = active_queries.find(res->id);
00234 
00235                         if (n != active_queries.end())
00236                         {
00237                                 n->second->Go(res);
00238                                 active_queries.erase(n);
00239                         }
00240 
00241                         return SQLSUCCESS;
00242                 }
00243 
00244                 return NULL;
00245         }
00246 
00247         void AddLogEntry(int category, const std::string &nick, const std::string &host, const std::string &source)
00248         {
00249                 // is the sql module loaded? If not, we don't attempt to do anything.
00250                 if (!SQLModule)
00251                         return;
00252 
00253                 SQLrequest req = SQLrequest(this, SQLModule, dbid, SQLquery("SELECT id,actor FROM ircd_log_actors WHERE actor='?'") % source);
00254                 if(req.Send())
00255                 {
00256                         QueryInfo* i = new QueryInfo(ServerInstance, nick, source, host, req.id, category);
00257                         i->qs = FIND_SOURCE;
00258                         active_queries[req.id] = i;
00259                 }
00260         }
00261 
00262         virtual void OnOper(User* user, const std::string &opertype)
00263         {
00264                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
00265         }
00266 
00267         virtual void OnGlobalOper(User* user)
00268         {
00269                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
00270         }
00271 
00272         virtual int OnKill(User* source, User* dest, const std::string &reason)
00273         {
00274                 AddLogEntry(LT_KILL,dest->nick,dest->host,source->nick);
00275                 return 0;
00276         }
00277 
00278         virtual int OnPreCommand(std::string &command, std::vector<std::string> &parameters, User *user, bool validated, const std::string &original_line)
00279         {
00280                 if ((command == "GLINE" || command == "KLINE" || command == "ELINE" || command == "ZLINE") && validated)
00281                 {
00282                         AddLogEntry(LT_XLINE,user->nick,command[0]+std::string(":")+parameters[0],user->server);
00283                 }
00284                 return 0;
00285         }
00286 
00287         virtual void OnUserConnect(User* user)
00288         {
00289                 AddLogEntry(LT_CONNECT,user->nick,user->host,user->server);
00290         }
00291 
00292         virtual void OnUserQuit(User* user, const std::string &reason, const std::string &oper_message)
00293         {
00294                 AddLogEntry(LT_DISCONNECT,user->nick,user->host,user->server);
00295         }
00296 
00297         virtual void OnLoadModule(Module* mod, const std::string &name)
00298         {
00299                 AddLogEntry(LT_LOADMODULE,name,ServerInstance->Config->ServerName, ServerInstance->Config->ServerName);
00300         }
00301 
00302         virtual Version GetVersion()
00303         {
00304                 return Version("$Id: m_sqllog.cpp 10783 2008-11-01 23:02:23Z w00t $", VF_VENDOR, API_VERSION);
00305         }
00306 
00307 };
00308 
00309 MODULE_INIT(ModuleSQLLog)