]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqllog.cpp
Change this to use our md5 provider rather than MD5() in the query
[user/henk/code/inspircd.git] / src / modules / extra / m_sqllog.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "users.h"
15 #include "channels.h"
16 #include "modules.h"
17 #include "configreader.h"
18 #include "inspircd.h"
19 #include "m_sqlv2.h"
20
21
22 static Module* SQLModule;
23 static Module* MyMod;
24 static std::string dbid;
25
26 enum LogTypes { LT_OPER = 1, LT_KILL, LT_SERVLINK, LT_XLINE, LT_CONNECT, LT_DISCONNECT, LT_FLOOD, LT_LOADMODULE };
27
28 enum QueryState { FIND_SOURCE, FIND_NICK, FIND_HOST, DONE};
29
30 class QueryInfo;
31
32 std::map<unsigned long,QueryInfo*> active_queries;
33
34 class QueryInfo
35 {
36 public:
37         QueryState qs;
38         unsigned long id;
39         std::string nick;
40         std::string source;
41         std::string hostname;
42         int sourceid;
43         int nickid;
44         int hostid;
45         int category;
46         time_t date;
47         bool insert;
48
49         QueryInfo(const std::string &n, const std::string &s, const std::string &h, unsigned long i, int cat)
50         {
51                 qs = FIND_SOURCE;
52                 nick = n;
53                 source = s;
54                 hostname = h;
55                 id = i;
56                 category = cat;
57                 sourceid = nickid = hostid = -1;
58                 date = time(NULL);
59                 insert = false;
60         }
61
62         void Go(SQLresult* res)
63         {
64                 SQLrequest req = SQLreq(MyMod, SQLModule, dbid, "", "");
65                 switch (qs)
66                 {
67                         case FIND_SOURCE:
68                                 if (res->Rows() && sourceid == -1 && !insert)
69                                 {
70                                         sourceid = atoi(res->GetValue(0,0).d.c_str());
71                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
72                                         if(req.Send())
73                                         {
74                                                 insert = false;
75                                                 qs = FIND_NICK;
76                                                 active_queries[req.id] = this;
77                                         }
78                                 }
79                                 else if (res->Rows() && sourceid == -1 && insert)
80                                 {
81                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", source);
82                                         if(req.Send())
83                                         {
84                                                 insert = false;
85                                                 qs = FIND_SOURCE;
86                                                 active_queries[req.id] = this;
87                                         }
88                                 }
89                                 else
90                                 {
91                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors (actor) VALUES('?')", source);
92                                         if(req.Send())
93                                         {
94                                                 insert = true;
95                                                 qs = FIND_SOURCE;
96                                                 active_queries[req.id] = this;
97                                         }
98                                 }
99                         break;
100
101                         case FIND_NICK:
102                                 if (res->Rows() && nickid == -1 && !insert)
103                                 {
104                                         nickid = atoi(res->GetValue(0,0).d.c_str());
105                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'", hostname);
106                                         if(req.Send())
107                                         {
108                                                 insert = false;
109                                                 qs = FIND_HOST;
110                                                 active_queries[req.id] = this;
111                                         }
112                                 }
113                                 else if (res->Rows() && nickid == -1 && insert)
114                                 {
115                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
116                                         if(req.Send())
117                                         {
118                                                 insert = false;
119                                                 qs = FIND_NICK;
120                                                 active_queries[req.id] = this;
121                                         }
122                                 }
123                                 else
124                                 {
125                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors (actor) VALUES('?')",nick);
126                                         if(req.Send())
127                                         {
128                                                 insert = true;
129                                                 qs = FIND_NICK;
130                                                 active_queries[req.id] = this;
131                                         }
132                                 }
133                         break;
134
135                         case FIND_HOST:
136                                 if (res->Rows() && hostid == -1 && !insert)
137                                 {
138                                         hostid = atoi(res->GetValue(0,0).d.c_str());
139                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log (category_id,nick,host,source,dtime) VALUES("+ConvToStr(category)+","+ConvToStr(nickid)+","+ConvToStr(hostid)+","+ConvToStr(sourceid)+","+ConvToStr(date)+")");
140                                         if(req.Send())
141                                         {
142                                                 insert = true;
143                                                 qs = DONE;
144                                                 active_queries[req.id] = this;
145                                         }
146                                 }
147                                 else if (res->Rows() && hostid == -1 && insert)
148                                 {
149                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'", hostname);
150                                         if(req.Send())
151                                         {
152                                                 insert = false;
153                                                 qs = FIND_HOST;
154                                                 active_queries[req.id] = this;
155                                         }
156                                 }
157                                 else
158                                 {
159                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_hosts (hostname) VALUES('?')", hostname);
160                                         if(req.Send())
161                                         {
162                                                 insert = true;
163                                                 qs = FIND_HOST;
164                                                 active_queries[req.id] = this;
165                                         }
166                                 }
167                         break;
168
169                         case DONE:
170                                 delete active_queries[req.id];
171                                 active_queries[req.id] = NULL;
172                         break;
173                 }
174         }
175 };
176
177 /* $ModDesc: Logs network-wide data to an SQL database */
178
179 class ModuleSQLLog : public Module
180 {
181         InspIRCd* Srv;
182         ConfigReader* Conf;
183
184  public:
185         ModuleSQLLog(InspIRCd* Me)
186         : Module::Module(Me), Srv(Me)
187         {
188                 ServerInstance->UseInterface("SQLutils");
189                 ServerInstance->UseInterface("SQL");
190
191                 Module* SQLutils = ServerInstance->FindModule("m_sqlutils.so");
192                 if (!SQLutils)
193                         throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so.");
194
195                 SQLModule = Srv->FindFeature("SQL");
196
197                 OnRehash(NULL,"");
198                 MyMod = this;
199                 active_queries.clear();
200         }
201
202         virtual ~ModuleSQLLog()
203         {
204                 ServerInstance->DoneWithInterface("SQL");
205                 ServerInstance->DoneWithInterface("SQLutils");
206         }
207
208         void Implements(char* List)
209         {
210                 List[I_OnRehash] = List[I_OnOper] = List[I_OnGlobalOper] = List[I_OnKill] = 1;
211                 List[I_OnPreCommand] = List[I_OnUserConnect] = 1;
212                 List[I_OnUserQuit] = List[I_OnLoadModule] = List[I_OnRequest] = 1;
213         }
214
215         void ReadConfig()
216         {
217                 ConfigReader Conf(Srv);
218                 dbid = Conf.ReadValue("sqllog","dbid",0);       // database id of a database configured in sql module
219         }
220
221         virtual void OnRehash(userrec* user, const std::string &parameter)
222         {
223                 ReadConfig();
224         }
225
226         virtual char* OnRequest(Request* request)
227         {
228                 if(strcmp(SQLRESID, request->GetId()) == 0)
229                 {
230                         SQLresult* res;
231                         std::map<unsigned long, QueryInfo*>::iterator n;
232
233                         res = static_cast<SQLresult*>(request);
234                         ServerInstance->Log(DEBUG, "Got SQL result (%s) with ID %lu", res->GetId(), res->id);
235
236                         n = active_queries.find(res->id);
237
238                         if (n != active_queries.end())
239                         {
240                                 ServerInstance->Log(DEBUG,"This is an active query");
241                                 n->second->Go(res);
242
243                                 std::map<unsigned long, QueryInfo*>::iterator n = active_queries.find(res->id);
244                                 active_queries.erase(n);
245                         }
246
247                         return SQLSUCCESS;
248                 }
249
250                 ServerInstance->Log(DEBUG, "Got unsupported API version string: %s", request->GetId());
251
252                 return NULL;
253         }
254
255         void AddLogEntry(int category, const std::string &nick, const std::string &host, const std::string &source)
256         {
257                 // is the sql module loaded? If not, we don't attempt to do anything.
258                 if (!SQLModule)
259                         return;
260
261                 SQLrequest req = SQLreq(this, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", source);
262                 if(req.Send())
263                 {
264                         QueryInfo* i = new QueryInfo(nick, source, host, req.id, category);
265                         i->qs = FIND_SOURCE;
266                         active_queries[req.id] = i;
267                         ServerInstance->Log(DEBUG,"Active query id %d",req.id);
268                 }
269                 else
270                 {
271                         ServerInstance->Log(DEBUG, "SQLrequest failed: %s", req.error.Str());
272                 }
273         }
274
275         virtual void OnOper(userrec* user, const std::string &opertype)
276         {
277                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
278         }
279
280         virtual void OnGlobalOper(userrec* user)
281         {
282                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
283         }
284
285         virtual int OnKill(userrec* source, userrec* dest, const std::string &reason)
286         {
287                 AddLogEntry(LT_KILL,dest->nick,dest->host,source->nick);
288                 return 0;
289         }
290
291         virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line)
292         {
293                 if ((command == "GLINE" || command == "KLINE" || command == "ELINE" || command == "ZLINE") && validated)
294                 {
295                         AddLogEntry(LT_XLINE,user->nick,command[0]+std::string(":")+std::string(parameters[0]),user->server);
296                 }
297                 return 0;
298         }
299
300         virtual void OnUserConnect(userrec* user)
301         {
302                 AddLogEntry(LT_CONNECT,user->nick,user->host,user->server);
303         }
304
305         virtual void OnUserQuit(userrec* user, const std::string &reason)
306         {
307                 AddLogEntry(LT_DISCONNECT,user->nick,user->host,user->server);
308         }
309
310         virtual void OnLoadModule(Module* mod, const std::string &name)
311         {
312                 AddLogEntry(LT_LOADMODULE,name,Srv->Config->ServerName, Srv->Config->ServerName);
313         }
314
315         virtual Version GetVersion()
316         {
317                 return Version(1,1,0,1,VF_VENDOR,API_VERSION);
318         }
319         
320 };
321
322 class ModuleSQLLogFactory : public ModuleFactory
323 {
324  public:
325         ModuleSQLLogFactory()
326         {
327         }
328         
329         ~ModuleSQLLogFactory()
330         {
331         }
332         
333         virtual Module * CreateModule(InspIRCd* Me)
334         {
335                 return new ModuleSQLLog(Me);
336         }
337         
338 };
339
340
341 extern "C" void * init_module( void )
342 {
343         return new ModuleSQLLogFactory;
344 }