00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 static bool has_servicesmod = false;
00017 static bool has_globopsmod = false;
00018 static bool has_chghostmod = false;
00019 static bool has_chgidentmod = false;
00020 static bool has_hidechansmod = false;
00021
00022 class InspIRCdProto : public IRCDProto
00023 {
00024 public:
00025 InspIRCdProto(Module *creator) : IRCDProto(creator, "InspIRCd 1.1")
00026 {
00027 DefaultPseudoclientModes = "+I";
00028 CanSVSNick = true;
00029 CanSVSJoin = true;
00030 CanSetVHost = true;
00031 CanSetVIdent = true;
00032 CanSNLine = true;
00033 CanSQLine = true;
00034 CanSZLine = true;
00035 CanSVSHold = true;
00036 CanSVSO = true;
00037 MaxModes = 20;
00038 }
00039 private:
00040
00041 Anope::string current_pass;
00042
00043 void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent)
00044 {
00045 if (has_chgidentmod)
00046 {
00047 if (nick.empty() || vIdent.empty())
00048 return;
00049 UplinkSocket::Message(OperServ) << "CHGIDENT " << nick << " " << vIdent;
00050 }
00051 else
00052 Log() << "CHGIDENT not loaded!";
00053 }
00054
00055 void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost)
00056 {
00057 if (has_chghostmod)
00058 {
00059 if (nick.empty() || vhost.empty())
00060 return;
00061 UplinkSocket::Message(OperServ) << "CHGHOST " << nick << " " << vhost;
00062 }
00063 else
00064 Log() << "CHGHOST not loaded!";
00065 }
00066
00067 void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00068 {
00069 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
00070 }
00071
00072 void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00073 {
00074 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
00075 }
00076
00077 void SendAkillDel(const XLine *x) anope_override
00078 {
00079 if (x->IsRegex() || x->HasNickOrReal())
00080 return;
00081
00082
00083 try
00084 {
00085 if (x->GetUser() == "*")
00086 {
00087 sockaddrs(x->GetHost());
00088 IRCD->SendSZLineDel(x);
00089 return;
00090 }
00091 }
00092 catch (const SocketException &) { }
00093
00094 UplinkSocket::Message(OperServ) << "GLINE " << x->mask;
00095 }
00096
00097 void SendTopic(BotInfo *whosets, Channel *c) anope_override
00098 {
00099 UplinkSocket::Message(whosets) << "FTOPIC " << c->name << " " << c->topic_time << " " << c->topic_ts <<" :" << c->topic;
00100 }
00101
00102 void SendVhostDel(User *u) anope_override
00103 {
00104 if (u->HasMode("CLOAK"))
00105 inspircd_cmd_chghost(u->nick, u->chost);
00106 else
00107 inspircd_cmd_chghost(u->nick, u->host);
00108
00109 if (has_chgidentmod && u->GetIdent() != u->GetVIdent())
00110 inspircd_cmd_chgident(u->nick, u->GetIdent());
00111 }
00112
00113 void SendAkill(User *u, XLine *x) anope_override
00114 {
00115 if (x->IsRegex() || x->HasNickOrReal())
00116 {
00117 if (!u)
00118 {
00119
00120 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
00121 if (x->manager->Check(it->second, x))
00122 this->SendAkill(it->second, x);
00123 return;
00124 }
00125
00126 const XLine *old = x;
00127
00128 if (old->manager->HasEntry("*@" + u->host))
00129 return;
00130
00131
00132 x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
00133 old->manager->AddXLine(x);
00134
00135 Log(OperServ, "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
00136 }
00137
00138
00139 try
00140 {
00141 if (x->GetUser() == "*")
00142 {
00143 sockaddrs(x->GetHost());
00144 IRCD->SendSZLine(u, x);
00145 return;
00146 }
00147 }
00148 catch (const SocketException &) { }
00149
00150
00151 time_t timeleft = x->expires - Anope::CurTime;
00152 if (timeleft > 172800 || !x->expires)
00153 timeleft = 172800;
00154 UplinkSocket::Message(Me) << "ADDLINE G " << x->mask << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00155 }
00156
00157 void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override
00158 {
00159 if (source)
00160 {
00161 UplinkSocket::Message(source) << "KILL " << user->nick << " :" << buf;
00162 user->KillInternal(source->nick, buf);
00163 }
00164 else
00165 {
00166 UplinkSocket::Message(Me) << "KILL " << user->nick << " :" << buf;
00167 user->KillInternal(Me->GetName(), buf);
00168 }
00169 }
00170
00171 void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override
00172 {
00173 UplinkSocket::Message() << "PUSH " << dest << " ::" << Me->GetName() << " " << numeric << " " << dest << " " << buf;
00174 }
00175
00176 void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override
00177 {
00178 if (source)
00179 UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
00180 else
00181 UplinkSocket::Message(Me) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
00182 }
00183
00184 void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override
00185 {
00186 if (bi)
00187 UplinkSocket::Message(bi) << "MODE " << u->nick << " " << buf;
00188 else
00189 UplinkSocket::Message(Me) << "MODE " << u->nick << " " << buf;
00190 }
00191
00192 void SendClientIntroduction(const User *u) anope_override
00193 {
00194 Anope::string modes = "+" + u->GetModes();
00195 UplinkSocket::Message(Me) << "NICK " << u->timestamp << " " << u->nick << " " << u->host << " " << u->host << " " << u->GetIdent() << " " << modes << " 0.0.0.0 :" << u->realname;
00196 UplinkSocket::Message(u) << "OPERTYPE Service";
00197 }
00198
00199
00200 void SendServer(const Server *server) anope_override
00201 {
00202 UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << current_pass << " " << server->GetHops() << " :" << server->GetDescription();
00203 }
00204
00205
00206 void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override
00207 {
00208 UplinkSocket::Message(user) << "JOIN " << c->name << " " << c->creation_time;
00209 if (status)
00210 {
00211
00212 ChannelStatus cs = *status;
00213
00214
00215
00216 ChanUserContainer *uc = c->FindUser(user);
00217 if (uc != NULL)
00218 uc->status.modes.clear();
00219
00220 BotInfo *setter = BotInfo::Find(user->nick);
00221 for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00222 if (cs.modes.count(ModeManager::ChannelModes[i]->name))
00223 c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false);
00224 }
00225 }
00226
00227
00228 void SendSQLineDel(const XLine *x) anope_override
00229 {
00230 UplinkSocket::Message(OperServ) << "QLINE " << x->mask;
00231 }
00232
00233
00234 void SendSQLine(User *, const XLine *x) anope_override
00235 {
00236
00237 time_t timeleft = x->expires - Anope::CurTime;
00238 if (timeleft > 172800 || !x->expires)
00239 timeleft = 172800;
00240 UplinkSocket::Message(Me) << "ADDLINE Q " << x->mask << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00241 }
00242
00243
00244
00245 void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
00246 {
00247 if (!vIdent.empty())
00248 inspircd_cmd_chgident(u->nick, vIdent);
00249 if (!vhost.empty())
00250 inspircd_cmd_chghost(u->nick, vhost);
00251 }
00252
00253 void SendConnect() anope_override
00254 {
00255 current_pass = Config->Uplinks[Anope::CurrentUplink]->password;
00256 SendServer(Me);
00257 UplinkSocket::Message() << "BURST";
00258 Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
00259 UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << this->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
00260 }
00261
00262
00263 void SendSVSHold(const Anope::string &nick) anope_override
00264 {
00265 UplinkSocket::Message(OperServ) << "SVSHOLD " << nick << " " << Config->NSReleaseTimeout << "s :Being held for registered user";
00266 }
00267
00268
00269 void SendSVSHoldDel(const Anope::string &nick) anope_override
00270 {
00271 UplinkSocket::Message(OperServ) << "SVSHOLD " << nick;
00272 }
00273
00274
00275 void SendSZLineDel(const XLine *x) anope_override
00276 {
00277 UplinkSocket::Message(OperServ) << "ZLINE " << x->GetHost();
00278 }
00279
00280
00281 void SendSZLine(User *, const XLine *x) anope_override
00282 {
00283
00284 time_t timeleft = x->expires - Anope::CurTime;
00285 if (timeleft > 172800 || !x->expires)
00286 timeleft = 172800;
00287 UplinkSocket::Message(Me) << "ADDLINE Z " << x->GetHost() << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00288 }
00289
00290 void SendSVSJoin(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string &) anope_override
00291 {
00292 UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
00293 }
00294
00295 void SendSVSPart(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string ¶m) anope_override
00296 {
00297 if (!param.empty())
00298 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
00299 else
00300 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
00301 }
00302
00303 void SendBOB() anope_override
00304 {
00305 UplinkSocket::Message() << "BURST " << Anope::CurTime;
00306 }
00307
00308 void SendEOB() anope_override
00309 {
00310 UplinkSocket::Message() << "ENDBURST";
00311 }
00312
00313 void SendLogin(User *u) anope_override
00314 {
00315 if (!u->Account())
00316 return;
00317
00318 Anope::string svidbuf = stringify(u->timestamp);
00319 u->Account()->Extend("authenticationtoken", new ExtensibleItemClass<Anope::string>(svidbuf));
00320 }
00321
00322 void SendLogout(User *u) anope_override
00323 {
00324 }
00325 };
00326
00327 class ChannelModeFlood : public ChannelModeParam
00328 {
00329 public:
00330 ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
00331
00332 bool IsValid(const Anope::string &value) const anope_override
00333 {
00334 try
00335 {
00336 Anope::string rest;
00337 if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty())
00338 return true;
00339 }
00340 catch (const ConvertException &) { }
00341
00342 return false;
00343 }
00344 };
00345
00346 struct IRCDMessageCapab : Message::Capab
00347 {
00348 IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00349
00350 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00351 {
00352 if (params[0].equals_cs("START"))
00353 {
00354
00355 has_servicesmod = false;
00356 has_globopsmod = false;
00357 has_chghostmod = false;
00358 has_chgidentmod = false;
00359 has_hidechansmod = false;
00360 IRCD->CanSVSHold = false;
00361 }
00362 else if (params[0].equals_cs("MODULES") && params.size() > 1)
00363 {
00364 if (params[1].find("m_globops.so") != Anope::string::npos)
00365 has_globopsmod = true;
00366 if (params[1].find("m_services.so") != Anope::string::npos)
00367 has_servicesmod = true;
00368 if (params[1].find("m_svshold.so") != Anope::string::npos)
00369 IRCD->CanSVSHold = true;
00370 if (params[1].find("m_chghost.so") != Anope::string::npos)
00371 has_chghostmod = true;
00372 if (params[1].find("m_chgident.so") != Anope::string::npos)
00373 has_chgidentmod = true;
00374 if (params[1].find("m_hidechans.so") != Anope::string::npos)
00375 has_hidechansmod = true;
00376 }
00377 else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
00378 {
00379 spacesepstream ssep(params[1]);
00380 Anope::string capab;
00381 while (ssep.GetToken(capab))
00382 {
00383 if (capab.find("CHANMODES") != Anope::string::npos)
00384 {
00385 Anope::string modes(capab.begin() + 10, capab.end());
00386 commasepstream sep(modes);
00387 Anope::string modebuf;
00388
00389 sep.GetToken(modebuf);
00390 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00391 {
00392 switch (modebuf[t])
00393 {
00394 case 'b':
00395 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
00396 continue;
00397 case 'e':
00398 ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
00399 continue;
00400 case 'I':
00401 ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
00402 continue;
00403 default:
00404 ModeManager::AddChannelMode(new ChannelModeList("END", modebuf[t]));
00405 }
00406 }
00407
00408 sep.GetToken(modebuf);
00409 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00410 {
00411 switch (modebuf[t])
00412 {
00413 case 'k':
00414 ModeManager::AddChannelMode(new ChannelModeKey('k'));
00415 continue;
00416 default:
00417 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t]));
00418 }
00419 }
00420
00421 sep.GetToken(modebuf);
00422 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00423 {
00424 switch (modebuf[t])
00425 {
00426 case 'f':
00427 ModeManager::AddChannelMode(new ChannelModeFlood('f', false));
00428 continue;
00429 case 'l':
00430 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
00431 continue;
00432 case 'L':
00433 ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L', true));
00434 continue;
00435 default:
00436 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t], true));
00437 }
00438 }
00439
00440 sep.GetToken(modebuf);
00441 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00442 {
00443 switch (modebuf[t])
00444 {
00445 case 'i':
00446 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
00447 continue;
00448 case 'm':
00449 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
00450 continue;
00451 case 'n':
00452 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
00453 continue;
00454 case 'p':
00455 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
00456 continue;
00457 case 's':
00458 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
00459 continue;
00460 case 't':
00461 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
00462 continue;
00463 case 'r':
00464 ModeManager::AddChannelMode(new ChannelModeRegistered('r'));
00465 continue;
00466 case 'c':
00467 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
00468 continue;
00469 case 'u':
00470 ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u'));
00471 continue;
00472 case 'z':
00473 ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
00474 continue;
00475 case 'A':
00476 ModeManager::AddChannelMode(new ChannelMode("ALLINVITE", 'A'));
00477 continue;
00478 case 'C':
00479 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
00480 continue;
00481 case 'G':
00482 ModeManager::AddChannelMode(new ChannelMode("FILTER", 'G'));
00483 continue;
00484 case 'K':
00485 ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
00486 continue;
00487 case 'N':
00488 ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
00489 continue;
00490 case 'O':
00491 ModeManager::AddChannelMode(new ChannelModeOper('O'));
00492 continue;
00493 case 'Q':
00494 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
00495 continue;
00496 case 'R':
00497 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
00498 continue;
00499 case 'S':
00500 ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S'));
00501 continue;
00502 case 'V':
00503 ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V'));
00504 continue;
00505 default:
00506 ModeManager::AddChannelMode(new ChannelMode("END", modebuf[t]));
00507 }
00508 }
00509 }
00510 else if (capab.find("PREFIX=(") != Anope::string::npos)
00511 {
00512 Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
00513 Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
00514 unsigned short level = modes.length() - 1;
00515
00516 for (size_t t = 0, end = modes.length(); t < end; ++t)
00517 {
00518 switch (modes[t])
00519 {
00520 case 'q':
00521 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', level--));
00522 continue;
00523 case 'a':
00524 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', level--));
00525 continue;
00526 case 'o':
00527 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', level--));
00528 continue;
00529 case 'h':
00530 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', level--));
00531 continue;
00532 case 'v':
00533 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', level--));
00534 continue;
00535 default:
00536 ModeManager::AddChannelMode(new ChannelModeStatus("END", modes[t], chars[t], level--));
00537 }
00538 }
00539 }
00540 else if (capab.find("MAXMODES=") != Anope::string::npos)
00541 {
00542 Anope::string maxmodes(capab.begin() + 9, capab.end());
00543 IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
00544 }
00545 }
00546 }
00547 else if (params[0].equals_cs("END"))
00548 {
00549 if (!has_globopsmod)
00550 {
00551 UplinkSocket::Message() << "ERROR :m_globops is not loaded. This is required by Anope";
00552 Anope::QuitReason = "ERROR: Remote server does not have the m_globops module loaded, and this is required.";
00553 Anope::Quitting = true;
00554 return;
00555 }
00556 if (!has_servicesmod)
00557 {
00558 UplinkSocket::Message() << "ERROR :m_services is not loaded. This is required by Anope";
00559 Anope::QuitReason = "ERROR: Remote server does not have the m_services module loaded, and this is required.";
00560 Anope::Quitting = true;
00561 return;
00562 }
00563 if (!has_hidechansmod)
00564 {
00565 UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
00566 Anope::QuitReason = "ERROR: Remote server deos not have the m_hidechans module loaded, and this is required.";
00567 Anope::Quitting = true;
00568 return;
00569 }
00570 if (!IRCD->CanSVSHold)
00571 Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
00572 if (!has_chghostmod)
00573 Log() << "CHGHOST missing, Usage disabled until module is loaded.";
00574 if (!has_chgidentmod)
00575 Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
00576 }
00577
00578 Message::Capab::Run(source, params);
00579 }
00580 };
00581
00582 struct IRCDMessageChgIdent : IRCDMessage
00583 {
00584 IRCDMessageChgIdent(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 2) { }
00585
00586 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00587 {
00588 User *u = User::Find(params[0]);
00589 if (!u)
00590 {
00591 Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0];
00592 return;
00593 }
00594
00595 u->SetIdent(params[1]);
00596 }
00597 };
00598
00599 struct IRCDMessageChgName : IRCDMessage
00600 {
00601 IRCDMessageChgName(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00602
00603 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00604 {
00605 source.GetUser()->SetRealname(params[0]);
00606 }
00607 };
00608
00609 struct IRCDMessageEndBurst : IRCDMessage
00610 {
00611 IRCDMessageEndBurst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { }
00612
00613 void Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override
00614 {
00615 Me->GetLinks().front()->Sync(true);
00616 }
00617 };
00618
00619 struct IRCDMessageFHost : IRCDMessage
00620 {
00621 IRCDMessageFHost(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00622
00623 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00624 {
00625 source.GetUser()->SetDisplayedHost(params[0]);
00626 }
00627 };
00628
00629 struct IRCDMessageFJoin : IRCDMessage
00630 {
00631 IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00632
00633 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00634 {
00635 std::list<Message::Join::SJoinUser> users;
00636
00637 spacesepstream sep(params[params.size() - 1]);
00638 Anope::string buf;
00639
00640 while (sep.GetToken(buf))
00641 {
00642 Message::Join::SJoinUser sju;
00643
00644
00645 for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));)
00646 {
00647 ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
00648 buf.erase(buf.begin());
00649
00650 if (!cm)
00651 {
00652 Log() << "Received unknown mode prefix " << ch << " in FJOIN string";
00653 continue;
00654 }
00655
00656 sju.first.modes.insert(cm->name);
00657 }
00658
00659 buf.erase(buf.begin());
00660
00661 sju.second = User::Find(buf);
00662 if (!sju.second)
00663 {
00664 Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << params[0];
00665 continue;
00666 }
00667
00668 }
00669
00670 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
00671 Message::Join::SJoin(source, params[0], ts, "", users);
00672 }
00673 };
00674
00675 struct IRCDMessageFMode : IRCDMessage
00676 {
00677 IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00678
00679 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00680 {
00681
00682
00683 Channel *c = Channel::Find(params[0]);
00684 if (!c)
00685 return;
00686 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0;
00687
00688
00689
00690 Anope::string modes = "+" + params[2];
00691 for (unsigned n = 3; n < params.size(); ++n)
00692 modes += " " + params[n];
00693
00694 c->SetModesInternal(source, modes, ts);
00695 }
00696 };
00697
00698 struct IRCDMessageFTopic : IRCDMessage
00699 {
00700 IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { }
00701
00702 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00703 {
00704 Channel *c = Channel::Find(params[0]);
00705 if (c)
00706 c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime);
00707 }
00708 };
00709
00710 struct IRCDMessageIdle : IRCDMessage
00711 {
00712 IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00713
00714 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00715 {
00716 const BotInfo *bi = BotInfo::Find(params[0]);
00717 UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (bi ? Anope::CurTime - bi->lastmsg : 0);
00718 }
00719 };
00720
00721 struct IRCDMessageMode : IRCDMessage
00722 {
00723 IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00724
00725 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00726 {
00727 if (IRCD->IsChannelValid(params[0]))
00728 {
00729 Channel *c = Channel::Find(params[0]);
00730 time_t ts;
00731
00732 try
00733 {
00734 ts = convertTo<time_t>(params[2]);
00735 }
00736 catch (const ConvertException &)
00737 {
00738 ts = 0;
00739 }
00740
00741 if (c)
00742 c->SetModesInternal(source, params[1], ts);
00743 }
00744 else
00745 {
00746 User *u = User::Find(params[0]);
00747 if (u)
00748 u->SetModesInternal("%s", params[1].c_str());
00749 }
00750 }
00751 };
00752
00753 struct IRCDMessageNick : IRCDMessage
00754 {
00755 ServiceReference<NickServService> NSService;
00756
00757 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 1), NSService("NickServService", "NickServ") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00758
00759 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00760 {
00761 if (params.size() == 8 && source.GetServer())
00762 {
00763 time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
00764
00765 User *user = new User(params[1], params[4], params[2], params[3], params[6], source.GetServer(), params[7], ts, params[5]);
00766 if (NSService)
00767 {
00768 NickAlias *na = NickAlias::Find(user->nick);
00769 Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL;
00770 if (na && svidbuf && *svidbuf == params[0])
00771 NSService->Login(user, na);
00772 }
00773 }
00774 else if (params.size() == 1 && source.GetUser())
00775 source.GetUser()->ChangeNick(params[0]);
00776 }
00777 };
00778
00779 struct IRCDMessageOperType : IRCDMessage
00780 {
00781 IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00782
00783 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00784 {
00785
00786
00787 User *u = source.GetUser();
00788 if (!u->HasMode("OPER"))
00789 u->SetModesInternal("+o");
00790 }
00791 };
00792
00793 struct IRCDMessageRSQuit : IRCDMessage
00794 {
00795 IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00796
00797 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00798 {
00799 if (params.empty() || params.size() > 3)
00800 return;
00801
00802 Server *s;
00803
00804 if (params.size() > 1 && Config->ServerName.equals_cs(params[0]))
00805 s = Server::Find(params[1]);
00806 else
00807 s = Server::Find(params[0]);
00808
00809 source.GetServer()->Delete(source.GetServer()->GetName() + " " + (s ? s->GetName() : "<unknown>"));
00810 }
00811 };
00812
00813 struct IRCDMessageServer : IRCDMessage
00814 {
00815 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00816
00817 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00818 {
00819 unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
00820 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]);
00821 }
00822 };
00823
00824 class ProtoInspIRCd : public Module
00825 {
00826 InspIRCdProto ircd_proto;
00827
00828
00829 Message::Away message_away;
00830 Message::Error message_error;
00831 Message::Join message_join;
00832 Message::Kick message_kick;
00833 Message::Kill message_kill;
00834 Message::MOTD message_motd;
00835 Message::Part message_part;
00836 Message::Ping message_ping;
00837 Message::Privmsg message_privmsg;
00838 Message::Quit message_quit;
00839 Message::SQuit message_squit;
00840 Message::Stats message_stats;
00841 Message::Time message_time;
00842 Message::Topic message_topic;
00843 Message::Version message_version;
00844
00845
00846 IRCDMessageCapab message_capab;
00847 IRCDMessageChgIdent message_chgident, message_setident;
00848 IRCDMessageChgName message_chgname, message_setname;
00849 IRCDMessageEndBurst message_endburst;
00850 IRCDMessageFHost message_fhost, message_sethost;
00851 IRCDMessageFJoin message_fjoin;
00852 IRCDMessageFMode message_fmode;
00853 IRCDMessageFTopic message_ftopic;
00854 IRCDMessageIdle message_idle;
00855 IRCDMessageMode message_mode;
00856 IRCDMessageNick message_nick;
00857 IRCDMessageOperType message_opertype;
00858 IRCDMessageRSQuit message_rsquit;
00859 IRCDMessageServer message_server;
00860
00861 void AddModes()
00862 {
00863 ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
00864 ModeManager::AddUserMode(new UserMode("HELPOP", 'h'));
00865 ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
00866 ModeManager::AddUserMode(new UserMode("OPER", 'o'));
00867 ModeManager::AddUserMode(new UserMode("REGISTERED", 'r'));
00868 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
00869 ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
00870 }
00871
00872 public:
00873 ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
00874 ircd_proto(this),
00875 message_away(this), message_error(this), message_join(this), message_kick(this), message_kill(this),
00876 message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
00877 message_squit(this), message_stats(this), message_time(this), message_topic(this), message_version(this),
00878
00879 message_capab(this), message_chgident(this, "CHGIDENT"), message_setident(this, "SETIDENT"),
00880 message_chgname(this, "CHGNAME"), message_setname(this, "SETNAME"), message_endburst(this),
00881 message_fhost(this, "FHOST"), message_sethost(this, "SETHOST"), message_fjoin(this),
00882 message_fmode(this), message_ftopic(this), message_idle(this), message_mode(this),
00883 message_nick(this), message_opertype(this), message_rsquit(this), message_server(this)
00884 {
00885 this->SetAuthor("Anope");
00886
00887 Servers::Capab.insert("NOQUIT");
00888
00889 this->AddModes();
00890
00891 ModuleManager::Attach(I_OnUserNickChange, this);
00892 }
00893
00894 void OnUserNickChange(User *u, const Anope::string &) anope_override
00895 {
00896 u->RemoveModeInternal(ModeManager::FindUserModeByName("REGISTERED"));
00897 }
00898 };
00899
00900 MODULE_INIT(ProtoInspIRCd)