00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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);
00218 }
00219
00220 virtual void OnRehash(User* user, const std::string ¶meter)
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
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> ¶meters, 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)