anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
ns_set.cpp (42829B)
1 /* NickServ core 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 14 class CommandNSSet : public Command 15 { 16 public: 17 CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3) 18 { 19 this->SetDesc(_("Set options, including kill protection")); 20 this->SetSyntax(_("\037option\037 \037parameters\037")); 21 } 22 23 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 24 { 25 this->OnSyntaxError(source, ""); 26 return; 27 } 28 29 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 30 { 31 this->SendSyntax(source); 32 source.Reply(" "); 33 source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); 34 35 Anope::string this_name = source.command; 36 bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), 37 hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); 38 for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) 39 { 40 const Anope::string &c_name = it->first; 41 const CommandInfo &info = it->second; 42 43 if (c_name.find_ci(this_name + " ") == 0) 44 { 45 if (info.hide) 46 continue; 47 48 ServiceReference<Command> c("Command", info.name); 49 // XXX dup 50 if (!c) 51 continue; 52 else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) 53 continue; 54 else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) 55 continue; 56 57 source.command = c_name; 58 c->OnServHelp(source); 59 } 60 } 61 62 source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" 63 "on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); 64 65 return true; 66 } 67 }; 68 69 class CommandNSSASet : public Command 70 { 71 public: 72 CommandNSSASet(Module *creator) : Command(creator, "nickserv/saset", 2, 4) 73 { 74 this->SetDesc(_("Set SET-options on another nickname")); 75 this->SetSyntax(_("\037option\037 \037nickname\037 \037parameters\037")); 76 } 77 78 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 79 { 80 this->OnSyntaxError(source, ""); 81 return; 82 } 83 84 bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override 85 { 86 this->SendSyntax(source); 87 source.Reply(" "); 88 source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); 89 90 Anope::string this_name = source.command; 91 for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) 92 { 93 const Anope::string &c_name = it->first; 94 const CommandInfo &info = it->second; 95 96 if (c_name.find_ci(this_name + " ") == 0) 97 { 98 ServiceReference<Command> command("Command", info.name); 99 if (command) 100 { 101 source.command = c_name; 102 command->OnServHelp(source); 103 } 104 } 105 } 106 107 source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" 108 "on a specific option. The options will be set on the given\n" 109 "\037nickname\037."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); 110 return true; 111 } 112 }; 113 114 class CommandNSSetPassword : public Command 115 { 116 public: 117 CommandNSSetPassword(Module *creator) : Command(creator, "nickserv/set/password", 1) 118 { 119 this->SetDesc(_("Set your nickname password")); 120 this->SetSyntax(_("\037new-password\037")); 121 } 122 123 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 124 { 125 const Anope::string ¶m = params[0]; 126 unsigned len = param.length(); 127 128 if (Anope::ReadOnly) 129 { 130 source.Reply(READ_ONLY_MODE); 131 return; 132 } 133 134 if (source.GetNick().equals_ci(param) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5)) 135 { 136 source.Reply(MORE_OBSCURE_PASSWORD); 137 return; 138 } 139 140 unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"); 141 if (len > passlen) 142 { 143 source.Reply(PASSWORD_TOO_LONG, passlen); 144 return; 145 } 146 147 Log(LOG_COMMAND, source, this) << "to change their password"; 148 149 Anope::Encrypt(param, source.nc->pass); 150 Anope::string tmp_pass; 151 if (Anope::Decrypt(source.nc->pass, tmp_pass) == 1) 152 source.Reply(_("Password for \002%s\002 changed to \002%s\002."), source.nc->display.c_str(), tmp_pass.c_str()); 153 else 154 source.Reply(_("Password for \002%s\002 changed."), source.nc->display.c_str()); 155 } 156 157 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 158 { 159 this->SendSyntax(source); 160 source.Reply(" "); 161 source.Reply(_("Changes the password used to identify you as the nick's\n" 162 "owner.")); 163 return true; 164 } 165 }; 166 167 class CommandNSSASetPassword : public Command 168 { 169 public: 170 CommandNSSASetPassword(Module *creator) : Command(creator, "nickserv/saset/password", 2, 2) 171 { 172 this->SetDesc(_("Set the nickname password")); 173 this->SetSyntax(_("\037nickname\037 \037new-password\037")); 174 } 175 176 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 177 { 178 if (Anope::ReadOnly) 179 { 180 source.Reply(READ_ONLY_MODE); 181 return; 182 } 183 184 const NickAlias *setter_na = NickAlias::Find(params[0]); 185 if (setter_na == NULL) 186 { 187 source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); 188 return; 189 } 190 NickCore *nc = setter_na->nc; 191 192 size_t len = params[1].length(); 193 194 if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper()) 195 { 196 source.Reply(_("You may not change the password of other Services Operators.")); 197 return; 198 } 199 200 if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5)) 201 { 202 source.Reply(MORE_OBSCURE_PASSWORD); 203 return; 204 } 205 206 unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"); 207 if (len > passlen) 208 { 209 source.Reply(PASSWORD_TOO_LONG, passlen); 210 return; 211 } 212 213 Log(LOG_ADMIN, source, this) << "to change the password of " << nc->display; 214 215 Anope::Encrypt(params[1], nc->pass); 216 Anope::string tmp_pass; 217 if (Anope::Decrypt(nc->pass, tmp_pass) == 1) 218 source.Reply(_("Password for \002%s\002 changed to \002%s\002."), nc->display.c_str(), tmp_pass.c_str()); 219 else 220 source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str()); 221 } 222 223 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 224 { 225 this->SendSyntax(source); 226 source.Reply(" "); 227 source.Reply(_("Changes the password used to identify as the nick's owner.")); 228 return true; 229 } 230 }; 231 232 class CommandNSSetAutoOp : public Command 233 { 234 public: 235 CommandNSSetAutoOp(Module *creator, const Anope::string &sname = "nickserv/set/autoop", size_t min = 1) : Command(creator, sname, min, min + 1) 236 { 237 this->SetDesc(_("Sets whether services should set channel status modes on you automatically.")); 238 this->SetSyntax("{ON | OFF}"); 239 } 240 241 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 242 { 243 if (Anope::ReadOnly) 244 { 245 source.Reply(READ_ONLY_MODE); 246 return; 247 } 248 249 const NickAlias *na = NickAlias::Find(user); 250 if (na == NULL) 251 { 252 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 253 return; 254 } 255 NickCore *nc = na->nc; 256 257 EventReturn MOD_RESULT; 258 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 259 if (MOD_RESULT == EVENT_STOP) 260 return; 261 262 if (param.equals_ci("ON")) 263 { 264 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable autoop for " << na->nc->display; 265 nc->Extend<bool>("AUTOOP"); 266 source.Reply(_("Services will from now on set status modes on %s in channels."), nc->display.c_str()); 267 } 268 else if (param.equals_ci("OFF")) 269 { 270 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable autoop for " << na->nc->display; 271 nc->Shrink<bool>("AUTOOP"); 272 source.Reply(_("Services will no longer set status modes on %s in channels."), nc->display.c_str()); 273 } 274 else 275 this->OnSyntaxError(source, "AUTOOP"); 276 } 277 278 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 279 { 280 this->Run(source, source.nc->display, params[0]); 281 } 282 283 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 284 { 285 BotInfo *bi = Config->GetClient("ChanServ"); 286 this->SendSyntax(source); 287 source.Reply(" "); 288 source.Reply(_("Sets whether you will be given your channel status modes automatically.\n" 289 "Set to \002ON\002 to allow %s to set status modes on you automatically\n" 290 "when entering channels. Note that depending on channel settings some modes\n" 291 "may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ"); 292 return true; 293 } 294 }; 295 296 class CommandNSSASetAutoOp : public CommandNSSetAutoOp 297 { 298 public: 299 CommandNSSASetAutoOp(Module *creator) : CommandNSSetAutoOp(creator, "nickserv/saset/autoop", 2) 300 { 301 this->ClearSyntax(); 302 this->SetSyntax(_("\037nickname\037 {ON | OFF}")); 303 } 304 305 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 306 { 307 this->Run(source, params[0], params[1]); 308 } 309 310 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 311 { 312 BotInfo *bi = Config->GetClient("ChanServ"); 313 this->SendSyntax(source); 314 source.Reply(" "); 315 source.Reply(_("Sets whether the given nickname will be given its status modes\n" 316 "in channels automatically. Set to \002ON\002 to allow %s\n" 317 "to set status modes on the given nickname automatically when it\n" 318 "is entering channels. Note that depending on channel settings\n" 319 "some modes may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ"); 320 return true; 321 } 322 }; 323 324 class CommandNSSetDisplay : public Command 325 { 326 public: 327 CommandNSSetDisplay(Module *creator, const Anope::string &sname = "nickserv/set/display", size_t min = 1) : Command(creator, sname, min, min + 1) 328 { 329 this->SetDesc(_("Set the display of your group in Services")); 330 this->SetSyntax(_("\037new-display\037")); 331 } 332 333 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 334 { 335 if (Anope::ReadOnly) 336 { 337 source.Reply(READ_ONLY_MODE); 338 return; 339 } 340 341 NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param); 342 343 if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) 344 { 345 source.Reply(_("This command may not be used on this network because nickname ownership is disabled.")); 346 return; 347 } 348 if (user_na == NULL) 349 { 350 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 351 return; 352 } 353 else if (!na || *na->nc != *user_na->nc) 354 { 355 source.Reply(_("The new display MUST be a nickname of the nickname group %s."), user_na->nc->display.c_str()); 356 return; 357 } 358 359 EventReturn MOD_RESULT; 360 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, user_na->nc, param)); 361 if (MOD_RESULT == EVENT_STOP) 362 return; 363 364 Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick; 365 366 user_na->nc->SetDisplay(na); 367 368 /* Send updated account name */ 369 for (std::list<User *>::iterator it = user_na->nc->users.begin(); it != user_na->nc->users.end(); ++it) 370 { 371 User *u = *it; 372 IRCD->SendLogin(u, user_na); 373 } 374 375 source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str()); 376 } 377 378 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 379 { 380 this->Run(source, source.nc->display, params[0]); 381 } 382 383 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 384 { 385 this->SendSyntax(source); 386 source.Reply(" "); 387 source.Reply(_("Changes the display used to refer to your nickname group in\n" 388 "Services. The new display MUST be a nick of your group.")); 389 return true; 390 } 391 }; 392 393 class CommandNSSASetDisplay : public CommandNSSetDisplay 394 { 395 public: 396 CommandNSSASetDisplay(Module *creator) : CommandNSSetDisplay(creator, "nickserv/saset/display", 2) 397 { 398 this->ClearSyntax(); 399 this->SetSyntax(_("\037nickname\037 \037new-display\037")); 400 } 401 402 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 403 { 404 this->Run(source, params[0], params[1]); 405 } 406 407 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 408 { 409 this->SendSyntax(source); 410 source.Reply(" "); 411 source.Reply(_("Changes the display used to refer to the nickname group in\n" 412 "Services. The new display MUST be a nick of the group.")); 413 return true; 414 } 415 }; 416 417 class CommandNSSetEmail : public Command 418 { 419 static bool SendConfirmMail(User *u, NickCore *nc, BotInfo *bi, const Anope::string &new_email) 420 { 421 Anope::string code = Anope::Random(9); 422 423 std::pair<Anope::string, Anope::string> *n = nc->Extend<std::pair<Anope::string, Anope::string> >("ns_set_email"); 424 n->first = new_email; 425 n->second = code; 426 427 Anope::string subject = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_subject"), 428 message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message"); 429 430 subject = subject.replace_all_cs("%e", nc->email); 431 subject = subject.replace_all_cs("%E", new_email); 432 subject = subject.replace_all_cs("%n", nc->display); 433 subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); 434 subject = subject.replace_all_cs("%c", code); 435 436 message = message.replace_all_cs("%e", nc->email); 437 message = message.replace_all_cs("%E", new_email); 438 message = message.replace_all_cs("%n", nc->display); 439 message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); 440 message = message.replace_all_cs("%c", code); 441 442 Anope::string old = nc->email; 443 nc->email = new_email; 444 bool b = Mail::Send(u, nc, bi, subject, message); 445 nc->email = old; 446 return b; 447 } 448 449 public: 450 CommandNSSetEmail(Module *creator, const Anope::string &cname = "nickserv/set/email", size_t min = 0) : Command(creator, cname, min, min + 1) 451 { 452 this->SetDesc(_("Associate an E-mail address with your nickname")); 453 this->SetSyntax(_("\037address\037")); 454 } 455 456 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 457 { 458 if (Anope::ReadOnly) 459 { 460 source.Reply(READ_ONLY_MODE); 461 return; 462 } 463 464 const NickAlias *na = NickAlias::Find(user); 465 if (!na) 466 { 467 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 468 return; 469 } 470 NickCore *nc = na->nc; 471 472 if (nc->HasExt("UNCONFIRMED")) 473 { 474 source.Reply(_("You may not change the email of an unconfirmed account.")); 475 return; 476 } 477 478 if (param.empty() && Config->GetModule("nickserv")->Get<bool>("forceemail", "yes")) 479 { 480 source.Reply(_("You cannot unset the e-mail on this network.")); 481 return; 482 } 483 else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper()) 484 { 485 source.Reply(_("You may not change the e-mail of other Services Operators.")); 486 return; 487 } 488 else if (!param.empty() && !Mail::Validate(param)) 489 { 490 source.Reply(MAIL_X_INVALID, param.c_str()); 491 return; 492 } 493 494 EventReturn MOD_RESULT; 495 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 496 if (MOD_RESULT == EVENT_STOP) 497 return; 498 499 if (!param.empty() && Config->GetModule("nickserv")->Get<bool>("confirmemailchanges") && !source.IsServicesOper()) 500 { 501 if (SendConfirmMail(source.GetUser(), source.GetAccount(), source.service, param)) 502 { 503 Log(LOG_COMMAND, source, this) << "to request changing the email of " << nc->display << " to " << param; 504 source.Reply(_("A confirmation e-mail has been sent to \002%s\002. Follow the instructions in it to change your e-mail address."), param.c_str()); 505 } 506 } 507 else 508 { 509 if (!param.empty()) 510 { 511 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the email of " << nc->display << " to " << param; 512 nc->email = param; 513 source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str()); 514 } 515 else 516 { 517 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the email of " << nc->display; 518 nc->email.clear(); 519 source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str()); 520 } 521 } 522 } 523 524 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 525 { 526 this->Run(source, source.nc->display, params.size() ? params[0] : ""); 527 } 528 529 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 530 { 531 this->SendSyntax(source); 532 source.Reply(" "); 533 source.Reply(_("Associates the given E-mail address with your nickname.\n" 534 "This address will be displayed whenever someone requests\n" 535 "information on the nickname with the \002INFO\002 command.")); 536 return true; 537 } 538 }; 539 540 class CommandNSSASetEmail : public CommandNSSetEmail 541 { 542 public: 543 CommandNSSASetEmail(Module *creator) : CommandNSSetEmail(creator, "nickserv/saset/email", 2) 544 { 545 this->ClearSyntax(); 546 this->SetSyntax(_("\037nickname\037 \037address\037")); 547 } 548 549 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 550 { 551 this->Run(source, params[0], params.size() > 1 ? params[1] : ""); 552 } 553 554 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 555 { 556 this->SendSyntax(source); 557 source.Reply(" "); 558 source.Reply(_("Associates the given E-mail address with the nickname.")); 559 return true; 560 } 561 }; 562 563 class CommandNSSetKeepModes : public Command 564 { 565 public: 566 CommandNSSetKeepModes(Module *creator, const Anope::string &sname = "nickserv/set/keepmodes", size_t min = 1) : Command(creator, sname, min, min + 1) 567 { 568 this->SetDesc(_("Enable or disable keep modes")); 569 this->SetSyntax("{ON | OFF}"); 570 } 571 572 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 573 { 574 if (Anope::ReadOnly) 575 { 576 source.Reply(READ_ONLY_MODE); 577 return; 578 } 579 580 const NickAlias *na = NickAlias::Find(user); 581 if (!na) 582 { 583 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 584 return; 585 } 586 NickCore *nc = na->nc; 587 588 EventReturn MOD_RESULT; 589 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 590 if (MOD_RESULT == EVENT_STOP) 591 return; 592 593 if (param.equals_ci("ON")) 594 { 595 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable keepmodes for " << nc->display; 596 nc->Extend<bool>("NS_KEEP_MODES"); 597 source.Reply(_("Keep modes for %s is now \002on\002."), nc->display.c_str()); 598 } 599 else if (param.equals_ci("OFF")) 600 { 601 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable keepmodes for " << nc->display; 602 nc->Shrink<bool>("NS_KEEP_MODES"); 603 source.Reply(_("Keep modes for %s is now \002off\002."), nc->display.c_str()); 604 } 605 else 606 this->OnSyntaxError(source, ""); 607 } 608 609 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 610 { 611 this->Run(source, source.nc->display, params[0]); 612 } 613 614 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 615 { 616 this->SendSyntax(source); 617 source.Reply(" "); 618 source.Reply(_("Enables or disables keepmodes for your nick. If keep\n" 619 "modes is enabled, services will remember your usermodes\n" 620 "and attempt to re-set them the next time you authenticate.")); 621 return true; 622 } 623 }; 624 625 class CommandNSSASetKeepModes : public CommandNSSetKeepModes 626 { 627 public: 628 CommandNSSASetKeepModes(Module *creator) : CommandNSSetKeepModes(creator, "nickserv/saset/keepmodes", 2) 629 { 630 this->ClearSyntax(); 631 this->SetSyntax(_("\037nickname\037 {ON | OFF}")); 632 } 633 634 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 635 { 636 this->Run(source, params[0], params[1]); 637 } 638 639 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 640 { 641 this->SendSyntax(source); 642 source.Reply(" "); 643 source.Reply(_("Enables or disables keepmodes for the given nick. If keep\n" 644 "modes is enabled, services will remember users' usermodes\n" 645 "and attempt to re-set them the next time they authenticate.")); 646 return true; 647 } 648 }; 649 650 class CommandNSSetKill : public Command 651 { 652 public: 653 CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1) : Command(creator, sname, min, min + 1) 654 { 655 this->SetDesc(_("Turn protection on or off")); 656 this->SetSyntax("{ON | QUICK | IMMED | OFF}"); 657 } 658 659 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 660 { 661 if (Anope::ReadOnly) 662 { 663 source.Reply(READ_ONLY_MODE); 664 return; 665 } 666 667 if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) 668 { 669 source.Reply(_("This command may not be used on this network because nickname ownership is disabled.")); 670 return; 671 } 672 673 const NickAlias *na = NickAlias::Find(user); 674 if (!na) 675 { 676 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 677 return; 678 } 679 NickCore *nc = na->nc; 680 681 EventReturn MOD_RESULT; 682 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 683 if (MOD_RESULT == EVENT_STOP) 684 return; 685 686 if (param.equals_ci("ON")) 687 { 688 nc->Extend<bool>("KILLPROTECT"); 689 nc->Shrink<bool>("KILL_QUICK"); 690 nc->Shrink<bool>("KILL_IMMED"); 691 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display; 692 source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str()); 693 } 694 else if (param.equals_ci("QUICK")) 695 { 696 nc->Extend<bool>("KILLPROTECT"); 697 nc->Extend<bool>("KILL_QUICK"); 698 nc->Shrink<bool>("KILL_IMMED"); 699 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display; 700 source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str()); 701 } 702 else if (param.equals_ci("IMMED")) 703 { 704 if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed")) 705 { 706 nc->Extend<bool>("KILLPROTECT"); 707 nc->Shrink<bool>("KILL_QUICK"); 708 nc->Extend<bool>("KILL_IMMED"); 709 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display; 710 source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str()); 711 } 712 else 713 source.Reply(_("The \002IMMED\002 option is not available on this network.")); 714 } 715 else if (param.equals_ci("OFF")) 716 { 717 nc->Shrink<bool>("KILLPROTECT"); 718 nc->Shrink<bool>("KILL_QUICK"); 719 nc->Shrink<bool>("KILL_IMMED"); 720 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display; 721 source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str()); 722 } 723 else 724 this->OnSyntaxError(source, "KILL"); 725 726 return; 727 } 728 729 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 730 { 731 this->Run(source, source.nc->display, params[0]); 732 } 733 734 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 735 { 736 this->SendSyntax(source); 737 source.Reply(" "); 738 source.Reply(_("Turns the automatic protection option for your nick\n" 739 "on or off. With protection on, if another user\n" 740 "tries to take your nick, they will be given one minute to\n" 741 "change to another nick, after which %s will forcibly change\n" 742 "their nick.\n" 743 " \n" 744 "If you select \002QUICK\002, the user will be given only 20 seconds\n" 745 "to change nicks instead of the usual 60. If you select\n" 746 "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" 747 "warned first or given a chance to change their nick; please\n" 748 "do not use this option unless necessary. Also, your\n" 749 "network's administrators may have disabled this option."), source.service->nick.c_str()); 750 return true; 751 } 752 }; 753 754 class CommandNSSASetKill : public CommandNSSetKill 755 { 756 public: 757 CommandNSSASetKill(Module *creator) : CommandNSSetKill(creator, "nickserv/saset/kill", 2) 758 { 759 this->ClearSyntax(); 760 this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}")); 761 } 762 763 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 764 { 765 this->Run(source, params[0], params[1]); 766 } 767 768 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 769 { 770 this->SendSyntax(source); 771 source.Reply(" "); 772 source.Reply(_("Turns the automatic protection option for the nick\n" 773 "on or off. With protection on, if another user\n" 774 "tries to take the nick, they will be given one minute to\n" 775 "change to another nick, after which %s will forcibly change\n" 776 "their nick.\n" 777 " \n" 778 "If you select \002QUICK\002, the user will be given only 20 seconds\n" 779 "to change nicks instead of the usual 60. If you select\n" 780 "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" 781 "warned first or given a chance to change their nick; please\n" 782 "do not use this option unless necessary. Also, your\n" 783 "network's administrators may have disabled this option."), source.service->nick.c_str()); 784 return true; 785 } 786 }; 787 788 class CommandNSSetLanguage : public Command 789 { 790 public: 791 CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1) : Command(creator, sname, min, min + 1) 792 { 793 this->SetDesc(_("Set the language Services will use when messaging you")); 794 this->SetSyntax(_("\037language\037")); 795 } 796 797 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 798 { 799 if (Anope::ReadOnly) 800 { 801 source.Reply(READ_ONLY_MODE); 802 return; 803 } 804 805 const NickAlias *na = NickAlias::Find(user); 806 if (!na) 807 { 808 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 809 return; 810 } 811 NickCore *nc = na->nc; 812 813 EventReturn MOD_RESULT; 814 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 815 if (MOD_RESULT == EVENT_STOP) 816 return; 817 818 if (param != "en_US") 819 for (unsigned j = 0; j < Language::Languages.size(); ++j) 820 { 821 if (Language::Languages[j] == param) 822 break; 823 else if (j + 1 == Language::Languages.size()) 824 { 825 this->OnSyntaxError(source, ""); 826 return; 827 } 828 } 829 830 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << param; 831 832 nc->language = param; 833 if (source.GetAccount() == nc) 834 source.Reply(_("Language changed to \002English\002.")); 835 else 836 source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), Language::Translate(param.c_str(), _("English"))); 837 } 838 839 void Execute(CommandSource &source, const std::vector<Anope::string> ¶m) anope_override 840 { 841 this->Run(source, source.nc->display, param[0]); 842 } 843 844 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 845 { 846 this->SendSyntax(source); 847 source.Reply(" "); 848 source.Reply(_("Changes the language Services uses when sending messages to\n" 849 "you (for example, when responding to a command you send).\n" 850 "\037language\037 should be chosen from the following list of\n" 851 "supported languages:")); 852 853 source.Reply(" en_US (English)"); 854 for (unsigned j = 0; j < Language::Languages.size(); ++j) 855 { 856 const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English")); 857 if (langname == "English") 858 continue; 859 source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str()); 860 } 861 862 return true; 863 } 864 }; 865 866 class CommandNSSASetLanguage : public CommandNSSetLanguage 867 { 868 public: 869 CommandNSSASetLanguage(Module *creator) : CommandNSSetLanguage(creator, "nickserv/saset/language", 2) 870 { 871 this->ClearSyntax(); 872 this->SetSyntax(_("\037nickname\037 \037language\037")); 873 } 874 875 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 876 { 877 this->Run(source, params[0], params[1]); 878 } 879 880 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 881 { 882 this->SendSyntax(source); 883 source.Reply(" "); 884 source.Reply(_("Changes the language Services uses when sending messages to\n" 885 "the given user (for example, when responding to a command they send).\n" 886 "\037language\037 should be chosen from the following list of\n" 887 "supported languages:")); 888 source.Reply(" en (English)"); 889 for (unsigned j = 0; j < Language::Languages.size(); ++j) 890 { 891 const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English")); 892 if (langname == "English") 893 continue; 894 source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str()); 895 } 896 return true; 897 } 898 }; 899 900 class CommandNSSetMessage : public Command 901 { 902 public: 903 CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1) : Command(creator, sname, min, min + 1) 904 { 905 this->SetDesc(_("Change the communication method of Services")); 906 this->SetSyntax("{ON | OFF}"); 907 } 908 909 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 910 { 911 if (Anope::ReadOnly) 912 { 913 source.Reply(READ_ONLY_MODE); 914 return; 915 } 916 917 const NickAlias *na = NickAlias::Find(user); 918 if (!na) 919 { 920 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 921 return; 922 } 923 NickCore *nc = na->nc; 924 925 if (!Config->GetBlock("options")->Get<bool>("useprivmsg")) 926 { 927 source.Reply(_("You cannot %s on this network."), source.command.c_str()); 928 return; 929 } 930 931 EventReturn MOD_RESULT; 932 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 933 if (MOD_RESULT == EVENT_STOP) 934 return; 935 936 if (param.equals_ci("ON")) 937 { 938 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display; 939 nc->Extend<bool>("MSG"); 940 source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str()); 941 } 942 else if (param.equals_ci("OFF")) 943 { 944 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display; 945 nc->Shrink<bool>("MSG"); 946 source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str()); 947 } 948 else 949 this->OnSyntaxError(source, "MSG"); 950 } 951 952 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 953 { 954 this->Run(source, source.nc->display, params[0]); 955 } 956 957 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 958 { 959 Anope::string cmd = source.command; 960 size_t i = cmd.find_last_of(' '); 961 if (i != Anope::string::npos) 962 cmd = cmd.substr(i + 1); 963 964 this->SendSyntax(source); 965 source.Reply(" "); 966 source.Reply(_("Allows you to choose the way Services are communicating with\n" 967 "you. With \002%s\002 set, Services will use messages, else they'll\n" 968 "use notices."), cmd.upper().c_str()); 969 return true; 970 } 971 972 void OnServHelp(CommandSource &source) anope_override 973 { 974 if (Config->GetBlock("options")->Get<bool>("useprivmsg")) 975 Command::OnServHelp(source); 976 } 977 }; 978 979 class CommandNSSASetMessage : public CommandNSSetMessage 980 { 981 public: 982 CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2) 983 { 984 this->ClearSyntax(); 985 this->SetSyntax(_("\037nickname\037 {ON | OFF}")); 986 } 987 988 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 989 { 990 this->SendSyntax(source); 991 source.Reply(" "); 992 source.Reply(_("Allows you to choose the way Services are communicating with\n" 993 "the given user. With \002MSG\002 set, Services will use messages,\n" 994 "else they'll use notices.")); 995 return true; 996 } 997 998 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 999 { 1000 this->Run(source, params[0], params[1]); 1001 } 1002 }; 1003 1004 class CommandNSSetSecure : public Command 1005 { 1006 public: 1007 CommandNSSetSecure(Module *creator, const Anope::string &sname = "nickserv/set/secure", size_t min = 1) : Command(creator, sname, min, min + 1) 1008 { 1009 this->SetDesc(_("Turn nickname security on or off")); 1010 this->SetSyntax("{ON | OFF}"); 1011 } 1012 1013 void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) 1014 { 1015 if (Anope::ReadOnly) 1016 { 1017 source.Reply(READ_ONLY_MODE); 1018 return; 1019 } 1020 1021 const NickAlias *na = NickAlias::Find(user); 1022 if (!na) 1023 { 1024 source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); 1025 return; 1026 } 1027 NickCore *nc = na->nc; 1028 1029 EventReturn MOD_RESULT; 1030 FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); 1031 if (MOD_RESULT == EVENT_STOP) 1032 return; 1033 1034 if (param.equals_ci("ON")) 1035 { 1036 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable secure for " << nc->display; 1037 nc->Extend<bool>("NS_SECURE"); 1038 source.Reply(_("Secure option is now \002on\002 for \002%s\002."), nc->display.c_str()); 1039 } 1040 else if (param.equals_ci("OFF")) 1041 { 1042 Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable secure for " << nc->display; 1043 nc->Shrink<bool>("NS_SECURE"); 1044 source.Reply(_("Secure option is now \002off\002 for \002%s\002."), nc->display.c_str()); 1045 } 1046 else 1047 this->OnSyntaxError(source, "SECURE"); 1048 } 1049 1050 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 1051 { 1052 this->Run(source, source.nc->display, params[0]); 1053 } 1054 1055 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 1056 { 1057 this->SendSyntax(source); 1058 source.Reply(" "); 1059 source.Reply(_("Turns %s's security features on or off for your\n" 1060 "nick. With \002SECURE\002 set, you must enter your password\n" 1061 "before you will be recognized as the owner of the nick,\n" 1062 "regardless of whether your address is on the access\n" 1063 "list. However, if you are on the access list, %s\n" 1064 "will not auto-kill you regardless of the setting of the\n" 1065 "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str()); 1066 return true; 1067 } 1068 }; 1069 1070 class CommandNSSASetSecure : public CommandNSSetSecure 1071 { 1072 public: 1073 CommandNSSASetSecure(Module *creator) : CommandNSSetSecure(creator, "nickserv/saset/secure", 2) 1074 { 1075 this->ClearSyntax(); 1076 this->SetSyntax(_("\037nickname\037 {ON | OFF}")); 1077 } 1078 1079 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 1080 { 1081 this->Run(source, params[0], params[1]); 1082 } 1083 1084 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 1085 { 1086 this->SendSyntax(source); 1087 source.Reply(" "); 1088 source.Reply(_("Turns %s's security features on or off for your\n" 1089 "nick. With \002SECURE\002 set, you must enter your password\n" 1090 "before you will be recognized as the owner of the nick,\n" 1091 "regardless of whether your address is on the access\n" 1092 "list. However, if you are on the access list, %s\n" 1093 "will not auto-kill you regardless of the setting of the\n" 1094 "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str()); 1095 return true; 1096 } 1097 }; 1098 1099 class CommandNSSASetNoexpire : public Command 1100 { 1101 public: 1102 CommandNSSASetNoexpire(Module *creator) : Command(creator, "nickserv/saset/noexpire", 1, 2) 1103 { 1104 this->SetDesc(_("Prevent the nickname from expiring")); 1105 this->SetSyntax(_("\037nickname\037 {ON | OFF}")); 1106 } 1107 1108 void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override 1109 { 1110 if (Anope::ReadOnly) 1111 { 1112 source.Reply(READ_ONLY_MODE); 1113 return; 1114 } 1115 1116 NickAlias *na = NickAlias::Find(params[0]); 1117 if (na == NULL) 1118 { 1119 source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); 1120 return; 1121 } 1122 1123 Anope::string param = params.size() > 1 ? params[1] : ""; 1124 1125 if (param.equals_ci("ON")) 1126 { 1127 Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nick << " (" << na->nc->display << ")"; 1128 na->Extend<bool>("NS_NO_EXPIRE"); 1129 source.Reply(_("Nick %s \002will not\002 expire."), na->nick.c_str()); 1130 } 1131 else if (param.equals_ci("OFF")) 1132 { 1133 Log(LOG_ADMIN, source, this) << "to disable noexpire for " << na->nick << " (" << na->nc->display << ")"; 1134 na->Shrink<bool>("NS_NO_EXPIRE"); 1135 source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str()); 1136 } 1137 else 1138 this->OnSyntaxError(source, "NOEXPIRE"); 1139 } 1140 1141 bool OnHelp(CommandSource &source, const Anope::string &) anope_override 1142 { 1143 this->SendSyntax(source); 1144 source.Reply(" "); 1145 source.Reply(_("Sets whether the given nickname will expire. Setting this\n" 1146 "to \002ON\002 prevents the nickname from expiring.")); 1147 return true; 1148 } 1149 }; 1150 1151 class NSSet : public Module 1152 { 1153 CommandNSSet commandnsset; 1154 CommandNSSASet commandnssaset; 1155 1156 CommandNSSetAutoOp commandnssetautoop; 1157 CommandNSSASetAutoOp commandnssasetautoop; 1158 1159 CommandNSSetDisplay commandnssetdisplay; 1160 CommandNSSASetDisplay commandnssasetdisplay; 1161 1162 CommandNSSetEmail commandnssetemail; 1163 CommandNSSASetEmail commandnssasetemail; 1164 1165 CommandNSSetKeepModes commandnssetkeepmodes; 1166 CommandNSSASetKeepModes commandnssasetkeepmodes; 1167 1168 CommandNSSetKill commandnssetkill; 1169 CommandNSSASetKill commandnssasetkill; 1170 1171 CommandNSSetLanguage commandnssetlanguage; 1172 CommandNSSASetLanguage commandnssasetlanguage; 1173 1174 CommandNSSetMessage commandnssetmessage; 1175 CommandNSSASetMessage commandnssasetmessage; 1176 1177 CommandNSSetPassword commandnssetpassword; 1178 CommandNSSASetPassword commandnssasetpassword; 1179 1180 CommandNSSetSecure commandnssetsecure; 1181 CommandNSSASetSecure commandnssasetsecure; 1182 1183 CommandNSSASetNoexpire commandnssasetnoexpire; 1184 1185 SerializableExtensibleItem<bool> autoop, killprotect, kill_quick, kill_immed, 1186 message, secure, noexpire; 1187 1188 struct KeepModes : SerializableExtensibleItem<bool> 1189 { 1190 KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { } 1191 1192 void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override 1193 { 1194 SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data); 1195 1196 if (s->GetSerializableType()->GetName() != "NickCore") 1197 return; 1198 1199 const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(s); 1200 Anope::string modes; 1201 for (User::ModeList::const_iterator it = nc->last_modes.begin(); it != nc->last_modes.end(); ++it) 1202 { 1203 if (!modes.empty()) 1204 modes += " "; 1205 modes += it->first; 1206 if (!it->second.empty()) 1207 modes += "," + it->second; 1208 } 1209 data["last_modes"] << modes; 1210 } 1211 1212 void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override 1213 { 1214 SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data); 1215 1216 if (s->GetSerializableType()->GetName() != "NickCore") 1217 return; 1218 1219 NickCore *nc = anope_dynamic_static_cast<NickCore *>(s); 1220 Anope::string modes; 1221 data["last_modes"] >> modes; 1222 nc->last_modes.clear(); 1223 for (spacesepstream sep(modes); sep.GetToken(modes);) 1224 { 1225 size_t c = modes.find(','); 1226 if (c == Anope::string::npos) 1227 nc->last_modes.insert(std::make_pair(modes, "")); 1228 else 1229 nc->last_modes.insert(std::make_pair(modes.substr(0, c), modes.substr(c + 1))); 1230 } 1231 } 1232 } keep_modes; 1233 1234 /* email, passcode */ 1235 PrimitiveExtensibleItem<std::pair<Anope::string, Anope::string > > ns_set_email; 1236 1237 public: 1238 NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), 1239 commandnsset(this), commandnssaset(this), 1240 commandnssetautoop(this), commandnssasetautoop(this), 1241 commandnssetdisplay(this), commandnssasetdisplay(this), 1242 commandnssetemail(this), commandnssasetemail(this), 1243 commandnssetkeepmodes(this), commandnssasetkeepmodes(this), 1244 commandnssetkill(this), commandnssasetkill(this), 1245 commandnssetlanguage(this), commandnssasetlanguage(this), 1246 commandnssetmessage(this), commandnssasetmessage(this), 1247 commandnssetpassword(this), commandnssasetpassword(this), 1248 commandnssetsecure(this), commandnssasetsecure(this), 1249 commandnssasetnoexpire(this), 1250 1251 autoop(this, "AUTOOP"), 1252 killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"), 1253 kill_immed(this, "KILL_IMMED"), message(this, "MSG"), 1254 secure(this, "NS_SECURE"), noexpire(this, "NS_NO_EXPIRE"), 1255 1256 keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email") 1257 { 1258 1259 } 1260 1261 EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override 1262 { 1263 NickCore *uac = source.nc; 1264 1265 if (command->name == "nickserv/confirm" && !params.empty() && uac) 1266 { 1267 std::pair<Anope::string, Anope::string> *n = ns_set_email.Get(uac); 1268 if (n) 1269 { 1270 if (params[0] == n->second) 1271 { 1272 uac->email = n->first; 1273 Log(LOG_COMMAND, source, command) << "to confirm their email address change to " << uac->email; 1274 source.Reply(_("Your email address has been changed to \002%s\002."), uac->email.c_str()); 1275 ns_set_email.Unset(uac); 1276 return EVENT_STOP; 1277 } 1278 } 1279 } 1280 1281 return EVENT_CONTINUE; 1282 } 1283 1284 void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override 1285 { 1286 if (chan->ci) 1287 { 1288 /* Only give modes if autoop is set */ 1289 give_modes &= !user->Account() || autoop.HasExt(user->Account()); 1290 } 1291 } 1292 1293 void OnPreNickExpire(NickAlias *na, bool &expire) anope_override 1294 { 1295 if (noexpire.HasExt(na)) 1296 expire = false; 1297 } 1298 1299 void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override 1300 { 1301 if (!show_hidden) 1302 return; 1303 1304 if (kill_immed.HasExt(na->nc)) 1305 info.AddOption(_("Immediate protection")); 1306 else if (kill_quick.HasExt(na->nc)) 1307 info.AddOption(_("Quick protection")); 1308 else if (killprotect.HasExt(na->nc)) 1309 info.AddOption(_("Protection")); 1310 if (secure.HasExt(na->nc)) 1311 info.AddOption(_("Security")); 1312 if (message.HasExt(na->nc)) 1313 info.AddOption(_("Message mode")); 1314 if (autoop.HasExt(na->nc)) 1315 info.AddOption(_("Auto-op")); 1316 if (noexpire.HasExt(na)) 1317 info.AddOption(_("No expire")); 1318 if (keep_modes.HasExt(na->nc)) 1319 info.AddOption(_("Keep modes")); 1320 } 1321 1322 void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override 1323 { 1324 if (u->Account() && setter.GetUser() == u) 1325 u->Account()->last_modes = u->GetModeList(); 1326 } 1327 1328 void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) anope_override 1329 { 1330 if (u->Account() && setter.GetUser() == u) 1331 u->Account()->last_modes = u->GetModeList(); 1332 } 1333 1334 void OnUserLogin(User *u) anope_override 1335 { 1336 if (keep_modes.HasExt(u->Account())) 1337 { 1338 User::ModeList modes = u->Account()->last_modes; 1339 for (User::ModeList::iterator it = modes.begin(); it != modes.end(); ++it) 1340 { 1341 UserMode *um = ModeManager::FindUserModeByName(it->first); 1342 /* if the null user can set the mode, then it's probably safe */ 1343 if (um && um->CanSet(NULL)) 1344 u->SetMode(NULL, it->first, it->second); 1345 } 1346 } 1347 } 1348 }; 1349 1350 MODULE_INIT(NSSet)