]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqllog.cpp
Remove OnPostConnect here, it was being used under the assumption that it still did...
[user/henk/code/inspircd.git] / src / modules / extra / m_sqllog.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                     E-mail:
7  *              <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *          the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "users.h"
18 #include "channels.h"
19 #include "modules.h"
20 #include "configreader.h"
21 #include "inspircd.h"
22 #include "m_sqlv2.h"
23
24
25 static Module* SQLModule;
26 static Module* MyMod;
27 static std::string dbid;
28
29 enum LogTypes { LT_OPER = 1, LT_KILL, LT_SERVLINK, LT_XLINE, LT_CONNECT, LT_DISCONNECT, LT_FLOOD, LT_LOADMODULE };
30
31 enum QueryState { FIND_SOURCE, INSERT_SOURCE, FIND_NICK, INSERT_NICK, FIND_HOST, INSERT_HOST, INSERT_LOGENTRY, DONE };
32
33 class QueryInfo;
34
35 std::map<unsigned long,QueryInfo*> active_queries;
36
37 class QueryInfo
38 {
39  public:
40         QueryState qs;
41         unsigned long id;
42         std::string nick;
43         std::string hostname;
44         int sourceid;
45         int nickid;
46         int hostid;
47         int category;
48         time_t date;
49         std::string lastquery;
50
51         QueryInfo(const std::string &n, const std::string &h, unsigned long i, int cat)
52         {
53                 qs = FIND_SOURCE;
54                 nick = n;
55                 hostname = h;
56                 id = i;
57                 category = cat;
58                 sourceid = nickid = hostid = -1;
59                 date = time(NULL);
60                 lastquery = "";
61         }
62
63         void Go(SQLresult* res)
64         {
65                 // Nothing here and not sent yet
66                 SQLrequest req = SQLreq(MyMod, SQLModule, dbid, "", "");
67
68                 switch (qs)
69                 {
70                         case FIND_SOURCE:
71                                 // "SELECT id,actor FROM ircd_log_actors WHERE actor='"+nick+"'"
72                                 // If we find it, advance to FIND_NICK state, otherwise go to INSERT_SOURCE
73                                 if (res->Cols())
74                                 {
75                                         if (sourceid == -1)
76                                         {
77                                                 sourceid = atoi(res->GetValue(0,0).d.c_str());
78                                                 qs = FIND_NICK;
79                                         }
80                                         else qs = INSERT_SOURCE;
81                                 }
82                                 else
83                                 {
84                                         if (lastquery == "SELECT id,actor FROM ircd_log_actors WHERE actor='?'")
85                                         {
86                                                 qs = INSERT_SOURCE;
87                                         }
88                                         else
89                                         {
90                                                 lastquery = "SELECT id,actor FROM ircd_log_actors WHERE actor='?'";
91                                                 req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
92                                                 if(req.Send())
93                                                 {
94                                                         qs = FIND_SOURCE;
95                                                         active_queries[req.id] = this;
96                                                 }
97                                                 else
98                                                 {
99                                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
100                                                 }
101                                                 break;
102                                         }
103                                 }
104                         case INSERT_SOURCE:
105                                 // "INSERT INTO ircd_log_actors VALUES('','"+nick+"')")
106                                 // after we've done this, go back to FIND_SOURCE
107                                 lastquery = "INSERT INTO ircd_log_actors VALUES('','?')";
108                                 req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors VALUES('','?')", nick);
109                                 if(req.Send())
110                                 {
111                                         qs = FIND_NICK;
112                                         active_queries[req.id] = this;
113                                 }
114                                 else
115                                 {
116                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
117                                 }
118                                 
119                         break;
120                         case FIND_NICK:
121                                 // "SELECT id,actor FROM ircd_log_actors WHERE actor='"+nick+"'"
122                                 // If we find it, advance to FIND_HOST state, otherwise go to INSERT_NICK
123                                 if (res->Cols())
124                                 {
125                                         if (nickid == -1)
126                                         {
127                                                 nickid = atoi(res->GetValue(0,0).d.c_str());
128                                                 qs = FIND_HOST;
129                                         }
130                                         else qs = INSERT_NICK;
131                                 }
132                                 else
133                                 {
134                                         if (lastquery == "SELECT id,actor FROM ircd_log_actors WHERE actor='?'")
135                                         {
136                                                 qs = INSERT_NICK;
137                                         }
138                                         else
139                                         {
140                                                 req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
141                                                 if(req.Send())
142                                                 {
143                                                         qs = FIND_NICK;
144                                                         active_queries[req.id] = this;
145                                                 }
146                                                 else
147                                                 {
148                                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
149                                                 }
150                                                 break;
151                                         }
152                                 }
153                         case INSERT_NICK:
154                                 // "INSERT INTO ircd_log_actors VALUES('','"+nick+"')")
155                                 // after we've done this, go back to FIND_NICK
156                                 req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors VALUES('','?')",nick);
157                                 if(req.Send())
158                                 {
159                                         qs = FIND_HOST;
160                                         active_queries[req.id] = this;
161                                 }
162                                 else
163                                 {
164                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
165                                 }
166                         break;
167                         case FIND_HOST:
168                                 // "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='"+host+"'"
169                                 // If we find it, advance to INSERT_LOGENTRY state, otherwise go to INSERT_HOST
170                                 if (res->Cols())
171                                 {
172                                         if (hostid == -1)
173                                         {
174                                                 hostid = atoi(res->GetValue(0,0).d.c_str());
175                                                 qs = INSERT_LOGENTRY;
176                                         }
177                                         else qs = INSERT_HOST;
178                                 }
179                                 else
180                                 {
181                                         if (lastquery == "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'")
182                                         {
183                                                 qs = INSERT_HOST;
184                                         }
185                                         else
186                                         {
187                                                 lastquery = "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'";
188                                                 req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'",hostname);
189                                                 if(req.Send())
190                                                 {
191                                                         qs = FIND_HOST;
192                                                         active_queries[req.id] = this;
193                                                 }
194                                                 else
195                                                 {
196                                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
197                                                 }
198                                                 break;
199                                         }
200                                 }
201                         case INSERT_HOST:
202                                 // "INSERT INTO ircd_log_hosts VALUES('','"+host+"')"
203                                 // after we've done this, go back to FIND_HOST
204                                 lastquery = "INSERT INTO ircd_log_hosts VALUES('','?')";
205                                 req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_hosts VALUES('','?')", hostname);
206                                 if(req.Send())
207                                 {
208                                         qs = INSERT_LOGENTRY;
209                                         active_queries[req.id] = this;
210                                 }
211                                 else
212                                 {
213                                         //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
214                                 }
215                         break;
216                         case INSERT_LOGENTRY:
217                                 // INSERT INTO ircd_log VALUES('',%lu,%lu,%lu,%lu,%lu)",(unsigned long)category,(unsigned long)nickid,(unsigned long)hostid,(unsigned long)sourceid,(unsigned long)date
218                                 // aaand done! (discard result)
219                                 if ((nickid == -1) || (hostid == -1) || (sourceid == -1))
220                                 {
221                                         qs = FIND_SOURCE;
222                                         this->Go(res);
223                                 }
224                                 else
225                                 {
226                                         lastquery = "INSERT INTO ircd_log VALUES()";
227                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log VALUES('',"+ConvToStr(category)+","+ConvToStr(nickid)+","+ConvToStr(hostid)+","+ConvToStr(sourceid)+","+ConvToStr(date)+")");
228                                                         /*,category,
229                                                         nickid,
230                                                         hostid,
231                                                         sourceid,
232                                                         date);*/
233                                         if(req.Send())
234                                         {
235                                                 qs = DONE;
236                                         }
237                                         else
238                                         {
239                                                 //ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
240                                         }
241                                 }
242                         break;
243                         case DONE:
244                                 active_queries[req.id] = NULL;
245                         break;
246                 }
247         }
248 };
249
250 /* $ModDesc: Logs network-wide data to an SQL database */
251
252 class ModuleSQLLog : public Module
253 {
254         InspIRCd* Srv;
255         ConfigReader* Conf;
256
257  public:
258         bool ReadConfig()
259         {
260                 ConfigReader Conf(Srv);
261                 
262                 dbid = Conf.ReadValue("sqllog","dbid",0);       // database id of a database configured in sql module
263                 
264                 SQLModule = Srv->FindFeature("SQL");
265                 if (!SQLModule)
266                         ServerInstance->Log(DEFAULT,"WARNING: m_sqllog.so could not initialize because an SQL module is not loaded. Load the module and rehash your server.");
267                 return (SQLModule);
268         }
269
270         ModuleSQLLog(InspIRCd* Me)
271         : Module::Module(Me), Srv(Me)
272         {
273                 ReadConfig();
274                 MyMod = this;
275                 active_queries.clear();
276         }
277
278         void Implements(char* List)
279         {
280                 List[I_OnRehash] = List[I_OnOper] = List[I_OnGlobalOper] = List[I_OnKill] = 1;
281                 List[I_OnPreCommand] = List[I_OnUserConnect] = 1;
282                 List[I_OnUserQuit] = List[I_OnLoadModule] = List[I_OnRequest] = 1;
283         }
284
285         virtual void OnRehash(const std::string &parameter)
286         {
287                 ReadConfig();
288         }
289
290         virtual char* OnRequest(Request* request)
291         {
292                 ServerInstance->Log(DEBUG,"OnRequest in m_sqllog.so");
293                 if(strcmp(SQLRESID, request->GetId()) == 0)
294                 {
295                         SQLresult* res;
296                         std::map<unsigned long, QueryInfo*>::iterator n;
297
298                         res = static_cast<SQLresult*>(request);
299                         ServerInstance->Log(DEBUG, "Got SQL result (%s) with ID %lu", res->GetId(), res->id);
300
301                         n = active_queries.find(res->id);
302
303                         if (n != active_queries.end())
304                         {
305                                 ServerInstance->Log(DEBUG,"This is an active query");
306                                 n->second->Go(res);
307
308                                 std::map<unsigned long, QueryInfo*>::iterator n = active_queries.find(res->id);
309                                 active_queries.erase(n);
310                         }
311                 }
312                 return SQLSUCCESS;
313         }
314
315         void AddLogEntry(int category, const std::string &nick, const std::string &host, const std::string &source)
316         {
317                 // is the sql module loaded? If not, we don't attempt to do anything.
318                 if (!SQLModule)
319                         return;
320
321                 SQLrequest req = SQLreq(this, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
322                 if(req.Send())
323                 {
324                         QueryInfo* i = new QueryInfo(nick, host, req.id, category);
325                         i->qs = FIND_SOURCE;
326                         active_queries[req.id] = i;
327                         ServerInstance->Log(DEBUG,"Active query id %d",req.id);
328                 }
329                 else
330                 {
331                         ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
332                 }
333
334                 /*long nickid = InsertNick(nick);
335                 long sourceid = InsertNick(source);
336                 long hostid = InsertHost(host);
337                 InsertEntry((unsigned)category,(unsigned)nickid,(unsigned)hostid,(unsigned)sourceid,(unsigned long)time(NULL));*/
338         }
339
340         virtual void OnOper(userrec* user, const std::string &opertype)
341         {
342                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
343         }
344
345         virtual void OnGlobalOper(userrec* user)
346         {
347                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
348         }
349
350         virtual int OnKill(userrec* source, userrec* dest, const std::string &reason)
351         {
352                 AddLogEntry(LT_KILL,dest->nick,dest->host,source->nick);
353                 return 0;
354         }
355
356         virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated)
357         {
358                 if ((command == "GLINE") || (command == "KLINE") || (command == "ELINE") || (command == "ZLINE"))
359                 {
360                         AddLogEntry(LT_XLINE,user->nick,command[0]+std::string(":")+std::string(parameters[0]),user->server);
361                 }
362                 return 0;
363         }
364
365         virtual void OnUserConnect(userrec* user)
366         {
367                 AddLogEntry(LT_CONNECT,user->nick,user->host,user->server);
368         }
369
370         virtual void OnUserQuit(userrec* user, const std::string &reason)
371         {
372                 AddLogEntry(LT_DISCONNECT,user->nick,user->host,user->server);
373         }
374
375         virtual void OnLoadModule(Module* mod, const std::string &name)
376         {
377                 AddLogEntry(LT_LOADMODULE,name,Srv->Config->ServerName, Srv->Config->ServerName);
378         }
379
380         virtual ~ModuleSQLLog()
381         {
382         }
383         
384         virtual Version GetVersion()
385         {
386                 return Version(1,0,0,1,VF_VENDOR);
387         }
388         
389 };
390
391 class ModuleSQLLogFactory : public ModuleFactory
392 {
393  public:
394         ModuleSQLLogFactory()
395         {
396         }
397         
398         ~ModuleSQLLogFactory()
399         {
400         }
401         
402         virtual Module * CreateModule(InspIRCd* Me)
403         {
404                 return new ModuleSQLLog(Me);
405         }
406         
407 };
408
409
410 extern "C" void * init_module( void )
411 {
412         return new ModuleSQLLogFactory;
413 }