]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/extra/m_sqllog.cpp
OOPS! We try again, since I'm smoking craq. LF is 0x0a NOT CR.
[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 "inspircd.h"
15 #include "users.h"
16 #include "channels.h"
17 #include "modules.h"
18 #include "configreader.h"
19 #include "m_sqlv2.h"
20
21 static Module* SQLModule;
22 static Module* MyMod;
23 static std::string dbid;
24
25 enum LogTypes { LT_OPER = 1, LT_KILL, LT_SERVLINK, LT_XLINE, LT_CONNECT, LT_DISCONNECT, LT_FLOOD, LT_LOADMODULE };
26
27 enum QueryState { FIND_SOURCE, FIND_NICK, FIND_HOST, DONE};
28
29 class QueryInfo;
30
31 std::map<unsigned long,QueryInfo*> active_queries;
32
33 class QueryInfo
34 {
35 public:
36         QueryState qs;
37         unsigned long id;
38         std::string nick;
39         std::string source;
40         std::string hostname;
41         int sourceid;
42         int nickid;
43         int hostid;
44         int category;
45         time_t date;
46         bool insert;
47
48         QueryInfo(const std::string &n, const std::string &s, const std::string &h, unsigned long i, int cat)
49         {
50                 qs = FIND_SOURCE;
51                 nick = n;
52                 source = s;
53                 hostname = h;
54                 id = i;
55                 category = cat;
56                 sourceid = nickid = hostid = -1;
57                 date = time(NULL);
58                 insert = false;
59         }
60
61         void Go(SQLresult* res)
62         {
63                 SQLrequest req = SQLreq(MyMod, SQLModule, dbid, "", "");
64                 switch (qs)
65                 {
66                         case FIND_SOURCE:
67                                 if (res->Rows() && sourceid == -1 && !insert)
68                                 {
69                                         sourceid = atoi(res->GetValue(0,0).d.c_str());
70                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
71                                         if(req.Send())
72                                         {
73                                                 insert = false;
74                                                 qs = FIND_NICK;
75                                                 active_queries[req.id] = this;
76                                         }
77                                 }
78                                 else if (res->Rows() && sourceid == -1 && insert)
79                                 {
80                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", source);
81                                         if(req.Send())
82                                         {
83                                                 insert = false;
84                                                 qs = FIND_SOURCE;
85                                                 active_queries[req.id] = this;
86                                         }
87                                 }
88                                 else
89                                 {
90                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors (actor) VALUES('?')", source);
91                                         if(req.Send())
92                                         {
93                                                 insert = true;
94                                                 qs = FIND_SOURCE;
95                                                 active_queries[req.id] = this;
96                                         }
97                                 }
98                         break;
99
100                         case FIND_NICK:
101                                 if (res->Rows() && nickid == -1 && !insert)
102                                 {
103                                         nickid = atoi(res->GetValue(0,0).d.c_str());
104                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,hostname FROM ircd_log_hosts WHERE hostname='?'", hostname);
105                                         if(req.Send())
106                                         {
107                                                 insert = false;
108                                                 qs = FIND_HOST;
109                                                 active_queries[req.id] = this;
110                                         }
111                                 }
112                                 else if (res->Rows() && nickid == -1 && insert)
113                                 {
114                                         req = SQLreq(MyMod, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", nick);
115                                         if(req.Send())
116                                         {
117                                                 insert = false;
118                                                 qs = FIND_NICK;
119                                                 active_queries[req.id] = this;
120                                         }
121                                 }
122                                 else
123                                 {
124                                         req = SQLreq(MyMod, SQLModule, dbid, "INSERT INTO ircd_log_actors (actor) VALUES('?')",nick);
125                                         if(req.Send())
126                                         {
127                                                 insert = true;
128                                                 qs = FIND_NICK;
129                                                 active_queries[req.id] = this;
130                                         }
131                                 }
132                         break;
133
134                         case FIND_HOST:
135                                 if (res->Rows() && hostid == -1 && !insert)
136                                 {
137                                         hostid = atoi(res->GetValue(0,0).d.c_str());
138                                         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)+")");
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 = SQLreq(MyMod, SQLModule, dbid, "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 = SQLreq(MyMod, SQLModule, dbid, "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                                 delete active_queries[req.id];
170                                 active_queries[req.id] = NULL;
171                         break;
172                 }
173         }
174 };
175
176 /* $ModDesc: Logs network-wide data to an SQL database */
177
178 class ModuleSQLLog : public Module
179 {
180         ConfigReader* Conf;
181
182  public:
183         ModuleSQLLog(InspIRCd* Me)
184         : Module::Module(Me)
185         {
186                 ServerInstance->UseInterface("SQLutils");
187                 ServerInstance->UseInterface("SQL");
188
189                 Module* SQLutils = ServerInstance->FindModule("m_sqlutils.so");
190                 if (!SQLutils)
191                         throw ModuleException("Can't find m_sqlutils.so. Please load m_sqlutils.so before m_sqlauth.so.");
192
193                 SQLModule = ServerInstance->FindFeature("SQL");
194
195                 OnRehash(NULL,"");
196                 MyMod = this;
197                 active_queries.clear();
198         }
199
200         virtual ~ModuleSQLLog()
201         {
202                 ServerInstance->DoneWithInterface("SQL");
203                 ServerInstance->DoneWithInterface("SQLutils");
204         }
205
206         void Implements(char* List)
207         {
208                 List[I_OnRehash] = List[I_OnOper] = List[I_OnGlobalOper] = List[I_OnKill] = 1;
209                 List[I_OnPreCommand] = List[I_OnUserConnect] = 1;
210                 List[I_OnUserQuit] = List[I_OnLoadModule] = List[I_OnRequest] = 1;
211         }
212
213         void ReadConfig()
214         {
215                 ConfigReader Conf(ServerInstance);
216                 dbid = Conf.ReadValue("sqllog","dbid",0);       // database id of a database configured in sql module
217         }
218
219         virtual void OnRehash(userrec* user, const std::string &parameter)
220         {
221                 ReadConfig();
222         }
223
224         virtual char* OnRequest(Request* request)
225         {
226                 if(strcmp(SQLRESID, request->GetId()) == 0)
227                 {
228                         SQLresult* res;
229                         std::map<unsigned long, QueryInfo*>::iterator n;
230
231                         res = static_cast<SQLresult*>(request);
232                         n = active_queries.find(res->id);
233
234                         if (n != active_queries.end())
235                         {
236                                 n->second->Go(res);
237                                 std::map<unsigned long, QueryInfo*>::iterator n = active_queries.find(res->id);
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 = SQLreq(this, SQLModule, dbid, "SELECT id,actor FROM ircd_log_actors WHERE actor='?'", source);
254                 if(req.Send())
255                 {
256                         QueryInfo* i = new QueryInfo(nick, source, host, req.id, category);
257                         i->qs = FIND_SOURCE;
258                         active_queries[req.id] = i;
259                 }
260         }
261
262         virtual void OnOper(userrec* user, const std::string &opertype)
263         {
264                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
265         }
266
267         virtual void OnGlobalOper(userrec* user)
268         {
269                 AddLogEntry(LT_OPER,user->nick,user->host,user->server);
270         }
271
272         virtual int OnKill(userrec* source, userrec* dest, const std::string &reason)
273         {
274                 AddLogEntry(LT_KILL,dest->nick,dest->host,source->nick);
275                 return 0;
276         }
277
278         virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *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(":")+std::string(parameters[0]),user->server);
283                 }
284                 return 0;
285         }
286
287         virtual void OnUserConnect(userrec* user)
288         {
289                 AddLogEntry(LT_CONNECT,user->nick,user->host,user->server);
290         }
291
292         virtual void OnUserQuit(userrec* 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(1,1,0,1,VF_VENDOR,API_VERSION);
305         }
306         
307 };
308
309 MODULE_INIT(ModuleSQLLog);
310