From f62de63955ff77e800360eb140f108b5d2c6c075 Mon Sep 17 00:00:00 2001 From: brain Date: Mon, 19 Dec 2005 18:32:09 +0000 Subject: Design flaw my ass. git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@2580 e03df62e-2008-0410-955e-edbf42e46eb7 --- docs/module-doc/users_8cpp-source.html | 818 --------------------------------- 1 file changed, 818 deletions(-) delete mode 100644 docs/module-doc/users_8cpp-source.html (limited to 'docs/module-doc/users_8cpp-source.html') diff --git a/docs/module-doc/users_8cpp-source.html b/docs/module-doc/users_8cpp-source.html deleted file mode 100644 index 8b129741a..000000000 --- a/docs/module-doc/users_8cpp-source.html +++ /dev/null @@ -1,818 +0,0 @@ - -
-00001 /* +------------------------------------+ -00002 * | Inspire Internet Relay Chat Daemon | -00003 * +------------------------------------+ -00004 * -00005 * Inspire is copyright (C) 2002-2004 ChatSpike-Dev. -00006 * E-mail: -00007 * <brain@chatspike.net> -00008 * <Craig@chatspike.net> -00009 * -00010 * Written by Craig Edwards, Craig McLure, and others. -00011 * This program is free but copyrighted software; see -00012 * the file COPYING for details. -00013 * -00014 * --------------------------------------------------- -00015 */ -00016 -00017 using namespace std; -00018 -00019 #include "inspircd_config.h" -00020 #include "channels.h" -00021 #include "connection.h" -00022 #include "users.h" -00023 #include "inspircd.h" -00024 #include <stdio.h> -00025 #ifdef THREADED_DNS -00026 #include <pthread.h> -00027 #include <signal.h> -00028 #endif -00029 #include "inspstring.h" -00030 #include "commands.h" -00031 #include "helperfuncs.h" -00032 #include "typedefs.h" -00033 #include "socketengine.h" -00034 #include "hashcomp.h" -00035 #include "message.h" -00036 #include "wildcard.h" -00037 #include "xline.h" -00038 -00039 extern InspIRCd* ServerInstance; -00040 extern int WHOWAS_STALE; -00041 extern int WHOWAS_MAX; -00042 extern std::vector<Module*> modules; -00043 extern std::vector<ircd_module*> factory; -00044 extern std::vector<InspSocket*> module_sockets; -00045 extern int MODCOUNT; -00046 extern InspSocket* socket_ref[65535]; -00047 extern time_t TIME; -00048 extern userrec* fd_ref_table[65536]; -00049 extern ServerConfig *Config; -00050 extern user_hash clientlist; -00051 extern whowas_hash whowas; -00052 std::vector<userrec*> local_users; -00053 -00054 std::vector<userrec*> all_opers; -00055 -00056 template<typename T> inline string ConvToStr(const T &in) -00057 { -00058 stringstream tmp; -00059 if (!(tmp << in)) return string(); -00060 return tmp.str(); -00061 } -00062 -00063 userrec::userrec() -00064 { -00065 // the PROPER way to do it, AVOID bzero at *ALL* costs -00066 strcpy(nick,""); -00067 strcpy(ip,"127.0.0.1"); -00068 timeout = 0; -00069 strcpy(ident,""); -00070 strcpy(host,""); -00071 strcpy(dhost,""); -00072 strcpy(fullname,""); -00073 strcpy(modes,""); -00074 server = (char*)FindServerNamePtr(Config->ServerName); -00075 strcpy(awaymsg,""); -00076 strcpy(oper,""); -00077 reset_due = TIME; -00078 lines_in = 0; -00079 fd = lastping = signon = idle_lastmsg = nping = registered = 0; -00080 flood = port = bytes_in = bytes_out = cmds_in = cmds_out = 0; -00081 haspassed = false; -00082 dns_done = false; -00083 recvq = ""; -00084 sendq = ""; -00085 chans.clear(); -00086 invites.clear(); -00087 } -00088 -00089 userrec::~userrec() -00090 { -00091 } -00092 -00093 void userrec::CloseSocket() -00094 { -00095 shutdown(this->fd,2); -00096 close(this->fd); -00097 } -00098 -00099 char* userrec::GetFullHost() -00100 { -00101 static char result[MAXBUF]; -00102 snprintf(result,MAXBUF,"%s!%s@%s",nick,ident,dhost); -00103 return result; -00104 } -00105 -00106 int userrec::ReadData(void* buffer, size_t size) -00107 { -00108 if (this->fd > -1) -00109 { -00110 return read(this->fd, buffer, size); -00111 } -00112 else return 0; -00113 } -00114 -00115 -00116 char* userrec::GetFullRealHost() -00117 { -00118 static char fresult[MAXBUF]; -00119 snprintf(fresult,MAXBUF,"%s!%s@%s",nick,ident,host); -00120 return fresult; -00121 } -00122 -00123 bool userrec::IsInvited(irc::string &channel) -00124 { -00125 for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++) -00126 { -00127 irc::string compare = i->channel; -00128 if (compare == channel) -00129 { -00130 return true; -00131 } -00132 } -00133 return false; -00134 } -00135 -00136 InvitedList* userrec::GetInviteList() -00137 { -00138 return &invites; -00139 } -00140 -00141 void userrec::InviteTo(irc::string &channel) -00142 { -00143 Invited i; -00144 i.channel = channel; -00145 invites.push_back(i); -00146 } -00147 -00148 void userrec::RemoveInvite(irc::string &channel) -00149 { -00150 log(DEBUG,"Removing invites"); -00151 if (invites.size()) -00152 { -00153 for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++) -00154 { -00155 irc::string compare = i->channel; -00156 if (compare == channel) -00157 { -00158 invites.erase(i); -00159 return; -00160 } -00161 } -00162 } -00163 } -00164 -00165 bool userrec::HasPermission(std::string &command) -00166 { -00167 char TypeName[MAXBUF],Classes[MAXBUF],ClassName[MAXBUF],CommandList[MAXBUF]; -00168 char* mycmd; -00169 char* savept; -00170 char* savept2; -00171 -00172 // users on u-lined servers can completely bypass -00173 // all permissions based checks. -00174 // -00175 // of course, if this is sent to a remote server and this -00176 // server is not ulined there, then that other server -00177 // silently drops the command. -00178 if (is_uline(this->server)) -00179 return true; -00180 -00181 // are they even an oper at all? -00182 if (strchr(this->modes,'o')) -00183 { -00184 for (int j =0; j < Config->ConfValueEnum("type",&Config->config_f); j++) -00185 { -00186 Config->ConfValue("type","name",j,TypeName,&Config->config_f); -00187 if (!strcmp(TypeName,this->oper)) -00188 { -00189 Config->ConfValue("type","classes",j,Classes,&Config->config_f); -00190 char* myclass = strtok_r(Classes," ",&savept); -00191 while (myclass) -00192 { -00193 for (int k =0; k < Config->ConfValueEnum("class",&Config->config_f); k++) -00194 { -00195 Config->ConfValue("class","name",k,ClassName,&Config->config_f); -00196 if (!strcmp(ClassName,myclass)) -00197 { -00198 Config->ConfValue("class","commands",k,CommandList,&Config->config_f); -00199 mycmd = strtok_r(CommandList," ",&savept2); -00200 while (mycmd) -00201 { -00202 if ((!strcasecmp(mycmd,command.c_str())) || (*mycmd == '*')) -00203 { -00204 return true; -00205 } -00206 mycmd = strtok_r(NULL," ",&savept2); -00207 } -00208 } -00209 } -00210 myclass = strtok_r(NULL," ",&savept); -00211 } -00212 } -00213 } -00214 } -00215 return false; -00216 } -00217 -00218 -00219 bool userrec::AddBuffer(std::string a) -00220 { -00221 std::string b = ""; -00222 for (unsigned int i = 0; i < a.length(); i++) -00223 if ((a[i] != '\r') && (a[i] != '\0') && (a[i] != 7)) -00224 b = b + a[i]; -00225 std::stringstream stream(recvq); -00226 stream << b; -00227 recvq = stream.str(); -00228 unsigned int i = 0; -00229 // count the size of the first line in the buffer. -00230 while (i < recvq.length()) -00231 { -00232 if (recvq[i++] == '\n') -00233 break; -00234 } -00235 if (recvq.length() > (unsigned)this->recvqmax) -00236 { -00237 this->SetWriteError("RecvQ exceeded"); -00238 WriteOpers("*** User %s RecvQ of %d exceeds connect class maximum of %d",this->nick,recvq.length(),this->recvqmax); -00239 } -00240 // return false if we've had more than 600 characters WITHOUT -00241 // a carriage return (this is BAD, drop the socket) -00242 return (i < 600); -00243 } -00244 -00245 bool userrec::BufferIsReady() -00246 { -00247 for (unsigned int i = 0; i < recvq.length(); i++) -00248 if (recvq[i] == '\n') -00249 return true; -00250 return false; -00251 } -00252 -00253 void userrec::ClearBuffer() -00254 { -00255 recvq = ""; -00256 } -00257 -00258 std::string userrec::GetBuffer() -00259 { -00260 if (recvq == "") -00261 return ""; -00262 char* line = (char*)recvq.c_str(); -00263 std::string ret = ""; -00264 while ((*line != '\n') && (strlen(line))) -00265 { -00266 ret = ret + *line; -00267 line++; -00268 } -00269 if ((*line == '\n') || (*line == '\r')) -00270 line++; -00271 recvq = line; -00272 return ret; -00273 } -00274 -00275 void userrec::AddWriteBuf(std::string data) -00276 { -00277 if (this->GetWriteError() != "") -00278 return; -00279 if (sendq.length() + data.length() > (unsigned)this->sendqmax) -00280 { -00281 /* Fix by brain - Set the error text BEFORE calling writeopers, because -00282 * if we dont it'll recursively call here over and over again trying -00283 * to repeatedly add the text to the sendq! -00284 */ -00285 this->SetWriteError("SendQ exceeded"); -00286 WriteOpers("*** User %s SendQ of %d exceeds connect class maximum of %d",this->nick,sendq.length() + data.length(),this->sendqmax); -00287 return; -00288 } -00289 std::stringstream stream; -00290 stream << sendq << data; -00291 sendq = stream.str(); -00292 } -00293 -00294 // send AS MUCH OF THE USERS SENDQ as we are able to (might not be all of it) -00295 void userrec::FlushWriteBuf() -00296 { -00297 if (sendq.length()) -00298 { -00299 char* tb = (char*)this->sendq.c_str(); -00300 int n_sent = write(this->fd,tb,this->sendq.length()); -00301 if (n_sent == -1) -00302 { -00303 this->SetWriteError(strerror(errno)); -00304 } -00305 else -00306 { -00307 // advance the queue -00308 tb += n_sent; -00309 this->sendq = tb; -00310 // update the user's stats counters -00311 this->bytes_out += n_sent; -00312 this->cmds_out++; -00313 } -00314 } -00315 } -00316 -00317 void userrec::SetWriteError(std::string error) -00318 { -00319 log(DEBUG,"Setting error string for %s to '%s'",this->nick,error.c_str()); -00320 // don't try to set the error twice, its already set take the first string. -00321 if (this->WriteError == "") -00322 this->WriteError = error; -00323 } -00324 -00325 std::string userrec::GetWriteError() -00326 { -00327 return this->WriteError; -00328 } -00329 -00330 void AddOper(userrec* user) -00331 { -00332 log(DEBUG,"Oper added to optimization list"); -00333 all_opers.push_back(user); -00334 } -00335 -00336 void DeleteOper(userrec* user) -00337 { -00338 for (std::vector<userrec*>::iterator a = all_opers.begin(); a < all_opers.end(); a++) -00339 { -00340 if (*a == user) -00341 { -00342 log(DEBUG,"Oper removed from optimization list"); -00343 all_opers.erase(a); -00344 return; -00345 } -00346 } -00347 } -00348 -00349 void kill_link(userrec *user,const char* r) -00350 { -00351 user_hash::iterator iter = clientlist.find(user->nick); -00352 -00353 char reason[MAXBUF]; -00354 -00355 strncpy(reason,r,MAXBUF); -00356 -00357 if (strlen(reason)>MAXQUIT) -00358 { -00359 reason[MAXQUIT-1] = '\0'; -00360 } -00361 -00362 log(DEBUG,"kill_link: %s '%s'",user->nick,reason); -00363 Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason); -00364 log(DEBUG,"closing fd %lu",(unsigned long)user->fd); -00365 -00366 if (user->registered == 7) { -00367 FOREACH_MOD OnUserQuit(user,reason); -00368 WriteCommonExcept(user,"QUIT :%s",reason); -00369 } -00370 -00371 user->FlushWriteBuf(); -00372 -00373 FOREACH_MOD OnUserDisconnect(user); -00374 -00375 if (user->fd > -1) -00376 { -00377 if (Config->GetIOHook(user->port)) -00378 { -00379 Config->GetIOHook(user->port)->OnRawSocketClose(user->fd); -00380 } -00381 ServerInstance->SE->DelFd(user->fd); -00382 user->CloseSocket(); -00383 } -00384 -00385 // this must come before the WriteOpers so that it doesnt try to fill their buffer with anything -00386 // if they were an oper with +s. -00387 if (user->registered == 7) { -00388 purge_empty_chans(user); -00389 // fix by brain: only show local quits because we only show local connects (it just makes SENSE) -00390 if (user->fd > -1) -00391 WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason); -00392 AddWhoWas(user); -00393 } -00394 -00395 if (iter != clientlist.end()) -00396 { -00397 log(DEBUG,"deleting user hash value %lu",(unsigned long)user); -00398 if (user->fd > -1) -00399 { -00400 fd_ref_table[user->fd] = NULL; -00401 if (find(local_users.begin(),local_users.end(),user) != local_users.end()) -00402 { -00403 local_users.erase(find(local_users.begin(),local_users.end(),user)); -00404 log(DEBUG,"Delete local user"); -00405 } -00406 } -00407 clientlist.erase(iter); -00408 } -00409 delete user; -00410 } -00411 -00412 void kill_link_silent(userrec *user,const char* r) -00413 { -00414 user_hash::iterator iter = clientlist.find(user->nick); -00415 -00416 char reason[MAXBUF]; -00417 -00418 strncpy(reason,r,MAXBUF); -00419 -00420 if (strlen(reason)>MAXQUIT) -00421 { -00422 reason[MAXQUIT-1] = '\0'; -00423 } -00424 -00425 log(DEBUG,"kill_link: %s '%s'",user->nick,reason); -00426 Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason); -00427 log(DEBUG,"closing fd %lu",(unsigned long)user->fd); -00428 -00429 user->FlushWriteBuf(); -00430 -00431 if (user->registered == 7) { -00432 FOREACH_MOD OnUserQuit(user,reason); -00433 WriteCommonExcept(user,"QUIT :%s",reason); -00434 } -00435 -00436 FOREACH_MOD OnUserDisconnect(user); -00437 -00438 if (user->fd > -1) -00439 { -00440 if (Config->GetIOHook(user->port)) -00441 { -00442 Config->GetIOHook(user->port)->OnRawSocketClose(user->fd); -00443 } -00444 ServerInstance->SE->DelFd(user->fd); -00445 user->CloseSocket(); -00446 } -00447 -00448 if (user->registered == 7) { -00449 purge_empty_chans(user); -00450 } -00451 -00452 if (iter != clientlist.end()) -00453 { -00454 log(DEBUG,"deleting user hash value %lu",(unsigned long)user); -00455 if (user->fd > -1) -00456 { -00457 fd_ref_table[user->fd] = NULL; -00458 if (find(local_users.begin(),local_users.end(),user) != local_users.end()) -00459 { -00460 log(DEBUG,"Delete local user"); -00461 local_users.erase(find(local_users.begin(),local_users.end(),user)); -00462 } -00463 } -00464 clientlist.erase(iter); -00465 } -00466 delete user; -00467 } -00468 -00469 -00470 /* adds or updates an entry in the whowas list */ -00471 void AddWhoWas(userrec* u) -00472 { -00473 whowas_hash::iterator iter = whowas.find(u->nick); -00474 WhoWasUser *a = new WhoWasUser(); -00475 strlcpy(a->nick,u->nick,NICKMAX); -00476 strlcpy(a->ident,u->ident,IDENTMAX); -00477 strlcpy(a->dhost,u->dhost,160); -00478 strlcpy(a->host,u->host,160); -00479 strlcpy(a->fullname,u->fullname,MAXGECOS); -00480 strlcpy(a->server,u->server,256); -00481 a->signon = u->signon; -00482 -00483 /* MAX_WHOWAS: max number of /WHOWAS items -00484 * WHOWAS_STALE: number of hours before a WHOWAS item is marked as stale and -00485 * can be replaced by a newer one -00486 */ -00487 -00488 if (iter == whowas.end()) -00489 { -00490 if (whowas.size() >= (unsigned)WHOWAS_MAX) -00491 { -00492 for (whowas_hash::iterator i = whowas.begin(); i != whowas.end(); i++) -00493 { -00494 // 3600 seconds in an hour ;) -00495 if ((i->second->signon)<(TIME-(WHOWAS_STALE*3600))) -00496 { -00497 // delete the old one -00498 if (i->second) delete i->second; -00499 // replace with new one -00500 i->second = a; -00501 log(DEBUG,"added WHOWAS entry, purged an old record"); -00502 return; -00503 } -00504 } -00505 // no space left and user doesnt exist. Don't leave ram in use! -00506 log(DEBUG,"Not able to update whowas (list at WHOWAS_MAX entries and trying to add new?), freeing excess ram"); -00507 delete a; -00508 } -00509 else -00510 { -00511 log(DEBUG,"added fresh WHOWAS entry"); -00512 whowas[a->nick] = a; -00513 } -00514 } -00515 else -00516 { -00517 log(DEBUG,"updated WHOWAS entry"); -00518 if (iter->second) delete iter->second; -00519 iter->second = a; -00520 } -00521 } -00522 -00523 /* add a client connection to the sockets list */ -00524 void AddClient(int socket, char* host, int port, bool iscached, char* ip) -00525 { -00526 string tempnick; -00527 char tn2[MAXBUF]; -00528 user_hash::iterator iter; -00529 -00530 tempnick = ConvToStr(socket) + "-unknown"; -00531 sprintf(tn2,"%lu-unknown",(unsigned long)socket); -00532 -00533 iter = clientlist.find(tempnick); -00534 -00535 // fix by brain. -00536 // as these nicknames are 'RFC impossible', we can be sure nobody is going to be -00537 // using one as a registered connection. As theyre per fd, we can also safely assume -00538 // that we wont have collisions. Therefore, if the nick exists in the list, its only -00539 // used by a dead socket, erase the iterator so that the new client may reclaim it. -00540 // this was probably the cause of 'server ignores me when i hammer it with reconnects' -00541 // issue in earlier alphas/betas -00542 if (iter != clientlist.end()) -00543 { -00544 userrec* goner = iter->second; -00545 delete goner; -00546 clientlist.erase(iter); -00547 } -00548 -00549 /* -00550 * It is OK to access the value here this way since we know -00551 * it exists, we just created it above. -00552 * -00553 * At NO other time should you access a value in a map or a -00554 * hash_map this way. -00555 */ -00556 clientlist[tempnick] = new userrec(); -00557 -00558 log(DEBUG,"AddClient: %lu %s %d %s",(unsigned long)socket,host,port,ip); -00559 -00560 clientlist[tempnick]->fd = socket; -00561 strlcpy(clientlist[tempnick]->nick, tn2,NICKMAX); -00562 strlcpy(clientlist[tempnick]->host, host,160); -00563 strlcpy(clientlist[tempnick]->dhost, host,160); -00564 clientlist[tempnick]->server = (char*)FindServerNamePtr(Config->ServerName); -00565 strlcpy(clientlist[tempnick]->ident, "unknown",IDENTMAX); -00566 clientlist[tempnick]->registered = 0; -00567 clientlist[tempnick]->signon = TIME + Config->dns_timeout; -00568 clientlist[tempnick]->lastping = 1; -00569 clientlist[tempnick]->port = port; -00570 strlcpy(clientlist[tempnick]->ip,ip,16); -00571 -00572 // set the registration timeout for this user -00573 unsigned long class_regtimeout = 90; -00574 int class_flood = 0; -00575 long class_threshold = 5; -00576 long class_sqmax = 262144; // 256kb -00577 long class_rqmax = 4096; // 4k -00578 -00579 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++) -00580 { -00581 if (match(clientlist[tempnick]->host,i->host) && (i->type == CC_ALLOW)) -00582 { -00583 class_regtimeout = (unsigned long)i->registration_timeout; -00584 class_flood = i->flood; -00585 clientlist[tempnick]->pingmax = i->pingtime; -00586 class_threshold = i->threshold; -00587 class_sqmax = i->sendqmax; -00588 class_rqmax = i->recvqmax; -00589 break; -00590 } -00591 } -00592 -00593 clientlist[tempnick]->nping = TIME+clientlist[tempnick]->pingmax + Config->dns_timeout; -00594 clientlist[tempnick]->timeout = TIME+class_regtimeout; -00595 clientlist[tempnick]->flood = class_flood; -00596 clientlist[tempnick]->threshold = class_threshold; -00597 clientlist[tempnick]->sendqmax = class_sqmax; -00598 clientlist[tempnick]->recvqmax = class_rqmax; -00599 -00600 ucrec a; -00601 a.channel = NULL; -00602 a.uc_modes = 0; -00603 for (int i = 0; i < MAXCHANS; i++) -00604 clientlist[tempnick]->chans.push_back(a); -00605 -00606 if (clientlist.size() > Config->SoftLimit) -00607 { -00608 kill_link(clientlist[tempnick],"No more connections allowed"); -00609 return; -00610 } -00611 -00612 if (clientlist.size() >= MAXCLIENTS) -00613 { -00614 kill_link(clientlist[tempnick],"No more connections allowed"); -00615 return; -00616 } -00617 -00618 // this is done as a safety check to keep the file descriptors within range of fd_ref_table. -00619 // its a pretty big but for the moment valid assumption: -00620 // file descriptors are handed out starting at 0, and are recycled as theyre freed. -00621 // therefore if there is ever an fd over 65535, 65536 clients must be connected to the -00622 // irc server at once (or the irc server otherwise initiating this many connections, files etc) -00623 // which for the time being is a physical impossibility (even the largest networks dont have more -00624 // than about 10,000 users on ONE server!) -00625 if ((unsigned)socket > 65534) -00626 { -00627 kill_link(clientlist[tempnick],"Server is full"); -00628 return; -00629 } -00630 char* e = matches_exception(ip); -00631 if (!e) -00632 { -00633 char* r = matches_zline(ip); -00634 if (r) -00635 { -00636 char reason[MAXBUF]; -00637 snprintf(reason,MAXBUF,"Z-Lined: %s",r); -00638 kill_link(clientlist[tempnick],reason); -00639 return; -00640 } -00641 } -00642 fd_ref_table[socket] = clientlist[tempnick]; -00643 local_users.push_back(clientlist[tempnick]); -00644 ServerInstance->SE->AddFd(socket,true,X_ESTAB_CLIENT); -00645 } -00646 -00647 void FullConnectUser(userrec* user) -00648 { -00649 ServerInstance->stats->statsConnects++; -00650 user->idle_lastmsg = TIME; -00651 log(DEBUG,"ConnectUser: %s",user->nick); -00652 -00653 if ((strcmp(Passwd(user),"")) && (!user->haspassed)) -00654 { -00655 kill_link(user,"Invalid password"); -00656 return; -00657 } -00658 if (IsDenied(user)) -00659 { -00660 kill_link(user,"Unauthorised connection"); -00661 return; -00662 } -00663 -00664 char match_against[MAXBUF]; -00665 snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host); -00666 char* e = matches_exception(match_against); -00667 if (!e) -00668 { -00669 char* r = matches_gline(match_against); -00670 if (r) -00671 { -00672 char reason[MAXBUF]; -00673 snprintf(reason,MAXBUF,"G-Lined: %s",r); -00674 kill_link_silent(user,reason); -00675 return; -00676 } -00677 r = matches_kline(user->host); -00678 if (r) -00679 { -00680 char reason[MAXBUF]; -00681 snprintf(reason,MAXBUF,"K-Lined: %s",r); -00682 kill_link_silent(user,reason); -00683 return; -00684 } -00685 } -00686 -00687 -00688 WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Config->Network); -00689 WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Config->Network,user->nick,user->ident,user->host); -00690 WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,Config->ServerName,VERSION); -00691 WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__); -00692 WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,Config->ServerName,VERSION); -00693 // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it... -00694 std::stringstream v; -00695 v << "WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS; -00696 v << " MAXBANS=60 NICKLEN=" << NICKMAX; -00697 v << " TOPICLEN=" << MAXTOPIC << " KICKLEN=" << MAXKICK << " MAXTARGETS=20 AWAYLEN=" << MAXAWAY << " CHANMODES=ohvb,k,l,psmnti NETWORK="; -00698 v << Config->Network; -00699 std::string data005 = v.str(); -00700 FOREACH_MOD On005Numeric(data005); -00701 // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line... -00702 // so i'd better split it :) -00703 std::stringstream out(data005); -00704 std::string token = ""; -00705 std::string line5 = ""; -00706 int token_counter = 0; -00707 while (!out.eof()) -00708 { -00709 out >> token; -00710 line5 = line5 + token + " "; -00711 token_counter++; -00712 if ((token_counter >= 13) || (out.eof() == true)) -00713 { -00714 WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str()); -00715 line5 = ""; -00716 token_counter = 0; -00717 } -00718 } -00719 ShowMOTD(user); -00720 -00721 // fix 3 by brain, move registered = 7 below these so that spurious modes and host changes dont go out -00722 // onto the network and produce 'fake direction' -00723 FOREACH_MOD OnUserConnect(user); -00724 FOREACH_MOD OnGlobalConnect(user); -00725 user->registered = 7; -00726 WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,user->ip); -00727 } -00728 -00729 -00730 /* shows the message of the day, and any other on-logon stuff */ -00731 void ConnectUser(userrec *user) -00732 { -00733 // dns is already done, things are fast. no need to wait for dns to complete just pass them straight on -00734 if ((user->dns_done) && (user->registered >= 3) && (AllModulesReportReady(user))) -00735 { -00736 FullConnectUser(user); -00737 } -00738 } -00739 -00740 /* re-allocates a nick in the user_hash after they change nicknames, -00741 * returns a pointer to the new user as it may have moved */ -00742 -00743 userrec* ReHashNick(char* Old, char* New) -00744 { -00745 //user_hash::iterator newnick; -00746 user_hash::iterator oldnick = clientlist.find(Old); -00747 -00748 log(DEBUG,"ReHashNick: %s %s",Old,New); -00749 -00750 if (!strcasecmp(Old,New)) -00751 { -00752 log(DEBUG,"old nick is new nick, skipping"); -00753 return oldnick->second; -00754 } -00755 -00756 if (oldnick == clientlist.end()) return NULL; /* doesnt exist */ -00757 -00758 log(DEBUG,"ReHashNick: Found hashed nick %s",Old); -00759 -00760 userrec* olduser = oldnick->second; -00761 clientlist[New] = olduser; -00762 clientlist.erase(oldnick); -00763 -00764 log(DEBUG,"ReHashNick: Nick rehashed as %s",New); -00765 -00766 return clientlist[New]; -00767 } -00768 -00769 void force_nickchange(userrec* user,const char* newnick) -00770 { -00771 char nick[MAXBUF]; -00772 int MOD_RESULT = 0; -00773 -00774 strcpy(nick,""); -00775 -00776 FOREACH_RESULT(OnUserPreNick(user,newnick)); -00777 if (MOD_RESULT) { -00778 ServerInstance->stats->statsCollisions++; -00779 kill_link(user,"Nickname collision"); -00780 return; -00781 } -00782 if (matches_qline(newnick)) -00783 { -00784 ServerInstance->stats->statsCollisions++; -00785 kill_link(user,"Nickname collision"); -00786 return; -00787 } -00788 -00789 if (user) -00790 { -00791 if (newnick) -00792 { -00793 strncpy(nick,newnick,MAXBUF); -00794 } -00795 if (user->registered == 7) -00796 { -00797 char* pars[1]; -00798 pars[0] = nick; -00799 std::string cmd = "NICK"; -00800 ServerInstance->Parser->CallHandler(cmd,pars,1,user); -00801 } -00802 } -00803 } -00804 -
1.4.4-20050815
-
-
--
cgit v1.3.1-10-gc9f91