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