00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using namespace std;
00018
00019 #include "inspircd_config.h"
00020 #include "inspircd.h"
00021 #include "inspircd_io.h"
00022 #include "inspircd_util.h"
00023 #include <unistd.h>
00024 #include <sys/errno.h>
00025 #include <sys/ioctl.h>
00026 #include <sys/utsname.h>
00027 #include <time.h>
00028 #include <string>
00029 #ifdef GCC3
00030 #include <ext/hash_map>
00031 #else
00032 #include <hash_map>
00033 #endif
00034 #include <map>
00035 #include <sstream>
00036 #include <vector>
00037 #include <deque>
00038 #include "users.h"
00039 #include "ctables.h"
00040 #include "globals.h"
00041 #include "modules.h"
00042 #include "dynamic.h"
00043 #include "commands.h"
00044 #include "wildcard.h"
00045 #include "message.h"
00046 #include "mode.h"
00047 #include "xline.h"
00048 #include "inspstring.h"
00049 #include "helperfuncs.h"
00050 #include "typedefs.h"
00051
00052 #ifdef GCC3
00053 #define nspace __gnu_cxx
00054 #else
00055 #define nspace std
00056 #endif
00057
00058 extern ServerConfig* Config;
00059
00060 extern int MODCOUNT;
00061 extern std::vector<Module*> modules;
00062 extern std::vector<ircd_module*> factory;
00063 extern int WHOWAS_STALE;
00064 extern int WHOWAS_MAX;
00065 extern time_t TIME;
00066 extern chan_hash chanlist;
00067
00068 using namespace std;
00069
00070 std::vector<ModeParameter> custom_mode_params;
00071
00072 chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created);
00073
00074 chanrec::chanrec()
00075 {
00076 strcpy(name,"");
00077 strcpy(custom_modes,"");
00078 strcpy(topic,"");
00079 strcpy(setby,"");
00080 strcpy(key,"");
00081 created = topicset = limit = 0;
00082 binarymodes = 0;
00083 internal_userlist.clear();
00084 }
00085
00086 void chanrec::SetCustomMode(char mode,bool mode_on)
00087 {
00088 if (mode_on) {
00089 static char m[3];
00090 m[0] = mode;
00091 m[1] = '\0';
00092 if (!strchr(this->custom_modes,mode))
00093 {
00094 strlcat(custom_modes,m,MAXMODES);
00095 }
00096 log(DEBUG,"Custom mode %c set",mode);
00097 }
00098 else {
00099
00100 std::string a = this->custom_modes;
00101 int pos = a.find(mode);
00102 a.erase(pos,1);
00103 strncpy(this->custom_modes,a.c_str(),MAXMODES);
00104
00105 log(DEBUG,"Custom mode %c removed: modelist='%s'",mode,this->custom_modes);
00106 this->SetCustomModeParam(mode,"",false);
00107 }
00108 }
00109
00110
00111 void chanrec::SetCustomModeParam(char mode,char* parameter,bool mode_on)
00112 {
00113
00114 log(DEBUG,"SetCustomModeParam called");
00115 ModeParameter M;
00116 M.mode = mode;
00117 strlcpy(M.channel,this->name,CHANMAX);
00118 strlcpy(M.parameter,parameter,MAXBUF);
00119 if (mode_on)
00120 {
00121 log(DEBUG,"Custom mode parameter %c %s added",mode,parameter);
00122 custom_mode_params.push_back(M);
00123 }
00124 else
00125 {
00126 if (custom_mode_params.size())
00127 {
00128 for (vector<ModeParameter>::iterator i = custom_mode_params.begin(); i < custom_mode_params.end(); i++)
00129 {
00130 if ((i->mode == mode) && (!strcasecmp(this->name,i->channel)))
00131 {
00132 log(DEBUG,"Custom mode parameter %c %s removed",mode,parameter);
00133 custom_mode_params.erase(i);
00134 return;
00135 }
00136 }
00137 }
00138 log(DEBUG,"*** BUG *** Attempt to remove non-existent mode parameter!");
00139 }
00140 }
00141
00142 bool chanrec::IsCustomModeSet(char mode)
00143 {
00144 return (strchr(this->custom_modes,mode));
00145 }
00146
00147 std::string chanrec::GetModeParameter(char mode)
00148 {
00149 if (custom_mode_params.size())
00150 {
00151 for (vector<ModeParameter>::iterator i = custom_mode_params.begin(); i < custom_mode_params.end(); i++)
00152 {
00153 if ((i->mode == mode) && (!strcasecmp(this->name,i->channel)))
00154 {
00155 return i->parameter;
00156 }
00157 }
00158 }
00159 return "";
00160 }
00161
00162 long chanrec::GetUserCounter()
00163 {
00164 return (this->internal_userlist.size());
00165 }
00166
00167 void chanrec::AddUser(char* castuser)
00168 {
00169 internal_userlist.push_back(castuser);
00170 log(DEBUG,"Added casted user to channel's internal list");
00171 }
00172
00173 void chanrec::DelUser(char* castuser)
00174 {
00175 for (std::vector<char*>::iterator a = internal_userlist.begin(); a < internal_userlist.end(); a++)
00176 {
00177 if (*a == castuser)
00178 {
00179 log(DEBUG,"Removed casted user from channel's internal list");
00180 internal_userlist.erase(a);
00181 return;
00182 }
00183 }
00184 log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
00185 }
00186
00187 std::vector<char*> *chanrec::GetUsers()
00188 {
00189 return &internal_userlist;
00190 }
00191
00192
00193
00194
00195 chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override)
00196 {
00197 if ((!user) || (!cn))
00198 {
00199 log(DEFAULT,"*** BUG *** add_channel was given an invalid parameter");
00200 return 0;
00201 }
00202
00203 int created = 0;
00204 char cname[MAXBUF];
00205 int MOD_RESULT = 0;
00206 strncpy(cname,cn,CHANMAX);
00207
00208 log(DEBUG,"add_channel: %s %s",user->nick,cname);
00209
00210 chanrec* Ptr = FindChan(cname);
00211
00212 if (!Ptr)
00213 {
00214 if (user->fd > -1)
00215 {
00216 MOD_RESULT = 0;
00217 FOREACH_RESULT(OnUserPreJoin(user,NULL,cname));
00218 if (MOD_RESULT == 1)
00219 return NULL;
00220 }
00221
00222 chanlist[cname] = new chanrec();
00223 strlcpy(chanlist[cname]->name, cname,CHANMAX);
00224 chanlist[cname]->binarymodes = CM_TOPICLOCK | CM_NOEXTERNAL;
00225 chanlist[cname]->created = TIME;
00226 strcpy(chanlist[cname]->topic, "");
00227 strncpy(chanlist[cname]->setby, user->nick,NICKMAX);
00228 chanlist[cname]->topicset = 0;
00229 Ptr = chanlist[cname];
00230 log(DEBUG,"add_channel: created: %s",cname);
00231
00232
00233
00234 created = 2;
00235 }
00236 else
00237 {
00238
00239 if (has_channel(user,Ptr))
00240 return NULL;
00241
00242
00243
00244 if (user->fd > -1)
00245 {
00246 MOD_RESULT = 0;
00247 FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname));
00248 if (MOD_RESULT == 1)
00249 {
00250 return NULL;
00251 }
00252 else
00253 {
00254 if (*Ptr->key)
00255 {
00256 MOD_RESULT = 0;
00257 FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : ""));
00258 if (!MOD_RESULT)
00259 {
00260 if (!key)
00261 {
00262 log(DEBUG,"add_channel: no key given in JOIN");
00263 WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name);
00264 return NULL;
00265 }
00266 else
00267 {
00268 if (strcasecmp(key,Ptr->key))
00269 {
00270 log(DEBUG,"add_channel: bad key given in JOIN");
00271 WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name);
00272 return NULL;
00273 }
00274 }
00275 }
00276 }
00277 if (Ptr->binarymodes & CM_INVITEONLY)
00278 {
00279 MOD_RESULT = 0;
00280 FOREACH_RESULT(OnCheckInvite(user, Ptr));
00281 if (!MOD_RESULT)
00282 {
00283 log(DEBUG,"add_channel: channel is +i");
00284 if (user->IsInvited(Ptr->name))
00285 {
00286
00287
00288 }
00289 else
00290 {
00291 WriteServ(user->fd,"473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name);
00292 return NULL;
00293 }
00294 }
00295 user->RemoveInvite(Ptr->name);
00296 }
00297 if (Ptr->limit)
00298 {
00299 MOD_RESULT = 0;
00300 FOREACH_RESULT(OnCheckLimit(user, Ptr));
00301 if (!MOD_RESULT)
00302 {
00303 if (usercount(Ptr) >= Ptr->limit)
00304 {
00305 WriteServ(user->fd,"471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name);
00306 return NULL;
00307 }
00308 }
00309 }
00310 if (Ptr->bans.size())
00311 {
00312 log(DEBUG,"add_channel: about to walk banlist");
00313 MOD_RESULT = 0;
00314 FOREACH_RESULT(OnCheckBan(user, Ptr));
00315 if (!MOD_RESULT)
00316 {
00317 for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
00318 {
00319 if (match(user->GetFullHost(),i->data))
00320 {
00321 WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name);
00322 return NULL;
00323 }
00324 }
00325 }
00326 }
00327 }
00328 }
00329 else
00330 {
00331 log(DEBUG,"Overridden checks");
00332 }
00333 created = 1;
00334 }
00335
00336 log(DEBUG,"Passed channel checks");
00337
00338 for (unsigned int index =0; index < user->chans.size(); index++)
00339 {
00340 if (user->chans[index].channel == NULL)
00341 {
00342 return ForceChan(Ptr,user->chans[index],user,created);
00343 }
00344 }
00345
00346
00347
00348
00349 if (user->fd < 0)
00350 {
00351 ucrec a;
00352 chanrec* c = ForceChan(Ptr,a,user,created);
00353 user->chans.push_back(a);
00354 return c;
00355 }
00356 else if (strchr(user->modes,'o'))
00357 {
00358
00359 if (user->chans.size() < OPERMAXCHANS)
00360 {
00361 ucrec a;
00362 chanrec* c = ForceChan(Ptr,a,user,created);
00363 user->chans.push_back(a);
00364 return c;
00365 }
00366 }
00367 log(DEBUG,"add_channel: user channel max exceeded: %s %s",user->nick,cname);
00368 WriteServ(user->fd,"405 %s %s :You are on too many channels",user->nick, cname);
00369 return NULL;
00370 }
00371
00372 chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created)
00373 {
00374 if (created == 2)
00375 {
00376
00377 a.uc_modes = UCMODE_OP;
00378 }
00379 else
00380 {
00381 a.uc_modes = 0;
00382 }
00383 a.channel = Ptr;
00384 Ptr->AddUser((char*)user);
00385 WriteChannel(Ptr,user,"JOIN :%s",Ptr->name);
00386 log(DEBUG,"Sent JOIN to client");
00387 if (Ptr->topicset)
00388 {
00389 WriteServ(user->fd,"332 %s %s :%s", user->nick, Ptr->name, Ptr->topic);
00390 WriteServ(user->fd,"333 %s %s %s %lu", user->nick, Ptr->name, Ptr->setby, (unsigned long)Ptr->topicset);
00391 }
00392 userlist(user,Ptr);
00393 WriteServ(user->fd,"366 %s %s :End of /NAMES list.", user->nick, Ptr->name);
00394 FOREACH_MOD OnUserJoin(user,Ptr);
00395 return Ptr;
00396 }
00397
00398
00399
00400
00401 chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local)
00402 {
00403 if ((!user) || (!cname))
00404 {
00405 log(DEFAULT,"*** BUG *** del_channel was given an invalid parameter");
00406 return NULL;
00407 }
00408
00409 chanrec* Ptr = FindChan(cname);
00410
00411 if (!Ptr)
00412 return NULL;
00413
00414 FOREACH_MOD OnUserPart(user,Ptr);
00415 log(DEBUG,"del_channel: removing: %s %s",user->nick,Ptr->name);
00416
00417 for (unsigned int i =0; i < user->chans.size(); i++)
00418 {
00419
00420 if (user->chans[i].channel == Ptr)
00421 {
00422 if (reason)
00423 {
00424 WriteChannel(Ptr,user,"PART %s :%s",Ptr->name, reason);
00425 }
00426 else
00427 {
00428 WriteChannel(Ptr,user,"PART :%s",Ptr->name);
00429 }
00430 user->chans[i].uc_modes = 0;
00431 user->chans[i].channel = NULL;
00432 log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name);
00433 break;
00434 }
00435 }
00436
00437 Ptr->DelUser((char*)user);
00438
00439
00440 if (!usercount(Ptr))
00441 {
00442 chan_hash::iterator iter = chanlist.find(Ptr->name);
00443
00444 log(DEBUG,"del_channel: destroying channel: %s",Ptr->name);
00445
00446
00447 if (iter != chanlist.end())
00448 {
00449 log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
00450 delete Ptr;
00451 chanlist.erase(iter);
00452 }
00453 }
00454
00455 return NULL;
00456 }
00457
00458
00459 void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
00460 {
00461 if ((!src) || (!user) || (!Ptr) || (!reason))
00462 {
00463 log(DEFAULT,"*** BUG *** kick_channel was given an invalid parameter");
00464 return;
00465 }
00466
00467 if ((!Ptr) || (!user) || (!src))
00468 {
00469 return;
00470 }
00471
00472 log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick);
00473
00474 if (!has_channel(user,Ptr))
00475 {
00476 WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name);
00477 return;
00478 }
00479
00480 int MOD_RESULT = 0;
00481 FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK));
00482 if ((MOD_RESULT == ACR_DENY) && (!is_uline(src->server)))
00483 return;
00484
00485 if ((MOD_RESULT == ACR_DEFAULT) || (!is_uline(src->server)))
00486 {
00487 if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr)))
00488 {
00489 if (cstatus(src,Ptr) == STATUS_HOP)
00490 {
00491 WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name);
00492 }
00493 else
00494 {
00495 WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name);
00496 }
00497
00498 return;
00499 }
00500 }
00501
00502 if (!is_uline(src->server))
00503 {
00504 MOD_RESULT = 0;
00505 FOREACH_RESULT(OnUserPreKick(src,user,Ptr,reason));
00506 if (MOD_RESULT)
00507 return;
00508 }
00509
00510 FOREACH_MOD OnUserKick(src,user,Ptr,reason);
00511
00512 for (unsigned int i =0; i < user->chans.size(); i++)
00513 {
00514
00515 if (user->chans[i].channel)
00516 if (!strcasecmp(user->chans[i].channel->name,Ptr->name))
00517 {
00518 WriteChannel(Ptr,src,"KICK %s %s :%s",Ptr->name, user->nick, reason);
00519 user->chans[i].uc_modes = 0;
00520 user->chans[i].channel = NULL;
00521 log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name);
00522 break;
00523 }
00524 }
00525
00526 Ptr->DelUser((char*)user);
00527
00528
00529 if (!usercount(Ptr))
00530 {
00531 chan_hash::iterator iter = chanlist.find(Ptr->name);
00532
00533 log(DEBUG,"del_channel: destroying channel: %s",Ptr->name);
00534
00535
00536 if (iter != chanlist.end())
00537 {
00538 log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
00539 delete Ptr;
00540 chanlist.erase(iter);
00541 }
00542 }
00543 }
00544
00545