00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "inspircd.h"
00017 #include "configreader.h"
00018 #include "users.h"
00019 #include "channels.h"
00020 #include "modules.h"
00021 #include "commands/cmd_whois.h"
00022 #include "commands/cmd_stats.h"
00023 #include "socket.h"
00024 #include "wildcard.h"
00025 #include "xline.h"
00026 #include "transport.h"
00027
00028 #include "m_spanningtree/timesynctimer.h"
00029 #include "m_spanningtree/resolvers.h"
00030 #include "m_spanningtree/main.h"
00031 #include "m_spanningtree/utils.h"
00032 #include "m_spanningtree/treeserver.h"
00033 #include "m_spanningtree/link.h"
00034 #include "m_spanningtree/treesocket.h"
00035 #include "m_spanningtree/rconnect.h"
00036 #include "m_spanningtree/rsquit.h"
00037
00038
00039
00040 ModuleSpanningTree::ModuleSpanningTree(InspIRCd* Me)
00041 : Module(Me), max_local(0), max_global(0)
00042 {
00043 ServerInstance->UseInterface("InspSocketHook");
00044 Utils = new SpanningTreeUtilities(Me, this);
00045 command_rconnect = new cmd_rconnect(ServerInstance, this, Utils);
00046 ServerInstance->AddCommand(command_rconnect);
00047 command_rsquit = new cmd_rsquit(ServerInstance, this, Utils);
00048 ServerInstance->AddCommand(command_rsquit);
00049 }
00050
00051 void ModuleSpanningTree::ShowLinks(TreeServer* Current, userrec* user, int hops)
00052 {
00053 std::string Parent = Utils->TreeRoot->GetName();
00054 if (Current->GetParent())
00055 {
00056 Parent = Current->GetParent()->GetName();
00057 }
00058 for (unsigned int q = 0; q < Current->ChildCount(); q++)
00059 {
00060 if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str()))))
00061 {
00062 if (*user->oper)
00063 {
00064 ShowLinks(Current->GetChild(q),user,hops+1);
00065 }
00066 }
00067 else
00068 {
00069 ShowLinks(Current->GetChild(q),user,hops+1);
00070 }
00071 }
00072
00073 if ((Utils->HideULines) && (ServerInstance->ULine(Current->GetName().c_str())) && (!IS_OPER(user)))
00074 return;
00075
00076 else if ((Current->Hidden) && (!IS_OPER(user)))
00077 return;
00078
00079 user->WriteServ("364 %s %s %s :%d %s", user->nick,Current->GetName().c_str(),
00080 (Utils->FlatLinks && (!IS_OPER(user))) ? ServerInstance->Config->ServerName : Parent.c_str(),
00081 (Utils->FlatLinks && (!IS_OPER(user))) ? 0 : hops,
00082 Current->GetDesc().c_str());
00083 }
00084
00085 int ModuleSpanningTree::CountLocalServs()
00086 {
00087 return Utils->TreeRoot->ChildCount();
00088 }
00089
00090 int ModuleSpanningTree::CountServs()
00091 {
00092 return Utils->serverlist.size();
00093 }
00094
00095 void ModuleSpanningTree::HandleLinks(const char** parameters, int pcnt, userrec* user)
00096 {
00097 ShowLinks(Utils->TreeRoot,user,0);
00098 user->WriteServ("365 %s * :End of /LINKS list.",user->nick);
00099 return;
00100 }
00101
00102 void ModuleSpanningTree::HandleLusers(const char** parameters, int pcnt, userrec* user)
00103 {
00104 unsigned int n_users = ServerInstance->UserCount();
00105
00106
00107 if ((unsigned int)ServerInstance->LocalUserCount() > max_local)
00108 max_local = ServerInstance->LocalUserCount();
00109 if (n_users > max_global)
00110 max_global = n_users;
00111
00112 unsigned int ulined_count = 0;
00113 unsigned int ulined_local_count = 0;
00114
00115
00116
00117
00118 if ((Utils->HideULines) && (!*user->oper))
00119 {
00120 for (server_hash::iterator q = Utils->serverlist.begin(); q != Utils->serverlist.end(); q++)
00121 {
00122 if (ServerInstance->ULine(q->second->GetName().c_str()))
00123 {
00124 ulined_count++;
00125 if (q->second->GetParent() == Utils->TreeRoot)
00126 ulined_local_count++;
00127 }
00128 }
00129 }
00130 user->WriteServ("251 %s :There are %d users and %d invisible on %d servers",user->nick,
00131 n_users-ServerInstance->InvisibleUserCount(),
00132 ServerInstance->InvisibleUserCount(),
00133 ulined_count ? this->CountServs() - ulined_count : this->CountServs());
00134
00135 if (ServerInstance->OperCount())
00136 user->WriteServ("252 %s %d :operator(s) online",user->nick,ServerInstance->OperCount());
00137
00138 if (ServerInstance->UnregisteredUserCount())
00139 user->WriteServ("253 %s %d :unknown connections",user->nick,ServerInstance->UnregisteredUserCount());
00140
00141 if (ServerInstance->ChannelCount())
00142 user->WriteServ("254 %s %d :channels formed",user->nick,ServerInstance->ChannelCount());
00143
00144 user->WriteServ("255 %s :I have %d clients and %d servers",user->nick,ServerInstance->LocalUserCount(),ulined_local_count ? this->CountLocalServs() - ulined_local_count : this->CountLocalServs());
00145 user->WriteServ("265 %s :Current Local Users: %d Max: %d",user->nick,ServerInstance->LocalUserCount(),max_local);
00146 user->WriteServ("266 %s :Current Global Users: %d Max: %d",user->nick,n_users,max_global);
00147 return;
00148 }
00149
00150 std::string ModuleSpanningTree::TimeToStr(time_t secs)
00151 {
00152 time_t mins_up = secs / 60;
00153 time_t hours_up = mins_up / 60;
00154 time_t days_up = hours_up / 24;
00155 secs = secs % 60;
00156 mins_up = mins_up % 60;
00157 hours_up = hours_up % 24;
00158 return ((days_up ? (ConvToStr(days_up) + "d") : std::string(""))
00159 + (hours_up ? (ConvToStr(hours_up) + "h") : std::string(""))
00160 + (mins_up ? (ConvToStr(mins_up) + "m") : std::string(""))
00161 + ConvToStr(secs) + "s");
00162 }
00163
00164 const std::string ModuleSpanningTree::MapOperInfo(TreeServer* Current)
00165 {
00166 time_t secs_up = ServerInstance->Time() - Current->age;
00167 return (" [Up: " + TimeToStr(secs_up) + " Lag: "+ConvToStr(Current->rtt)+"ms]");
00168 }
00169
00170
00171 void ModuleSpanningTree::ShowMap(TreeServer* Current, userrec* user, int depth, char matrix[250][250], float &totusers, float &totservers)
00172 {
00173 if (line < 250)
00174 {
00175 for (int t = 0; t < depth; t++)
00176 {
00177 matrix[line][t] = ' ';
00178 }
00179
00180
00181 char spacer[80];
00182 memset(spacer,' ',80);
00183 if ((80 - Current->GetName().length() - depth) > 1) {
00184 spacer[80 - Current->GetName().length() - depth] = '\0';
00185 }
00186 else
00187 {
00188 spacer[5] = '\0';
00189 }
00190 float percent;
00191 char text[250];
00192
00193 memset(text, 0, 250);
00194
00195 if (ServerInstance->clientlist->size() == 0) {
00196
00197 percent = 0;
00198 }
00199 else
00200 {
00201 percent = ((float)Current->GetUserCount() / (float)ServerInstance->clientlist->size()) * 100;
00202 }
00203 const std::string operdata = IS_OPER(user) ? MapOperInfo(Current) : "";
00204 snprintf(text, 249, "%s %s%5d [%5.2f%%]%s", Current->GetName().c_str(), spacer, Current->GetUserCount(), percent, operdata.c_str());
00205 totusers += Current->GetUserCount();
00206 totservers++;
00207 strlcpy(&matrix[line][depth], text, 249);
00208 line++;
00209 for (unsigned int q = 0; q < Current->ChildCount(); q++)
00210 {
00211 if ((Current->GetChild(q)->Hidden) || ((Utils->HideULines) && (ServerInstance->ULine(Current->GetChild(q)->GetName().c_str()))))
00212 {
00213 if (*user->oper)
00214 {
00215 ShowMap(Current->GetChild(q),user,(Utils->FlatLinks && (!*user->oper)) ? depth : depth+2,matrix,totusers,totservers);
00216 }
00217 }
00218 else
00219 {
00220 ShowMap(Current->GetChild(q),user,(Utils->FlatLinks && (!*user->oper)) ? depth : depth+2,matrix,totusers,totservers);
00221 }
00222 }
00223 }
00224 }
00225
00226 int ModuleSpanningTree::HandleMotd(const char** parameters, int pcnt, userrec* user)
00227 {
00228 if (pcnt > 0)
00229 {
00230 if (match(ServerInstance->Config->ServerName, parameters[0]))
00231 return 0;
00232
00233
00234 std::deque<std::string> params;
00235 params.push_back(parameters[0]);
00236
00237 TreeServer* s = Utils->FindServerMask(parameters[0]);
00238 if (s)
00239 {
00240 params[0] = s->GetName();
00241 Utils->DoOneToOne(user->nick, "MOTD", params, s->GetName());
00242 }
00243 else
00244 user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
00245 return 1;
00246 }
00247 return 0;
00248 }
00249
00250 int ModuleSpanningTree::HandleAdmin(const char** parameters, int pcnt, userrec* user)
00251 {
00252 if (pcnt > 0)
00253 {
00254 if (match(ServerInstance->Config->ServerName, parameters[0]))
00255 return 0;
00256
00257
00258 std::deque<std::string> params;
00259 params.push_back(parameters[0]);
00260
00261 TreeServer* s = Utils->FindServerMask(parameters[0]);
00262 if (s)
00263 {
00264 params[0] = s->GetName();
00265 Utils->DoOneToOne(user->nick, "ADMIN", params, s->GetName());
00266 }
00267 else
00268 user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
00269 return 1;
00270 }
00271 return 0;
00272 }
00273
00274 int ModuleSpanningTree::HandleModules(const char** parameters, int pcnt, userrec* user)
00275 {
00276 if (pcnt > 0)
00277 {
00278 if (match(ServerInstance->Config->ServerName, parameters[0]))
00279 return 0;
00280
00281 std::deque<std::string> params;
00282 params.push_back(parameters[0]);
00283 TreeServer* s = Utils->FindServerMask(parameters[0]);
00284 if (s)
00285 {
00286 params[0] = s->GetName();
00287 Utils->DoOneToOne(user->nick, "MODULES", params, s->GetName());
00288 }
00289 else
00290 user->WriteServ( "402 %s %s :No such server", user->nick, parameters[0]);
00291 return 1;
00292 }
00293 return 0;
00294 }
00295
00296 int ModuleSpanningTree::HandleStats(const char** parameters, int pcnt, userrec* user)
00297 {
00298 if (pcnt > 1)
00299 {
00300 if (match(ServerInstance->Config->ServerName, parameters[1]))
00301 return 0;
00302
00303
00304 std::deque<std::string> params;
00305 params.push_back(parameters[0]);
00306 params.push_back(parameters[1]);
00307
00308
00309 TreeServer* s = Utils->FindServerMask(parameters[1]);
00310 if (s)
00311 {
00312 params[1] = s->GetName();
00313 Utils->DoOneToOne(user->nick, "STATS", params, s->GetName());
00314 }
00315 else
00316 {
00317 user->WriteServ( "402 %s %s :No such server", user->nick, parameters[1]);
00318 }
00319 return 1;
00320 }
00321 return 0;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 void ModuleSpanningTree::HandleMap(const char** parameters, int pcnt, userrec* user)
00333 {
00334
00335
00336
00337 float totusers = 0;
00338 float totservers = 0;
00339 char matrix[250][250];
00340 for (unsigned int t = 0; t < 250; t++)
00341 {
00342 matrix[t][0] = '\0';
00343 }
00344 line = 0;
00345
00346 ShowMap(Utils->TreeRoot,user,0,matrix,totusers,totservers);
00347
00348
00349
00350
00351 for (int l = 1; l < line; l++)
00352 {
00353
00354
00355
00356
00357 int first_nonspace = 0;
00358 while (matrix[l][first_nonspace] == ' ')
00359 {
00360 first_nonspace++;
00361 }
00362 first_nonspace--;
00363
00364
00365
00366 matrix[l][first_nonspace] = '-';
00367 matrix[l][first_nonspace-1] = '`';
00368 int l2 = l - 1;
00369
00370
00371 while ((matrix[l2][first_nonspace-1] == ' ') || (matrix[l2][first_nonspace-1] == '`'))
00372 {
00373 matrix[l2][first_nonspace-1] = '|';
00374 l2--;
00375 }
00376 }
00377
00378 for (int t = 0; t < line; t++)
00379 {
00380 user->WriteServ("006 %s :%s",user->nick,&matrix[t][0]);
00381 }
00382 float avg_users = totusers / totservers;
00383 user->WriteServ("270 %s :%.0f server%s and %.0f user%s, average %.2f users per server",user->nick,totservers,(totservers > 1 ? "s" : ""),totusers,(totusers > 1 ? "s" : ""),avg_users);
00384 user->WriteServ("007 %s :End of /MAP",user->nick);
00385 return;
00386 }
00387
00388 int ModuleSpanningTree::HandleSquit(const char** parameters, int pcnt, userrec* user)
00389 {
00390 TreeServer* s = Utils->FindServerMask(parameters[0]);
00391 if (s)
00392 {
00393 if (s == Utils->TreeRoot)
00394 {
00395 user->WriteServ("NOTICE %s :*** SQUIT: Foolish mortal, you cannot make a server SQUIT itself! (%s matches local server name)",user->nick,parameters[0]);
00396 return 1;
00397 }
00398 TreeSocket* sock = s->GetSocket();
00399 if (sock)
00400 {
00401 ServerInstance->SNO->WriteToSnoMask('l',"SQUIT: Server \002%s\002 removed from network by %s",parameters[0],user->nick);
00402 sock->Squit(s,std::string("Server quit by ") + user->GetFullRealHost());
00403 ServerInstance->SE->DelFd(sock);
00404 sock->Close();
00405 }
00406 else
00407 {
00408 if (IS_LOCAL(user))
00409 user->WriteServ("NOTICE %s :*** WARNING: Using SQUIT to split remote servers is deprecated. Please use RSQUIT instead.",user->nick);
00410 }
00411 }
00412 else
00413 {
00414 user->WriteServ("NOTICE %s :*** SQUIT: The server \002%s\002 does not exist on the network.",user->nick,parameters[0]);
00415 }
00416 return 1;
00417 }
00418
00419 int ModuleSpanningTree::HandleTime(const char** parameters, int pcnt, userrec* user)
00420 {
00421 if ((IS_LOCAL(user)) && (pcnt))
00422 {
00423 TreeServer* found = Utils->FindServerMask(parameters[0]);
00424 if (found)
00425 {
00426
00427 if (found == Utils->TreeRoot)
00428 return 0;
00429
00430 std::deque<std::string> params;
00431 params.push_back(found->GetName());
00432 params.push_back(user->nick);
00433 Utils->DoOneToOne(ServerInstance->Config->ServerName,"TIME",params,found->GetName());
00434 }
00435 else
00436 {
00437 user->WriteServ("402 %s %s :No such server",user->nick,parameters[0]);
00438 }
00439 }
00440 return 1;
00441 }
00442
00443 int ModuleSpanningTree::HandleRemoteWhois(const char** parameters, int pcnt, userrec* user)
00444 {
00445 if ((IS_LOCAL(user)) && (pcnt > 1))
00446 {
00447 userrec* remote = ServerInstance->FindNick(parameters[1]);
00448 if ((remote) && (remote->GetFd() < 0))
00449 {
00450 std::deque<std::string> params;
00451 params.push_back(parameters[1]);
00452 Utils->DoOneToOne(user->nick,"IDLE",params,remote->server);
00453 return 1;
00454 }
00455 else if (!remote)
00456 {
00457 user->WriteServ("401 %s %s :No such nick/channel",user->nick, parameters[1]);
00458 user->WriteServ("318 %s %s :End of /WHOIS list.",user->nick, parameters[1]);
00459 return 1;
00460 }
00461 }
00462 return 0;
00463 }
00464
00465 void ModuleSpanningTree::DoPingChecks(time_t curtime)
00466 {
00467 for (unsigned int j = 0; j < Utils->TreeRoot->ChildCount(); j++)
00468 {
00469 TreeServer* serv = Utils->TreeRoot->GetChild(j);
00470 TreeSocket* sock = serv->GetSocket();
00471 if (sock)
00472 {
00473 if (curtime >= serv->NextPingTime())
00474 {
00475 if (serv->AnsweredLastPing())
00476 {
00477 sock->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" PING "+serv->GetName());
00478 serv->SetNextPingTime(curtime + Utils->PingFreq);
00479 serv->LastPing = curtime;
00480 #ifndef WIN32
00481 timeval t;
00482 gettimeofday(&t, NULL);
00483 long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000);
00484 serv->LastPingMsec = ts;
00485 #endif
00486 serv->Warned = false;
00487 }
00488 else
00489 {
00490
00491 sock->SendError("Ping timeout");
00492 sock->Squit(serv,"Ping timeout");
00493 ServerInstance->SE->DelFd(sock);
00494 sock->Close();
00495 return;
00496 }
00497 }
00498 else if ((Utils->PingWarnTime) && (!serv->Warned) && (curtime >= serv->NextPingTime() - (Utils->PingFreq - Utils->PingWarnTime)) && (!serv->AnsweredLastPing()))
00499 {
00500
00501 ServerInstance->SNO->WriteToSnoMask('l',"Server \002%s\002 has not responded to PING for %d seconds, high latency.", serv->GetName().c_str(), Utils->PingWarnTime);
00502 serv->Warned = true;
00503 }
00504 }
00505 }
00506
00507
00508
00509
00510 for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++)
00511 Utils->SetRemoteBursting(i->second, false);
00512 }
00513
00514 void ModuleSpanningTree::ConnectServer(Link* x)
00515 {
00516 bool ipvalid = true;
00517 QueryType start_type = DNS_QUERY_A;
00518 #ifdef IPV6
00519 start_type = DNS_QUERY_AAAA;
00520 if (strchr(x->IPAddr.c_str(),':'))
00521 {
00522 in6_addr n;
00523 if (inet_pton(AF_INET6, x->IPAddr.c_str(), &n) < 1)
00524 ipvalid = false;
00525 }
00526 else
00527 #endif
00528 {
00529 in_addr n;
00530 if (inet_aton(x->IPAddr.c_str(),&n) < 1)
00531 ipvalid = false;
00532 }
00533
00534
00535 if (ipvalid)
00536 {
00537
00538 if ((!x->Hook.empty()) && (Utils->hooks.find(x->Hook.c_str()) == Utils->hooks.end()))
00539 return;
00540 TreeSocket* newsocket = new TreeSocket(Utils, ServerInstance, x->IPAddr,x->Port,false,x->Timeout ? x->Timeout : 10,x->Name.c_str(), x->Bind, x->Hook.empty() ? NULL : Utils->hooks[x->Hook.c_str()]);
00541 if (newsocket->GetFd() > -1)
00542 {
00543
00544 }
00545 else
00546 {
00547 RemoteMessage(NULL, "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(),strerror(errno));
00548 if (ServerInstance->SocketCull.find(newsocket) == ServerInstance->SocketCull.end())
00549 ServerInstance->SocketCull[newsocket] = newsocket;
00550 Utils->DoFailOver(x);
00551 }
00552 }
00553 else
00554 {
00555 try
00556 {
00557 bool cached;
00558 ServernameResolver* snr = new ServernameResolver((Module*)this, Utils, ServerInstance,x->IPAddr, *x, cached, start_type);
00559 ServerInstance->AddResolver(snr, cached);
00560 }
00561 catch (ModuleException& e)
00562 {
00563 RemoteMessage(NULL, "CONNECT: Error connecting \002%s\002: %s.",x->Name.c_str(), e.GetReason());
00564 Utils->DoFailOver(x);
00565 }
00566 }
00567 }
00568
00569 void ModuleSpanningTree::AutoConnectServers(time_t curtime)
00570 {
00571 for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00572 {
00573 if ((x->AutoConnect) && (curtime >= x->NextConnectTime))
00574 {
00575 x->NextConnectTime = curtime + x->AutoConnect;
00576 TreeServer* CheckDupe = Utils->FindServer(x->Name.c_str());
00577 if (x->FailOver.length())
00578 {
00579 TreeServer* CheckFailOver = Utils->FindServer(x->FailOver.c_str());
00580 if (CheckFailOver)
00581 {
00582
00583
00584
00585
00586 continue;
00587 }
00588 }
00589 if (!CheckDupe)
00590 {
00591
00592 ServerInstance->SNO->WriteToSnoMask('l',"AUTOCONNECT: Auto-connecting server \002%s\002 (%lu seconds until next attempt)",x->Name.c_str(),x->AutoConnect);
00593 this->ConnectServer(&(*x));
00594 }
00595 }
00596 }
00597 }
00598
00599 int ModuleSpanningTree::HandleVersion(const char** parameters, int pcnt, userrec* user)
00600 {
00601
00602 TreeServer* found = Utils->FindServerMask(parameters[0]);
00603 if (found)
00604 {
00605 std::string Version = found->GetVersion();
00606 user->WriteServ("351 %s :%s",user->nick,Version.c_str());
00607 if (found == Utils->TreeRoot)
00608 {
00609 ServerInstance->Config->Send005(user);
00610 }
00611 }
00612 else
00613 {
00614 user->WriteServ("402 %s %s :No such server",user->nick,parameters[0]);
00615 }
00616 return 1;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626 void ModuleSpanningTree::RemoteMessage(userrec* user, const char* format, ...)
00627 {
00628
00629
00630
00631
00632 static bool SendingRemoteMessage = false;
00633 if (SendingRemoteMessage)
00634 return;
00635 SendingRemoteMessage = true;
00636
00637 std::deque<std::string> params;
00638 char text[MAXBUF];
00639 va_list argsPtr;
00640
00641 va_start(argsPtr, format);
00642 vsnprintf(text, MAXBUF, format, argsPtr);
00643 va_end(argsPtr);
00644
00645 if (!user)
00646 {
00647
00648 ServerInstance->SNO->WriteToSnoMask('l', "%s", text);
00649 params.push_back("l");
00650 params.push_back(std::string(":") + text);
00651 Utils->DoOneToMany(ServerInstance->Config->ServerName, "SNONOTICE", params);
00652 }
00653 else
00654 {
00655 if (IS_LOCAL(user))
00656 user->WriteServ("NOTICE %s :%s", user->nick, text);
00657 else
00658 {
00659 params.push_back(user->nick);
00660 params.push_back(std::string("::") + ServerInstance->Config->ServerName + " NOTICE " + user->nick + " :*** From " +
00661 ServerInstance->Config->ServerName+ ": " + text);
00662 Utils->DoOneToMany(ServerInstance->Config->ServerName, "PUSH", params);
00663 }
00664 }
00665
00666 SendingRemoteMessage = false;
00667 }
00668
00669 int ModuleSpanningTree::HandleConnect(const char** parameters, int pcnt, userrec* user)
00670 {
00671 for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++)
00672 {
00673 if (ServerInstance->MatchText(x->Name.c_str(),parameters[0]))
00674 {
00675 TreeServer* CheckDupe = Utils->FindServer(x->Name.c_str());
00676 if (!CheckDupe)
00677 {
00678 RemoteMessage(user, "*** CONNECT: Connecting to server: \002%s\002 (%s:%d)",x->Name.c_str(),(x->HiddenFromStats ? "<hidden>" : x->IPAddr.c_str()),x->Port);
00679 ConnectServer(&(*x));
00680 return 1;
00681 }
00682 else
00683 {
00684 RemoteMessage(user, "*** CONNECT: Server \002%s\002 already exists on the network and is connected via \002%s\002",x->Name.c_str(),CheckDupe->GetParent()->GetName().c_str());
00685 return 1;
00686 }
00687 }
00688 }
00689 RemoteMessage(user, "*** CONNECT: No server matching \002%s\002 could be found in the config file.",parameters[0]);
00690 return 1;
00691 }
00692
00693 void ModuleSpanningTree::BroadcastTimeSync()
00694 {
00695 if (Utils->MasterTime)
00696 {
00697 std::deque<std::string> params;
00698 params.push_back(ConvToStr(ServerInstance->Time(false)));
00699 params.push_back("FORCE");
00700 Utils->DoOneToMany(Utils->TreeRoot->GetName(), "TIMESET", params);
00701 }
00702 }
00703
00704 int ModuleSpanningTree::OnStats(char statschar, userrec* user, string_list &results)
00705 {
00706 if ((statschar == 'c') || (statschar == 'n'))
00707 {
00708 for (unsigned int i = 0; i < Utils->LinkBlocks.size(); i++)
00709 {
00710 results.push_back(std::string(ServerInstance->Config->ServerName)+" 213 "+user->nick+" "+statschar+" *@"+(Utils->LinkBlocks[i].HiddenFromStats ? "<hidden>" : Utils->LinkBlocks[i].IPAddr)+" * "+Utils->LinkBlocks[i].Name.c_str()+" "+ConvToStr(Utils->LinkBlocks[i].Port)+" "+(Utils->LinkBlocks[i].Hook.empty() ? "plaintext" : Utils->LinkBlocks[i].Hook)+" "+(Utils->LinkBlocks[i].AutoConnect ? 'a' : '-')+'s');
00711 if (statschar == 'c')
00712 results.push_back(std::string(ServerInstance->Config->ServerName)+" 244 "+user->nick+" H * * "+Utils->LinkBlocks[i].Name.c_str());
00713 }
00714 results.push_back(std::string(ServerInstance->Config->ServerName)+" 219 "+user->nick+" "+statschar+" :End of /STATS report");
00715 ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",(!strcmp(user->server,ServerInstance->Config->ServerName) ? "Stats" : "Remote stats"),statschar,user->nick,user->ident,user->host);
00716 return 1;
00717 }
00718
00719 if (statschar == 'p')
00720 {
00721
00722
00723 for (unsigned int i = 0; i < Utils->Bindings.size(); i++)
00724 {
00725 std::string ip = Utils->Bindings[i]->IP;
00726 if (ip.empty())
00727 ip = "*";
00728
00729 std::string transport("plaintext");
00730 if (Utils->Bindings[i]->GetHook())
00731 transport = InspSocketNameRequest(this, Utils->Bindings[i]->GetHook()).Send();
00732
00733 results.push_back(ConvToStr(ServerInstance->Config->ServerName) + " 249 "+user->nick+" :" + ip + ":" + ConvToStr(Utils->Bindings[i]->port)+
00734 " (server, " + transport + ")");
00735 }
00736 }
00737 return 0;
00738 }
00739
00740 int ModuleSpanningTree::OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line)
00741 {
00742
00743 if (!validated)
00744 return 0;
00745
00746 if (command == "CONNECT")
00747 {
00748 return this->HandleConnect(parameters,pcnt,user);
00749 }
00750 else if (command == "STATS")
00751 {
00752 return this->HandleStats(parameters,pcnt,user);
00753 }
00754 else if (command == "MOTD")
00755 {
00756 return this->HandleMotd(parameters,pcnt,user);
00757 }
00758 else if (command == "ADMIN")
00759 {
00760 return this->HandleAdmin(parameters,pcnt,user);
00761 }
00762 else if (command == "SQUIT")
00763 {
00764 return this->HandleSquit(parameters,pcnt,user);
00765 }
00766 else if (command == "MAP")
00767 {
00768 this->HandleMap(parameters,pcnt,user);
00769 return 1;
00770 }
00771 else if ((command == "TIME") && (pcnt > 0))
00772 {
00773 return this->HandleTime(parameters,pcnt,user);
00774 }
00775 else if (command == "LUSERS")
00776 {
00777 this->HandleLusers(parameters,pcnt,user);
00778 return 1;
00779 }
00780 else if (command == "LINKS")
00781 {
00782 this->HandleLinks(parameters,pcnt,user);
00783 return 1;
00784 }
00785 else if (command == "WHOIS")
00786 {
00787 if (pcnt > 1)
00788 {
00789
00790 return this->HandleRemoteWhois(parameters,pcnt,user);
00791 }
00792 }
00793 else if ((command == "VERSION") && (pcnt > 0))
00794 {
00795 this->HandleVersion(parameters,pcnt,user);
00796 return 1;
00797 }
00798 else if ((command == "MODULES") && (pcnt > 0))
00799 {
00800 return this->HandleModules(parameters,pcnt,user);
00801 }
00802 return 0;
00803 }
00804
00805 void ModuleSpanningTree::OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line)
00806 {
00807 if ((result == CMD_SUCCESS) && (ServerInstance->IsValidModuleCommand(command, pcnt, user)))
00808 {
00809
00810
00811
00812
00813
00814 std::deque<std::string> params;
00815 params.clear();
00816
00817
00818
00819
00820
00821 for (int j = 0; j < pcnt - 1; j++)
00822 {
00823 params.push_back(parameters[j]);
00824 }
00825 if (pcnt)
00826 params.push_back(":" + std::string(parameters[pcnt - 1]));
00827
00828 Utils->DoOneToMany(user->nick,command,params);
00829 }
00830 }
00831
00832 void ModuleSpanningTree::OnGetServerDescription(const std::string &servername,std::string &description)
00833 {
00834 TreeServer* s = Utils->FindServer(servername);
00835 if (s)
00836 {
00837 description = s->GetDesc();
00838 }
00839 }
00840
00841 void ModuleSpanningTree::OnUserInvite(userrec* source,userrec* dest,chanrec* channel)
00842 {
00843 if (IS_LOCAL(source))
00844 {
00845 std::deque<std::string> params;
00846 params.push_back(dest->nick);
00847 params.push_back(channel->name);
00848 Utils->DoOneToMany(source->nick,"INVITE",params);
00849 }
00850 }
00851
00852 void ModuleSpanningTree::OnPostLocalTopicChange(userrec* user, chanrec* chan, const std::string &topic)
00853 {
00854 std::deque<std::string> params;
00855 params.push_back(chan->name);
00856 params.push_back(":"+topic);
00857 Utils->DoOneToMany(user->nick,"TOPIC",params);
00858 }
00859
00860 void ModuleSpanningTree::OnWallops(userrec* user, const std::string &text)
00861 {
00862 if (IS_LOCAL(user))
00863 {
00864 std::deque<std::string> params;
00865 params.push_back(":"+text);
00866 Utils->DoOneToMany(user->nick,"WALLOPS",params);
00867 }
00868 }
00869
00870 void ModuleSpanningTree::OnUserNotice(userrec* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
00871 {
00872 if (target_type == TYPE_USER)
00873 {
00874 userrec* d = (userrec*)dest;
00875 if ((d->GetFd() < 0) && (IS_LOCAL(user)))
00876 {
00877 std::deque<std::string> params;
00878 params.clear();
00879 params.push_back(d->nick);
00880 params.push_back(":"+text);
00881 Utils->DoOneToOne(user->nick,"NOTICE",params,d->server);
00882 }
00883 }
00884 else if (target_type == TYPE_CHANNEL)
00885 {
00886 if (IS_LOCAL(user))
00887 {
00888 chanrec *c = (chanrec*)dest;
00889 if (c)
00890 {
00891 std::string cname = c->name;
00892 if (status)
00893 cname = status + cname;
00894 TreeServerList list;
00895 Utils->GetListOfServersForChannel(c,list,status,exempt_list);
00896 for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
00897 {
00898 TreeSocket* Sock = i->second->GetSocket();
00899 if (Sock)
00900 Sock->WriteLine(":"+std::string(user->nick)+" NOTICE "+cname+" :"+text);
00901 }
00902 }
00903 }
00904 }
00905 else if (target_type == TYPE_SERVER)
00906 {
00907 if (IS_LOCAL(user))
00908 {
00909 char* target = (char*)dest;
00910 std::deque<std::string> par;
00911 par.push_back(target);
00912 par.push_back(":"+text);
00913 Utils->DoOneToMany(user->nick,"NOTICE",par);
00914 }
00915 }
00916 }
00917
00918 void ModuleSpanningTree::OnUserMessage(userrec* user, void* dest, int target_type, const std::string &text, char status, const CUList &exempt_list)
00919 {
00920 if (target_type == TYPE_USER)
00921 {
00922
00923
00924 userrec* d = (userrec*)dest;
00925 if ((d->GetFd() < 0) && (IS_LOCAL(user)))
00926 {
00927 std::deque<std::string> params;
00928 params.clear();
00929 params.push_back(d->nick);
00930 params.push_back(":"+text);
00931 Utils->DoOneToOne(user->nick,"PRIVMSG",params,d->server);
00932 }
00933 }
00934 else if (target_type == TYPE_CHANNEL)
00935 {
00936 if (IS_LOCAL(user))
00937 {
00938 chanrec *c = (chanrec*)dest;
00939 if (c)
00940 {
00941 std::string cname = c->name;
00942 if (status)
00943 cname = status + cname;
00944 TreeServerList list;
00945 Utils->GetListOfServersForChannel(c,list,status,exempt_list);
00946 for (TreeServerList::iterator i = list.begin(); i != list.end(); i++)
00947 {
00948 TreeSocket* Sock = i->second->GetSocket();
00949 if (Sock)
00950 Sock->WriteLine(":"+std::string(user->nick)+" PRIVMSG "+cname+" :"+text);
00951 }
00952 }
00953 }
00954 }
00955 else if (target_type == TYPE_SERVER)
00956 {
00957 if (IS_LOCAL(user))
00958 {
00959 char* target = (char*)dest;
00960 std::deque<std::string> par;
00961 par.push_back(target);
00962 par.push_back(":"+text);
00963 Utils->DoOneToMany(user->nick,"PRIVMSG",par);
00964 }
00965 }
00966 }
00967
00968 void ModuleSpanningTree::OnBackgroundTimer(time_t curtime)
00969 {
00970 AutoConnectServers(curtime);
00971 DoPingChecks(curtime);
00972 if (curtime % 60 == 0)
00973 {
00974 if (Utils->EnableTimeSync)
00975 BroadcastTimeSync();
00976 Utils->RefreshIPCache();
00977 }
00978 }
00979
00980 void ModuleSpanningTree::OnUserJoin(userrec* user, chanrec* channel, bool &silent)
00981 {
00982
00983 if (IS_LOCAL(user))
00984 {
00985 if (channel->GetUserCounter() == 1)
00986 {
00987 std::deque<std::string> params;
00988
00989
00990
00991 params.push_back(channel->name);
00992 params.push_back(ConvToStr(channel->age));
00993 params.push_back(std::string(channel->GetAllPrefixChars(user))+","+std::string(user->nick));
00994 Utils->DoOneToMany(ServerInstance->Config->ServerName,"FJOIN",params);
00995
00996 params.pop_back();
00997 params.push_back(channel->ChanModes(true));
00998 Utils->DoOneToMany(ServerInstance->Config->ServerName,"FMODE",params);
00999 }
01000 else
01001 {
01002 std::deque<std::string> params;
01003 params.push_back(channel->name);
01004 params.push_back(ConvToStr(channel->age));
01005 Utils->DoOneToMany(user->nick,"JOIN",params);
01006 }
01007 }
01008 }
01009
01010 void ModuleSpanningTree::OnChangeHost(userrec* user, const std::string &newhost)
01011 {
01012
01013 if (user->registered != REG_ALL)
01014 return;
01015 std::deque<std::string> params;
01016 params.push_back(newhost);
01017 Utils->DoOneToMany(user->nick,"FHOST",params);
01018 }
01019
01020 void ModuleSpanningTree::OnChangeName(userrec* user, const std::string &gecos)
01021 {
01022
01023 if (user->registered != REG_ALL)
01024 return;
01025 std::deque<std::string> params;
01026 params.push_back(gecos);
01027 Utils->DoOneToMany(user->nick,"FNAME",params);
01028 }
01029
01030 void ModuleSpanningTree::OnUserPart(userrec* user, chanrec* channel, const std::string &partmessage, bool &silent)
01031 {
01032 if (IS_LOCAL(user))
01033 {
01034 std::deque<std::string> params;
01035 params.push_back(channel->name);
01036 if (!partmessage.empty())
01037 params.push_back(":"+partmessage);
01038 Utils->DoOneToMany(user->nick,"PART",params);
01039 }
01040 }
01041
01042 void ModuleSpanningTree::OnUserConnect(userrec* user)
01043 {
01044 char agestr[MAXBUF];
01045 if (IS_LOCAL(user))
01046 {
01047 std::deque<std::string> params;
01048 snprintf(agestr,MAXBUF,"%lu",(unsigned long)user->age);
01049 params.push_back(agestr);
01050 params.push_back(user->nick);
01051 params.push_back(user->host);
01052 params.push_back(user->dhost);
01053 params.push_back(user->ident);
01054 params.push_back("+"+std::string(user->FormatModes()));
01055 params.push_back(user->GetIPString());
01056 params.push_back(":"+std::string(user->fullname));
01057 Utils->DoOneToMany(ServerInstance->Config->ServerName,"NICK",params);
01058
01059 TreeServer* SourceServer = Utils->FindServer(user->server);
01060 if (SourceServer)
01061 {
01062 SourceServer->AddUserCount();
01063 }
01064 }
01065 }
01066
01067 void ModuleSpanningTree::OnUserQuit(userrec* user, const std::string &reason, const std::string &oper_message)
01068 {
01069 if ((IS_LOCAL(user)) && (user->registered == REG_ALL))
01070 {
01071 std::deque<std::string> params;
01072
01073 if (oper_message != reason)
01074 {
01075 params.push_back(":"+oper_message);
01076 Utils->DoOneToMany(user->nick,"OPERQUIT",params);
01077 }
01078 params.clear();
01079 params.push_back(":"+reason);
01080 Utils->DoOneToMany(user->nick,"QUIT",params);
01081 }
01082
01083 TreeServer* SourceServer = Utils->FindServer(user->server);
01084 if (SourceServer)
01085 {
01086 SourceServer->DelUserCount();
01087 }
01088 }
01089
01090 void ModuleSpanningTree::OnUserPostNick(userrec* user, const std::string &oldnick)
01091 {
01092 if (IS_LOCAL(user))
01093 {
01094 std::deque<std::string> params;
01095 params.push_back(user->nick);
01096 Utils->DoOneToMany(oldnick,"NICK",params);
01097 }
01098 }
01099
01100 void ModuleSpanningTree::OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason, bool &silent)
01101 {
01102 if ((source) && (IS_LOCAL(source)))
01103 {
01104 std::deque<std::string> params;
01105 params.push_back(chan->name);
01106 params.push_back(user->nick);
01107 params.push_back(":"+reason);
01108 Utils->DoOneToMany(source->nick,"KICK",params);
01109 }
01110 else if (!source)
01111 {
01112 std::deque<std::string> params;
01113 params.push_back(chan->name);
01114 params.push_back(user->nick);
01115 params.push_back(":"+reason);
01116 Utils->DoOneToMany(ServerInstance->Config->ServerName,"KICK",params);
01117 }
01118 }
01119
01120 void ModuleSpanningTree::OnRemoteKill(userrec* source, userrec* dest, const std::string &reason, const std::string &operreason)
01121 {
01122 if (!IS_LOCAL(source)) return;
01123 std::deque<std::string> params;
01124 params.push_back(":"+reason);
01125 Utils->DoOneToMany(dest->nick,"OPERQUIT",params);
01126 params.clear();
01127 params.push_back(dest->nick);
01128 params.push_back(":"+reason);
01129 dest->SetOperQuit(operreason);
01130 Utils->DoOneToMany(source->nick,"KILL",params);
01131 }
01132
01133 void ModuleSpanningTree::OnRehash(userrec* user, const std::string ¶meter)
01134 {
01135 if (!parameter.empty())
01136 {
01137 std::deque<std::string> params;
01138 params.push_back(parameter);
01139 Utils->DoOneToMany(user ? user->nick : ServerInstance->Config->ServerName, "REHASH", params);
01140
01141 if (ServerInstance->MatchText(ServerInstance->Config->ServerName,parameter))
01142 {
01143 ServerInstance->WriteOpers("*** Remote rehash initiated locally by \002%s\002", user ? user->nick : ServerInstance->Config->ServerName);
01144 ServerInstance->RehashServer();
01145 }
01146 }
01147 Utils->ReadConfiguration(true);
01148 InitializeDisabledCommands(ServerInstance->Config->DisabledCommands, ServerInstance);
01149 }
01150
01151
01152
01153
01154 void ModuleSpanningTree::OnOper(userrec* user, const std::string &opertype)
01155 {
01156 if (IS_LOCAL(user))
01157 {
01158 std::deque<std::string> params;
01159 params.push_back(opertype);
01160 Utils->DoOneToMany(user->nick,"OPERTYPE",params);
01161 }
01162 }
01163
01164 void ModuleSpanningTree::OnLine(userrec* source, const std::string &host, bool adding, char linetype, long duration, const std::string &reason)
01165 {
01166 if (!source)
01167 {
01168
01169 char data[MAXBUF];
01170 snprintf(data,MAXBUF,"%c %s %s %lu %lu :%s", linetype, host.c_str(), ServerInstance->Config->ServerName, (unsigned long)ServerInstance->Time(false),
01171 (unsigned long)duration, reason.c_str());
01172 std::deque<std::string> params;
01173 params.push_back(data);
01174 Utils->DoOneToMany(ServerInstance->Config->ServerName, "ADDLINE", params);
01175 }
01176 else
01177 {
01178 if (IS_LOCAL(source))
01179 {
01180 char type[8];
01181 snprintf(type,8,"%cLINE",linetype);
01182 std::string stype = type;
01183 if (adding)
01184 {
01185 char sduration[MAXBUF];
01186 snprintf(sduration,MAXBUF,"%ld",duration);
01187 std::deque<std::string> params;
01188 params.push_back(host);
01189 params.push_back(sduration);
01190 params.push_back(":"+reason);
01191 Utils->DoOneToMany(source->nick,stype,params);
01192 }
01193 else
01194 {
01195 std::deque<std::string> params;
01196 params.push_back(host);
01197 Utils->DoOneToMany(source->nick,stype,params);
01198 }
01199 }
01200 }
01201 }
01202
01203 void ModuleSpanningTree::OnAddGLine(long duration, userrec* source, const std::string &reason, const std::string &hostmask)
01204 {
01205 OnLine(source,hostmask,true,'G',duration,reason);
01206 }
01207
01208 void ModuleSpanningTree::OnAddZLine(long duration, userrec* source, const std::string &reason, const std::string &ipmask)
01209 {
01210 OnLine(source,ipmask,true,'Z',duration,reason);
01211 }
01212
01213 void ModuleSpanningTree::OnAddQLine(long duration, userrec* source, const std::string &reason, const std::string &nickmask)
01214 {
01215 OnLine(source,nickmask,true,'Q',duration,reason);
01216 }
01217
01218 void ModuleSpanningTree::OnAddELine(long duration, userrec* source, const std::string &reason, const std::string &hostmask)
01219 {
01220 OnLine(source,hostmask,true,'E',duration,reason);
01221 }
01222
01223 void ModuleSpanningTree::OnDelGLine(userrec* source, const std::string &hostmask)
01224 {
01225 OnLine(source,hostmask,false,'G',0,"");
01226 }
01227
01228 void ModuleSpanningTree::OnDelZLine(userrec* source, const std::string &ipmask)
01229 {
01230 OnLine(source,ipmask,false,'Z',0,"");
01231 }
01232
01233 void ModuleSpanningTree::OnDelQLine(userrec* source, const std::string &nickmask)
01234 {
01235 OnLine(source,nickmask,false,'Q',0,"");
01236 }
01237
01238 void ModuleSpanningTree::OnDelELine(userrec* source, const std::string &hostmask)
01239 {
01240 OnLine(source,hostmask,false,'E',0,"");
01241 }
01242
01243 void ModuleSpanningTree::OnMode(userrec* user, void* dest, int target_type, const std::string &text)
01244 {
01245 if ((IS_LOCAL(user)) && (user->registered == REG_ALL))
01246 {
01247 std::deque<std::string> params;
01248 std::string command;
01249
01250 if (target_type == TYPE_USER)
01251 {
01252 userrec* u = (userrec*)dest;
01253 params.push_back(u->nick);
01254 params.push_back(text);
01255 command = "MODE";
01256 }
01257 else
01258 {
01259 chanrec* c = (chanrec*)dest;
01260 params.push_back(c->name);
01261 params.push_back(ConvToStr(c->age));
01262 params.push_back(text);
01263 command = "FMODE";
01264 }
01265 Utils->DoOneToMany(user->nick, command, params);
01266 }
01267 }
01268
01269 void ModuleSpanningTree::OnSetAway(userrec* user)
01270 {
01271 if (IS_LOCAL(user))
01272 {
01273 std::deque<std::string> params;
01274 params.push_back(":"+std::string(user->awaymsg));
01275 Utils->DoOneToMany(user->nick,"AWAY",params);
01276 }
01277 }
01278
01279 void ModuleSpanningTree::OnCancelAway(userrec* user)
01280 {
01281 if (IS_LOCAL(user))
01282 {
01283 std::deque<std::string> params;
01284 params.clear();
01285 Utils->DoOneToMany(user->nick,"AWAY",params);
01286 }
01287 }
01288
01289 void ModuleSpanningTree::ProtoSendMode(void* opaque, int target_type, void* target, const std::string &modeline)
01290 {
01291 TreeSocket* s = (TreeSocket*)opaque;
01292 if (target)
01293 {
01294 if (target_type == TYPE_USER)
01295 {
01296 userrec* u = (userrec*)target;
01297 s->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" FMODE "+u->nick+" "+ConvToStr(u->age)+" "+modeline);
01298 }
01299 else
01300 {
01301 chanrec* c = (chanrec*)target;
01302 s->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" FMODE "+c->name+" "+ConvToStr(c->age)+" "+modeline);
01303 }
01304 }
01305 }
01306
01307 void ModuleSpanningTree::ProtoSendMetaData(void* opaque, int target_type, void* target, const std::string &extname, const std::string &extdata)
01308 {
01309 TreeSocket* s = (TreeSocket*)opaque;
01310 if (target)
01311 {
01312 if (target_type == TYPE_USER)
01313 {
01314 userrec* u = (userrec*)target;
01315 s->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" METADATA "+u->nick+" "+extname+" :"+extdata);
01316 }
01317 else if (target_type == TYPE_CHANNEL)
01318 {
01319 chanrec* c = (chanrec*)target;
01320 s->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" METADATA "+c->name+" "+extname+" :"+extdata);
01321 }
01322 }
01323 if (target_type == TYPE_OTHER)
01324 {
01325 s->WriteLine(std::string(":")+ServerInstance->Config->ServerName+" METADATA * "+extname+" :"+extdata);
01326 }
01327 }
01328
01329 void ModuleSpanningTree::OnEvent(Event* event)
01330 {
01331 std::deque<std::string>* params = (std::deque<std::string>*)event->GetData();
01332 if (event->GetEventID() == "send_metadata")
01333 {
01334 if (params->size() < 3)
01335 return;
01336 (*params)[2] = ":" + (*params)[2];
01337 Utils->DoOneToMany(ServerInstance->Config->ServerName,"METADATA",*params);
01338 }
01339 else if (event->GetEventID() == "send_topic")
01340 {
01341 if (params->size() < 2)
01342 return;
01343 (*params)[1] = ":" + (*params)[1];
01344 params->insert(params->begin() + 1,ServerInstance->Config->ServerName);
01345 params->insert(params->begin() + 1,ConvToStr(ServerInstance->Time(true)));
01346 Utils->DoOneToMany(ServerInstance->Config->ServerName,"FTOPIC",*params);
01347 }
01348 else if (event->GetEventID() == "send_mode")
01349 {
01350 if (params->size() < 2)
01351 return;
01352
01353 time_t ourTS = 0;
01354 userrec* a = ServerInstance->FindNick((*params)[0]);
01355 if (a)
01356 {
01357 ourTS = a->age;
01358 Utils->DoOneToMany(ServerInstance->Config->ServerName,"MODE",*params);
01359 return;
01360 }
01361 else
01362 {
01363 chanrec* a = ServerInstance->FindChan((*params)[0]);
01364 if (a)
01365 {
01366 ourTS = a->age;
01367 params->insert(params->begin() + 1,ConvToStr(ourTS));
01368 Utils->DoOneToMany(ServerInstance->Config->ServerName,"FMODE",*params);
01369 }
01370 }
01371 }
01372 else if (event->GetEventID() == "send_mode_explicit")
01373 {
01374 if (params->size() < 2)
01375 return;
01376 Utils->DoOneToMany(ServerInstance->Config->ServerName,"MODE",*params);
01377 }
01378 else if (event->GetEventID() == "send_opers")
01379 {
01380 if (params->size() < 1)
01381 return;
01382 (*params)[0] = ":" + (*params)[0];
01383 Utils->DoOneToMany(ServerInstance->Config->ServerName,"OPERNOTICE",*params);
01384 }
01385 else if (event->GetEventID() == "send_modeset")
01386 {
01387 if (params->size() < 2)
01388 return;
01389 (*params)[1] = ":" + (*params)[1];
01390 Utils->DoOneToMany(ServerInstance->Config->ServerName,"MODENOTICE",*params);
01391 }
01392 else if (event->GetEventID() == "send_snoset")
01393 {
01394 if (params->size() < 2)
01395 return;
01396 (*params)[1] = ":" + (*params)[1];
01397 Utils->DoOneToMany(ServerInstance->Config->ServerName,"SNONOTICE",*params);
01398 }
01399 else if (event->GetEventID() == "send_push")
01400 {
01401 if (params->size() < 2)
01402 return;
01403
01404 userrec *a = ServerInstance->FindNick((*params)[0]);
01405
01406 if (!a)
01407 return;
01408
01409 (*params)[1] = ":" + (*params)[1];
01410 Utils->DoOneToOne(ServerInstance->Config->ServerName, "PUSH", *params, a->server);
01411 }
01412 }
01413
01414 ModuleSpanningTree::~ModuleSpanningTree()
01415 {
01416
01417 delete Utils;
01418 ServerInstance->DoneWithInterface("InspSocketHook");
01419 }
01420
01421 Version ModuleSpanningTree::GetVersion()
01422 {
01423 return Version(1,1,0,2,VF_VENDOR,API_VERSION);
01424 }
01425
01426 void ModuleSpanningTree::Implements(char* List)
01427 {
01428 List[I_OnPreCommand] = List[I_OnGetServerDescription] = List[I_OnUserInvite] = List[I_OnPostLocalTopicChange] = 1;
01429 List[I_OnWallops] = List[I_OnUserNotice] = List[I_OnUserMessage] = List[I_OnBackgroundTimer] = 1;
01430 List[I_OnUserJoin] = List[I_OnChangeHost] = List[I_OnChangeName] = List[I_OnUserPart] = List[I_OnUserConnect] = 1;
01431 List[I_OnUserQuit] = List[I_OnUserPostNick] = List[I_OnUserKick] = List[I_OnRemoteKill] = List[I_OnRehash] = 1;
01432 List[I_OnOper] = List[I_OnAddGLine] = List[I_OnAddZLine] = List[I_OnAddQLine] = List[I_OnAddELine] = 1;
01433 List[I_OnDelGLine] = List[I_OnDelZLine] = List[I_OnDelQLine] = List[I_OnDelELine] = List[I_ProtoSendMode] = List[I_OnMode] = 1;
01434 List[I_OnStats] = List[I_ProtoSendMetaData] = List[I_OnEvent] = List[I_OnSetAway] = List[I_OnCancelAway] = List[I_OnPostCommand] = 1;
01435 }
01436
01437
01438
01439
01440
01441
01442
01443
01444 Priority ModuleSpanningTree::Prioritize()
01445 {
01446 return PRIORITY_LAST;
01447 }
01448
01449 MODULE_INIT(ModuleSpanningTree)
01450