00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "inspircd.h"
00015 #include "configreader.h"
00016 #include "users.h"
00017 #include "channels.h"
00018 #include "modules.h"
00019 #include "commands/cmd_whois.h"
00020 #include "commands/cmd_stats.h"
00021 #include "socket.h"
00022 #include "wildcard.h"
00023 #include "xline.h"
00024 #include "transport.h"
00025 #include "socketengine.h"
00026
00027 #include "m_spanningtree/main.h"
00028 #include "m_spanningtree/utils.h"
00029 #include "m_spanningtree/treeserver.h"
00030 #include "m_spanningtree/link.h"
00031 #include "m_spanningtree/treesocket.h"
00032 #include "m_spanningtree/resolvers.h"
00033 #include "m_spanningtree/handshaketimer.h"
00034
00035
00036
00037 static std::map<std::string, std::string> warned;
00038
00039 void TreeSocket::WriteLine(std::string line)
00040 {
00041 Instance->Log(DEBUG, "S[%d] -> %s", this->GetFd(), line.c_str());
00042 line.append("\r\n");
00043 this->Write(line);
00044 }
00045
00046
00047
00048 bool TreeSocket::Error(std::deque<std::string> ¶ms)
00049 {
00050 if (params.size() < 1)
00051 return false;
00052 this->Instance->SNO->WriteToSnoMask('l',"ERROR from %s: %s",(!InboundServerName.empty() ? InboundServerName.c_str() : myhost.c_str()),params[0].c_str());
00053
00054 return false;
00055 }
00056
00057 bool TreeSocket::Modules(const std::string &prefix, std::deque<std::string> ¶ms)
00058 {
00059 if (params.empty())
00060 return true;
00061
00062 if (!this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00063 {
00064
00065 Utils->DoOneToOne(prefix, "MODULES", params, params[0]);
00066 return true;
00067 }
00068
00069 char strbuf[MAXBUF];
00070 std::deque<std::string> par;
00071 par.push_back(prefix);
00072 par.push_back("");
00073
00074 userrec* source = this->Instance->FindNick(prefix);
00075 if (!source)
00076 return true;
00077
00078 for (unsigned int i = 0; i < Instance->Config->module_names.size(); i++)
00079 {
00080 Version V = Instance->modules[i]->GetVersion();
00081 char modulename[MAXBUF];
00082 char flagstate[MAXBUF];
00083 *flagstate = 0;
00084 if (V.Flags & VF_STATIC)
00085 strlcat(flagstate,", static",MAXBUF);
00086 if (V.Flags & VF_VENDOR)
00087 strlcat(flagstate,", vendor",MAXBUF);
00088 if (V.Flags & VF_COMMON)
00089 strlcat(flagstate,", common",MAXBUF);
00090 if (V.Flags & VF_SERVICEPROVIDER)
00091 strlcat(flagstate,", service provider",MAXBUF);
00092 if (!flagstate[0])
00093 strcpy(flagstate," <no flags>");
00094 strlcpy(modulename,Instance->Config->module_names[i].c_str(),256);
00095 if (*source->oper)
00096 {
00097 snprintf(strbuf, MAXBUF, "::%s 702 %s :0x%08lx %d.%d.%d.%d %s (%s)",Instance->Config->ServerName,source->nick,(long unsigned int)Instance->modules[i],V.Major,V.Minor,V.Revision,V.Build,ServerConfig::CleanFilename(modulename),flagstate+2);
00098 }
00099 else
00100 {
00101 snprintf(strbuf, MAXBUF, "::%s 702 %s :%s",Instance->Config->ServerName,source->nick,ServerConfig::CleanFilename(modulename));
00102 }
00103 par[1] = strbuf;
00104 Utils->DoOneToOne(Instance->Config->ServerName, "PUSH", par, source->server);
00105 }
00106 snprintf(strbuf, MAXBUF, "::%s 703 %s :End of MODULES list", Instance->Config->ServerName, source->nick);
00107 par[1] = strbuf;
00108 Utils->DoOneToOne(Instance->Config->ServerName, "PUSH", par, source->server);
00109 return true;
00110 }
00111
00113 bool TreeSocket::Motd(const std::string &prefix, std::deque<std::string> ¶ms)
00114 {
00115 if (params.size() > 0)
00116 {
00117 if (this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00118 {
00119
00120 string_list results;
00121 userrec* source = this->Instance->FindNick(prefix);
00122
00123 if (source)
00124 {
00125 std::deque<std::string> par;
00126 par.push_back(prefix);
00127 par.push_back("");
00128
00129 if (!Instance->Config->MOTD.size())
00130 {
00131 par[1] = std::string("::")+Instance->Config->ServerName+" 422 "+source->nick+" :Message of the day file is missing.";
00132 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00133 return true;
00134 }
00135
00136 par[1] = std::string("::")+Instance->Config->ServerName+" 375 "+source->nick+" :"+Instance->Config->ServerName+" message of the day";
00137 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00138
00139 for (unsigned int i = 0; i < Instance->Config->MOTD.size(); i++)
00140 {
00141 par[1] = std::string("::")+Instance->Config->ServerName+" 372 "+source->nick+" :- "+Instance->Config->MOTD[i];
00142 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00143 }
00144
00145 par[1] = std::string("::")+Instance->Config->ServerName+" 376 "+source->nick+" :End of message of the day.";
00146 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00147 }
00148 }
00149 else
00150 {
00151
00152 userrec* source = this->Instance->FindNick(prefix);
00153 if (source)
00154 Utils->DoOneToOne(prefix, "MOTD", params, params[0]);
00155 }
00156 }
00157 return true;
00158 }
00159
00161 bool TreeSocket::Admin(const std::string &prefix, std::deque<std::string> ¶ms)
00162 {
00163 if (params.size() > 0)
00164 {
00165 if (this->Instance->MatchText(this->Instance->Config->ServerName, params[0]))
00166 {
00167
00168 string_list results;
00169 userrec* source = this->Instance->FindNick(prefix);
00170 if (source)
00171 {
00172 std::deque<std::string> par;
00173 par.push_back(prefix);
00174 par.push_back("");
00175 par[1] = std::string("::")+Instance->Config->ServerName+" 256 "+source->nick+" :Administrative info for "+Instance->Config->ServerName;
00176 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00177 par[1] = std::string("::")+Instance->Config->ServerName+" 257 "+source->nick+" :Name - "+Instance->Config->AdminName;
00178 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00179 par[1] = std::string("::")+Instance->Config->ServerName+" 258 "+source->nick+" :Nickname - "+Instance->Config->AdminNick;
00180 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00181 par[1] = std::string("::")+Instance->Config->ServerName+" 258 "+source->nick+" :E-Mail - "+Instance->Config->AdminEmail;
00182 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00183 }
00184 }
00185 else
00186 {
00187
00188 userrec* source = this->Instance->FindNick(prefix);
00189 if (source)
00190 Utils->DoOneToOne(prefix, "ADMIN", params, params[0]);
00191 }
00192 }
00193 return true;
00194 }
00195
00196 bool TreeSocket::Stats(const std::string &prefix, std::deque<std::string> ¶ms)
00197 {
00198
00199
00200
00201 if (params.size() > 1)
00202 {
00203 if (this->Instance->MatchText(this->Instance->Config->ServerName, params[1]))
00204 {
00205
00206 string_list results;
00207 userrec* source = this->Instance->FindNick(prefix);
00208 if (source)
00209 {
00210 std::deque<std::string> par;
00211 par.push_back(prefix);
00212 par.push_back("");
00213 DoStats(this->Instance, *(params[0].c_str()), source, results);
00214 for (size_t i = 0; i < results.size(); i++)
00215 {
00216 par[1] = "::" + results[i];
00217 Utils->DoOneToOne(this->Instance->Config->ServerName, "PUSH",par, source->server);
00218 }
00219 }
00220 }
00221 else
00222 {
00223
00224 userrec* source = this->Instance->FindNick(prefix);
00225 if (source)
00226 Utils->DoOneToOne(prefix, "STATS", params, params[1]);
00227 }
00228 }
00229 return true;
00230 }
00231
00232
00236 bool TreeSocket::OperType(const std::string &prefix, std::deque<std::string> ¶ms)
00237 {
00238 if (params.size() != 1)
00239 return true;
00240 std::string opertype = params[0];
00241 userrec* u = this->Instance->FindNick(prefix);
00242 if (u)
00243 {
00244 if (!u->IsModeSet('o'))
00245 this->Instance->all_opers.push_back(u);
00246 u->modes[UM_OPERATOR] = 1;
00247 strlcpy(u->oper,opertype.c_str(),NICKMAX-1);
00248 Utils->DoOneToAllButSender(u->nick,"OPERTYPE",params,u->server);
00249 this->Instance->SNO->WriteToSnoMask('o',"From %s: User %s (%s@%s) is now an IRC operator of type %s",u->server, u->nick,u->ident,u->host,irc::Spacify(opertype.c_str()));
00250 }
00251 return true;
00252 }
00253
00257 bool TreeSocket::ForceNick(const std::string &prefix, std::deque<std::string> ¶ms)
00258 {
00259 if (params.size() < 3)
00260 return true;
00261
00262 userrec* u = this->Instance->FindNick(params[0]);
00263
00264 if (u)
00265 {
00266 Utils->DoOneToAllButSender(prefix,"SVSNICK",params,prefix);
00267 if (IS_LOCAL(u))
00268 {
00269 std::deque<std::string> par;
00270 par.push_back(params[1]);
00271 if (!u->ForceNickChange(params[1].c_str()))
00272 {
00273 userrec::QuitUser(this->Instance, u, "Nickname collision");
00274 return true;
00275 }
00276 u->age = atoi(params[2].c_str());
00277 }
00278 }
00279 return true;
00280 }
00281
00282 bool TreeSocket::OperQuit(const std::string &prefix, std::deque<std::string> ¶ms)
00283 {
00284 if (params.size() < 1)
00285 return true;
00286
00287 userrec* u = this->Instance->FindNick(prefix);
00288
00289 if (u)
00290 {
00291 u->SetOperQuit(params[0]);
00292 params[0] = ":" + params[0];
00293 Utils->DoOneToAllButSender(prefix,"OPERQUIT",params,prefix);
00294 }
00295 return true;
00296 }
00297
00298 bool TreeSocket::ServiceJoin(const std::string &prefix, std::deque<std::string> ¶ms)
00299 {
00300 if (params.size() < 2)
00301 return true;
00302
00303 if (!this->Instance->IsChannel(params[1].c_str()))
00304 return true;
00305
00306 userrec* u = this->Instance->FindNick(params[0]);
00307
00308 if (u)
00309 {
00310
00311 if (IS_LOCAL(u))
00312 chanrec::JoinUser(this->Instance, u, params[1].c_str(), false, "", Instance->Time());
00313 Utils->DoOneToAllButSender(prefix,"SVSJOIN",params,prefix);
00314 }
00315 return true;
00316 }
00317
00318 bool TreeSocket::ServicePart(const std::string &prefix, std::deque<std::string> ¶ms)
00319 {
00320 if (params.size() < 2)
00321 return true;
00322
00323 if (!this->Instance->IsChannel(params[1].c_str()))
00324 return true;
00325
00326 userrec* u = this->Instance->FindNick(params[0]);
00327 chanrec* c = this->Instance->FindChan(params[1]);
00328
00329 if (u)
00330 {
00331
00332 if (IS_LOCAL(u))
00333 if (!c->PartUser(u, "Services forced part"))
00334 delete c;
00335 Utils->DoOneToAllButSender(prefix,"SVSPART",params,prefix);
00336 }
00337
00338 return true;
00339 }
00340
00341 bool TreeSocket::RemoteRehash(const std::string &prefix, std::deque<std::string> ¶ms)
00342 {
00343 if (params.size() < 1)
00344 return false;
00345
00346 std::string servermask = params[0];
00347 std::string parameter;
00348
00349 if (params.size() > 1)
00350 {
00351 parameter = params[1];
00352 }
00353
00354 if (this->Instance->MatchText(this->Instance->Config->ServerName,servermask))
00355 {
00356 this->Instance->SNO->WriteToSnoMask('l',"Remote rehash initiated by \002"+prefix+"\002.");
00357 this->Instance->RehashServer();
00358 Utils->ReadConfiguration(true);
00359 FOREACH_MOD_I(this->Instance, I_OnRehash, OnRehash(NULL, parameter));
00360 InitializeDisabledCommands(Instance->Config->DisabledCommands, Instance);
00361 }
00362 Utils->DoOneToAllButSender(prefix,"REHASH",params,prefix);
00363 return true;
00364 }
00365
00366 bool TreeSocket::RemoteKill(const std::string &prefix, std::deque<std::string> ¶ms)
00367 {
00368 if (params.size() != 2)
00369 return true;
00370
00371 userrec* who = this->Instance->FindNick(params[0]);
00372
00373 if (who)
00374 {
00375
00376 if ((*(params[1].c_str()) != 'K') && (*(params[1].c_str()) != '['))
00377 {
00378 params[1] = "Killed (" + params[1] +")";
00379 }
00380 std::string reason = params[1];
00381 params[1] = ":" + params[1];
00382 Utils->DoOneToAllButSender(prefix,"KILL",params,prefix);
00383
00384
00385 who->Write(":%s KILL %s :%s (%s)", prefix.c_str(), who->nick, prefix.c_str(), reason.c_str());
00386 userrec::QuitUser(this->Instance,who,reason);
00387 }
00388 return true;
00389 }
00390
00391 bool TreeSocket::LocalPong(const std::string &prefix, std::deque<std::string> ¶ms)
00392 {
00393 if (params.size() < 1)
00394 return true;
00395
00396 if (params.size() == 1)
00397 {
00398 TreeServer* ServerSource = Utils->FindServer(prefix);
00399 if (ServerSource)
00400 {
00401 ServerSource->SetPingFlag();
00402 timeval t;
00403 gettimeofday(&t, NULL);
00404 long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000);
00405 ServerSource->rtt = ts - ServerSource->LastPingMsec;
00406 }
00407 }
00408 else
00409 {
00410 std::string forwardto = params[1];
00411 if (forwardto == this->Instance->Config->ServerName)
00412 {
00413
00414
00415
00416
00417
00418
00419 userrec* u = this->Instance->FindNick(prefix);
00420 if (u)
00421 {
00422 u->WriteServ("PONG %s %s",params[0].c_str(),params[1].c_str());
00423 }
00424 }
00425 else
00426 {
00427
00428 Utils->DoOneToOne(prefix,"PONG",params,forwardto);
00429 }
00430 }
00431
00432 return true;
00433 }
00434
00435 bool TreeSocket::MetaData(const std::string &prefix, std::deque<std::string> ¶ms)
00436 {
00437 if (params.size() < 2)
00438 return true;
00439 else if (params.size() < 3)
00440 params.push_back("");
00441 TreeServer* ServerSource = Utils->FindServer(prefix);
00442 if (ServerSource)
00443 {
00444 Utils->SetRemoteBursting(ServerSource, false);
00445
00446 if (params[0] == "*")
00447 {
00448 FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_OTHER,NULL,params[1],params[2]));
00449 }
00450 else if (*(params[0].c_str()) == '#')
00451 {
00452 chanrec* c = this->Instance->FindChan(params[0]);
00453 if (c)
00454 {
00455 FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_CHANNEL,c,params[1],params[2]));
00456 }
00457 }
00458 else if (*(params[0].c_str()) != '#')
00459 {
00460 userrec* u = this->Instance->FindNick(params[0]);
00461 if (u)
00462 {
00463 FOREACH_MOD_I(this->Instance,I_OnDecodeMetaData,OnDecodeMetaData(TYPE_USER,u,params[1],params[2]));
00464 }
00465 }
00466 }
00467
00468 params[2] = ":" + params[2];
00469 Utils->DoOneToAllButSender(prefix,"METADATA",params,prefix);
00470 return true;
00471 }
00472
00473 bool TreeSocket::ServerVersion(const std::string &prefix, std::deque<std::string> ¶ms)
00474 {
00475 if (params.size() < 1)
00476 return true;
00477
00478 TreeServer* ServerSource = Utils->FindServer(prefix);
00479
00480 if (ServerSource)
00481 {
00482 ServerSource->SetVersion(params[0]);
00483 }
00484 params[0] = ":" + params[0];
00485 Utils->DoOneToAllButSender(prefix,"VERSION",params,prefix);
00486 return true;
00487 }
00488
00489 bool TreeSocket::ChangeHost(const std::string &prefix, std::deque<std::string> ¶ms)
00490 {
00491 if (params.size() < 1)
00492 return true;
00493 userrec* u = this->Instance->FindNick(prefix);
00494
00495 if (u)
00496 {
00497 u->ChangeDisplayedHost(params[0].c_str());
00498 Utils->DoOneToAllButSender(prefix,"FHOST",params,u->server);
00499 }
00500 return true;
00501 }
00502
00503 bool TreeSocket::AddLine(const std::string &prefix, std::deque<std::string> ¶ms)
00504 {
00505 if (params.size() < 6)
00506 return true;
00507 bool propogate = false;
00508 if (!this->bursting)
00509 Utils->lines_to_apply = 0;
00510 switch (*(params[0].c_str()))
00511 {
00512 case 'Z':
00513 propogate = Instance->XLines->add_zline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00514 Instance->XLines->zline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00515 if (propogate)
00516 Utils->lines_to_apply |= APPLY_ZLINES;
00517 break;
00518 case 'Q':
00519 propogate = Instance->XLines->add_qline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00520 Instance->XLines->qline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00521 if (propogate)
00522 Utils->lines_to_apply |= APPLY_QLINES;
00523 break;
00524 case 'E':
00525 propogate = Instance->XLines->add_eline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00526 Instance->XLines->eline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00527 break;
00528 case 'G':
00529 propogate = Instance->XLines->add_gline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00530 Instance->XLines->gline_set_creation_time(params[1].c_str(), atoi(params[3].c_str()));
00531 if (propogate)
00532 Utils->lines_to_apply |= APPLY_GLINES;
00533 break;
00534 case 'K':
00535 propogate = Instance->XLines->add_kline(atoi(params[4].c_str()), params[2].c_str(), params[5].c_str(), params[1].c_str());
00536 if (propogate)
00537 Utils->lines_to_apply |= APPLY_KLINES;
00538 break;
00539 default:
00540
00541 this->Instance->SNO->WriteToSnoMask('x',"\2WARNING\2: Invalid xline type '"+params[0]+"' sent by server "+prefix+", ignored!");
00542 propogate = false;
00543 break;
00544 }
00545
00546 if (propogate)
00547 {
00548 if (atoi(params[4].c_str()))
00549 {
00550 time_t c_requires_crap = ConvToInt(params[4]) + Instance->Time();
00551 this->Instance->SNO->WriteToSnoMask('x',"%s Added %cLINE on %s to expire on %s (%s).",prefix.c_str(),*(params[0].c_str()),params[1].c_str(),Instance->TimeString(c_requires_crap).c_str(),params[5].c_str());
00552 }
00553 else
00554 {
00555 this->Instance->SNO->WriteToSnoMask('x',"%s Added permanent %cLINE on %s (%s).",prefix.c_str(),*(params[0].c_str()),params[1].c_str(),params[5].c_str());
00556 }
00557 params[5] = ":" + params[5];
00558 Utils->DoOneToAllButSender(prefix,"ADDLINE",params,prefix);
00559 }
00560 if (!this->bursting)
00561 {
00562 Instance->XLines->apply_lines(Utils->lines_to_apply);
00563 Utils->lines_to_apply = 0;
00564 }
00565 return true;
00566 }
00567
00568 bool TreeSocket::ChangeName(const std::string &prefix, std::deque<std::string> ¶ms)
00569 {
00570 if (params.size() < 1)
00571 return true;
00572 userrec* u = this->Instance->FindNick(prefix);
00573 if (u)
00574 {
00575 u->ChangeName(params[0].c_str());
00576 params[0] = ":" + params[0];
00577 Utils->DoOneToAllButSender(prefix,"FNAME",params,u->server);
00578 }
00579 return true;
00580 }
00581
00582 bool TreeSocket::Whois(const std::string &prefix, std::deque<std::string> ¶ms)
00583 {
00584 if (params.size() < 1)
00585 return true;
00586 userrec* u = this->Instance->FindNick(prefix);
00587 if (u)
00588 {
00589
00590 if (params.size() == 1)
00591 {
00592 userrec* x = this->Instance->FindNick(params[0]);
00593 if ((x) && (IS_LOCAL(x)))
00594 {
00595 userrec* x = this->Instance->FindNick(params[0]);
00596 char signon[MAXBUF];
00597 char idle[MAXBUF];
00598 snprintf(signon, MAXBUF, "%lu", (unsigned long)x->signon);
00599 snprintf(idle, MAXBUF, "%lu", (unsigned long)abs((x->idle_lastmsg) - Instance->Time(true)));
00600 std::deque<std::string> par;
00601 par.push_back(prefix);
00602 par.push_back(signon);
00603 par.push_back(idle);
00604
00605 Utils->DoOneToOne(params[0], "IDLE", par, u->server);
00606 }
00607 else
00608 {
00609
00610 if (x)
00611 Utils->DoOneToOne(prefix, "IDLE", params, x->server);
00612 }
00613 }
00614 else if (params.size() == 3)
00615 {
00616 std::string who_did_the_whois = params[0];
00617 userrec* who_to_send_to = this->Instance->FindNick(who_did_the_whois);
00618 if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
00619 {
00620
00621 std::string nick_whoised = prefix;
00622 unsigned long signon = atoi(params[1].c_str());
00623 unsigned long idle = atoi(params[2].c_str());
00624 if ((who_to_send_to) && (IS_LOCAL(who_to_send_to)))
00625 {
00626 do_whois(this->Instance, who_to_send_to, u, signon, idle, nick_whoised.c_str());
00627 }
00628 }
00629 else
00630 {
00631
00632 if (who_to_send_to)
00633 Utils->DoOneToOne(prefix, "IDLE", params, who_to_send_to->server);
00634 }
00635 }
00636 }
00637 return true;
00638 }
00639
00640 bool TreeSocket::Push(const std::string &prefix, std::deque<std::string> ¶ms)
00641 {
00642 if (params.size() < 2)
00643 return true;
00644 userrec* u = this->Instance->FindNick(params[0]);
00645 if (!u)
00646 return true;
00647 if (IS_LOCAL(u))
00648 {
00649 u->Write(params[1]);
00650 }
00651 else
00652 {
00653
00654 params[1] = ":" + params[1];
00655 Utils->DoOneToOne(prefix,"PUSH",params,u->server);
00656 }
00657 return true;
00658 }
00659
00660 bool TreeSocket::HandleSetTime(const std::string &prefix, std::deque<std::string> ¶ms)
00661 {
00662 if (!params.size() || !Utils->EnableTimeSync)
00663 return true;
00664
00665 bool force = false;
00666
00667 if ((params.size() == 2) && (params[1] == "FORCE"))
00668 force = true;
00669
00670 time_t them = atoi(params[0].c_str());
00671 time_t us = Instance->Time(false);
00672
00673 time_t diff = them - us;
00674
00675 Utils->DoOneToAllButSender(prefix, "TIMESET", params, prefix);
00676
00677 if (force || (them != us))
00678 {
00679 time_t old = Instance->SetTimeDelta(diff);
00680 Instance->Log(DEBUG, "TS (diff %d) from %s applied (old delta was %d)", diff, prefix.c_str(), old);
00681 }
00682
00683 return true;
00684 }
00685
00686 bool TreeSocket::Time(const std::string &prefix, std::deque<std::string> ¶ms)
00687 {
00688
00689
00690 if (params.size() == 2)
00691 {
00692
00693 if (this->Instance->Config->ServerName == params[0])
00694 {
00695 userrec* u = this->Instance->FindNick(params[1]);
00696 if (u)
00697 {
00698 params.push_back(ConvToStr(Instance->Time(false)));
00699 params[0] = prefix;
00700 Utils->DoOneToOne(this->Instance->Config->ServerName,"TIME",params,params[0]);
00701 }
00702 }
00703 else
00704 {
00705
00706 userrec* u = this->Instance->FindNick(params[1]);
00707 if (u)
00708 Utils->DoOneToOne(prefix,"TIME",params,params[0]);
00709 }
00710 }
00711 else if (params.size() == 3)
00712 {
00713
00714 userrec* u = this->Instance->FindNick(params[1]);
00715 if ((u) && (IS_LOCAL(u)))
00716 {
00717 time_t rawtime = atol(params[2].c_str());
00718 struct tm * timeinfo;
00719 timeinfo = localtime(&rawtime);
00720 char tms[26];
00721 snprintf(tms,26,"%s",asctime(timeinfo));
00722 tms[24] = 0;
00723 u->WriteServ("391 %s %s :%s",u->nick,prefix.c_str(),tms);
00724 }
00725 else
00726 {
00727 if (u)
00728 Utils->DoOneToOne(prefix,"TIME",params,u->server);
00729 }
00730 }
00731 return true;
00732 }
00733
00734 bool TreeSocket::LocalPing(const std::string &prefix, std::deque<std::string> ¶ms)
00735 {
00736 if (params.size() < 1)
00737 return true;
00738 if (params.size() == 1)
00739 {
00740 std::string stufftobounce = params[0];
00741 this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" PONG "+stufftobounce);
00742 return true;
00743 }
00744 else
00745 {
00746 std::string forwardto = params[1];
00747 if (forwardto == this->Instance->Config->ServerName)
00748 {
00749
00750 params[1] = params[0];
00751 params[0] = forwardto;
00752 Utils->DoOneToOne(forwardto,"PONG",params,params[1]);
00753 }
00754 else
00755 {
00756
00757 Utils->DoOneToOne(prefix,"PING",params,forwardto);
00758 }
00759 return true;
00760 }
00761 }
00762
00765 bool TreeSocket::RemoveStatus(const std::string &prefix, std::deque<std::string> ¶ms)
00766 {
00767 if (params.size() < 1)
00768 return true;
00769 chanrec* c = Instance->FindChan(params[0]);
00770 if (c)
00771 {
00772 for (char modeletter = 'A'; modeletter <= 'z'; modeletter++)
00773 {
00774 ModeHandler* mh = Instance->Modes->FindMode(modeletter, MODETYPE_CHANNEL);
00775 if (mh)
00776 mh->RemoveMode(c);
00777 }
00778 }
00779 return true;
00780 }
00781
00782 bool TreeSocket::RemoteServer(const std::string &prefix, std::deque<std::string> ¶ms)
00783 {
00784 if (params.size() < 4)
00785 return false;
00786 std::string servername = params[0];
00787 std::string password = params[1];
00788
00789 std::string description = params[3];
00790 TreeServer* ParentOfThis = Utils->FindServer(prefix);
00791 if (!ParentOfThis)
00792 {
00793 this->SendError("Protocol error - Introduced remote server from unknown server "+prefix);
00794 return false;
00795 }
00796 TreeServer* CheckDupe = Utils->FindServer(servername);
00797 if (CheckDupe)
00798 {
00799 this->SendError("Server "+servername+" already exists!");
00800 this->Instance->SNO->WriteToSnoMask('l',"Server \2"+servername+"\2 being introduced from \2" + prefix + "\2 denied, already exists. Closing link with " + prefix);
00801 return false;
00802 }
00803 Link* lnk = Utils->FindLink(servername);
00804 TreeServer* Node = new TreeServer(this->Utils,this->Instance,servername,description,ParentOfThis,NULL, lnk ? lnk->Hidden : false);
00805 ParentOfThis->AddChild(Node);
00806 params[3] = ":" + params[3];
00807 Utils->SetRemoteBursting(Node, true);
00808 Utils->DoOneToAllButSender(prefix,"SERVER",params,prefix);
00809 this->Instance