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 <unistd.h>
00023 #include <sys/errno.h>
00024 #include <sys/ioctl.h>
00025 #include <sys/utsname.h>
00026 #include <time.h>
00027 #include <string>
00028 #ifdef GCC3
00029 #include <ext/hash_map>
00030 #else
00031 #include <hash_map>
00032 #endif
00033 #include <map>
00034 #include <sstream>
00035 #include <vector>
00036 #include <deque>
00037 #include "users.h"
00038 #include "ctables.h"
00039 #include "globals.h"
00040 #include "modules.h"
00041 #include "dynamic.h"
00042 #include "commands.h"
00043 #include "wildcard.h"
00044 #include "message.h"
00045 #include "mode.h"
00046 #include "xline.h"
00047 #include "inspstring.h"
00048 #include "helperfuncs.h"
00049 #include "typedefs.h"
00050
00051 #ifdef GCC3
00052 #define nspace __gnu_cxx
00053 #else
00054 #define nspace std
00055 #endif
00056
00057 extern ServerConfig* Config;
00058
00059 extern int MODCOUNT;
00060 extern std::vector<Module*> modules;
00061 extern std::vector<ircd_module*> factory;
00062 extern int WHOWAS_STALE;
00063 extern int WHOWAS_MAX;
00064 extern time_t TIME;
00065 extern chan_hash chanlist;
00066
00067 using namespace std;
00068
00069 std::vector<ModeParameter> custom_mode_params;
00070
00071 chanrec* ForceChan(chanrec* Ptr,ucrec &a,userrec* user, int created);
00072
00073 chanrec::chanrec()
00074 {
00075 strcpy(name,"");
00076 strcpy(custom_modes,"");
00077 strcpy(topic,"");
00078 strcpy(setby,"");
00079 strcpy(key,"");
00080 created = topicset = limit = 0;
00081 binarymodes = 0;
00082 internal_userlist.clear();
00083 }
00084
00085 void chanrec::SetCustomMode(char mode,bool mode_on)
00086 {
00087 if (mode_on) {
00088 static char m[3];
00089 m[0] = mode;
00090 m[1] = '\0';
00091 if (!strchr(this->custom_modes,mode))
00092 {
00093 strlcat(custom_modes,m,MAXMODES);
00094 }
00095 log(DEBUG,"Custom mode %c set",mode);
00096 }
00097 else {
00098
00099 std::string a = this->custom_modes;
00100 int pos = a.find(mode);
00101 a.erase(pos,1);
00102 strncpy(this->custom_modes,a.c_str(),MAXMODES);
00103
00104 log(DEBUG,"Custom mode %c removed: modelist='%s'",mode,this->custom_modes);
00105 this->SetCustomModeParam(mode,"",false);
00106 }
00107 }
00108
00109
00110 void chanrec::SetCustomModeParam(char mode,char* parameter,bool mode_on)
00111 {
00112
00113 log(DEBUG,"SetCustomModeParam called");
00114 ModeParameter M;
00115 M.mode = mode;
00116 strlcpy(M.channel,this->name,CHANMAX);
00117 strlcpy(M.parameter,parameter,MAXBUF);
00118 if (mode_on)
00119 {
00120 log(DEBUG,"Custom mode parameter %c %s added",mode,parameter);
00121 custom_mode_params.push_back(M);
00122 }
00123 else
00124 {
00125 if (custom_mode_params.size())
00126 {
00127 for (vector<ModeParameter>::iterator i = custom_mode_params.begin(); i < custom_mode_params.end(); i++)
00128 {
00129 if ((i->mode == mode) && (!strcasecmp(this->name,i->channel)))
00130 {
00131 log(DEBUG,"Custom mode parameter %c %s removed",mode,parameter);
00132 custom_mode_params.erase(i);
00133 return;
00134 }
00135 }
00136 }
00137 log(DEBUG,"*** BUG *** Attempt to remove non-existent mode parameter!");
00138 }
00139 }
00140
00141 bool chanrec::IsCustomModeSet(char mode)
00142 {
00143 return (strchr(this->custom_modes,mode));
00144 }
00145
00146 std::string chanrec::GetModeParameter(char mode)
00147 {
00148 if (custom_mode_params.size())
00149 {
00150 for (vector<ModeParameter>::iterator i = custom_mode_params.begin(); i < custom_mode_params.end(); i++)
00151 {
00152 if ((i->mode == mode) && (!strcasecmp(this->name,i->channel)))
00153 {
00154 return i->parameter;
00155 }
00156 }
00157 }
00158 return "";
00159 }
00160
00161 long chanrec::GetUserCounter()
00162 {
00163 return (this->internal_userlist.size());
00164 }
00165
00166 void chanrec::AddUser(char* castuser)
00167 {
00168 internal_userlist.push_back(castuser);
00169 log(DEBUG,"Added casted user to channel's internal list");
00170 }
00171
00172 void chanrec::DelUser(char* castuser)
00173 {
00174 for (std::vector<char*>::iterator a = internal_userlist.begin(); a < internal_userlist.end(); a++)
00175 {
00176 if (*a == castuser)
00177 {
00178 log(DEBUG,"Removed casted user from channel's internal list");
00179 internal_userlist.erase(a);
00180 return;
00181 }
00182 }
00183 log(DEBUG,"BUG BUG BUG! Attempt to remove an uncasted user from the internal list of %s!",name);
00184 }
00185
00186 std::vector<char*> *chanrec::GetUsers()
00187 {
00188 return &internal_userlist;
00189 }
00190
00191
00192
00193
00194 chanrec* add_channel(userrec *user, const char* cn, const char* key, bool override)
00195 {
00196 if ((!user) || (!cn))
00197 {
00198 log(DEFAULT,"*** BUG *** add_channel was given an invalid parameter");
00199 return 0;
00200 }
00201
00202 int created = 0;
00203 char cname[MAXBUF];
00204 int MOD_RESULT = 0;
00205 strncpy(cname,cn,CHANMAX);
00206
00207 log(DEBUG,"add_channel: %s %s",user->nick,cname);
00208
00209 chanrec* Ptr = FindChan(cname);
00210
00211 if (!Ptr)
00212 {
00213 if (user->fd > -1)
00214 {
00215 MOD_RESULT = 0;
00216 FOREACH_RESULT(OnUserPreJoin(user,NULL,cname));
00217 if (MOD_RESULT == 1)
00218 return NULL;
00219 }
00220
00221 chanlist[cname] = new chanrec();
00222 strlcpy(chanlist[cname]->name, cname,CHANMAX);
00223 chanlist[cname]->binarymodes = CM_TOPICLOCK | CM_NOEXTERNAL;
00224 chanlist[cname]->created = TIME;
00225 strcpy(chanlist[cname]->topic, "");
00226 strncpy(chanlist[cname]->setby, user->nick,NICKMAX);
00227 chanlist[cname]->topicset = 0;
00228 Ptr = chanlist[cname];
00229 log(DEBUG,"add_channel: created: %s",cname);
00230
00231
00232
00233 created = 2;
00234 }
00235 else
00236 {
00237
00238 if (has_channel(user,Ptr))
00239 return NULL;
00240
00241
00242
00243 if (user->fd > -1)
00244 {
00245 MOD_RESULT = 0;
00246 FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname));
00247 if (MOD_RESULT == 1)
00248 {
00249 return NULL;
00250 }
00251 else
00252 {
00253 if (*Ptr->key)
00254 {
00255 MOD_RESULT = 0;
00256 FOREACH_RESULT(OnCheckKey(user, Ptr, key ? key : ""));
00257 if (!MOD_RESULT)
00258 {
00259 if (!key)
00260 {
00261 log(DEBUG,"add_channel: no key given in JOIN");
00262 WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name);
00263 return NULL;
00264 }
00265 else
00266 {
00267 if (strcasecmp(key,Ptr->key))
00268 {
00269 log(DEBUG,"add_channel: bad key given in JOIN");
00270 WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name);
00271 return NULL;
00272 }
00273 }
00274 }
00275 }
00276 if (Ptr->binarymodes & CM_INVITEONLY)
00277 {
00278 MOD_RESULT = 0;
00279 irc::string xname(Ptr->name);
00280 FOREACH_RESULT(OnCheckInvite(user, Ptr));
00281 if (!MOD_RESULT)
00282 {
00283 log(DEBUG,"add_channel: channel is +i");
00284 if (user->IsInvited(xname))
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(xname);
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