anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
inspircd12.cpp (43509B)
1 /* inspircd 1.2 functions 2 * 3 * (C) 2003-2022 Anope Team 4 * Contact us at team@anope.org 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/sasl.h" 14 15 struct SASLUser 16 { 17 Anope::string uid; 18 Anope::string acc; 19 time_t created; 20 }; 21 22 static std::list<SASLUser> saslusers; 23 24 static Anope::string rsquit_server, rsquit_id; 25 26 class ChannelModeFlood : public ChannelModeParam 27 { 28 public: 29 ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { } 30 31 bool IsValid(Anope::string &value) const anope_override 32 { 33 try 34 { 35 Anope::string rest; 36 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()) 37 return true; 38 } 39 catch (const ConvertException &) { } 40 41 return false; 42 } 43 }; 44 45 class InspIRCd12Proto : public IRCDProto 46 { 47 private: 48 void SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf) anope_override 49 { 50 IRCDProto::SendSVSKillInternal(source, user, buf); 51 user->KillInternal(source, buf); 52 } 53 54 void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent) 55 { 56 if (!Servers::Capab.count("CHGIDENT")) 57 Log() << "CHGIDENT not loaded!"; 58 else 59 UplinkSocket::Message(Me) << "CHGIDENT " << nick << " " << vIdent; 60 } 61 62 void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost) 63 { 64 if (!Servers::Capab.count("CHGHOST")) 65 Log() << "CHGHOST not loaded!"; 66 else 67 UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost; 68 } 69 70 void SendAddLine(const Anope::string &xtype, const Anope::string &mask, time_t duration, const Anope::string &addedby, const Anope::string &reason) 71 { 72 UplinkSocket::Message(Me) << "ADDLINE " << xtype << " " << mask << " " << addedby << " " << Anope::CurTime << " " << duration << " :" << reason; 73 } 74 75 void SendDelLine(const Anope::string &xtype, const Anope::string &mask) 76 { 77 UplinkSocket::Message(Me) << "DELLINE " << xtype << " " << mask; 78 } 79 80 public: 81 InspIRCd12Proto(Module *creator) : IRCDProto(creator, "InspIRCd 1.2") 82 { 83 DefaultPseudoclientModes = "+I"; 84 CanSVSNick = true; 85 CanSVSJoin = true; 86 CanSetVHost = true; 87 CanSetVIdent = true; 88 CanSQLine = true; 89 CanSZLine = true; 90 CanSVSHold = true; 91 CanCertFP = true; 92 RequiresID = true; 93 MaxModes = 20; 94 } 95 96 void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 97 { 98 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; 99 } 100 101 void SendGlobalPrivmsg(BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override 102 { 103 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; 104 } 105 106 void SendAkillDel(const XLine *x) anope_override 107 { 108 /* InspIRCd may support regex bans 109 * Mask is expected in format: 'n!u@h\sr' and spaces as '\s' 110 * We remove the '//' and replace '#' and any ' ' with '\s' 111 */ 112 if (x->IsRegex() && Servers::Capab.count("RLINE")) 113 { 114 Anope::string mask = x->mask; 115 if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/') 116 mask = mask.substr(1, mask.length() - 2); 117 size_t h = mask.find('#'); 118 if (h != Anope::string::npos) 119 { 120 mask = mask.replace(h, 1, "\\s"); 121 mask = mask.replace_all_cs(" ", "\\s"); 122 } 123 SendDelLine("R", mask); 124 return; 125 } 126 else if (x->IsRegex() || x->HasNickOrReal()) 127 return; 128 129 /* ZLine if we can instead */ 130 if (x->GetUser() == "*") 131 { 132 cidr addr(x->GetHost()); 133 if (addr.valid()) 134 { 135 IRCD->SendSZLineDel(x); 136 return; 137 } 138 } 139 140 SendDelLine("G", x->GetUser() + "@" + x->GetHost()); 141 } 142 143 void SendTopic(const MessageSource &source, Channel *c) anope_override 144 { 145 if (Servers::Capab.count("SVSTOPIC")) 146 { 147 UplinkSocket::Message(c->ci->WhoSends()) << "SVSTOPIC " << c->name << " " << c->topic_ts << " " << c->topic_setter << " :" << c->topic; 148 } 149 else 150 { 151 /* If the last time a topic was set is after the TS we want for this topic we must bump this topic's timestamp to now */ 152 time_t ts = c->topic_ts; 153 if (c->topic_time > ts) 154 ts = Anope::CurTime; 155 /* But don't modify c->topic_ts, it should remain set to the real TS we want as ci->last_topic_time pulls from it */ 156 UplinkSocket::Message(source) << "FTOPIC " << c->name << " " << ts << " " << c->topic_setter << " :" << c->topic; 157 } 158 } 159 160 void SendVhostDel(User *u) anope_override 161 { 162 UserMode *um = ModeManager::FindUserModeByName("CLOAK"); 163 164 if (um && !u->HasMode(um->name)) 165 // Just set +x if we can 166 u->SetMode(NULL, um); 167 else 168 // Try to restore cloaked host 169 this->SendChgHostInternal(u->nick, u->chost); 170 } 171 172 void SendAkill(User *u, XLine *x) anope_override 173 { 174 // Calculate the time left before this would expire, capping it at 2 days 175 time_t timeleft = x->expires - Anope::CurTime; 176 if (timeleft > 172800 || !x->expires) 177 timeleft = 172800; 178 179 /* InspIRCd may support regex bans, if they do we can send this and forget about it 180 * Mask is expected in format: 'n!u@h\sr' and spaces as '\s' 181 * We remove the '//' and replace '#' and any ' ' with '\s' 182 */ 183 if (x->IsRegex() && Servers::Capab.count("RLINE")) 184 { 185 Anope::string mask = x->mask; 186 if (mask.length() >= 2 && mask[0] == '/' && mask[mask.length() - 1] == '/') 187 mask = mask.substr(1, mask.length() - 2); 188 size_t h = mask.find('#'); 189 if (h != Anope::string::npos) 190 { 191 mask = mask.replace(h, 1, "\\s"); 192 mask = mask.replace_all_cs(" ", "\\s"); 193 } 194 SendAddLine("R", mask, timeleft, x->by, x->GetReason()); 195 return; 196 } 197 else if (x->IsRegex() || x->HasNickOrReal()) 198 { 199 if (!u) 200 { 201 /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */ 202 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) 203 if (x->manager->Check(it->second, x)) 204 this->SendAkill(it->second, x); 205 return; 206 } 207 208 const XLine *old = x; 209 210 if (old->manager->HasEntry("*@" + u->host)) 211 return; 212 213 /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */ 214 x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id); 215 old->manager->AddXLine(x); 216 217 Log(Config->GetClient("OperServ"), "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask; 218 } 219 220 /* ZLine if we can instead */ 221 if (x->GetUser() == "*") 222 { 223 cidr addr(x->GetHost()); 224 if (addr.valid()) 225 { 226 IRCD->SendSZLine(u, x); 227 return; 228 } 229 } 230 231 SendAddLine("G", x->GetUser() + "@" + x->GetHost(), timeleft, x->by, x->GetReason()); 232 } 233 234 void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override 235 { 236 User *u = User::Find(dest); 237 UplinkSocket::Message() << "PUSH " << dest << " ::" << Me->GetName() << " " << numeric << " " << (u ? u->nick : dest) << " " << buf; 238 } 239 240 void SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf) anope_override 241 { 242 UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf; 243 } 244 245 void SendClientIntroduction(User *u) anope_override 246 { 247 Anope::string modes = "+" + u->GetModes(); 248 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; 249 if (modes.find('o') != Anope::string::npos) 250 UplinkSocket::Message(u) << "OPERTYPE :service"; 251 } 252 253 /* SERVER services-dev.chatspike.net password 0 :Description here */ 254 void SendServer(const Server *server) anope_override 255 { 256 /* if rsquit is set then we are waiting on a squit */ 257 if (rsquit_id.empty() && rsquit_server.empty()) 258 UplinkSocket::Message() << "SERVER " << server->GetName() << " " << Config->Uplinks[Anope::CurrentUplink].password << " " << server->GetHops() << " " << server->GetSID() << " :" << server->GetDescription(); 259 } 260 261 void SendSquit(Server *s, const Anope::string &message) anope_override 262 { 263 if (s != Me) 264 { 265 rsquit_id = s->GetSID(); 266 rsquit_server = s->GetName(); 267 UplinkSocket::Message() << "RSQUIT " << s->GetName() << " :" << message; 268 } 269 else 270 UplinkSocket::Message() << "SQUIT " << s->GetName() << " :" << message; 271 } 272 273 /* JOIN */ 274 void SendJoin(User *user, Channel *c, const ChannelStatus *status) anope_override 275 { 276 UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :," << user->GetUID(); 277 /* Note that we can send this with the FJOIN but choose not to 278 * because the mode stacker will handle this and probably will 279 * merge these modes with +nrt and other mlocked modes 280 */ 281 if (status) 282 { 283 /* First save the channel status incase uc->Status == status */ 284 ChannelStatus cs = *status; 285 /* If the user is internally on the channel with flags, kill them so that 286 * the stacker will allow this. 287 */ 288 ChanUserContainer *uc = c->FindUser(user); 289 if (uc != NULL) 290 uc->status.Clear(); 291 292 BotInfo *setter = BotInfo::Find(user->GetUID()); 293 for (size_t i = 0; i < cs.Modes().length(); ++i) 294 c->SetMode(setter, ModeManager::FindChannelModeByChar(cs.Modes()[i]), user->GetUID(), false); 295 296 if (uc != NULL) 297 uc->status = cs; 298 } 299 } 300 301 /* UNSQLINE */ 302 void SendSQLineDel(const XLine *x) anope_override 303 { 304 SendDelLine("Q", x->mask); 305 } 306 307 /* SQLINE */ 308 void SendSQLine(User *, const XLine *x) anope_override 309 { 310 // Calculate the time left before this would expire, capping it at 2 days 311 time_t timeleft = x->expires - Anope::CurTime; 312 if (timeleft > 172800 || !x->expires) 313 timeleft = 172800; 314 SendAddLine("Q", x->mask, timeleft, x->by, x->GetReason()); 315 } 316 317 void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override 318 { 319 if (!vIdent.empty()) 320 this->SendChgIdentInternal(u->nick, vIdent); 321 if (!vhost.empty()) 322 this->SendChgHostInternal(u->nick, vhost); 323 } 324 325 void SendConnect() anope_override 326 { 327 SendServer(Me); 328 } 329 330 /* SVSHOLD - set */ 331 void SendSVSHold(const Anope::string &nick, time_t t) anope_override 332 { 333 UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick << " " << t << " :Being held for registered user"; 334 } 335 336 /* SVSHOLD - release */ 337 void SendSVSHoldDel(const Anope::string &nick) anope_override 338 { 339 UplinkSocket::Message(Config->GetClient("NickServ")) << "SVSHOLD " << nick; 340 } 341 342 /* UNSZLINE */ 343 void SendSZLineDel(const XLine *x) anope_override 344 { 345 SendDelLine("Z", x->GetHost()); 346 } 347 348 /* SZLINE */ 349 void SendSZLine(User *, const XLine *x) anope_override 350 { 351 // Calculate the time left before this would expire, capping it at 2 days 352 time_t timeleft = x->expires - Anope::CurTime; 353 if (timeleft > 172800 || !x->expires) 354 timeleft = 172800; 355 SendAddLine("Z", x->GetHost(), timeleft, x->by, x->GetReason()); 356 } 357 358 void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &) anope_override 359 { 360 UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan; 361 } 362 363 void SendSVSPart(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string ¶m) anope_override 364 { 365 if (!param.empty()) 366 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param; 367 else 368 UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan; 369 } 370 371 void SendSWhois(const MessageSource &, const Anope::string &who, const Anope::string &mask) anope_override 372 { 373 User *u = User::Find(who); 374 375 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " swhois :" << mask; 376 } 377 378 void SendBOB() anope_override 379 { 380 UplinkSocket::Message(Me) << "BURST " << Anope::CurTime; 381 Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); 382 UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << IRCD->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString(); 383 } 384 385 void SendEOB() anope_override 386 { 387 UplinkSocket::Message(Me) << "ENDBURST"; 388 } 389 390 void SendGlobopsInternal(const MessageSource &source, const Anope::string &buf) anope_override 391 { 392 if (Servers::Capab.count("GLOBOPS")) 393 UplinkSocket::Message(source) << "SNONOTICE g :" << buf; 394 else 395 UplinkSocket::Message(source) << "SNONOTICE A :" << buf; 396 } 397 398 void SendLogin(User *u, NickAlias *na) anope_override 399 { 400 /* InspIRCd uses an account to bypass chmode +R, not umode +r, so we can't send this here */ 401 if (na->nc->HasExt("UNCONFIRMED")) 402 return; 403 404 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :" << na->nc->display; 405 } 406 407 void SendLogout(User *u) anope_override 408 { 409 UplinkSocket::Message(Me) << "METADATA " << u->GetUID() << " accountname :"; 410 } 411 412 void SendChannel(Channel *c) anope_override 413 { 414 UplinkSocket::Message(Me) << "FJOIN " << c->name << " " << c->creation_time << " +" << c->GetModes(true, true) << " :"; 415 } 416 417 void SendOper(User *u) anope_override 418 { 419 } 420 421 void SendSASLMessage(const SASL::Message &message) anope_override 422 { 423 UplinkSocket::Message(Me) << "ENCAP " << message.target.substr(0, 3) << " SASL " << message.source << " " << message.target << " " << message.type << " " << message.data << (message.ext.empty() ? "" : (" " + message.ext)); 424 } 425 426 void SendSVSLogin(const Anope::string &uid, const Anope::string &acc, const Anope::string &vident, const Anope::string &vhost) anope_override 427 { 428 UplinkSocket::Message(Me) << "METADATA " << uid << " accountname :" << acc; 429 430 if (!vident.empty()) 431 UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << vident; 432 if (!vhost.empty()) 433 UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << vhost; 434 435 SASLUser su; 436 su.uid = uid; 437 su.acc = acc; 438 su.created = Anope::CurTime; 439 440 for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();) 441 { 442 SASLUser &u = *it; 443 444 if (u.created + 30 < Anope::CurTime || u.uid == uid) 445 it = saslusers.erase(it); 446 else 447 ++it; 448 } 449 450 saslusers.push_back(su); 451 } 452 453 bool IsExtbanValid(const Anope::string &mask) anope_override 454 { 455 return mask.length() >= 3 && mask[1] == ':'; 456 } 457 458 bool IsIdentValid(const Anope::string &ident) anope_override 459 { 460 if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen")) 461 return false; 462 463 for (unsigned i = 0; i < ident.length(); ++i) 464 { 465 const char &c = ident[i]; 466 467 if (c >= 'A' && c <= '}') 468 continue; 469 470 if ((c >= '0' && c <= '9') || c == '-' || c == '.') 471 continue; 472 473 return false; 474 } 475 476 return true; 477 } 478 }; 479 480 class InspIRCdExtBan : public ChannelModeList 481 { 482 public: 483 InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } 484 485 bool Matches(User *u, const Entry *e) anope_override 486 { 487 const Anope::string &mask = e->GetMask(); 488 489 if (mask.find("m:") == 0 || mask.find("N:") == 0) 490 { 491 Anope::string real_mask = mask.substr(2); 492 493 Entry en(this->name, real_mask); 494 if (en.Matches(u)) 495 return true; 496 } 497 else if (mask.find("j:") == 0) 498 { 499 Anope::string real_mask = mask.substr(2); 500 501 Channel *c = Channel::Find(real_mask); 502 if (c != NULL && c->FindUser(u) != NULL) 503 return true; 504 } 505 else if (mask.find("M:") == 0 || mask.find("R:") == 0) 506 { 507 Anope::string real_mask = mask.substr(2); 508 509 if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display)) 510 return true; 511 } 512 else if (mask.find("r:") == 0) 513 { 514 Anope::string real_mask = mask.substr(2); 515 516 if (Anope::Match(u->realname, real_mask)) 517 return true; 518 } 519 else if (mask.find("s:") == 0) 520 { 521 Anope::string real_mask = mask.substr(2); 522 523 if (Anope::Match(u->server->GetName(), real_mask)) 524 return true; 525 } 526 527 return false; 528 } 529 }; 530 531 struct IRCDMessageCapab : Message::Capab 532 { 533 IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 534 535 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 536 { 537 if (params[0].equals_cs("START")) 538 { 539 /* reset CAPAB */ 540 Servers::Capab.clear(); 541 Servers::Capab.insert("NOQUIT"); 542 IRCD->CanSVSHold = false; 543 } 544 else if (params[0].equals_cs("MODULES") && params.size() > 1) 545 { 546 if (params[1].find("m_globops.so") != Anope::string::npos) 547 Servers::Capab.insert("GLOBOPS"); 548 if (params[1].find("m_services_account.so") != Anope::string::npos) 549 Servers::Capab.insert("SERVICES"); 550 if (params[1].find("m_svshold.so") != Anope::string::npos) 551 IRCD->CanSVSHold = true; 552 if (params[1].find("m_chghost.so") != Anope::string::npos) 553 Servers::Capab.insert("CHGHOST"); 554 if (params[1].find("m_chgident.so") != Anope::string::npos) 555 Servers::Capab.insert("CHGIDENT"); 556 if (params[1].find("m_hidechans.so") != Anope::string::npos) 557 Servers::Capab.insert("HIDECHANS"); 558 if (params[1].find("m_servprotect.so") != Anope::string::npos) 559 IRCD->DefaultPseudoclientModes = "+Ik"; 560 if (params[1].find("m_rline.so") != Anope::string::npos) 561 Servers::Capab.insert("RLINE"); 562 } 563 else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) 564 { 565 spacesepstream ssep(params[1]); 566 Anope::string capab; 567 while (ssep.GetToken(capab)) 568 { 569 if (capab.find("CHANMODES") != Anope::string::npos) 570 { 571 Anope::string modes(capab.begin() + 10, capab.end()); 572 commasepstream sep(modes); 573 Anope::string modebuf; 574 575 sep.GetToken(modebuf); 576 for (size_t t = 0, end = modebuf.length(); t < end; ++t) 577 { 578 switch (modebuf[t]) 579 { 580 case 'b': 581 ModeManager::AddChannelMode(new InspIRCdExtBan("BAN", 'b')); 582 continue; 583 case 'e': 584 ModeManager::AddChannelMode(new InspIRCdExtBan("EXCEPT", 'e')); 585 continue; 586 case 'I': 587 ModeManager::AddChannelMode(new InspIRCdExtBan("INVITEOVERRIDE", 'I')); 588 continue; 589 /* InspIRCd sends q and a here if they have no prefixes */ 590 case 'q': 591 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '@', 4)); 592 continue; 593 case 'a': 594 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT" , 'a', '@', 3)); 595 continue; 596 default: 597 ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t])); 598 } 599 } 600 601 sep.GetToken(modebuf); 602 for (size_t t = 0, end = modebuf.length(); t < end; ++t) 603 { 604 switch (modebuf[t]) 605 { 606 case 'k': 607 ModeManager::AddChannelMode(new ChannelModeKey('k')); 608 continue; 609 default: 610 ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t])); 611 } 612 } 613 614 sep.GetToken(modebuf); 615 for (size_t t = 0, end = modebuf.length(); t < end; ++t) 616 { 617 switch (modebuf[t]) 618 { 619 case 'F': 620 ModeManager::AddChannelMode(new ChannelModeParam("NICKFLOOD", 'F', true)); 621 continue; 622 case 'J': 623 ModeManager::AddChannelMode(new ChannelModeParam("NOREJOIN", 'J', true)); 624 continue; 625 case 'L': 626 ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L', true)); 627 continue; 628 case 'f': 629 ModeManager::AddChannelMode(new ChannelModeFlood('f', true)); 630 continue; 631 case 'j': 632 ModeManager::AddChannelMode(new ChannelModeParam("JOINFLOOD", 'j', true)); 633 continue; 634 case 'l': 635 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true)); 636 continue; 637 default: 638 ModeManager::AddChannelMode(new ChannelModeParam("", modebuf[t], true)); 639 } 640 } 641 642 sep.GetToken(modebuf); 643 for (size_t t = 0, end = modebuf.length(); t < end; ++t) 644 { 645 switch (modebuf[t]) 646 { 647 case 'A': 648 ModeManager::AddChannelMode(new ChannelMode("ALLINVITE", 'A')); 649 continue; 650 case 'B': 651 ModeManager::AddChannelMode(new ChannelMode("BLOCKCAPS", 'B')); 652 continue; 653 case 'C': 654 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C')); 655 continue; 656 case 'D': 657 ModeManager::AddChannelMode(new ChannelMode("DELAYEDJOIN", 'D')); 658 continue; 659 case 'G': 660 ModeManager::AddChannelMode(new ChannelMode("CENSOR", 'G')); 661 continue; 662 case 'K': 663 ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K')); 664 continue; 665 case 'M': 666 ModeManager::AddChannelMode(new ChannelMode("REGMODERATED", 'M')); 667 continue; 668 case 'N': 669 ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N')); 670 continue; 671 case 'O': 672 ModeManager::AddChannelMode(new ChannelModeOperOnly("OPERONLY", 'O')); 673 continue; 674 case 'P': 675 ModeManager::AddChannelMode(new ChannelMode("PERM", 'P')); 676 continue; 677 case 'Q': 678 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q')); 679 continue; 680 case 'R': 681 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R')); 682 continue; 683 case 'S': 684 ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S')); 685 continue; 686 case 'T': 687 ModeManager::AddChannelMode(new ChannelMode("NONOTICE", 'T')); 688 continue; 689 case 'c': 690 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c')); 691 continue; 692 case 'i': 693 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i')); 694 continue; 695 case 'm': 696 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm')); 697 continue; 698 case 'n': 699 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n')); 700 continue; 701 case 'p': 702 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p')); 703 continue; 704 case 'r': 705 ModeManager::AddChannelMode(new ChannelModeNoone("REGISTERED", 'r')); 706 continue; 707 case 's': 708 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's')); 709 continue; 710 case 't': 711 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't')); 712 continue; 713 case 'u': 714 ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u')); 715 continue; 716 case 'z': 717 ModeManager::AddChannelMode(new ChannelMode("SSL", 'z')); 718 continue; 719 default: 720 ModeManager::AddChannelMode(new ChannelMode("", modebuf[t])); 721 } 722 } 723 } 724 else if (capab.find("USERMODES") != Anope::string::npos) 725 { 726 Anope::string modes(capab.begin() + 10, capab.end()); 727 commasepstream sep(modes); 728 Anope::string modebuf; 729 730 while (sep.GetToken(modebuf)) 731 { 732 for (size_t t = 0, end = modebuf.length(); t < end; ++t) 733 { 734 switch (modebuf[t]) 735 { 736 case 'h': 737 ModeManager::AddUserMode(new UserModeOperOnly("HELPOP", 'h')); 738 continue; 739 case 'B': 740 ModeManager::AddUserMode(new UserMode("BOT", 'B')); 741 continue; 742 case 'G': 743 ModeManager::AddUserMode(new UserMode("CENSOR", 'G')); 744 continue; 745 case 'H': 746 ModeManager::AddUserMode(new UserModeOperOnly("HIDEOPER", 'H')); 747 continue; 748 case 'I': 749 ModeManager::AddUserMode(new UserMode("PRIV", 'I')); 750 continue; 751 case 'Q': 752 ModeManager::AddUserMode(new UserModeOperOnly("HIDDEN", 'Q')); 753 continue; 754 case 'R': 755 ModeManager::AddUserMode(new UserMode("REGPRIV", 'R')); 756 continue; 757 case 'S': 758 ModeManager::AddUserMode(new UserMode("STRIPCOLOR", 'S')); 759 continue; 760 case 'W': 761 ModeManager::AddUserMode(new UserMode("WHOIS", 'W')); 762 continue; 763 case 'c': 764 ModeManager::AddUserMode(new UserMode("COMMONCHANS", 'c')); 765 continue; 766 case 'g': 767 ModeManager::AddUserMode(new UserMode("CALLERID", 'g')); 768 continue; 769 case 'i': 770 ModeManager::AddUserMode(new UserMode("INVIS", 'i')); 771 continue; 772 case 'k': 773 ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'k')); 774 continue; 775 case 'o': 776 ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); 777 continue; 778 case 'r': 779 ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r')); 780 continue; 781 case 'w': 782 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w')); 783 continue; 784 case 'x': 785 ModeManager::AddUserMode(new UserMode("CLOAK", 'x')); 786 continue; 787 case 'd': 788 ModeManager::AddUserMode(new UserMode("DEAF", 'd')); 789 continue; 790 default: 791 ModeManager::AddUserMode(new UserMode("", modebuf[t])); 792 } 793 } 794 } 795 } 796 else if (capab.find("PREFIX=(") != Anope::string::npos) 797 { 798 Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); 799 Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); 800 unsigned short level = modes.length() - 1; 801 802 for (size_t t = 0, end = modes.length(); t < end; ++t) 803 { 804 switch (modes[t]) 805 { 806 case 'q': 807 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', chars[t], level--)); 808 continue; 809 case 'a': 810 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', chars[t], level--)); 811 continue; 812 case 'o': 813 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', chars[t], level--)); 814 continue; 815 case 'h': 816 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', chars[t], level--)); 817 continue; 818 case 'v': 819 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', chars[t], level--)); 820 continue; 821 default: 822 ModeManager::AddChannelMode(new ChannelModeStatus("", modes[t], chars[t], level--)); 823 } 824 } 825 826 ModeManager::RebuildStatusModes(); 827 } 828 else if (capab.find("MAXMODES=") != Anope::string::npos) 829 { 830 Anope::string maxmodes(capab.begin() + 9, capab.end()); 831 IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; 832 } 833 } 834 } 835 else if (params[0].equals_cs("END")) 836 { 837 if (!Servers::Capab.count("GLOBOPS")) 838 { 839 UplinkSocket::Message() << "ERROR :m_globops is not loaded. This is required by Anope"; 840 Anope::QuitReason = "Remote server does not have the m_globops module loaded, and this is required."; 841 Anope::Quitting = true; 842 return; 843 } 844 if (!Servers::Capab.count("SERVICES")) 845 { 846 UplinkSocket::Message() << "ERROR :m_services_account.so is not loaded. This is required by Anope"; 847 Anope::QuitReason = "ERROR: Remote server does not have the m_services_account module loaded, and this is required."; 848 Anope::Quitting = true; 849 return; 850 } 851 if (!Servers::Capab.count("HIDECHANS")) 852 { 853 UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope"; 854 Anope::QuitReason = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required."; 855 Anope::Quitting = true; 856 return; 857 } 858 if (!IRCD->CanSVSHold) 859 Log() << "SVSHOLD missing, Usage disabled until module is loaded."; 860 if (!Servers::Capab.count("CHGHOST")) 861 Log() << "CHGHOST missing, Usage disabled until module is loaded."; 862 if (!Servers::Capab.count("CHGIDENT")) 863 Log() << "CHGIDENT missing, Usage disabled until module is loaded."; 864 } 865 866 Message::Capab::Run(source, params); 867 } 868 }; 869 870 struct IRCDMessageChgIdent : IRCDMessage 871 { 872 IRCDMessageChgIdent(Module *creator) : IRCDMessage(creator, "CHGIDENT", 2) { } 873 874 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 875 { 876 User *u = User::Find(params[0]); 877 if (u) 878 u->SetIdent(params[1]); 879 } 880 }; 881 882 struct IRCDMessageChgName : IRCDMessage 883 { 884 IRCDMessageChgName(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 885 886 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 887 { 888 source.GetUser()->SetRealname(params[0]); 889 } 890 }; 891 892 struct IRCDMessageEncap : IRCDMessage 893 { 894 IRCDMessageEncap(Module *creator) : IRCDMessage(creator, "ENCAP", 4) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 895 896 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 897 { 898 if (!Anope::Match(Me->GetSID(), params[0]) && !Anope::Match(Me->GetName(), params[0])) 899 return; 900 901 if (SASL::sasl && params[1] == "SASL" && params.size() >= 6) 902 { 903 SASL::Message m; 904 m.source = params[2]; 905 m.target = params[3]; 906 m.type = params[4]; 907 m.data = params[5]; 908 m.ext = params.size() > 6 ? params[6] : ""; 909 910 SASL::sasl->ProcessMessage(m); 911 } 912 } 913 }; 914 915 struct IRCDMessageEndburst : IRCDMessage 916 { 917 IRCDMessageEndburst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 918 919 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 920 { 921 Server *s = source.GetServer(); 922 923 Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); 924 925 s->Sync(true); 926 } 927 }; 928 929 struct IRCDMessageFHost : IRCDMessage 930 { 931 IRCDMessageFHost(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 932 933 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 934 { 935 source.GetUser()->SetDisplayedHost(params[0]); 936 } 937 }; 938 939 struct IRCDMessageFJoin : IRCDMessage 940 { 941 IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 942 943 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 944 { 945 Anope::string modes; 946 if (params.size() >= 3) 947 { 948 for (unsigned i = 2; i < params.size() - 1; ++i) 949 modes += " " + params[i]; 950 if (!modes.empty()) 951 modes.erase(modes.begin()); 952 } 953 954 std::list<Message::Join::SJoinUser> users; 955 956 spacesepstream sep(params[params.size() - 1]); 957 Anope::string buf; 958 while (sep.GetToken(buf)) 959 { 960 Message::Join::SJoinUser sju; 961 962 /* Loop through prefixes and find modes for them */ 963 for (char c; (c = buf[0]) != ',' && c;) 964 { 965 buf.erase(buf.begin()); 966 sju.first.AddMode(c); 967 } 968 /* Erase the , */ 969 if (!buf.empty()) 970 buf.erase(buf.begin()); 971 972 sju.second = User::Find(buf); 973 if (!sju.second) 974 { 975 Log(LOG_DEBUG) << "FJOIN for nonexistent user " << buf << " on " << params[0]; 976 continue; 977 } 978 979 users.push_back(sju); 980 } 981 982 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; 983 Message::Join::SJoin(source, params[0], ts, modes, users); 984 } 985 }; 986 987 struct IRCDMessageFMode : IRCDMessage 988 { 989 IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 990 991 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 992 { 993 /* :source FMODE #test 12345678 +nto foo */ 994 995 Anope::string modes = params[2]; 996 for (unsigned n = 3; n < params.size(); ++n) 997 modes += " " + params[n]; 998 999 Channel *c = Channel::Find(params[0]); 1000 time_t ts; 1001 1002 try 1003 { 1004 ts = convertTo<time_t>(params[1]); 1005 } 1006 catch (const ConvertException &) 1007 { 1008 ts = 0; 1009 } 1010 1011 if (c) 1012 c->SetModesInternal(source, modes, ts); 1013 } 1014 }; 1015 1016 struct IRCDMessageFTopic : IRCDMessage 1017 { 1018 IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { } 1019 1020 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1021 { 1022 /* :source FTOPIC channel topicts setby :topic */ 1023 1024 Channel *c = Channel::Find(params[0]); 1025 if (c) 1026 c->ChangeTopicInternal(NULL, params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); 1027 } 1028 }; 1029 1030 struct IRCDMessageIdle : IRCDMessage 1031 { 1032 IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { } 1033 1034 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1035 { 1036 BotInfo *bi = BotInfo::Find(params[0]); 1037 if (bi) 1038 UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (Anope::CurTime - bi->lastmsg); 1039 else 1040 { 1041 User *u = User::Find(params[0]); 1042 if (u && u->server == Me) 1043 UplinkSocket::Message(u) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " 0"; 1044 } 1045 } 1046 }; 1047 1048 /* 1049 * source = numeric of the sending server 1050 * params[0] = uuid 1051 * params[1] = metadata name 1052 * params[2] = data 1053 */ 1054 struct IRCDMessageMetadata : IRCDMessage 1055 { 1056 IRCDMessageMetadata(Module *creator) : IRCDMessage(creator, "METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 1057 1058 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1059 { 1060 if (isdigit(params[0][0])) 1061 { 1062 if (params[1].equals_cs("accountname")) 1063 { 1064 User *u = User::Find(params[0]); 1065 NickCore *nc = NickCore::Find(params[2]); 1066 if (u && nc) 1067 u->Login(nc); 1068 } 1069 1070 /* 1071 * possible incoming ssl_cert messages: 1072 * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> 1073 * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) 1074 */ 1075 else if (params[1].equals_cs("ssl_cert")) 1076 { 1077 User *u = User::Find(params[0]); 1078 if (!u) 1079 return; 1080 u->Extend<bool>("ssl"); 1081 Anope::string data = params[2].c_str(); 1082 size_t pos1 = data.find(' ') + 1; 1083 size_t pos2 = data.find(' ', pos1); 1084 if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. 1085 { 1086 u->fingerprint = data.substr(pos1, pos2 - pos1); 1087 } 1088 FOREACH_MOD(OnFingerprint, (u)); 1089 } 1090 } 1091 else if (params[0][0] == '#') 1092 { 1093 } 1094 else if (params[0] == "*") 1095 { 1096 // Wed Oct 3 15:40:27 2012: S[14] O :20D METADATA * modules :-m_svstopic.so 1097 1098 if (params[1].equals_cs("modules") && !params[2].empty()) 1099 { 1100 // only interested when it comes from our uplink 1101 Server* server = source.GetServer(); 1102 if (!server || server->GetUplink() != Me) 1103 return; 1104 1105 bool plus = (params[2][0] == '+'); 1106 if (!plus && params[2][0] != '-') 1107 return; 1108 1109 bool required = false; 1110 Anope::string capab, module = params[2].substr(1); 1111 1112 if (module.equals_cs("m_services_account.so")) 1113 required = true; 1114 else if (module.equals_cs("m_hidechans.so")) 1115 required = true; 1116 else if (module.equals_cs("m_chghost.so")) 1117 capab = "CHGHOST"; 1118 else if (module.equals_cs("m_chgident.so")) 1119 capab = "CHGIDENT"; 1120 else if (module.equals_cs("m_svshold.so")) 1121 capab = "SVSHOLD"; 1122 else if (module.equals_cs("m_rline.so")) 1123 capab = "RLINE"; 1124 else if (module.equals_cs("m_topiclock.so")) 1125 capab = "TOPICLOCK"; 1126 else 1127 return; 1128 1129 if (required) 1130 { 1131 if (!plus) 1132 Log() << "Warning: InspIRCd unloaded module " << module << ", Anope won't function correctly without it"; 1133 } 1134 else 1135 { 1136 if (plus) 1137 Servers::Capab.insert(capab); 1138 else 1139 Servers::Capab.erase(capab); 1140 1141 Log() << "InspIRCd " << (plus ? "loaded" : "unloaded") << " module " << module << ", adjusted functionality"; 1142 } 1143 1144 } 1145 } 1146 } 1147 }; 1148 1149 struct IRCDMessageMode : IRCDMessage 1150 { 1151 IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 1152 1153 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1154 { 1155 if (IRCD->IsChannelValid(params[0])) 1156 { 1157 Channel *c = Channel::Find(params[0]); 1158 1159 Anope::string modes = params[1]; 1160 for (unsigned n = 2; n < params.size(); ++n) 1161 modes += " " + params[n]; 1162 1163 if (c) 1164 c->SetModesInternal(source, modes); 1165 } 1166 else 1167 { 1168 /* InspIRCd lets opers change another 1169 users modes, we have to kludge this 1170 as it slightly breaks RFC1459 1171 */ 1172 User *u = User::Find(params[0]); 1173 if (u) 1174 u->SetModesInternal(source, "%s", params[1].c_str()); 1175 } 1176 } 1177 }; 1178 1179 struct IRCDMessageNick : IRCDMessage 1180 { 1181 IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 1182 1183 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1184 { 1185 source.GetUser()->ChangeNick(params[0]); 1186 } 1187 }; 1188 1189 struct IRCDMessageOperType : IRCDMessage 1190 { 1191 IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } 1192 1193 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1194 { 1195 /* opertype is equivalent to mode +o because servers 1196 don't do this directly */ 1197 User *u = source.GetUser(); 1198 if (!u->HasMode("OPER")) 1199 u->SetModesInternal(source, "+o"); 1200 } 1201 }; 1202 1203 struct IRCDMessageRSQuit : IRCDMessage 1204 { 1205 IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 1206 1207 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1208 { 1209 Server *s = Server::Find(params[0]); 1210 const Anope::string &reason = params.size() > 1 ? params[1] : ""; 1211 if (!s) 1212 return; 1213 1214 UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << reason; 1215 s->Delete(s->GetName() + " " + s->GetUplink()->GetName()); 1216 } 1217 }; 1218 1219 struct IRCDMessageSetIdent : IRCDMessage 1220 { 1221 IRCDMessageSetIdent(Module *creator) : IRCDMessage(creator, "SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } 1222 1223 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1224 { 1225 source.GetUser()->SetIdent(params[0]); 1226 } 1227 }; 1228 1229 struct IRCDMessageServer : IRCDMessage 1230 { 1231 IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } 1232 1233 /* 1234 * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! 1235 * 0: name 1236 * 1: pass 1237 * 2: hops 1238 * 3: numeric 1239 * 4: desc 1240 */ 1241 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1242 { 1243 unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0; 1244 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]); 1245 } 1246 }; 1247 1248 struct IRCDMessageSQuit : Message::SQuit 1249 { 1250 IRCDMessageSQuit(Module *creator) : Message::SQuit(creator) { } 1251 1252 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1253 { 1254 if (params[0] == rsquit_id || params[0] == rsquit_server) 1255 { 1256 /* squit for a recently squit server, introduce the juped server now */ 1257 Server *s = Server::Find(rsquit_server); 1258 1259 rsquit_id.clear(); 1260 rsquit_server.clear(); 1261 1262 if (s && s->IsJuped()) 1263 IRCD->SendServer(s); 1264 } 1265 else 1266 Message::SQuit::Run(source, params); 1267 } 1268 }; 1269 1270 struct IRCDMessageTime : IRCDMessage 1271 { 1272 IRCDMessageTime(Module *creator) : IRCDMessage(creator, "TIME", 2) { } 1273 1274 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1275 { 1276 UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime; 1277 } 1278 }; 1279 1280 struct IRCDMessageUID : IRCDMessage 1281 { 1282 IRCDMessageUID(Module *creator) : IRCDMessage(creator, "UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } 1283 1284 /* 1285 * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> 1286 * 0: uid 1287 * 1: ts 1288 * 2: nick 1289 * 3: host 1290 * 4: dhost 1291 * 5: ident 1292 * 6: ip 1293 * 7: signon 1294 * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! 1295 * last: realname 1296 */ 1297 void Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override 1298 { 1299 time_t ts = convertTo<time_t>(params[1]); 1300 1301 Anope::string modes = params[8]; 1302 for (unsigned i = 9; i < params.size() - 1; ++i) 1303 modes += " " + params[i]; 1304 1305 NickAlias *na = NULL; 1306 if (SASL::sasl) 1307 for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();) 1308 { 1309 SASLUser &u = *it; 1310 1311 if (u.created + 30 < Anope::CurTime) 1312 it = saslusers.erase(it); 1313 else if (u.uid == params[0]) 1314 { 1315 na = NickAlias::Find(u.acc); 1316 it = saslusers.erase(it); 1317 } 1318 else 1319 ++it; 1320 } 1321 1322 User *u = User::OnIntroduce(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0], na ? *na->nc : NULL); 1323 if (u) 1324 u->signon = convertTo<time_t>(params[7]); 1325 } 1326 }; 1327 1328 class ProtoInspIRCd12 : public Module 1329 { 1330 InspIRCd12Proto ircd_proto; 1331 ExtensibleItem<bool> ssl; 1332 1333 /* Core message handlers */ 1334 Message::Away message_away; 1335 Message::Error message_error; 1336 Message::Invite message_invite; 1337 Message::Join message_join; 1338 Message::Kick message_kick; 1339 Message::Kill message_kill; 1340 Message::MOTD message_motd; 1341 Message::Notice message_notice; 1342 Message::Part message_part; 1343 Message::Ping message_ping; 1344 Message::Privmsg message_privmsg; 1345 Message::Quit message_quit; 1346 Message::Stats message_stats; 1347 Message::Topic message_topic; 1348 1349 /* Our message handlers */ 1350 IRCDMessageChgIdent message_chgident; 1351 IRCDMessageChgName message_setname, message_chgname; 1352 IRCDMessageCapab message_capab; 1353 IRCDMessageEncap message_encap; 1354 IRCDMessageEndburst message_endburst; 1355 IRCDMessageFHost message_fhost, message_sethost; 1356 IRCDMessageFJoin message_fjoin; 1357 IRCDMessageFMode message_fmode; 1358 IRCDMessageFTopic message_ftopic; 1359 IRCDMessageIdle message_idle; 1360 IRCDMessageMetadata message_metadata; 1361 IRCDMessageMode message_mode; 1362 IRCDMessageNick message_nick; 1363 IRCDMessageOperType message_opertype; 1364 IRCDMessageRSQuit message_rsquit; 1365 IRCDMessageSetIdent message_setident; 1366 IRCDMessageServer message_server; 1367 IRCDMessageSQuit message_squit; 1368 IRCDMessageTime message_time; 1369 IRCDMessageUID message_uid; 1370 1371 public: 1372 ProtoInspIRCd12(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR), 1373 ircd_proto(this), ssl(this, "ssl"), 1374 message_away(this), message_error(this), message_invite(this), message_join(this), message_kick(this), message_kill(this), 1375 message_motd(this), message_notice(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this), 1376 message_stats(this), message_topic(this), 1377 1378 message_chgident(this), message_setname(this, "SETNAME"), message_chgname(this, "FNAME"), message_capab(this), message_encap(this), 1379 message_endburst(this), 1380 message_fhost(this, "FHOST"), message_sethost(this, "SETHOST"), message_fjoin(this), message_fmode(this), message_ftopic(this), 1381 message_idle(this), message_metadata(this), message_mode(this), message_nick(this), message_opertype(this), message_rsquit(this), 1382 message_setident(this), message_server(this), message_squit(this), message_time(this), message_uid(this) 1383 { 1384 Servers::Capab.insert("NOQUIT"); 1385 } 1386 1387 void OnUserNickChange(User *u, const Anope::string &) anope_override 1388 { 1389 /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later 1390 * this will cancel out this -r, resulting in no mode changes. 1391 * 1392 * Do not set -r if we don't have a NickServ loaded - DP 1393 */ 1394 BotInfo *NickServ = Config->GetClient("NickServ"); 1395 if (NickServ) 1396 u->RemoveMode(NickServ, "REGISTERED"); 1397 } 1398 }; 1399 1400 MODULE_INIT(ProtoInspIRCd12)