00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "module.h"
00015
00016 static unsigned int spanningtree_proto_ver = 0;
00017
00018 static ServiceReference<IRCDProto> insp12("IRCDProto", "inspircd12");
00019
00020 class InspIRCd20Proto : public IRCDProto
00021 {
00022 public:
00023 InspIRCd20Proto(Module *creator) : IRCDProto(creator, "InspIRCd 2.0")
00024 {
00025 DefaultPseudoclientModes = "+I";
00026 CanSVSNick = true;
00027 CanSVSJoin = true;
00028 CanSetVHost = true;
00029 CanSetVIdent = true;
00030 CanSQLine = true;
00031 CanSZLine = true;
00032 CanSVSHold = true;
00033 CanCertFP = true;
00034 RequiresID = true;
00035 MaxModes = 20;
00036 }
00037
00038 void SendConnect() anope_override
00039 {
00040 UplinkSocket::Message() << "CAPAB START 1202";
00041 UplinkSocket::Message() << "CAPAB CAPABILITIES :PROTOCOL=1202";
00042 UplinkSocket::Message() << "CAPAB END";
00043 insp12->SendConnect();
00044 }
00045
00046 void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override { insp12->SendSVSKillInternal(source, user, buf); }
00047 void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalNotice(bi, dest, msg); }
00048 void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override { insp12->SendGlobalPrivmsg(bi, dest, msg); }
00049 void SendAkillDel(const XLine *x) anope_override { insp12->SendAkillDel(x); }
00050 void SendTopic(BotInfo *whosets, Channel *c) anope_override { insp12->SendTopic(whosets, c); };
00051 void SendVhostDel(User *u) anope_override { insp12->SendVhostDel(u); }
00052 void SendAkill(User *u, XLine *x) anope_override { insp12->SendAkill(u, x); }
00053 void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override { insp12->SendNumericInternal(numeric, dest, buf); }
00054 void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override { insp12->SendModeInternal(source, dest, buf); }
00055 void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override { insp12->SendModeInternal(bi, u, buf); }
00056 void SendClientIntroduction(const User *u) anope_override { insp12->SendClientIntroduction(u); }
00057 void SendServer(const Server *server) anope_override { insp12->SendServer(server); }
00058 void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override { insp12->SendJoin(user, c, status); }
00059 void SendSQLineDel(const XLine *x) anope_override { insp12->SendSQLineDel(x); }
00060 void SendSQLine(User *u, const XLine *x) anope_override { insp12->SendSQLine(u, x); }
00061 void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) anope_override { insp12->SendVhost(u, vident, vhost); }
00062 void SendSVSHold(const Anope::string &nick) anope_override { insp12->SendSVSHold(nick); }
00063 void SendSVSHoldDel(const Anope::string &nick) anope_override { insp12->SendSVSHoldDel(nick); }
00064 void SendSZLineDel(const XLine *x) anope_override { insp12->SendSZLineDel(x); }
00065 void SendSZLine(User *u, const XLine *x) anope_override { insp12->SendSZLine(u, x); }
00066 void SendSVSJoin(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string &other) anope_override { insp12->SendSVSJoin(source, u, chan, other); }
00067 void SendSVSPart(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string ¶m) anope_override { insp12->SendSVSPart(source, u, chan, param); }
00068 void SendSWhois(const BotInfo *bi, const Anope::string &who, const Anope::string &mask) anope_override { insp12->SendSWhois(bi, who, mask); }
00069 void SendBOB() anope_override { insp12->SendBOB(); }
00070 void SendEOB() anope_override { insp12->SendEOB(); }
00071 void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) { insp12->SendGlobopsInternal(source, buf); }
00072 void SendLogin(User *u) anope_override { insp12->SendLogin(u); }
00073 void SendLogout(User *u) anope_override { insp12->SendLogout(u); }
00074 void SendChannel(Channel *c) anope_override { insp12->SendChannel(c); }
00075 bool IsExtbanValid(const Anope::string &mask) anope_override { return insp12->IsExtbanValid(mask); }
00076 };
00077
00078 class InspIRCdExtBan : public ChannelModeList
00079 {
00080 public:
00081 InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
00082
00083 bool Matches(const User *u, const Entry *e) anope_override
00084 {
00085 const Anope::string &mask = e->GetMask();
00086
00087 if (mask.find("m:") == 0 || mask.find("N:") == 0)
00088 {
00089 Anope::string real_mask = mask.substr(3);
00090
00091 Entry en(this->name, real_mask);
00092 if (en.Matches(u))
00093 return true;
00094 }
00095 else if (mask.find("j:") == 0)
00096 {
00097 Anope::string channel = mask.substr(3);
00098
00099 ChannelMode *cm = NULL;
00100 if (channel[0] != '#')
00101 {
00102 char modeChar = ModeManager::GetStatusChar(channel[0]);
00103 channel.erase(channel.begin());
00104 cm = ModeManager::FindChannelModeByChar(modeChar);
00105 if (cm != NULL && cm->type != MODE_STATUS)
00106 cm = NULL;
00107 }
00108
00109 Channel *c = Channel::Find(channel);
00110 if (c != NULL)
00111 {
00112 ChanUserContainer *uc = c->FindUser(u);
00113 if (uc != NULL)
00114 if (cm == NULL || uc->status.modes.count(cm->name))
00115 return true;
00116 }
00117 }
00118 else if (mask.find("R:") == 0)
00119 {
00120 Anope::string real_mask = mask.substr(2);
00121
00122 if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display))
00123 return true;
00124 }
00125 else if (mask.find("r:") == 0)
00126 {
00127 Anope::string real_mask = mask.substr(2);
00128
00129 if (Anope::Match(u->realname, real_mask))
00130 return true;
00131 }
00132 else if (mask.find("s:") == 0)
00133 {
00134 Anope::string real_mask = mask.substr(2);
00135
00136 if (Anope::Match(u->server->GetName(), real_mask))
00137 return true;
00138 }
00139 else if (mask.find("z:") == 0)
00140 {
00141 Anope::string real_mask = mask.substr(2);
00142
00143 if (Anope::Match(u->fingerprint, real_mask))
00144 return true;
00145 }
00146
00147 return false;
00148 }
00149 };
00150
00151 class ChannelModeFlood : public ChannelModeParam
00152 {
00153 public:
00154 ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
00155
00156 bool IsValid(const Anope::string &value) const anope_override
00157 {
00158 try
00159 {
00160 Anope::string rest;
00161 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())
00162 return true;
00163 }
00164 catch (const ConvertException &) { }
00165
00166 return false;
00167 }
00168 };
00169
00170 struct IRCDMessageCapab : Message::Capab
00171 {
00172 IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00173
00174 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00175 {
00176 if (params[0].equals_cs("START"))
00177 {
00178 if (params.size() >= 2)
00179 spanningtree_proto_ver = (Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0);
00180
00181 if (spanningtree_proto_ver < 1202)
00182 {
00183 UplinkSocket::Message() << "ERROR :Protocol mismatch, no or invalid protocol version given in CAPAB START";
00184 Anope::QuitReason = "Protocol mismatch, no or invalid protocol version given in CAPAB START";
00185 Anope::Quitting = true;
00186 return;
00187 }
00188
00189
00190 Servers::Capab.insert("SERVERS");
00191 Servers::Capab.insert("CHGHOST");
00192 Servers::Capab.insert("CHGIDENT");
00193 Servers::Capab.insert("TOPICLOCK");
00194 IRCD->CanSVSHold = false;
00195 }
00196 else if (params[0].equals_cs("CHANMODES") && params.size() > 1)
00197 {
00198 spacesepstream ssep(params[1]);
00199 Anope::string capab;
00200
00201 while (ssep.GetToken(capab))
00202 {
00203 Anope::string modename = capab.substr(0, capab.find('='));
00204 Anope::string modechar = capab.substr(capab.find('=') + 1);
00205 ChannelMode *cm = NULL;
00206
00207 if (modename.equals_cs("admin"))
00208 cm = new ChannelModeStatus("PROTECT", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0);
00209 else if (modename.equals_cs("allowinvite"))
00210 cm = new ChannelMode("ALLINVITE", modechar[0]);
00211 else if (modename.equals_cs("auditorium"))
00212 cm = new ChannelMode("AUDITORIUM", modechar[0]);
00213 else if (modename.equals_cs("ban"))
00214 cm = new InspIRCdExtBan("BAN", modechar[0]);
00215 else if (modename.equals_cs("banexception"))
00216 cm = new InspIRCdExtBan("EXCEPT", 'e');
00217 else if (modename.equals_cs("blockcaps"))
00218 cm = new ChannelMode("BLOCKCAPS", modechar[0]);
00219 else if (modename.equals_cs("blockcolor"))
00220 cm = new ChannelMode("BLOCKCOLOR", modechar[0]);
00221 else if (modename.equals_cs("c_registered"))
00222 cm = new ChannelModeRegistered(modechar[0]);
00223 else if (modename.equals_cs("censor"))
00224 cm = new ChannelMode("FILTER", modechar[0]);
00225 else if (modename.equals_cs("delayjoin"))
00226 cm = new ChannelMode("DELAYEDJOIN", modechar[0]);
00227 else if (modename.equals_cs("filter"))
00228 cm = new ChannelModeList("FILTER", modechar[0]);
00229 else if (modename.equals_cs("flood"))
00230 cm = new ChannelModeFlood(modechar[0], true);
00231 else if (modename.equals_cs("founder"))
00232 cm = new ChannelModeStatus("OWNER", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0);
00233 else if (modename.equals_cs("halfop"))
00234 cm = new ChannelModeStatus("HALFOP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0);
00235 else if (modename.equals_cs("invex"))
00236 cm = new InspIRCdExtBan("INVITEOVERRIDE", 'I');
00237 else if (modename.equals_cs("inviteonly"))
00238 cm = new ChannelMode("INVITE", modechar[0]);
00239 else if (modename.equals_cs("joinflood"))
00240 cm = new ChannelModeParam("JOINFLOOD", modechar[0], true);
00241 else if (modename.equals_cs("key"))
00242 cm = new ChannelModeKey(modechar[0]);
00243 else if (modename.equals_cs("kicknorejoin"))
00244 cm = new ChannelModeParam("NOREJOIN", modechar[0], true);
00245 else if (modename.equals_cs("limit"))
00246 cm = new ChannelModeParam("LIMIT", modechar[0], true);
00247 else if (modename.equals_cs("moderated"))
00248 cm = new ChannelMode("MODERATED", modechar[0]);
00249 else if (modename.equals_cs("nickflood"))
00250 cm = new ChannelModeParam("NICKFLOOD", modechar[0], true);
00251 else if (modename.equals_cs("noctcp"))
00252 cm = new ChannelMode("NOCTCP", modechar[0]);
00253 else if (modename.equals_cs("noextmsg"))
00254 cm = new ChannelMode("NOEXTERNAL", modechar[0]);
00255 else if (modename.equals_cs("nokick"))
00256 cm = new ChannelMode("NOKICK", modechar[0]);
00257 else if (modename.equals_cs("noknock"))
00258 cm = new ChannelMode("NOKNOCK", modechar[0]);
00259 else if (modename.equals_cs("nonick"))
00260 cm = new ChannelMode("NONICK", modechar[0]);
00261 else if (modename.equals_cs("nonotice"))
00262 cm = new ChannelMode("NONOTICE", modechar[0]);
00263 else if (modename.equals_cs("op"))
00264 cm = new ChannelModeStatus("OP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0);
00265 else if (modename.equals_cs("operonly"))
00266 cm = new ChannelModeOper(modechar[0]);
00267 else if (modename.equals_cs("permanent"))
00268 cm = new ChannelMode("PERM", modechar[0]);
00269 else if (modename.equals_cs("private"))
00270 cm = new ChannelMode("PRIVATE", modechar[0]);
00271 else if (modename.equals_cs("redirect"))
00272 cm = new ChannelModeParam("REDIRECT", modechar[0], true);
00273 else if (modename.equals_cs("reginvite"))
00274 cm = new ChannelMode("REGISTEREDONLY", modechar[0]);
00275 else if (modename.equals_cs("regmoderated"))
00276 cm = new ChannelMode("REGMODERATED", modechar[0]);
00277 else if (modename.equals_cs("secret"))
00278 cm = new ChannelMode("SECRET", modechar[0]);
00279 else if (modename.equals_cs("sslonly"))
00280 cm = new ChannelMode("SSL", modechar[0]);
00281 else if (modename.equals_cs("stripcolor"))
00282 cm = new ChannelMode("STRIPCOLOR", modechar[0]);
00283 else if (modename.equals_cs("topiclock"))
00284 cm = new ChannelMode("TOPIC", modechar[0]);
00285 else if (modename.equals_cs("voice"))
00286 cm = new ChannelModeStatus("VOICE", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0);
00287
00288 else if (modechar.length() == 2)
00289 cm = new ChannelModeStatus("END", modechar[1], modechar[0]);
00290
00291
00292 if (cm)
00293 ModeManager::AddChannelMode(cm);
00294 else
00295 Log() << "Unrecognized mode string in CAPAB CHANMODES: " << capab;
00296 }
00297 }
00298 if (params[0].equals_cs("USERMODES") && params.size() > 1)
00299 {
00300 spacesepstream ssep(params[1]);
00301 Anope::string capab;
00302
00303 while (ssep.GetToken(capab))
00304 {
00305 Anope::string modename = capab.substr(0, capab.find('='));
00306 Anope::string modechar = capab.substr(capab.find('=') + 1);
00307 UserMode *um = NULL;
00308
00309 if (modename.equals_cs("bot"))
00310 um = new UserMode("BOT", modechar[0]);
00311 else if (modename.equals_cs("callerid"))
00312 um = new UserMode("CALLERID", modechar[0]);
00313 else if (modename.equals_cs("cloak"))
00314 um = new UserMode("CLOAK", modechar[0]);
00315 else if (modename.equals_cs("deaf"))
00316 um = new UserMode("DEAF", modechar[0]);
00317 else if (modename.equals_cs("deaf_commonchan"))
00318 um = new UserMode("COMMONCHANS", modechar[0]);
00319 else if (modename.equals_cs("helpop"))
00320 um = new UserMode("HELPOP", modechar[0]);
00321 else if (modename.equals_cs("hidechans"))
00322 um = new UserMode("PRIV", modechar[0]);
00323 else if (modename.equals_cs("hideoper"))
00324 um = new UserMode("HIDEOPER", modechar[0]);
00325 else if (modename.equals_cs("invisible"))
00326 um = new UserMode("INVIS", modechar[0]);
00327 else if (modename.equals_cs("invis-oper"))
00328 um = new UserMode("INVISIBLE_OPER", modechar[0]);
00329 else if (modename.equals_cs("oper"))
00330 um = new UserMode("OPER", modechar[0]);
00331 else if (modename.equals_cs("regdeaf"))
00332 um = new UserMode("REGPRIV", modechar[0]);
00333 else if (modename.equals_cs("servprotect"))
00334 {
00335 um = new UserMode("PROTECTED", modechar[0]);
00336 IRCD->DefaultPseudoclientModes += "k";
00337 }
00338 else if (modename.equals_cs("showwhois"))
00339 um = new UserMode("WHOIS", modechar[0]);
00340 else if (modename.equals_cs("u_censor"))
00341 um = new UserMode("FILTER", modechar[0]);
00342 else if (modename.equals_cs("u_registered"))
00343 um = new UserMode("REGISTERED", modechar[0]);
00344 else if (modename.equals_cs("u_stripcolor"))
00345 um = new UserMode("STRIPCOLOR", modechar[0]);
00346 else if (modename.equals_cs("wallops"))
00347 um = new UserMode("WALLOPS", modechar[0]);
00348
00349 if (um)
00350 ModeManager::AddUserMode(um);
00351 else
00352 Log() << "Unrecognized mode string in CAPAB USERMODES: " << capab;
00353 }
00354 }
00355 else if (params[0].equals_cs("MODULES") && params.size() > 1)
00356 {
00357 spacesepstream ssep(params[1]);
00358 Anope::string module;
00359
00360 while (ssep.GetToken(module))
00361 {
00362 if (module.equals_cs("m_svshold.so"))
00363 IRCD->CanSVSHold = true;
00364 else if (module.find("m_rline.so") == 0)
00365 {
00366 Servers::Capab.insert("RLINE");
00367 if (!Config->RegexEngine.empty() && module.length() > 11 && Config->RegexEngine != module.substr(11))
00368 Log() << "Warning: InspIRCd is using regex engine " << module.substr(11) << ", but we have " << Config->RegexEngine << ". This may cause inconsistencies.";
00369 }
00370 else if (module.equals_cs("m_topiclock.so"))
00371 Servers::Capab.insert("TOPICLOCK");
00372 }
00373 }
00374 else if (params[0].equals_cs("MODSUPPORT") && params.size() > 1)
00375 {
00376 spacesepstream ssep(params[1]);
00377 Anope::string module;
00378
00379 while (ssep.GetToken(module))
00380 {
00381 if (module.equals_cs("m_services_account.so"))
00382 Servers::Capab.insert("SERVICES");
00383 else if (module.equals_cs("m_chghost.so"))
00384 Servers::Capab.insert("CHGHOST");
00385 else if (module.equals_cs("m_chgident.so"))
00386 Servers::Capab.insert("CHGIDENT");
00387 }
00388 }
00389 else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
00390 {
00391 spacesepstream ssep(params[1]);
00392 Anope::string capab;
00393 while (ssep.GetToken(capab))
00394 {
00395 if (capab.find("CHANMODES") != Anope::string::npos)
00396 {
00397 Anope::string modes(capab.begin() + 10, capab.end());
00398 commasepstream sep(modes);
00399 Anope::string modebuf;
00400
00401 sep.GetToken(modebuf);
00402 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00403 {
00404 if (ModeManager::FindChannelModeByChar(modebuf[t]))
00405 continue;
00406 ModeManager::AddChannelMode(new ChannelModeList("END", modebuf[t]));
00407 }
00408
00409 sep.GetToken(modebuf);
00410 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00411 {
00412 if (ModeManager::FindChannelModeByChar(modebuf[t]))
00413 continue;
00414 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t]));
00415 }
00416
00417 sep.GetToken(modebuf);
00418 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00419 {
00420 if (ModeManager::FindChannelModeByChar(modebuf[t]))
00421 continue;
00422 ModeManager::AddChannelMode(new ChannelModeParam("END", true));
00423 }
00424
00425 sep.GetToken(modebuf);
00426 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00427 {
00428 if (ModeManager::FindChannelModeByChar(modebuf[t]))
00429 continue;
00430 ModeManager::AddChannelMode(new ChannelMode("END", modebuf[t]));
00431 }
00432 }
00433 else if (capab.find("USERMODES") != Anope::string::npos)
00434 {
00435 Anope::string modes(capab.begin() + 10, capab.end());
00436 commasepstream sep(modes);
00437 Anope::string modebuf;
00438
00439 sep.GetToken(modebuf);
00440 sep.GetToken(modebuf);
00441
00442 if (sep.GetToken(modebuf))
00443 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00444 ModeManager::AddUserMode(new UserModeParam("END", modebuf[t]));
00445
00446 if (sep.GetToken(modebuf))
00447 for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00448 ModeManager::AddUserMode(new UserMode("END", modebuf[t]));
00449 }
00450 else if (capab.find("MAXMODES=") != Anope::string::npos)
00451 {
00452 Anope::string maxmodes(capab.begin() + 9, capab.end());
00453 IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
00454 }
00455 else if (capab.find("PREFIX=") != Anope::string::npos)
00456 {
00457 Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
00458 Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
00459 short level = modes.length() - 1;
00460
00461 for (size_t t = 0, end = modes.length(); t < end; ++t)
00462 {
00463 ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[t]);
00464 if (cm == NULL || cm->type != MODE_STATUS)
00465 {
00466 Log() << "CAPAB PREFIX gave unknown channel status mode " << modes[t];
00467 continue;
00468 }
00469
00470 ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
00471 cms->level = level--;
00472 }
00473 }
00474 }
00475 }
00476 else if (params[0].equals_cs("END"))
00477 {
00478 if (!Servers::Capab.count("SERVICES"))
00479 {
00480 UplinkSocket::Message() << "ERROR :m_services_account.so is not loaded. This is required by Anope";
00481 Anope::QuitReason = "ERROR: Remote server does not have the m_services_account module loaded, and this is required.";
00482 Anope::Quitting = true;
00483 return;
00484 }
00485 if (!ModeManager::FindUserModeByName("PRIV"))
00486 {
00487 UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
00488 Anope::QuitReason = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required.";
00489 Anope::Quitting = true;
00490 return;
00491 }
00492 if (!IRCD->CanSVSHold)
00493 Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
00494 if (!Servers::Capab.count("CHGHOST"))
00495 Log() << "CHGHOST missing, Usage disabled until module is loaded.";
00496 if (!Servers::Capab.count("CHGIDENT"))
00497 Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
00498 if (!Servers::Capab.count("TOPICLOCK") && Config->UseServerSideTopicLock)
00499 Log() << "m_topiclock missing, server side topic locking disabled until module is loaded.";
00500 }
00501
00502 Message::Capab::Run(source, params);
00503 }
00504 };
00505
00506 struct IRCDMessageEncap : IRCDMessage
00507 {
00508 IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00509
00510 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00511 {
00512 if (Anope::Match(Me->GetSID(), params[0]) == false)
00513 return;
00514
00515 if (params[1] == "CHGIDENT")
00516 {
00517 User *u = User::Find(params[2]);
00518 if (!u || u->server != Me)
00519 return;
00520
00521 u->SetIdent(params[3]);
00522 UplinkSocket::Message(u) << "FIDENT " << params[3];
00523 }
00524 else if (params[1] == "CHGHOST")
00525 {
00526 User *u = User::Find(params[2]);
00527 if (!u || u->server != Me)
00528 return;
00529
00530 u->SetDisplayedHost(params[3]);
00531 UplinkSocket::Message(u) << "FHOST " << params[3];
00532 }
00533 else if (params[1] == "CHGNAME")
00534 {
00535 User *u = User::Find(params[2]);
00536 if (!u || u->server != Me)
00537 return;
00538
00539 u->SetRealname(params[3]);
00540 UplinkSocket::Message(u) << "FNAME " << params[3];
00541 }
00542 else if (Config->NSSASL && params[1] == "SASL" && params.size() == 6)
00543 {
00544 class InspIRCDSASLIdentifyRequest : public IdentifyRequest
00545 {
00546 Anope::string uid;
00547
00548 public:
00549 InspIRCDSASLIdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), uid(id) { }
00550
00551 void OnSuccess() anope_override
00552 {
00553 UplinkSocket::Message(Me) << "METADATA " << this->uid << " accountname :" << this->GetAccount();
00554 UplinkSocket::Message(Me) << "ENCAP " << this->uid.substr(0, 3) << " SASL " << Me->GetSID() << " " << this->uid << " D S";
00555 }
00556
00557 void OnFail() anope_override
00558 {
00559 UplinkSocket::Message(Me) << "ENCAP " << this->uid.substr(0, 3) << " SASL " << Me->GetSID() << " " << this->uid << " " << " D F";
00560
00561 Log(NickServ) << "A user failed to identify for account " << this->GetAccount() << " using SASL";
00562 }
00563 };
00564
00565
00566
00567
00568
00569
00570
00571 if (params[4] == "S")
00572 {
00573 if (params[5] == "PLAIN")
00574 UplinkSocket::Message(Me) << "ENCAP " << params[2].substr(0, 3) << " SASL " << Me->GetSID() << " " << params[2] << " C +";
00575 else
00576 UplinkSocket::Message(Me) << "ENCAP " << params[2].substr(0, 3) << " SASL " << Me->GetSID() << " " << params[2] << " D F";
00577 }
00578 else if (params[4] == "C")
00579 {
00580 Anope::string decoded;
00581 Anope::B64Decode(params[5], decoded);
00582
00583 size_t p = decoded.find('\0');
00584 if (p == Anope::string::npos)
00585 return;
00586 decoded = decoded.substr(p + 1);
00587
00588 p = decoded.find('\0');
00589 if (p == Anope::string::npos)
00590 return;
00591
00592 Anope::string acc = decoded.substr(0, p),
00593 pass = decoded.substr(p + 1);
00594
00595 if (acc.empty() || pass.empty())
00596 return;
00597
00598 IdentifyRequest *req = new InspIRCDSASLIdentifyRequest(this->owner, params[2], acc, pass);
00599 FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req));
00600 req->Dispatch();
00601 }
00602 }
00603 }
00604 };
00605
00606 struct IRCDMessageFIdent : IRCDMessage
00607 {
00608 IRCDMessageFIdent(Module *creator) : IRCDMessage(creator, "FIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00609
00610 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override
00611 {
00612 source.GetUser()->SetIdent(params[0]);
00613 }
00614 };
00615
00616 class ProtoInspIRCd : public Module
00617 {
00618 Module *m_insp12;
00619
00620 InspIRCd20Proto ircd_proto;
00621
00622
00623 Message::Away message_away;
00624 Message::Error message_error;
00625 Message::Join message_join;
00626 Message::Kick message_kick;
00627 Message::Kill message_kill;
00628 Message::MOTD message_motd;
00629 Message::Part message_part;
00630 Message::Ping message_ping;
00631 Message::Privmsg message_privmsg;
00632 Message::Quit message_quit;
00633 Message::SQuit message_squit;
00634 Message::Stats message_stats;
00635 Message::Topic message_topic;
00636 Message::Version message_version;
00637
00638
00639 ServiceAlias message_endburst, message_fhost, message_fjoin, message_fmode,
00640 message_ftopic, message_idle, message_metadata, message_mode,
00641 message_nick, message_opertype, message_rsquit, message_server,
00642 message_time, message_uid;
00643
00644
00645 IRCDMessageCapab message_capab;
00646 IRCDMessageEncap message_encap;
00647 IRCDMessageFIdent message_fident;
00648
00649 void SendChannelMetadata(Channel *c, const Anope::string &metadataname, const Anope::string &value)
00650 {
00651 UplinkSocket::Message(Me) << "METADATA " << c->name << " " << metadataname << " :" << value;
00652 }
00653
00654 public:
00655 ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
00656 ircd_proto(this),
00657 message_away(this), message_error(this), message_join(this), message_kick(this), message_kill(this),
00658 message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
00659 message_squit(this), message_stats(this), message_topic(this), message_version(this),
00660
00661 message_endburst("IRCDMessage", "inspircd20/endburst", "inspircd12/endburst"),
00662 message_fhost("IRCDMessage", "inspircd20/fhost", "inspircd12/fhost"),
00663 message_fjoin("IRCDMessage", "inspircd20/fjoin", "inspircd12/fjoin"),
00664 message_fmode("IRCDMessage", "inspircd20/fmode", "inspircd12/fmode"),
00665 message_ftopic("IRCDMessage", "inspircd20/ftopic", "inspircd12/ftopic"),
00666 message_idle("IRCDMessage", "inspircd20/idle", "inspircd12/idle"),
00667 message_metadata("IRCDMessage", "inspircd20/metadata", "inspircd12/metadata"),
00668 message_mode("IRCDMessage", "inspircd20/mode", "inspircd12/mode"),
00669 message_nick("IRCDMessage", "inspircd20/nick", "inspircd12/nick"),
00670 message_opertype("IRCDMessage", "inspircd20/opertype", "inspircd12/opertype"),
00671 message_rsquit("IRCDMessage", "inspircd20/rsquit", "inspircd12/rsquit"),
00672 message_server("IRCDMessage", "inspircd20/server", "inspircd12/server"),
00673 message_time("IRCDMessage", "inspircd20/time", "inspircd12/time"),
00674 message_uid("IRCDMessage", "inspircd20/uid", "inspircd12/uid"),
00675
00676 message_capab(this), message_encap(this), message_fident(this)
00677 {
00678 this->SetAuthor("Anope");
00679
00680 if (ModuleManager::LoadModule("inspircd12", User::Find(creator)) != MOD_ERR_OK)
00681 throw ModuleException("Unable to load inspircd12");
00682 m_insp12 = ModuleManager::FindModule("inspircd12");
00683 if (!m_insp12)
00684 throw ModuleException("Unable to find inspircd12");
00685 if (!insp12)
00686 throw ModuleException("No protocol interface for insp12");
00687 ModuleManager::DetachAll(m_insp12);
00688
00689 Implementation i[] = { I_OnUserNickChange, I_OnChannelCreate, I_OnChanRegistered, I_OnDelChan, I_OnMLock, I_OnUnMLock, I_OnSetChannelOption };
00690 ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
00691 }
00692
00693 ~ProtoInspIRCd()
00694 {
00695 ModuleManager::UnloadModule(m_insp12, NULL);
00696 }
00697
00698 void OnUserNickChange(User *u, const Anope::string &) anope_override
00699 {
00700 u->RemoveModeInternal(ModeManager::FindUserModeByName("REGISTERED"));
00701 }
00702
00703 void OnChannelCreate(Channel *c) anope_override
00704 {
00705 if (c->ci && (Config->UseServerSideMLock || Config->UseServerSideTopicLock))
00706 this->OnChanRegistered(c->ci);
00707 }
00708
00709 void OnChanRegistered(ChannelInfo *ci) anope_override
00710 {
00711 if (Config->UseServerSideMLock && ci->c)
00712 {
00713 Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
00714 SendChannelMetadata(ci->c, "mlock", modes);
00715 }
00716
00717 if (Config->UseServerSideTopicLock && Servers::Capab.count("TOPICLOCK") && ci->c)
00718 {
00719 Anope::string on = ci->HasExt("TOPICLOCK") ? "1" : "";
00720 SendChannelMetadata(ci->c, "topiclock", on);
00721 }
00722 }
00723
00724 void OnDelChan(ChannelInfo *ci) anope_override
00725 {
00726 if (Config->UseServerSideMLock && ci->c)
00727 SendChannelMetadata(ci->c, "mlock", "");
00728
00729 if (Config->UseServerSideTopicLock && Servers::Capab.count("TOPICLOCK") && ci->c)
00730 SendChannelMetadata(ci->c, "topiclock", "");
00731 }
00732
00733 EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
00734 {
00735 ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
00736 if (cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Config->UseServerSideMLock)
00737 {
00738 Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
00739 SendChannelMetadata(ci->c, "mlock", modes);
00740 }
00741
00742 return EVENT_CONTINUE;
00743 }
00744
00745 EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
00746 {
00747 ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
00748 if (cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Config->UseServerSideMLock)
00749 {
00750 Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
00751 SendChannelMetadata(ci->c, "mlock", modes);
00752 }
00753
00754 return EVENT_CONTINUE;
00755 }
00756
00757 EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) anope_override
00758 {
00759 if (cmd->name == "chanserv/set/topiclock" && ci->c)
00760 SendChannelMetadata(ci->c, "topiclock", setting.equals_ci("ON") ? "1" : "");
00761
00762 return EVENT_CONTINUE;
00763 }
00764 };
00765
00766 MODULE_INIT(ProtoInspIRCd)