00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015 #include <sstream>
00016 #include <list>
00017 #include "users.h"
00018 #include "channels.h"
00019 #include "modules.h"
00020 #include "configreader.h"
00021 #include "m_sqlutils.h"
00022
00023
00024
00025
00026 typedef std::map<unsigned long, User*> IdUserMap;
00027 typedef std::map<unsigned long, Channel*> IdChanMap;
00028 typedef std::list<unsigned long> AssocIdList;
00029
00030 class ModuleSQLutils : public Module
00031 {
00032 private:
00033 IdUserMap iduser;
00034 IdChanMap idchan;
00035
00036 public:
00037 ModuleSQLutils(InspIRCd* Me)
00038 : Module::Module(Me)
00039 {
00040 ServerInstance->Modules->PublishInterface("SQLutils", this);
00041 Implementation eventlist[] = { I_OnChannelDelete, I_OnUnloadModule, I_OnRequest, I_OnUserDisconnect };
00042 ServerInstance->Modules->Attach(eventlist, this, 4);
00043 }
00044
00045 virtual ~ModuleSQLutils()
00046 {
00047 ServerInstance->Modules->UnpublishInterface("SQLutils", this);
00048 }
00049
00050
00051 virtual const char* OnRequest(Request* request)
00052 {
00053 if(strcmp(SQLUTILAU, request->GetId()) == 0)
00054 {
00055 AssociateUser* req = (AssociateUser*)request;
00056
00057 iduser.insert(std::make_pair(req->id, req->user));
00058
00059 AttachList(req->user, req->id);
00060 }
00061 else if(strcmp(SQLUTILAC, request->GetId()) == 0)
00062 {
00063 AssociateChan* req = (AssociateChan*)request;
00064
00065 idchan.insert(std::make_pair(req->id, req->chan));
00066
00067 AttachList(req->chan, req->id);
00068 }
00069 else if(strcmp(SQLUTILUA, request->GetId()) == 0)
00070 {
00071 UnAssociate* req = (UnAssociate*)request;
00072
00073
00074
00075
00076
00077 DoUnAssociate(iduser, req->id);
00078 DoUnAssociate(idchan, req->id);
00079 }
00080 else if(strcmp(SQLUTILGU, request->GetId()) == 0)
00081 {
00082 GetAssocUser* req = (GetAssocUser*)request;
00083
00084 IdUserMap::iterator iter = iduser.find(req->id);
00085
00086 if(iter != iduser.end())
00087 {
00088 req->user = iter->second;
00089 }
00090 }
00091 else if(strcmp(SQLUTILGC, request->GetId()) == 0)
00092 {
00093 GetAssocChan* req = (GetAssocChan*)request;
00094
00095 IdChanMap::iterator iter = idchan.find(req->id);
00096
00097 if(iter != idchan.end())
00098 {
00099 req->chan = iter->second;
00100 }
00101 }
00102
00103 return SQLUTILSUCCESS;
00104 }
00105
00106 virtual void OnUserDisconnect(User* user)
00107 {
00108
00109
00110
00111
00112 AssocIdList* il;
00113
00114 if(user->GetExt("sqlutils_queryids", il))
00115 {
00116 for(AssocIdList::iterator listiter = il->begin(); listiter != il->end(); listiter++)
00117 {
00118 IdUserMap::iterator iter;
00119
00120 iter = iduser.find(*listiter);
00121
00122 if(iter != iduser.end())
00123 {
00124 if(iter->second != user)
00125 {
00126 ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: ID associated with user %s doesn't have the same User* associated with it in the map (erasing anyway)", user->nick.c_str());
00127 }
00128
00129 iduser.erase(iter);
00130 }
00131 else
00132 {
00133 ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: user %s was extended with sqlutils_queryids but there was nothing matching in the map", user->nick.c_str());
00134 }
00135 }
00136
00137 user->Shrink("sqlutils_queryids");
00138 delete il;
00139 }
00140 }
00141
00142 void AttachList(Extensible* obj, unsigned long id)
00143 {
00144 AssocIdList* il;
00145
00146 if(!obj->GetExt("sqlutils_queryids", il))
00147 {
00148
00149 il = new AssocIdList;
00150 obj->Extend("sqlutils_queryids", il);
00151 }
00152
00153
00154 il->push_back(id);
00155 }
00156
00157 void RemoveFromList(Extensible* obj, unsigned long id)
00158 {
00159 AssocIdList* il;
00160
00161 if(obj->GetExt("sqlutils_queryids", il))
00162 {
00163
00164 il->remove(id);
00165
00166 if(il->empty())
00167 {
00168
00169 delete il;
00170 obj->Shrink("sqlutils_queryids");
00171 }
00172 }
00173 }
00174
00175 template <class T> void DoUnAssociate(T &map, unsigned long id)
00176 {
00177
00178
00179
00180
00181 typename T::iterator iter = map.find(id);
00182
00183 if(iter != map.end())
00184 {
00185
00186
00187
00188
00189 RemoveFromList(iter->second, id);
00190 }
00191 }
00192
00193 virtual void OnChannelDelete(Channel* chan)
00194 {
00195
00196
00197
00198
00199 AssocIdList* il;
00200
00201 if(chan->GetExt("sqlutils_queryids", il))
00202 {
00203 for(AssocIdList::iterator listiter = il->begin(); listiter != il->end(); listiter++)
00204 {
00205 IdChanMap::iterator iter;
00206
00207 iter = idchan.find(*listiter);
00208
00209 if(iter != idchan.end())
00210 {
00211 if(iter->second != chan)
00212 {
00213 ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: ID associated with channel %s doesn't have the same Channel* associated with it in the map (erasing anyway)", chan->name.c_str());
00214 }
00215 idchan.erase(iter);
00216 }
00217 else
00218 {
00219 ServerInstance->Logs->Log("m_sqlutils",DEBUG, "BUG: channel %s was extended with sqlutils_queryids but there was nothing matching in the map", chan->name.c_str());
00220 }
00221 }
00222
00223 chan->Shrink("sqlutils_queryids");
00224 delete il;
00225 }
00226 }
00227
00228 virtual Version GetVersion()
00229 {
00230 return Version("$Id: m_sqlutils.cpp 10290 2008-08-25 20:35:36Z w00t $", VF_VENDOR | VF_SERVICEPROVIDER, API_VERSION);
00231 }
00232
00233 };
00234
00235 MODULE_INIT(ModuleSQLutils)