00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 class ChannelModeFlood : public ChannelModeParam
00017 {
00018 public:
00019 ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
00020
00021 bool IsValid(const Anope::string &value) const anope_override
00022 {
00023 try
00024 {
00025 Anope::string rest;
00026 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())
00027 return true;
00028 }
00029 catch (const ConvertException &) { }
00030
00031 return false;
00032 }
00033 };
00034
00035 class InspIRCd12Proto : public IRCDProto
00036 {
00037 private:
00038 void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override
00039 {
00040 IRCDProto::SendSVSKillInternal(source, user, buf);
00041 user->KillInternal(source ? source->nick : Me->GetName(), buf);
00042 }
00043
00044 void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent)
00045 {
00046 if (!Servers::Capab.count("CHGIDENT"))
00047 Log() << "CHGIDENT not loaded!";
00048 else
00049 UplinkSocket::Message(HostServ) << "CHGIDENT " << nick << " " << vIdent;
00050 }
00051
00052 void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost)
00053 {
00054 if (!Servers::Capab.count("CHGHOST"))
00055 Log() << "CHGHOST not loaded!";
00056 else
00057 UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost;
00058 }
00059
00060 void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason)
00061 {
00062 UplinkSocket::Message(Me) << "ADDLINE " << xtype << " " << mask << " " << addedby << " " << Anope::CurTime << " " << duration << " :" << reason;
00063 }
00064
00065 void SendDelLine(const Anope::string &xtype, const Anope::string &mask)
00066 {
00067 UplinkSocket::Message(Me) << "DELLINE " << xtype << " " << mask;
00068 }
00069
00070 public:
00071 InspIRCd12Proto(Module *creator) : IRCDProto(creator, "InspIRCd 1.2")
00072 {
00073 DefaultPseudoclientModes = "+I";
00074 CanSVSNick = true;
00075 CanSVSJoin = true;
00076 CanSetVHost = true;
00077 CanSetVIdent = true;
00078 CanSQLine = true;
00079 CanSZLine = true;
00080 CanSVSHold = true;
00081 CanCertFP = true;
00082 RequiresID = true;
00083 MaxModes = 20;
00084 }
00085
00086 void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00087 {
00088 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
00089 }
00090
00091 void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00092 {
00093 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
00094 }
00095
00096 void SendAkillDel(const XLine *x) anope_override
00097 {
00098
00099 if (x->IsRegex() && Servers::Capab.count("RLINE"))
00100 {
00101 Anope::string mask = x->mask;
00102 size_t h = x->mask.find('#');
00103 if (h != Anope::string::npos)
00104 mask = mask.replace(h, 1, ' ');
00105 SendDelLine("R", mask);
00106 return;
00107 }
00108 else if (x->IsRegex() || x->HasNickOrReal())
00109 return;
00110
00111 SendDelLine("G", x->mask);
00112 }
00113
00114 void SendTopic(BotInfo *whosets, Channel *c) anope_override
00115 {
00116 if (Servers::Capab.count("SVSTOPIC"))
00117 {
00118 UplinkSocket::Message(c->ci->WhoSends()) << "SVSTOPIC " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic;
00119 }
00120 else
00121 {
00122
00123 time_t ts = c->topic_ts;
00124 if (c->topic_time > ts)
00125 ts = Anope::CurTime;
00126
00127 UplinkSocket::Message(whosets) << "FTOPIC " << c->name << " " << ts << " " << c->topic_setter << " :" << c->topic;
00128 }
00129 }
00130
00131 void SendVhostDel(User *u) anope_override
00132 {
00133 if (u->HasMode("CLOAK"))
00134 this->SendChgHostInternal(u->nick, u->chost);
00135 else
00136 this->SendChgHostInternal(u->nick, u->host);
00137
00138 if (Servers::Capab.count("CHGIDENT") && u->GetIdent() != u->GetVIdent())
00139 this->SendChgIdentInternal(u->nick, u->GetIdent());
00140 }
00141
00142 void SendAkill(User *u, XLine *x) anope_override
00143 {
00144
00145 time_t timeleft = x->expires - Anope::CurTime;
00146 if (timeleft > 172800 || !x->expires)
00147 timeleft = 172800;
00148
00149
00150 if (x->IsRegex() && Servers::Capab.count("RLINE"))
00151 {
00152 Anope::string mask = x->mask;
00153 size_t h = x->mask.find('#');
00154 if (h != Anope::string::npos)
00155 mask = mask.replace(h, 1, ' ');
00156 SendAddLine("R", mask, timeleft, x->by, x->GetReason());
00157 return;
00158 }
00159 else if (x->IsRegex() || x->HasNickOrReal())
00160 {
00161 if (!u)
00162 {
00163
00164 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
00165 if (x->manager->Check(it->second, x))
00166 this->SendAkill(it->second, x);
00167 return;
00168 }
00169
00170 const XLine *old = x;
00171
00172 if (old->manager->HasEntry("*@" + u->host))
00173 return;
00174
00175
00176 x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
00177 old->manager->AddXLine(x);
00178
00179 Log(OperServ, "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
00180 }
00181
00182
00183 try
00184 {
00185 if (x->GetUser() == "*")
00186 {
00187 sockaddrs(x->GetHost());
00188 IRCD->SendSZLine(u, x);
00189 return;
00190 }
00191 }
00192 catch (const SocketException &) { }
00193 SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason());
00194 }
00195
00196 void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override
00197 {
00198 UplinkSocket::Message() << "PUSH " << dest << " ::" << Me->GetName() << " " << numeric << " " << dest << " " << buf;
00199 }
00200
00201 void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override
00202 {
00203 UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
00204 }
00205
00206 void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override
00207 {
00208 UplinkSocket::Message(bi) << "MODE " << u->GetUID() << " " << buf;
00209 }
00210
00211 void SendClientIntroduction(const User *u) anope_override
00212 {
00213 Anope::string modes = "+" + u->GetModes();
00214 UplinkSocket::Message(Me) << "UID " << u->GetUID() << " " << u->timestamp << " " << u->nick << " " << u->host << " " << u->host << " " << u->GetIdent() << " 0.0.0.0 " << u->timestamp << " " << modes << " :" << u->realname;
00215 }
00216
00217
00218 void SendServer(const Server *server) anope_override
00219 {
00220 UplinkSocket::Message() << "SERVER " << server->GetName() << " " << Config->Uplinks[Anope::CurrentUplink]->password << " " << server->GetHops() << " " << server->GetSID() << " :" << server->GetDescription();
00221 }
00222
00223
00224 void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override
00225 {
00226 UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :," << user->GetUID();
00227
00228
00229
00230
00231 if (status)
00232 {
00233
00234 ChannelStatus cs = *status;
00235
00236
00237
00238 ChanUserContainer *uc = c->FindUser(user);
00239 if (uc != NULL)
00240 uc->status.modes.clear();
00241
00242 BotInfo *setter = BotInfo::Find(user->nick);
00243 for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00244 {
00245 ChannelMode *cm = ModeManager::ChannelModes[i];
00246
00247 if (cs.modes.count(cm->name) || cs.modes.count(cm->mchar))
00248 {
00249 c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false);
00250 cs.modes.insert(cm->name);
00251 }
00252 }
00253 }
00254 }
00255
00256
00257 void SendSQLineDel(const XLine *x) anope_override
00258 {
00259 SendDelLine("Q", x->mask);
00260 }
00261
00262
00263 void SendSQLine(User *, const XLine *x) anope_override
00264 {
00265
00266 time_t timeleft = x->expires - Anope::CurTime;
00267 if (timeleft > 172800 || !x->expires)
00268 timeleft = 172800;
00269 SendAddLine("Q", x->mask, timeleft, x->by, x->GetReason());
00270 }
00271
00272
00273
00274 void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
00275 {
00276 if (!vIdent.empty())
00277 this->SendChgIdentInternal(u->nick, vIdent);
00278 if (!vhost.empty())
00279 this->SendChgHostInternal(u->nick, vhost);
00280 }
00281
00282 void SendConnect() anope_override
00283 {
00284 SendServer(Me);
00285 UplinkSocket::Message(Me) << "BURST";
00286 Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
00287 UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << IRCD->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
00288 }
00289
00290
00291 void SendSVSHold(const Anope::string &nick) anope_override
00292 {
00293 UplinkSocket::Message(NickServ) << "SVSHOLD " << nick << " " << Config->NSReleaseTimeout << " :Being held for registered user";
00294 }
00295
00296
00297 void SendSVSHoldDel(const Anope::string &nick) anope_override
00298 {
00299 UplinkSocket::Message(NickServ) << "SVSHOLD " << nick;
00300 }
00301
00302
00303 void SendSZLineDel(const XLine *x) anope_override
00304 {
00305 SendDelLine("Z", x->GetHost());
00306 }
00307
00308
00309 void SendSZLine(User *, const XLine *x) anope_override
00310 {
00311
00312 time_t timeleft = x->expires - Anope::CurTime;
00313 if (timeleft > 172800 || !x->expires)
00314 timeleft = 172800;
00315 SendAddLine("Z", x->GetHost(), timeleft, x->by, x->GetReason());
00316 }
00317
00318 void SendSVSJoin(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string &) anope_override
00319 {
00320 UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
00321 }
00322
00323 void SendSVSPart(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string ¶m) anope_override
00324 {
00325 if (!param.empty())
00326 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
00327 else
00328 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
00329 }
00330
00331 void SendSWhois(const BotInfo *, const Anope::string &who, const Anope::string &mask) anope_override
00332 {
00333 User *u = User::Find(who);
00334
00335 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " swhois :" << mask;
00336 }
00337
00338 void SendBOB() anope_override
00339 {
00340 UplinkSocket::Message(Me) << "BURST " << Anope::CurTime;
00341 }
00342
00343 void SendEOB() anope_override
00344 {
00345 UplinkSocket::Message(Me) << "ENDBURST";
00346 }
00347
00348 void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf)
00349 {
00350 if (Servers::Capab.count("GLOBOPS"))
00351 UplinkSocket::Message(source) << "SNONOTICE g :" << buf;
00352 else
00353 UplinkSocket::Message(source) << "SNONOTICE A :" << buf;
00354 }
00355
00356 void SendLogin(User *u) anope_override
00357 {
00358 if (!u->Account() || u->Account()->HasExt("UNCONFIRMED"))
00359 return;
00360
00361 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << u->Account()->display;
00362 }
00363
00364 void SendLogout(User *u) anope_override
00365 {
00366 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :";
00367 }
00368
00369 void SendChannel(Channel *c) anope_override
00370 {
00371 UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :";
00372 }
00373
00374 void SendOper(User *u) anope_override
00375 {
00376 }
00377
00378 bool IsExtbanValid(const Anope::string &mask) anope_override
00379 {
00380 return mask.length() >= 3 && mask[1] == ':';
00381 }
00382 };
00383
00384 class InspIRCdExtBan : public ChannelModeList
00385 {
00386 public:
00387 InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
00388
00389 bool Matches(const User *u, const Entry *e) anope_override
00390 {
00391 const Anope::string &mask = e->GetMask();
00392
00393 if (mask.find("m:") == 0 || mask.find("N:") == 0)
00394 {
00395 Anope::string real_mask = mask.substr(2);
00396
00397 Entry en(this->name, real_mask);
00398 if (en.Matches(u))
00399 return true;
00400 }
00401 else if (mask.find("j:") == 0)
00402 {
00403 Anope::string real_mask = mask.substr(2);
00404
00405 Channel *c = Channel::Find(real_mask);
00406 if (c != NULL && c->FindUser(u) != NULL)
00407 return true;
00408 }
00409 else if (mask.find("M:") == 0 || mask.find("R:") == 0)
00410 {
00411 Anope::string real_mask = mask.substr(2);
00412
00413 if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display))
00414 return true;
00415 }
00416 else if (mask.find("r:") == 0)
00417 {
00418 Anope::string real_mask = mask.substr(2);
00419
00420 if (Anope::Match(u->realname, real_mask))
00421 return true;
00422 }
00423 else if (mask.find("s:") == 0)
00424 {
00425 Anope::string real_mask = mask.substr(2);
00426
00427 if (Anope::Match(u->server->GetName(), real_mask))
00428 return true;
00429 }
00430
00431 return false;
00432 }
00433 };
00434
00435 struct IRCDMessageCapab : Message::Capab
00436 {
00437 IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00438
00439 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00440 {
00441 if (params[0].equals_cs("START"))
00442 {
00443
00444 Servers::Capab.clear();
00445 Servers::Capab.insert("NOQUIT");
00446 IRCD->CanSVSHold = false;
00447 }
00448 else if (params[0].equals_cs("MODULES") && params.size() > 1)
00449 {
00450 if (params[1].find("m_globops.so") != Anope::string::npos)
00451 Servers::Capab.insert("GLOBOPS");
00452 if (params[1].find("m_services_account.so") != Anope::string::npos)
00453 Servers::Capab.insert("SERVICES");
00454 if (params[1].find("m_svshold.so") != Anope::string::npos)
00455 IRCD->CanSVSHold = true;
00456 if (params[1].find("m_chghost.so") != Anope::string::npos)
00457 Servers::Capab.insert("CHGHOST");
00458 if (params[1].find("m_chgident.so") != Anope::string::npos)
00459 Servers::Capab.insert("CHGIDENT");
00460 if (params[1].find("m_hidechans.so") != Anope::string::npos)
00461 Servers::Capab.insert("HIDECHANS");
00462 if (params[1].find("m_servprotect.so") != Anope::string::npos)
00463 IRCD->DefaultPseudoclientModes = "+Ik";
00464 if (params[1].find("m_rline.so") != Anope::string::npos)
00465 Servers::Capab.insert("RLINE");
00466 }
00467 else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
00468 {
00469 spacesepstream ssep(params[1]);
00470 Anope::string capab;
00471 while (ssep.GetToken(capab))
00472 {
00473 if (capab.find("CHANMODES") != Anope::string::npos)
00474 {
00475 Anope::string modes(capab.begin() + 10, capab.end());
00476 commasepstream sep(modes);
00477 Anope::string modebuf;
00478
00479 sep.GetToken(modebuf);
00480 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00481 {
00482 switch (modebuf[t])
00483 {
00484 case 'b':
00485 ModeManager::AddChannelMode(new InspIRCdExtBan("BAN", 'b'));
00486 continue;
00487 case 'e':
00488 ModeManager::AddChannelMode(new InspIRCdExtBan("EXCEPT", 'e'));
00489 continue;
00490 case 'I':
00491 ModeManager::AddChannelMode(new InspIRCdExtBan("INVITEOVERRIDE", 'I'));
00492 continue;
00493
00494 case 'q':
00495 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '@'));
00496 continue;
00497 case 'a':
00498 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT" , 'a', '@'));
00499 continue;
00500 default:
00501 ModeManager::AddChannelMode(new ChannelModeList("END", modebuf[t]));
00502 }
00503 }
00504
00505 sep.GetToken(modebuf);
00506 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00507 {
00508 switch (modebuf[t])
00509 {
00510 case 'k':
00511 ModeManager::AddChannelMode(new ChannelModeKey('k'));
00512 continue;
00513 default:
00514 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t]));
00515 }
00516 }
00517
00518 sep.GetToken(modebuf);
00519 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00520 {
00521 switch (modebuf[t])
00522 {
00523 case 'F':
00524 ModeManager::AddChannelMode(new ChannelModeParam("NICKFLOOD", 'F', true));
00525 continue;
00526 case 'J':
00527 ModeManager::AddChannelMode(new ChannelModeParam("NOREJOIN", 'J', true));
00528 continue;
00529 case 'L':
00530 ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L', true));
00531 continue;
00532 case 'f':
00533 ModeManager::AddChannelMode(new ChannelModeFlood('f', true));
00534 continue;
00535 case 'j':
00536 ModeManager::AddChannelMode(new ChannelModeParam("JOINFLOOD", 'j', true));
00537 continue;
00538 case 'l':
00539 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
00540 continue;
00541 default:
00542 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t], true));
00543 }
00544 }
00545
00546 sep.GetToken(modebuf);
00547 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00548 {
00549 switch (modebuf[t])
00550 {
00551 case 'A':
00552 ModeManager::AddChannelMode(new ChannelMode("ALLINVITE", 'A'));
00553 continue;
00554 case 'B':
00555 ModeManager::AddChannelMode(new ChannelMode("BLOCKCAPS", 'B'));
00556 continue;
00557 case 'C':
00558 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
00559 continue;
00560 case 'D':
00561 ModeManager::AddChannelMode(new ChannelMode("DELAYEDJOIN", 'D'));
00562 continue;
00563 case 'G':
00564 ModeManager::AddChannelMode(new ChannelMode("FILTER", 'G'));
00565 continue;
00566 case 'K':
00567 ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
00568 continue;
00569 case 'M':
00570 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M'));
00571 continue;
00572 case 'N':
00573 ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
00574 continue;
00575 case 'O':
00576 ModeManager::AddChannelMode(new ChannelModeOper('O'));
00577 continue;
00578 case 'P':
00579 ModeManager::AddChannelMode(new ChannelMode("PERM", 'P'));
00580 continue;
00581 case 'Q':
00582 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
00583 continue;
00584 case 'R':
00585 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
00586 continue;
00587 case 'S':
00588 ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S'));
00589 continue;
00590 case 'T':
00591 ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T'));
00592 continue;
00593 case 'c':
00594 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
00595 continue;
00596 case 'i':
00597 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
00598 continue;
00599 case 'm':
00600 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
00601 continue;
00602 case 'n':
00603 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
00604 continue;
00605 case 'p':
00606 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
00607 continue;
00608 case 'r':
00609 ModeManager::AddChannelMode(new ChannelModeRegistered('r'));
00610 continue;
00611 case 's':
00612 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
00613 continue;
00614 case 't':
00615 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
00616 continue;
00617 case 'u':
00618 ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u'));
00619 continue;
00620 case 'z':
00621 ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
00622 continue;
00623 default:
00624 ModeManager::AddChannelMode(new ChannelMode("END", modebuf[t]));
00625 }
00626 }
00627 }
00628 else if (capab.find("USERMODES") != Anope::string::npos)
00629 {
00630 Anope::string modes(capab.begin() + 10, capab.end());
00631 commasepstream sep(modes);
00632 Anope::string modebuf;
00633
00634 while (sep.GetToken(modebuf))
00635 {
00636 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00637 {
00638 switch (modebuf[t])
00639 {
00640 case 'h':
00641 ModeManager::AddUserMode(new UserMode("HELPOP", 'h'));
00642 continue;
00643 case 'B':
00644 ModeManager::AddUserMode(new UserMode("BOT", 'B'));
00645 continue;
00646 case 'G':
00647 ModeManager::AddUserMode(new UserMode("FILTER", 'G'));
00648 continue;
00649 case 'H':
00650 ModeManager::AddUserMode(new UserMode("HIDEOPER", 'H'));
00651 continue;
00652 case 'I':
00653 ModeManager::AddUserMode(new UserMode("PRIV", 'I'));
00654 continue;
00655 case 'Q':
00656 ModeManager::AddUserMode(new UserMode("HIDDEN", 'Q'));
00657 continue;
00658 case 'R':
00659 ModeManager::AddUserMode(new UserMode("REGPRIV", 'R'));
00660 continue;
00661 case 'S':
00662 ModeManager::AddUserMode(new UserMode("STRIPCOLOR", 'S'));
00663 continue;
00664 case 'W':
00665 ModeManager::AddUserMode(new UserMode("WHOIS", 'W'));
00666 continue;
00667 case 'c':
00668 ModeManager::AddUserMode(new UserMode("COMMONCHANS", 'c'));
00669 continue;
00670 case 'g':
00671 ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
00672 continue;
00673 case 'i':
00674 ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
00675 continue;
00676 case 'k':
00677 ModeManager::AddUserMode(new UserMode("PROTECTED", 'k'));
00678 continue;
00679 case 'o':
00680 ModeManager::AddUserMode(new UserMode("OPER", 'o'));
00681 continue;
00682 case 'r':
00683 ModeManager::AddUserMode(new UserMode("REGISTERED", 'r'));
00684 continue;
00685 case 'w':
00686 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
00687 continue;
00688 case 'x':
00689 ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
00690 continue;
00691 case 'd':
00692 ModeManager::AddUserMode(new UserMode("DEAF", 'd'));
00693 continue;
00694 default:
00695 ModeManager::AddUserMode(new UserMode("END", modebuf[t]));
00696 }
00697 }
00698 }
00699 }
00700 else if (capab.find("PREFIX=(") != Anope::string::npos)
00701 {
00702 Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
00703 Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
00704 unsigned short level = modes.length() - 1;
00705
00706 for (size_t t = 0, end = modes.length(); t < end; ++t)
00707 {
00708 switch (modes[t])
00709 {
00710 case 'q':
00711 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', chars[t], level--));
00712 continue;
00713 case 'a':
00714 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', chars[t], level--));
00715 continue;
00716 case 'o':
00717 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', chars[t], level--));
00718 continue;
00719 case 'h':
00720 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', chars[t], level--));
00721 continue;
00722 case 'v':
00723 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', chars[t], level--));
00724 continue;
00725 default:
00726 ModeManager::AddChannelMode(new ChannelModeStatus("END", modes[t], chars[t], level--));
00727 }
00728 }
00729 }
00730 else if (capab.find("MAXMODES=") != Anope::string::npos)
00731 {
00732 Anope::string maxmodes(capab.begin() + 9, capab.end());
00733 IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
00734 }
00735 }
00736 }
00737 else if (params[0].equals_cs("END"))
00738 {
00739 if (!Servers::Capab.count("GLOBOPS"))
00740 {
00741 UplinkSocket::Message() << "ERROR :m_globops is not loaded. This is required by Anope";
00742 Anope::QuitReason = "Remote server does not have the m_globops module loaded, and this is required.";
00743 Anope::Quitting = true;
00744 return;
00745 }
00746 if (!Servers::Capab.count("SERVICES"))
00747 {
00748 UplinkSocket::Message() << "ERROR :m_services_account.so is not loaded. This is required by Anope";
00749 Anope::QuitReason = "ERROR: Remote server does not have the m_services_account module loaded, and this is required.";
00750 Anope::Quitting = true;
00751 return;
00752 }
00753 if (!Servers::Capab.count("HIDECHANS"))
00754 {
00755 UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
00756 Anope::QuitReason = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required.";
00757 Anope::Quitting = true;
00758 return;
00759 }
00760 if (!IRCD->CanSVSHold)
00761 Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
00762 if (!Servers::Capab.count("CHGHOST"))
00763 Log() << "CHGHOST missing, Usage disabled until module is loaded.";
00764 if (!Servers::Capab.count("CHGIDENT"))
00765 Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
00766 }
00767
00768 Message::Capab::Run(source, params);
00769 }
00770 };
00771
00772 struct IRCDMessageChgIdent : IRCDMessage
00773 {
00774 IRCDMessageChgIdent(Module *creator) : IRCDMessage(creator, "CHGIDENT", 2) { }
00775
00776 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00777 {
00778 User *u = User::Find(params[0]);
00779 if (u)
00780 u->SetIdent(params[1]);
00781 }
00782 };
00783
00784 struct IRCDMessageChgName : IRCDMessage
00785 {
00786 IRCDMessageChgName(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00787
00788 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00789 {
00790 source.GetUser()->SetRealname(params[0]);
00791 }
00792 };
00793
00794 struct IRCDMessageEndburst : IRCDMessage
00795 {
00796 IRCDMessageEndburst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00797
00798 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00799 {
00800 Server *s = source.GetServer();
00801
00802 Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName();
00803
00804 s->Sync(true);
00805 }
00806 };
00807
00808 struct IRCDMessageFHost : IRCDMessage
00809 {
00810 IRCDMessageFHost(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00811
00812 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00813 {
00814 source.GetUser()->SetDisplayedHost(params[0]);
00815 }
00816 };
00817
00818 struct IRCDMessageFJoin : IRCDMessage
00819 {
00820 IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00821
00822 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00823 {
00824 Anope::string modes;
00825 if (params.size() >= 3)
00826 {
00827 for (unsigned i = 2; i < params.size() - 1; ++i)
00828 modes += " " + params[i];
00829 if (!modes.empty())
00830 modes.erase(modes.begin());
00831 }
00832
00833 std::list<Message::Join::SJoinUser> users;
00834
00835 spacesepstream sep(params[params.size() - 1]);
00836 Anope::string buf;
00837 while (sep.GetToken(buf))
00838 {
00839 Message::Join::SJoinUser sju;
00840
00841
00842 for (char c; (c = buf[0]) != ',';)
00843 {
00844 buf.erase(buf.begin());
00845 ChannelMode *cm = ModeManager::FindChannelModeByChar(c);
00846 if (!cm)
00847 {
00848 Log() << "Received unknown mode prefix " << c << " in FJOIN string";
00849 continue;
00850 }
00851
00852 sju.first.modes.insert(cm->name);
00853 }
00854
00855 buf.erase(buf.begin());
00856
00857 sju.second = User::Find(buf);
00858 if (!sju.second)
00859 {
00860 Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << params[0];
00861 continue;
00862 }
00863
00864 users.push_back(sju);
00865 }
00866
00867 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
00868 Message::Join::SJoin(source, params[0], ts, modes, users);
00869 }
00870 };
00871
00872 struct IRCDMessageFMode : IRCDMessage
00873 {
00874 IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00875
00876 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00877 {
00878
00879
00880 Anope::string modes = params[2];
00881 for (unsigned n = 3; n < params.size(); ++n)
00882 modes += " " + params[n];
00883
00884 Channel *c = Channel::Find(params[0]);
00885 time_t ts;
00886
00887 try
00888 {
00889 ts = convertTo<time_t>(params[1]);
00890 }
00891 catch (const ConvertException &)
00892 {
00893 ts = 0;
00894 }
00895
00896 if (c)
00897 c->SetModesInternal(source, modes, ts);
00898 }
00899 };
00900
00901 struct IRCDMessageFTopic : IRCDMessage
00902 {
00903 IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { }
00904
00905 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00906 {
00907
00908
00909 Channel *c = Channel::Find(params[0]);
00910 if (c)
00911 c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime);
00912 }
00913 };
00914
00915 struct IRCDMessageIdle : IRCDMessage
00916 {
00917 IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { }
00918
00919 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00920 {
00921 const BotInfo *bi = BotInfo::Find(params[0]);
00922 if (bi)
00923 UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (Anope::CurTime - bi->lastmsg);
00924 }
00925 };
00926
00927
00928
00929
00930
00931
00932
00933 struct IRCDMessageMetadata : IRCDMessage
00934 {
00935 IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00936
00937 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00938 {
00939 if (isdigit(params[0][0]))
00940 {
00941 if (params[1].equals_cs("accountname"))
00942 {
00943 User *u = User::Find(params[0]);
00944 NickCore *nc = NickCore::Find(params[2]);
00945 if (u && nc)
00946 {
00947 u->Login(nc);
00948
00949 const NickAlias *user_na = NickAlias::Find(u->nick);
00950 if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasExt("UNCONFIRMED") == false)
00951 u->SetMode(NickServ, "REGISTERED");
00952
00953
00954
00955
00956 if (u->server->IsSynced() && NickServ)
00957 u->SendMessage(NickServ, _("You have been logged in as \002%s\002."), nc->display.c_str());
00958 }
00959 }
00960
00961
00962
00963
00964
00965
00966 else if (params[1].equals_cs("ssl_cert"))
00967 {
00968 User *u = User::Find(params[0]);
00969 if (!u)
00970 return;
00971 std::string data = params[2].c_str();
00972 size_t pos1 = data.find(' ') + 1;
00973 size_t pos2 = data.find(' ', pos1);
00974 if ((pos2 - pos1) >= 32)
00975 {
00976 u->fingerprint = data.substr(pos1, pos2 - pos1);
00977 FOREACH_MOD(I_OnFingerprint, OnFingerprint(u));
00978 }
00979 }
00980 }
00981 else if (params[0][0] == '#')
00982 {
00983 }
00984 else if (params[0] == "*")
00985 {
00986
00987
00988 if (params[1].equals_cs("modules") && !params[2].empty())
00989 {
00990
00991 Server* server = source.GetServer();
00992 if (!server || server->GetUplink() != Me)
00993 return;
00994
00995 bool plus = (params[2][0] == '+');
00996 if (!plus && params[2][0] != '-')
00997 return;
00998
00999 bool required = false;
01000 Anope::string capab, module = params[2].substr(1);
01001
01002 if (module.equals_cs("m_services_account.so"))
01003 required = true;
01004 else if (module.equals_cs("m_hidechans.so"))
01005 required = true;
01006 else if (module.equals_cs("m_chghost.so"))
01007 capab = "CHGHOST";
01008 else if (module.equals_cs("m_chgident.so"))
01009 capab = "CHGIDENT";
01010 else if (module.equals_cs("m_svshold.so"))
01011 capab = "SVSHOLD";
01012 else if (module.equals_cs("m_rline.so"))
01013 capab = "RLINE";
01014 else if (module.equals_cs("m_topiclock.so"))
01015 capab = "TOPICLOCK";
01016 else
01017 return;
01018
01019 if (required)
01020 {
01021 if (!plus)
01022 Log() << "Warning: InspIRCd unloaded module " << module << ", Anope won't function correctly without it";
01023 }
01024 else
01025 {
01026 if (plus)
01027 Servers::Capab.insert(capab);
01028 else
01029 Servers::Capab.erase(capab);
01030
01031 Log() << "InspIRCd " << (plus ? "loaded" : "unloaded") << " module " << module << ", adjusted functionality";
01032 }
01033
01034 }
01035 }
01036 }
01037 };
01038
01039 struct IRCDMessageMode : IRCDMessage
01040 {
01041 IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
01042
01043 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01044 {
01045 if (IRCD->IsChannelValid(params[0]))
01046 {
01047 Channel *c = Channel::Find(params[0]);
01048
01049 Anope::string modes = params[1];
01050 for (unsigned n = 2; n < params.size(); ++n)
01051 modes += " " + params[n];
01052
01053 if (c)
01054 c->SetModesInternal(source, modes);
01055 }
01056 else
01057 {
01058
01059
01060
01061
01062 User *u = source.GetUser();
01063
01064 if (!u)
01065 u = User::Find(params[0]);
01066
01067
01068 if (u)
01069 u->SetModesInternal("%s", params[1].c_str());
01070 }
01071 }
01072 };
01073
01074 struct IRCDMessageNick : IRCDMessage
01075 {
01076 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
01077
01078 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01079 {
01080 source.GetUser()->ChangeNick(params[0]);
01081 }
01082 };
01083
01084 struct IRCDMessageOperType : IRCDMessage
01085 {
01086 IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); }
01087
01088 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01089 {
01090
01091
01092 User *u = source.GetUser();
01093 if (!u->HasMode("OPER"))
01094 u->SetModesInternal("+o");
01095 }
01096 };
01097
01098 struct IRCDMessageRSQuit : IRCDMessage
01099 {
01100 IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 1) { }
01101
01102 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01103 {
01104 Server *s = Server::Find(params[0]);
01105 if (!s)
01106 return;
01107
01108
01109 if (s->IsJuped())
01110 UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : "");
01111
01112 s->Delete(s->GetName() + " " + s->GetUplink()->GetName());
01113 }
01114 };
01115
01116 struct IRCDMessageSetIdent : IRCDMessage
01117 {
01118 IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
01119
01120 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01121 {
01122 source.GetUser()->SetIdent(params[0]);
01123 }
01124 };
01125
01126 struct IRCDMessageServer : IRCDMessage
01127 {
01128 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01139 {
01140 unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0;
01141 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]);
01142 }
01143 };
01144
01145 struct IRCDMessageTime : IRCDMessage
01146 {
01147 IRCDMessageTime(Module *creator) : IRCDMessage(creator, "TIME", 2) { }
01148
01149 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01150 {
01151 UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime;
01152 }
01153 };
01154
01155 struct IRCDMessageUID : IRCDMessage
01156 {
01157 IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
01173 {
01174 time_t ts = convertTo<time_t>(params[1]);
01175
01176 Anope::string modes = params[8];
01177 for (unsigned i = 9; i < params.size() - 1; ++i)
01178 modes += " " + params[i];
01179
01180 new User(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0]);
01181 }
01182 };
01183
01184 class ProtoInspIRCd : public Module
01185 {
01186 InspIRCd12Proto ircd_proto;
01187
01188
01189 Message::Away message_away;
01190 Message::Error message_error;
01191 Message::Join message_join;
01192 Message::Kick message_kick;
01193 Message::Kill message_kill;
01194 Message::MOTD message_motd;
01195 Message::Part message_part;
01196 Message::Ping message_ping;
01197 Message::Privmsg message_privmsg;
01198 Message::Quit message_quit;
01199 Message::SQuit message_squit;
01200 Message::Stats message_stats;
01201 Message::Topic message_topic;
01202 Message::Version message_version;
01203
01204
01205 IRCDMessageChgIdent message_chgident;
01206 IRCDMessageChgName message_setname, message_chgname;
01207 IRCDMessageCapab message_capab;
01208 IRCDMessageEndburst message_endburst;
01209 IRCDMessageFHost message_fhost, message_sethost;
01210 IRCDMessageFJoin message_fjoin;
01211 IRCDMessageFMode message_fmode;
01212 IRCDMessageFTopic message_ftopic;
01213 IRCDMessageIdle message_idle;
01214 IRCDMessageMetadata message_metadata;
01215 IRCDMessageMode message_mode;
01216 IRCDMessageNick message_nick;
01217 IRCDMessageOperType message_opertype;
01218 IRCDMessageRSQuit message_rsquit;
01219 IRCDMessageSetIdent message_setident;
01220 IRCDMessageServer message_server;
01221 IRCDMessageTime message_time;
01222 IRCDMessageUID message_uid;
01223
01224 public:
01225 ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
01226 ircd_proto(this),
01227 message_away(this), message_error(this), message_join(this), message_kick(this), message_kill(this),
01228 message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
01229 message_squit(this), message_stats(this), message_topic(this), message_version(this),
01230
01231 message_chgident(this), message_setname(this, "SETNAME"), message_chgname(this, "FNAME"), message_capab(this), message_endburst(this),
01232 message_fhost(this, "FHOST"), message_sethost(this, "SETHOST"), message_fjoin(this), message_fmode(this), message_ftopic(this),
01233 message_idle(this), message_metadata(this), message_mode(this), message_nick(this), message_opertype(this), message_rsquit(this),
01234 message_setident(this), message_server(this), message_time(this), message_uid(this)
01235 {
01236 this->SetAuthor("Anope");
01237
01238 Implementation i[] = { I_OnUserNickChange };
01239 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
01240
01241 Servers::Capab.insert("NOQUIT");
01242
01243 if (Config->Numeric.empty())
01244 {
01245 Anope::string numeric = Servers::TS6_SID_Retrieve();
01246 Me->SetSID(numeric);
01247 Config->Numeric = numeric;
01248 }
01249
01250 for (botinfo_map::iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
01251 it->second->GenerateUID();
01252 }
01253
01254 void OnUserNickChange(User *u, const Anope::string &) anope_override
01255 {
01256
01257
01258
01259 u->RemoveMode(NickServ, "REGISTERED");
01260 }
01261 };
01262
01263 MODULE_INIT(ProtoInspIRCd)