anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
hybrid.cpp (28614B)
1 /* ircd-hybrid protocol module. Minimum supported version of ircd-hybrid is 8.2.23. 2 * 3 * (C) 2003-2022 Anope Team <team@anope.org> 4 * (C) 2012-2022 ircd-hybrid development team 5 * 6 * Please read COPYING and README for further details. 7 * 8 * Based on the original code of Epona by Lara. 9 * Based on the original code of Services by Andy Church. 10 */ 11 12 #include "module.h" 13 #include "modules/cs_mode.h" 14 15 static Anope::string UplinkSID; 16 static bool UseSVSAccount = false; // Temporary backwards compatibility hack until old proto is deprecated 17 18 class HybridProto : public IRCDProto 19 { 20 void SendSVSKillInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override 21 { 22 IRCDProto::SendSVSKillInternal(source, u, buf); 23 u->KillInternal(source, buf); 24 } 25 26 public: 27 HybridProto(Module *creator) : IRCDProto(creator, "ircd-hybrid 8.2.23+") 28 { 29 DefaultPseudoclientModes = "+oi"; 30 CanSVSNick = true; 31 CanSVSHold = true; 32 CanSVSJoin = true; 33 CanSNLine = true; 34 CanSQLine = true; 35 CanSQLineChannel = true; 36 CanSZLine = true; 37 CanCertFP = true; 38 CanSetVHost = true; 39 RequiresID = true; 40 MaxModes = 6; 41 } 42 43 void SendInvite(const MessageSource &source, const Channel *c, User *u) anope_override 44 { 45 UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name << " " << c->creation_time; 46 } 47 48 void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 49 { 50 UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg; 51 } 52 53 void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 54 { 55 UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg; 56 } 57 58 void SendSQLine(User *, const XLine *x) anope_override 59 { 60 UplinkSocket::Message(Me) << "RESV * " << (x->expires ? x->expires - Anope::CurTime : 0) << " " << x->mask << " :" << x->reason; 61 } 62 63 void SendSGLineDel(const XLine *x) anope_override 64 { 65 UplinkSocket::Message(Me) << "UNXLINE * " << x->mask; 66 } 67 68 void SendSGLine(User *, const XLine *x) anope_override 69 { 70 UplinkSocket::Message(Me) << "XLINE * " << x->mask << " " << (x->expires ? x->expires - Anope::CurTime : 0) << " :" << x->GetReason(); 71 } 72 73 void SendSZLineDel(const XLine *x) anope_override 74 { 75 UplinkSocket::Message(Me) << "UNDLINE * " << x->GetHost(); 76 } 77 78 void SendSZLine(User *, const XLine *x) anope_override 79 { 80 /* Calculate the time left before this would expire, capping it at 2 days */ 81 time_t timeleft = x->expires - Anope::CurTime; 82 83 if (timeleft > 172800 || !x->expires) 84 timeleft = 172800; 85 86 UplinkSocket::Message(Me) << "DLINE * " << timeleft << " " << x->GetHost() << " :" << x->GetReason(); 87 } 88 89 void SendAkillDel(const XLine *x) anope_override 90 { 91 if (x->IsRegex() || x->HasNickOrReal()) 92 return; 93 94 UplinkSocket::Message(Me) << "UNKLINE * " << x->GetUser() << " " << x->GetHost(); 95 } 96 97 void SendSQLineDel(const XLine *x) anope_override 98 { 99 UplinkSocket::Message(Me) << "UNRESV * " << x->mask; 100 } 101 102 void SendJoin(User *u, Channel *c, const ChannelStatus *status) anope_override 103 { 104 UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " +" << c->GetModes(true, true) << " :" << u->GetUID(); 105 106 /* 107 * Note that we can send this with the SJOIN but choose not to 108 * because the mode stacker will handle this and probably will 109 * merge these modes with +nrt and other mlocked modes. 110 */ 111 if (status) 112 { 113 /* First save the channel status in case uc->status == status */ 114 ChannelStatus cs = *status; 115 116 /* 117 * If the user is internally on the channel with flags, kill them so that 118 * the stacker will allow this. 119 */ 120 ChanUserContainer *uc = c->FindUser(u); 121 if (uc) 122 uc->status.Clear(); 123 124 BotInfo *setter = BotInfo::Find(u->GetUID()); 125 for (size_t i = 0; i < cs.Modes().length(); ++i) 126 c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), u->GetUID(), false); 127 128 if (uc) 129 uc->status = cs; 130 } 131 } 132 133 void SendAkill(User *u, XLine *x) anope_override 134 { 135 if (x->IsRegex() || x->HasNickOrReal()) 136 { 137 if (!u) 138 { 139 /* 140 * No user (this akill was just added), and contains nick and/or realname. 141 * Find users that match and ban them. 142 */ 143 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) 144 if (x->manager->Check(it->second, x)) 145 this->SendAkill(it->second, x); 146 147 return; 148 } 149 150 const XLine *old = x; 151 152 if (old->manager->HasEntry("*@" + u->host)) 153 return; 154 155 /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */ 156 XLine *xline = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id); 157 158 old->manager->AddXLine(xline); 159 x = xline; 160 161 Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" 162 << u->realname << " matches " << old->mask; 163 } 164 165 /* Calculate the time left before this would expire, capping it at 2 days */ 166 time_t timeleft = x->expires - Anope::CurTime; 167 168 if (timeleft > 172800 || !x->expires) 169 timeleft = 172800; 170 171 UplinkSocket::Message(Me) << "KLINE * " << timeleft << " " << x->GetUser() << " " << x->GetHost() << " :" << x->GetReason(); 172 } 173 174 void SendServer(const Server *server) anope_override 175 { 176 if (server == Me) 177 UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " +" << " :" << server->GetDescription(); 178 else 179 UplinkSocket::Message(Me) << "SID " << server->GetName() << " " << server->GetHops() + 1 << " " << server->GetSID() << " +" << " :" << server->GetDescription(); 180 } 181 182 void SendConnect() anope_override 183 { 184 UplinkSocket::Message() << "PASS " << Config->Uplinks[Anope::CurrentUplink].password; 185 186 /* 187 * TBURST - Supports topic burst 188 * ENCAP - Supports ENCAP 189 * EOB - Supports End Of Burst message 190 * RHOST - Supports UID message with realhost information 191 * MLOCK - Supports MLOCK 192 */ 193 UplinkSocket::Message() << "CAPAB :ENCAP TBURST EOB RHOST MLOCK"; 194 195 SendServer(Me); 196 197 UplinkSocket::Message(Me) << "SVINFO 6 6 0 :" << Anope::CurTime; 198 } 199 200 void SendClientIntroduction(User *u) anope_override 201 { 202 Anope::string modes = "+" + u->GetModes(); 203 204 UplinkSocket::Message(Me) << "UID " << u->nick << " 1 " << u->timestamp << " " << modes << " " << u->GetIdent() << " " 205 << u->host << " " << u->host << " 0.0.0.0 " << u->GetUID() << " * :" << u->realname; 206 } 207 208 void SendEOB() anope_override 209 { 210 UplinkSocket::Message(Me) << "EOB"; 211 } 212 213 void SendModeInternal(const MessageSource &source, User *u, const Anope::string &buf) anope_override 214 { 215 UplinkSocket::Message(source) << "SVSMODE " << u->GetUID() << " " << u->timestamp << " " << buf; 216 } 217 218 void SendLogin(User *u, NickAlias *na) anope_override 219 { 220 if (UseSVSAccount == false) 221 IRCD->SendMode(Config->GetClient("NickServ"), u, "+d %s", na->nc->display.c_str()); 222 else 223 UplinkSocket::Message(Me) << "SVSACCOUNT " << u->GetUID() << " " << u->timestamp << " " << na->nc->display; 224 } 225 226 void SendLogout(User *u) anope_override 227 { 228 if (UseSVSAccount == false) 229 IRCD->SendMode(Config->GetClient("NickServ"), u, "+d *"); 230 else 231 UplinkSocket::Message(Me) << "SVSACCOUNT " << u->GetUID() << " " << u->timestamp << " *"; 232 } 233 234 void SendChannel(Channel *c) anope_override 235 { 236 Anope::string modes = "+" + c->GetModes(true, true); 237 UplinkSocket::Message(Me) << "SJOIN " << c->creation_time << " " << c->name << " " << modes << " :"; 238 } 239 240 void SendTopic(const MessageSource &source, Channel *c) anope_override 241 { 242 UplinkSocket::Message(source) << "TBURST " << c->creation_time << " " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic; 243 } 244 245 void SendForceNickChange(User *u, const Anope::string &newnick, time_t when) anope_override 246 { 247 UplinkSocket::Message(Me) << "SVSNICK " << u->GetUID() << " " << u->timestamp << " " << newnick << " " << when; 248 } 249 250 void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) anope_override 251 { 252 UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan; 253 } 254 255 void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) anope_override 256 { 257 if (!param.empty()) 258 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param; 259 else 260 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan; 261 } 262 263 void SendSVSHold(const Anope::string &nick, time_t t) anope_override 264 { 265 XLine x(nick, Me->GetName(), Anope::CurTime + t, "Being held for registered user"); 266 this->SendSQLine(NULL, &x); 267 } 268 269 void SendSVSHoldDel(const Anope::string &nick) anope_override 270 { 271 XLine x(nick); 272 this->SendSQLineDel(&x); 273 } 274 275 void SendVhost(User *u, const Anope::string &ident, const Anope::string &host) anope_override 276 { 277 UplinkSocket::Message(Me) << "SVSHOST " << u->GetUID() << " " << u->timestamp << " " << host; 278 } 279 280 void SendVhostDel(User *u) anope_override 281 { 282 UplinkSocket::Message(Me) << "SVSHOST " << u->GetUID() << " " << u->timestamp << " " << u->host; 283 } 284 285 bool IsExtbanValid(const Anope::string &mask) anope_override 286 { 287 return mask.length() >= 4 && mask[0] == '$' && mask[2] == ':'; 288 } 289 290 bool IsIdentValid(const Anope::string &ident) anope_override 291 { 292 if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen")) 293 return false; 294 295 /* 296 * If the user name begins with a tilde (~), make sure there is at least 297 * one succeeding character. 298 */ 299 unsigned i = ident[0] == '~'; 300 if (i >= ident.length()) 301 return false; 302 303 /* User names may not start with a '-', '_', or '.'. */ 304 const char &a = ident[i]; 305 if (a == '-' || a == '_' || a == '.') 306 return false; 307 308 for (i = 0; i < ident.length(); ++i) 309 { 310 const char &c = ident[i]; 311 312 /* A tilde can only be used as the first character of a user name. */ 313 if (c == '~' && i == 0) 314 continue; 315 316 if ((c >= 'A' && c <= 'Z') || 317 (c >= 'a' && c <= 'z') || 318 (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.') 319 continue; 320 321 return false; 322 } 323 324 return true; 325 } 326 }; 327 328 struct IRCDMessageBMask : IRCDMessage 329 { 330 IRCDMessageBMask(Module *creator) : IRCDMessage(creator, "BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 331 332 /* 0 1 2 3 */ 333 /* :0MC BMASK 1350157102 #channel b :*!*@*.test.com */ 334 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 335 { 336 Channel *c = Channel::Find(params[1]); 337 ChannelMode *mode = ModeManager::FindChannelModeByChar(params[2][0]); 338 339 if (c && mode) 340 { 341 spacesepstream bans(params[3]); 342 Anope::string token; 343 344 while (bans.GetToken(token)) 345 c->SetModeInternal(source, mode, token); 346 } 347 } 348 }; 349 350 struct IRCDMessageCapab : Message::Capab 351 { 352 IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 353 354 /* 0 */ 355 /* CAPAB :TBURST EOB MLOCK */ 356 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 357 { 358 spacesepstream sep(params[0]); 359 Anope::string capab; 360 361 while (sep.GetToken(capab)) 362 { 363 if (capab.find("HOP") != Anope::string::npos || capab.find("RHOST") != Anope::string::npos) 364 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', 1)); 365 if (capab.find("AOP") != Anope::string::npos) 366 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', 3)); 367 if (capab.find("QOP") != Anope::string::npos) 368 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', 4)); 369 } 370 371 Message::Capab::Run(source, params); 372 } 373 }; 374 375 struct IRCDMessageCertFP: IRCDMessage 376 { 377 IRCDMessageCertFP(Module *creator) : IRCDMessage(creator, "CERTFP", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 378 379 /* 0 */ 380 /* :0MCAAAAAB CERTFP 4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */ 381 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 382 { 383 User *u = source.GetUser(); 384 385 u->fingerprint = params[0]; 386 FOREACH_MOD(OnFingerprint, (u)); 387 } 388 }; 389 390 struct IRCDMessageEOB : IRCDMessage 391 { 392 IRCDMessageEOB(Module *creator) : IRCDMessage(creator, "EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 393 394 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 395 { 396 source.GetServer()->Sync(true); 397 } 398 }; 399 400 struct IRCDMessageJoin : Message::Join 401 { 402 IRCDMessageJoin(Module *creator) : Message::Join(creator, "JOIN") { } 403 404 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 405 { 406 if (params.size() < 2) 407 return; 408 409 std::vector<Anope::string> p = params; 410 p.erase(p.begin()); 411 412 Message::Join::Run(source, p); 413 } 414 }; 415 416 struct IRCDMessageMetadata : IRCDMessage 417 { 418 IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 419 420 /* 0 1 2 3 */ 421 /* :0MC METADATA client 0MCAAAAAB certfp :4C62287BA6776A89CD4F8FF10A62FFB35E79319F51AF6C62C674984974FCCB1D */ 422 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 423 { 424 if (params[0].equals_cs("client")) 425 { 426 User *u = User::Find(params[1]); 427 if (!u) 428 { 429 Log(LOG_DEBUG) << "METADATA for nonexistent user " << params[1]; 430 return; 431 } 432 433 if (params[2].equals_cs("certfp")) 434 { 435 u->fingerprint = params[3]; 436 FOREACH_MOD(OnFingerprint, (u)); 437 } 438 } 439 } 440 }; 441 442 struct IRCDMessageMLock : IRCDMessage 443 { 444 IRCDMessageMLock(Module *creator) : IRCDMessage(creator, "MLOCK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 445 446 /* 0 1 2 3 */ 447 /* :0MC MLOCK 1350157102 #channel 1350158923 :nt */ 448 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 449 { 450 Channel *c = Channel::Find(params[1]); 451 452 if (c && c->ci) 453 { 454 ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks"); 455 Anope::string modes; 456 457 if (modelocks) 458 modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", ""); 459 460 // Mode lock string is not what we say it is? 461 if (modes != params[3]) 462 UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->name << " " << Anope::CurTime << " :" << modes; 463 } 464 } 465 }; 466 467 struct IRCDMessageNick : IRCDMessage 468 { 469 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 470 471 /* 0 1 */ 472 /* :0MCAAAAAB NICK newnick 1350157102 */ 473 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 474 { 475 source.GetUser()->ChangeNick(params[0], convertTo<time_t>(params[1])); 476 } 477 }; 478 479 struct IRCDMessagePass : IRCDMessage 480 { 481 IRCDMessagePass(Module *creator) : IRCDMessage(creator, "PASS", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 482 483 /* 0 */ 484 /* PASS password */ 485 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 486 { 487 if (params.size() == 4) 488 UplinkSID = params[3]; 489 } 490 }; 491 492 struct IRCDMessagePong : IRCDMessage 493 { 494 IRCDMessagePong(Module *creator) : IRCDMessage(creator, "PONG", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 495 496 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 497 { 498 source.GetServer()->Sync(false); 499 } 500 }; 501 502 struct IRCDMessageServer : IRCDMessage 503 { 504 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 505 506 /* 0 1 2 3 4 */ 507 /* SERVER hades.arpa 1 4XY + :ircd-hybrid test server */ 508 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 509 { 510 /* Servers other than our immediate uplink are introduced via SID */ 511 if (params[1] != "1") 512 return; 513 514 if (params.size() == 5) 515 { 516 UplinkSID = params[2]; 517 UseSVSAccount = true; 518 } 519 520 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params.back(), UplinkSID); 521 522 IRCD->SendPing(Me->GetName(), params[0]); 523 } 524 }; 525 526 struct IRCDMessageSID : IRCDMessage 527 { 528 IRCDMessageSID(Module *creator) : IRCDMessage(creator, "SID", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 529 530 /* 0 1 2 3 4 */ 531 /* :0MC SID hades.arpa 2 4XY + :ircd-hybrid test server */ 532 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 533 { 534 unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; 535 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params.back(), params[2]); 536 537 IRCD->SendPing(Me->GetName(), params[0]); 538 } 539 }; 540 541 struct IRCDMessageSJoin : IRCDMessage 542 { 543 IRCDMessageSJoin(Module *creator) : IRCDMessage(creator, "SJOIN", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 544 545 /* 0 1 2 3 */ 546 /* :0MC SJOIN 1654877335 #nether +nt :@0MCAAAAAB +0MCAAAAAC */ 547 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 548 { 549 Anope::string modes; 550 551 for (unsigned i = 2; i < params.size() - 1; ++i) 552 modes += " " + params[i]; 553 554 if (!modes.empty()) 555 modes.erase(modes.begin()); 556 557 std::list<Message::Join::SJoinUser> users; 558 559 spacesepstream sep(params[params.size() - 1]); 560 Anope::string buf; 561 562 while (sep.GetToken(buf)) 563 { 564 Message::Join::SJoinUser sju; 565 566 /* Get prefixes from the nick */ 567 for (char ch; (ch = ModeManager::GetStatusChar(buf[0])); ) 568 { 569 buf.erase(buf.begin()); 570 sju.first.AddMode(ch); 571 } 572 573 sju.second = User::Find(buf); 574 if (!sju.second) 575 { 576 Log(LOG_DEBUG) << "SJOIN for nonexistent user " << buf << " on " << params[1]; 577 continue; 578 } 579 580 users.push_back(sju); 581 } 582 583 time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime; 584 Message::Join::SJoin(source, params[1], ts, modes, users); 585 } 586 }; 587 588 struct IRCDMessageSVSMode : IRCDMessage 589 { 590 IRCDMessageSVSMode(Module *creator) : IRCDMessage(creator, "SVSMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 591 592 /* 0 1 2 */ 593 /* :0MC SVSMODE 0MCAAAAAB 1350157102 +r */ 594 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 595 { 596 User *u = User::Find(params[0]); 597 598 if (!u) 599 return; 600 601 if (!params[1].is_pos_number_only() || convertTo<time_t>(params[1]) != u->timestamp) 602 return; 603 604 u->SetModesInternal(source, "%s", params[2].c_str()); 605 } 606 }; 607 608 struct IRCDMessageTBurst : IRCDMessage 609 { 610 IRCDMessageTBurst(Module *creator) : IRCDMessage(creator, "TBURST", 5) { } 611 612 /* 0 1 2 3 4 */ 613 /* :0MC TBURST 1654867975 #nether 1654877335 Steve!~steve@the.mines :Join the ghast nation */ 614 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 615 { 616 Anope::string setter; 617 sepstream(params[3], '!').GetToken(setter, 0); 618 time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; 619 Channel *c = Channel::Find(params[1]); 620 621 if (c) 622 c->ChangeTopicInternal(NULL, setter, params[4], topic_time); 623 } 624 }; 625 626 struct IRCDMessageTMode : IRCDMessage 627 { 628 IRCDMessageTMode(Module *creator) : IRCDMessage(creator, "TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 629 630 /* 0 1 2 */ 631 /* :0MC TMODE 1654867975 #nether +ntR */ 632 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 633 { 634 time_t ts = 0; 635 636 try 637 { 638 ts = convertTo<time_t>(params[0]); 639 } 640 catch (const ConvertException &) { } 641 642 Channel *c = Channel::Find(params[1]); 643 Anope::string modes = params[2]; 644 645 for (unsigned i = 3; i < params.size(); ++i) 646 modes += " " + params[i]; 647 648 if (c) 649 c->SetModesInternal(source, modes, ts); 650 } 651 }; 652 653 struct IRCDMessageUID : IRCDMessage 654 { 655 IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 656 657 /* 0 1 2 3 4 5 6 7 8 9 10 */ 658 /* :0MC UID Steve 1 1350157102 +oi ~steve virtual.host real.host 10.0.0.1 0MCAAAAAB Steve :Mining all the time */ 659 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 660 { 661 NickAlias *na = NULL; 662 663 if (params[9] != "*") 664 na = NickAlias::Find(params[9]); 665 666 /* Source is always the server */ 667 User::OnIntroduce(params[0], params[4], params[6], params[5], params[7], source.GetServer(), params[10], 668 params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, 669 params[3], params[8], na ? *na->nc : NULL); 670 } 671 }; 672 673 class ProtoHybrid : public Module 674 { 675 HybridProto ircd_proto; 676 677 /* Core message handlers */ 678 Message::Away message_away; 679 Message::Error message_error; 680 Message::Invite message_invite; 681 Message::Kick message_kick; 682 Message::Kill message_kill; 683 Message::Mode message_mode; 684 Message::MOTD message_motd; 685 Message::Notice message_notice; 686 Message::Part message_part; 687 Message::Ping message_ping; 688 Message::Privmsg message_privmsg; 689 Message::Quit message_quit; 690 Message::SQuit message_squit; 691 Message::Stats message_stats; 692 Message::Time message_time; 693 Message::Topic message_topic; 694 Message::Version message_version; 695 Message::Whois message_whois; 696 697 /* Our message handlers */ 698 IRCDMessageBMask message_bmask; 699 IRCDMessageCapab message_capab; 700 IRCDMessageCertFP message_certfp; 701 IRCDMessageEOB message_eob; 702 IRCDMessageJoin message_join; 703 IRCDMessageMetadata message_metadata; 704 IRCDMessageMLock message_mlock; 705 IRCDMessageNick message_nick; 706 IRCDMessagePass message_pass; 707 IRCDMessagePong message_pong; 708 IRCDMessageServer message_server; 709 IRCDMessageSID message_sid; 710 IRCDMessageSJoin message_sjoin; 711 IRCDMessageSVSMode message_svsmode; 712 IRCDMessageTBurst message_tburst; 713 IRCDMessageTMode message_tmode; 714 IRCDMessageUID message_uid; 715 716 bool use_server_side_mlock; 717 718 void AddModes() 719 { 720 /* Add user modes */ 721 ModeManager::AddUserMode(new UserModeOperOnly("ADMIN", 'a')); 722 ModeManager::AddUserMode(new UserMode("CALLERID", 'g')); 723 ModeManager::AddUserMode(new UserMode("INVIS", 'i')); 724 ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l')); 725 ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); 726 ModeManager::AddUserMode(new UserMode("HIDECHANS", 'p')); 727 ModeManager::AddUserMode(new UserMode("HIDEIDLE", 'q')); 728 ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r')); 729 ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); 730 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w')); 731 ModeManager::AddUserMode(new UserMode("BOT", 'B')); 732 ModeManager::AddUserMode(new UserMode("DEAF", 'D')); 733 ModeManager::AddUserMode(new UserMode("SOFTCALLERID", 'G')); 734 ModeManager::AddUserMode(new UserModeOperOnly("HIDEOPER", 'H')); 735 ModeManager::AddUserMode(new UserMode("REGPRIV", 'R')); 736 ModeManager::AddUserMode(new UserModeNoone("SSL", 'S')); 737 ModeManager::AddUserMode(new UserModeNoone("WEBIRC", 'W')); 738 ModeManager::AddUserMode(new UserMode("SECUREONLY", 'Z')); 739 740 /* b/e/I */ 741 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b')); 742 ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e')); 743 ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I')); 744 745 /* v/o */ 746 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', 0)); 747 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', 2)); 748 749 /* l/k */ 750 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true)); 751 ModeManager::AddChannelMode(new ChannelModeKey('k')); 752 753 /* Add channel modes */ 754 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c')); 755 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i')); 756 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm')); 757 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n')); 758 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p')); 759 ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r')); 760 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); 761 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); 762 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C')); 763 ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K')); 764 ModeManager::AddChannelMode(new ChannelModeOperOnly("LBAN", 'L')); 765 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M')); 766 ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N')); 767 ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O')); 768 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q')); 769 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R')); 770 ModeManager::AddChannelMode(new ChannelMode("SSL", 'S')); 771 ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T')); 772 ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V')); 773 ModeManager::AddChannelMode(new ChannelModeNoone("ISSECURE", 'Z')); 774 } 775 776 public: 777 ProtoHybrid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), 778 ircd_proto(this), 779 message_away(this), 780 message_error(this), 781 message_invite(this), 782 message_kick(this), 783 message_kill(this), 784 message_mode(this), 785 message_motd(this), 786 message_notice(this), 787 message_part(this), 788 message_ping(this), 789 message_privmsg(this), 790 message_quit(this), 791 message_squit(this), 792 message_stats(this), 793 message_time(this), 794 message_topic(this), 795 message_version(this), 796 message_whois(this), 797 message_bmask(this), 798 message_capab(this), 799 message_certfp(this), 800 message_eob(this), 801 message_join(this), 802 message_metadata(this), 803 message_mlock(this), 804 message_nick(this), 805 message_pass(this), 806 message_pong(this), 807 message_server(this), 808 message_sid(this), 809 message_sjoin(this), 810 message_svsmode(this), 811 message_tburst(this), 812 message_tmode(this), 813 message_uid(this) 814 { 815 if (Config->GetModule(this)) 816 this->AddModes(); 817 } 818 819 void OnUserNickChange(User *u, const Anope::string &) anope_override 820 { 821 u->RemoveModeInternal(Me, ModeManager::FindUserModeByName("REGISTERED")); 822 } 823 824 void OnReload(Configuration::Conf *conf) anope_override 825 { 826 use_server_side_mlock = conf->GetModule(this)->Get<bool>("use_server_side_mlock"); 827 } 828 829 void OnChannelSync(Channel *c) anope_override 830 { 831 if (!c->ci) 832 return; 833 834 ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks"); 835 if (use_server_side_mlock && modelocks && Servers::Capab.count("MLOCK")) 836 { 837 Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", ""); 838 UplinkSocket::Message(Me) << "MLOCK " << c->creation_time << " " << c->ci->name << " " << Anope::CurTime << " :" << modes; 839 } 840 } 841 842 void OnDelChan(ChannelInfo *ci) anope_override 843 { 844 if (use_server_side_mlock && ci->c && Servers::Capab.count("MLOCK")) 845 UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :"; 846 } 847 848 EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override 849 { 850 ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks"); 851 ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name); 852 if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK")) 853 { 854 Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar; 855 UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes; 856 } 857 858 return EVENT_CONTINUE; 859 } 860 861 EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override 862 { 863 ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks"); 864 ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name); 865 if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK")) 866 { 867 Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, ""); 868 UplinkSocket::Message(Me) << "MLOCK " << ci->c->creation_time << " " << ci->name << " " << Anope::CurTime << " :" << modes; 869 } 870 871 return EVENT_CONTINUE; 872 } 873 }; 874 875 MODULE_INIT(ProtoHybrid)