diff options
108 files changed, 1015 insertions, 659 deletions
diff --git a/cmake/Anope.cmake b/cmake/Anope.cmake index a9e7f6269..da8a88d54 100644 --- a/cmake/Anope.cmake +++ b/cmake/Anope.cmake @@ -359,12 +359,12 @@ macro(find_includes SRC INCLUDES) endmacro(find_includes) ############################################################################### -# calculate_depends(<source filename> <output variable set to TRUE on fail> [<optional output variable for includes>]) +# calculate_depends(<source filename> <output variable set to TRUE on fail> <TRUE to output error messages> [<optional output variable for includes>]) # # This macro is used in most of the src (sub)directories to calculate the # header file dependencies for the given source file. ############################################################################### -macro(calculate_depends SRC SKIP) +macro(calculate_depends SRC SKIP VERBOSE) # Temporarily set that we didn't get a 3rd argument before we actually check if we did get one or not set(CHECK_ANGLE_INCLUDES FALSE) # Check for a third argument @@ -402,14 +402,16 @@ macro(calculate_depends SRC SKIP) endif(FOUND_DEFAULT) endforeach(DEFAULT_INCLUDE_DIR) if(FOUND_IN_DEFAULTS EQUAL -1) - find_in_list(${ARGV2} "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_INCLUDES) + find_in_list(${ARGV3} "${FOUND_${FILENAME}_INCLUDE}" FOUND_IN_INCLUDES) if(FOUND_IN_INCLUDES EQUAL -1) - append_to_list(${ARGV2} "${FOUND_${FILENAME}_INCLUDE}") + append_to_list(${ARGV3} "${FOUND_${FILENAME}_INCLUDE}") endif(FOUND_IN_INCLUDES EQUAL -1) endif(FOUND_IN_DEFAULTS EQUAL -1) else(FOUND_${FILENAME}_INCLUDE) set(${SKIP} TRUE) - message("${SRC} needs header file ${FILENAME} but we were unable to locate that header file! Check that the header file is within the search path of your OS.") + if(VERBOSE) + message("${SRC} needs header file ${FILENAME} but we were unable to locate that header file! Check that the header file is within the search path of your OS.") + endif(VERBOSE) endif(FOUND_${FILENAME}_INCLUDE) endif(CHECK_ANGLE_INCLUDES) endif(QUOTE_TYPE STREQUAL "angle brackets") @@ -417,12 +419,12 @@ macro(calculate_depends SRC SKIP) endmacro(calculate_depends) ############################################################################### -# calculate_libraries(<source filename> <output variable set to TRUE on fail> <output variable for linker flags> <output variable for extra depends>) +# calculate_libraries(<source filename> <output variable set to TRUE on fail> <TRUE to output error messages> <output variable for linker flags> <output variable for extra depends>) # # This macro is used in most of the module (sub)directories to calculate the # library dependencies for the given source file. ############################################################################### -macro(calculate_libraries SRC SKIP SRC_LDFLAGS EXTRA_DEPENDS) +macro(calculate_libraries SRC SKIP VERBOSE SRC_LDFLAGS EXTRA_DEPENDS) # Set up a temporary LDFLAGS for this file set(THIS_LDFLAGS "${LDFLAGS}") # Reset extra dependencies @@ -464,8 +466,10 @@ macro(calculate_libraries SRC SKIP SRC_LDFLAGS EXTRA_DEPENDS) else(FOUND_${LIBRARY}_LIBRARY) # Skip this file set(${SKIP} TRUE) - # In the case of the library not being found, we fatally error so CMake stops trying to generate - message("${SRC} needs library ${LIBRARY} but we were unable to locate that library! Check that the library is within the search path of your OS.") + if(VERBOSE) + # In the case of the library not being found, we fatally error so CMake stops trying to generate + message(FATAL_ERROR "${SRC} needs library ${LIBRARY} but we were unable to locate that library! Check that the library is within the search path of your OS.") + endif(VERBOSE) endif(FOUND_${LIBRARY}_LIBRARY) endforeach(LIBRARY) endforeach(REQUIRED_LIBRARY) diff --git a/data/botserv.example.conf b/data/botserv.example.conf index e4605f1ab..66f5af396 100644 --- a/data/botserv.example.conf +++ b/data/botserv.example.conf @@ -308,3 +308,55 @@ command { service = "BotServ"; name = "SET NOBOT"; command = "botserv/set/nobot" module { name = "bs_set_private" } command { service = "BotServ"; name = "SET PRIVATE"; command = "botserv/set/private"; } +/* Fantasy commands + * + * Fantasy commands can be executed in channels that have a BotServ bot by prefixing the + * command with one of the fantasy characters configured in botserv:fantasycharacter. + * + * Sane defaults are provided below that do not need to be edited unless you wish to change the default behavior. + */ + +fantasy { name = "ACCESS"; command = "chanserv/access"; } +fantasy { name = "AKICK"; command = "chanserv/akick"; } +fantasy { name = "AOP"; command = "chanserv/aop"; } +fantasy { name = "APPENDTOPIC"; command = "chanserv/appendtopic"; } +fantasy { name = "BAN"; command = "chanserv/ban"; } +fantasy { name = "CLEARUSERS"; command = "chanserv/clearusers"; } +fantasy { name = "CLONE"; command = "chanserv/clone"; } +fantasy { name = "DEHALFOP"; command = "chanserv/dehalfop"; } +fantasy { name = "DEOP"; command = "chanserv/deop"; } +fantasy { name = "DEOWNER"; command = "chanserv/deowner"; } +fantasy { name = "DEPROTECT"; command = "chanserv/deprotect"; } +fantasy { name = "DEVOICE"; command = "chanserv/devoice"; } +fantasy { name = "DOWN"; command = "chanserv/down"; } +fantasy { name = "ENFORCE"; command = "chanserv/enforce"; } +fantasy { name = "ENTRYMSG"; command = "chanserv/entrymsg"; } +fantasy { name = "FLAGS"; command = "chanserv/flags"; } +fantasy { name = "HALFOP"; command = "chanserv/halfop"; } +fantasy { name = "HELP"; command = "generic/help"; } +fantasy { name = "HOP"; command = "chanserv/hop"; } +fantasy { name = "INFO"; command = "chanserv/info"; } +fantasy { name = "INVITE"; command = "chanserv/invite"; } +fantasy { name = "K"; command = "chanserv/kick"; } +fantasy { name = "KB"; command = "chanserv/ban"; } +fantasy { name = "KICK"; command = "chanserv/kick"; } +fantasy { name = "LEVELS"; command = "chanserv/levels"; } +fantasy { name = "LIST"; command = "chanserv/list"; } +fantasy { name = "LOG"; command = "chanserv/log"; } +fantasy { name = "MODE"; command = "chanserv/mode"; } +fantasy { name = "OP"; command = "chanserv/op"; } +fantasy { name = "OWNER"; command = "chanserv/owner"; } +fantasy { name = "PROTECT"; command = "chanserv/protect"; } +fantasy { name = "QOP"; command = "chanserv/qop"; } +fantasy { name = "SEEN"; command = "chanserv/seen"; } +fantasy { name = "SOP"; command = "chanserv/sop"; } +fantasy { name = "SUSPEND"; command = "chanserv/suspend"; } +fantasy { name = "SYNC"; command = "chanserv/sync"; } +fantasy { name = "TOPIC"; command = "chanserv/topic"; } +fantasy { name = "UNBAN"; command = "chanserv/unban"; } +fantasy { name = "UNBAN"; command = "chanserv/unban"; } +fantasy { name = "UNSUSPEND"; command = "chanserv/unsuspend"; } +fantasy { name = "UP"; command = "chanserv/up"; } +fantasy { name = "VOICE"; command = "chanserv/voice"; } +fantasy { name = "VOP"; command = "chanserv/vop"; } + diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index f507c5cab..e6e21dba3 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -882,7 +882,6 @@ command { service = "ChanServ"; name = "APPENDTOPIC"; command = "chanserv/append */ module { name = "cs_ban" } command { service = "ChanServ"; name = "BAN"; command = "chanserv/ban"; } -command { service = "ChanServ"; name = "KB"; command = "chanserv/ban"; } /* * cs_tban @@ -999,7 +998,6 @@ command { service = "ChanServ"; name = "INVITE"; command = "chanserv/invite"; } */ module { name = "cs_kick" } command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; } -command { service = "ChanServ"; name = "K"; command = "chanserv/kick"; } /* * cs_list diff --git a/data/modules.example.conf b/data/modules.example.conf index db8b555ba..4ff3c710c 100644 --- a/data/modules.example.conf +++ b/data/modules.example.conf @@ -359,6 +359,9 @@ m_sql_authentication * @n@ is replaced with the user's nickname * @i@ is replaced with the user's IP * + * Note that @n@ and @i@ may not always exist in the case of a user identifying outside of the normal + * nickserv/identify command, such as through the web panel. + * * Furthermore, if a field named email is returned from this query the user's email is * set to its value. */ diff --git a/include/account.h b/include/account.h index 8b4920fe4..19b7729d3 100644 --- a/include/account.h +++ b/include/account.h @@ -304,7 +304,40 @@ class CoreExport NickCore : public Extensible, public Flags<NickCoreFlag, NI_END * Deletes all the memory allocated in the certificate list vector and then clears the vector. */ void ClearCert(); +}; + +class IdentifyRequest +{ + Module *owner; + Anope::string account; + Anope::string password; + + std::set<Module *> holds; + bool dispatched; + bool success; + + static std::set<IdentifyRequest *> requests; + + protected: + IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass); + virtual ~IdentifyRequest(); + + public: + virtual void OnSuccess() = 0; + virtual void OnFail() = 0; + + const Anope::string &GetAccount() const { return account; } + const Anope::string &GetPassword() const { return password; } + + /* Hold this request. Once held it must be Release()d later on */ + void Hold(Module *m); + void Release(Module *m); + + void Success(Module *m); + + void Dispatch(); + static void ModuleUnload(Module *m); }; extern CoreExport void change_core_display(NickCore *nc); diff --git a/include/bots.h b/include/bots.h index fa3053b57..19f921dbb 100644 --- a/include/bots.h +++ b/include/bots.h @@ -43,8 +43,7 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END>, public Se public: time_t created; /* Birth date ;) */ time_t lastmsg; /* Last time we said something */ - typedef Anope::insensitive_map<CommandInfo> command_map; - command_map commands; /* Commands, actual name to service name */ + CommandInfo::map commands; /* Commands, actual name to service name */ Anope::string botmodes; /* Modes the bot should have as configured in service:modes */ std::vector<Anope::string> botchannels; /* Channels the bot should be in as configured in service:channels */ bool introduced; /* Whether or not this bot is introduced */ diff --git a/include/commands.h b/include/commands.h index 45b122247..59e8f5f1c 100644 --- a/include/commands.h +++ b/include/commands.h @@ -29,6 +29,8 @@ const Anope::string CommandFlagStrings[] = { struct CommandInfo { + typedef Anope::insensitive_map<CommandInfo> map; + Anope::string name; Anope::string permission; }; @@ -53,15 +55,13 @@ class CoreExport CommandSource /* Channel the command was executed on (fantasy) */ dynamic_reference<Channel> c; /* The service this command is on */ - dynamic_reference<BotInfo> owner; - /* The service the reply should come from, *not* necessarily the service the command is on */ dynamic_reference<BotInfo> service; /* The actual name of the command being executed */ Anope::string command; /* The permission of the command being executed */ Anope::string permission; - CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply); + CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *reply, BotInfo *bi); const Anope::string &GetNick() const; User *GetUser(); diff --git a/include/config.h b/include/config.h index de68d3105..554959e38 100644 --- a/include/config.h +++ b/include/config.h @@ -688,6 +688,9 @@ class CoreExport ServerConfig std::list<OperType *> MyOperTypes; /* List of pairs of opers and their opertype from the config */ std::vector<Oper *> Opers; + + /* Map of fantasy commands */ + CommandInfo::map Fantasy; }; /** This class can be used on its own to represent an exception, or derived to represent a module-specific exception. diff --git a/include/defs.h b/include/defs.h index d58f7fed6..c08d683a0 100644 --- a/include/defs.h +++ b/include/defs.h @@ -26,6 +26,7 @@ class ConnectionSocket; class DNSPacket; class dynamic_reference_base; class Entry; +class IdentifyRequest; class InfoFormatter; class ListenSocket; class Log; diff --git a/include/modules.h b/include/modules.h index 4b992a15d..627bbab59 100644 --- a/include/modules.h +++ b/include/modules.h @@ -348,20 +348,22 @@ class CoreExport Module : public Extensible virtual EventReturn OnDecrypt(const Anope::string &hashm, const Anope::string &src, Anope::string &dest) { return EVENT_CONTINUE; } /** Called on fantasy command - * @param command The command - * @param u The user using the command + * @param source The source of the command + * @param c The command * @param ci The channel it's being used in * @param params The params + * @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed */ - virtual void OnBotFantasy(const Anope::string &command, User *u, ChannelInfo *ci, const Anope::string ¶ms) { } + virtual EventReturn OnBotFantasy(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; } /** Called on fantasy command without access - * @param command The command - * @param u The user using the command + * @param source The source of the command + * @param c The command * @param ci The channel it's being used in * @param params The params + * @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed */ - virtual void OnBotNoFantasyAccess(const Anope::string &command, User *u, ChannelInfo *ci, const Anope::string ¶ms) { } + virtual EventReturn OnBotNoFantasyAccess(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; } /** Called after a bot joins a channel * @param c The channel @@ -765,15 +767,11 @@ class CoreExport Module : public Extensible */ virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool ShowHidden) { } - /** Check whether a users password is correct. - * @param u The user - * @param command The command the user is doing - * @param params Command params - * @param account The account the password should be checked against - * @param password The password - * @return EVENT_ALLOW to allow the password, EVENT_STOP to stop processing completely + /** Check whether a username and password is correct + * @param u The user trying to identify, if applicable. + * @param req The login request */ - virtual EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; } + virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) { } /** Called when a user does /ns update * @param u The user diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index b49b53d37..e1adec666 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -42,7 +42,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) # Temporary variable for the current source's include directories set(TEMP_INCLUDES) # Calculate the header file dependencies for the given source file - calculate_depends(${SRC} SKIP_DEPENDS TEMP_INCLUDES) + calculate_depends(${SRC} SKIP_DEPENDS FALSE TEMP_INCLUDES) # If there were some extra include directories, add them to the list if(TEMP_INCLUDES) append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES}) @@ -54,7 +54,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) # Reset skip_libraries set(SKIP_LIBRARIES) # Calculate the library dependencies for the given source file - calculate_libraries(${SRC} SKIP_LIBRARIES TEMP_LDFLAGS TEMP_DEPENDENCIES) + calculate_libraries(${SRC} SKIP_LIBRARIES FALSE TEMP_LDFLAGS TEMP_DEPENDENCIES) if(NOT SKIP_DEPENDS AND NOT SKIP_LIBRARIES) # Reset has_function set(HAS_FUNCTION) @@ -95,7 +95,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) ) endif(HAS_FUNCTION) else(NOT SKIP_DEPENDS AND NOT SKIP_LIBRARIES) - message(" This is not a fatal error - ${SRC} will not be built.") + message(" ${SRC} can not be built due to missing dependencies.") endif(NOT SKIP_DEPENDS AND NOT SKIP_LIBRARIES) endforeach(SRC) @@ -138,7 +138,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) # Temporary variable for the current source's include directories set(TEMP_INCLUDES) # Calculate the header file dependencies for the given source file - calculate_depends(${SRC} SKIP_DEPENDS TEMP_INCLUDES) + calculate_depends(${SRC} SKIP_DEPENDS FALSE TEMP_INCLUDES) # If there were some extra include directories, add them to the list if(TEMP_INCLUDES) append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES}) @@ -148,7 +148,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) # Reset extra dependencies set(TEMP_DEPENDENCIES) # Calculate the library dependencies for the given source file - calculate_libraries(${SRC} SKIP_LIBRARIES TEMP_LDFLAGS TEMP_DEPENDENCIES) + calculate_libraries(${SRC} SKIP_LIBRARIES FALSE TEMP_LDFLAGS TEMP_DEPENDENCIES) # Check the function dependencies for the given source file check_functions(${SRC} HAS_FUNCTION) @@ -195,7 +195,7 @@ foreach(MODULE_FOLDER ${MODULES_FOLDERS}) DESTINATION ${LIB_DIR}/modules ) else(NOT SKIP_DEPENDS AND NOT SKIP_LIBRARIES AND HAS_FUNCTION) - message(" This is not a fatal error - ${SUBDIR} will not be built.") + message(" ${SRC} can not be built due to missing dependencies.") endif(NOT SKIP_DEPENDS AND NOT SKIP_LIBRARIES AND HAS_FUNCTION) # Run the directories CMakeLists.txt if there is one diff --git a/modules/commands/bs_badwords.cpp b/modules/commands/bs_badwords.cpp index 30de67d29..ad7a49085 100644 --- a/modules/commands/bs_badwords.cpp +++ b/modules/commands/bs_badwords.cpp @@ -289,7 +289,7 @@ class CommandBSBadwords : public Command "will be done if a user says a word that ends with\n" "\037word\037. If you don't specify anything, a kick will\n" "be issued every time \037word\037 is said by a user.\n" - " \n"), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + " \n"), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str()); source.Reply(_("The \002DEL\002 command removes the given word from the\n" "bad words list. If a list of entry numbers is given, those\n" "entries are deleted. (See the example for LIST below.)\n" diff --git a/modules/commands/bs_info.cpp b/modules/commands/bs_info.cpp index d5b2693ad..199b17e3e 100644 --- a/modules/commands/bs_info.cpp +++ b/modules/commands/bs_info.cpp @@ -228,7 +228,7 @@ class CommandBSInfo : public Command "If the parameter is a channel, then you'll get information\n" "such as enabled kickers. If the parameter is a nick,\n" "you'll get information about a bot, such as creation\n" - "time or number of channels it is on."), source.owner->nick.c_str()); + "time or number of channels it is on."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index 32cfbe952..eeaccd5f9 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -482,7 +482,7 @@ class CommandBSKick : public Command "on a specific option.\n" " \n" "Note: access to this command is controlled by the\n" - "level SET."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "level SET."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); } else if (subcommand.equals_ci("BADWORDS")) source.Reply(_("Syntax: \002\037#channel\037 BADWORDS {\037ON|OFF\037} [\037ttb\037]\002\n" @@ -494,7 +494,7 @@ class CommandBSKick : public Command "more information.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" - "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); else if (subcommand.equals_ci("BOLDS")) source.Reply(_("Syntax: \002\037channel\037 BOLDS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the bolds kicker on or off. When enabled, this\n" diff --git a/modules/commands/bs_set.cpp b/modules/commands/bs_set.cpp index 61839ab1e..e169f3c83 100644 --- a/modules/commands/bs_set.cpp +++ b/modules/commands/bs_set.cpp @@ -35,7 +35,7 @@ class CommandBSSet : public Command " \n" "Available options:")); Anope::string this_name = source.command; - for (BotInfo::command_map::const_iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; @@ -50,7 +50,7 @@ class CommandBSSet : public Command } } source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "particular option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index df724db1e..9ad72623f 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -508,7 +508,7 @@ class CommandCSAccess : public Command "user levels allow for access to different subsets of\n" "privileges. Any registered user not on the access list has\n" "a user level of 0, and any unregistered user has a user level\n" - "of -1."), source.owner->nick.c_str()); + "of -1."), source.service->nick.c_str()); source.Reply(" "); source.Reply(_("The \002ACCESS ADD\002 command adds the given mask to the\n" "access list with the given user level; if the mask is\n" @@ -557,7 +557,7 @@ class CommandCSAccess : public Command " \n" "These levels may be changed, or new ones added, using the\n" "\002LEVELS\002 command; type \002%s%s HELP LEVELS\002 for\n" - "information."), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "information."), source.service->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; @@ -592,7 +592,7 @@ class CommandCSLevels : public Command { Privilege *p = PrivilegeManager::FindPrivilege(what); if (p == NULL) - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); else { ci->SetLevel(p->name, level); @@ -630,7 +630,7 @@ class CommandCSLevels : public Command } } - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return; } @@ -772,7 +772,7 @@ class CommandCSLevels : public Command "\002HELP ACCESS LEVELS\002).\n" " \n" "For a list of the features and functions whose levels can be\n" - "set, see \002HELP LEVELS DESC\002."), source.owner->nick.c_str()); + "set, see \002HELP LEVELS DESC\002."), source.service->nick.c_str()); } return true; } diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp index 1ff67215c..6c0dfa386 100644 --- a/modules/commands/cs_akick.cpp +++ b/modules/commands/cs_akick.cpp @@ -464,7 +464,7 @@ class CommandCSAKick : public Command "When akicking a \037registered nick\037 the nickserv account\n" "will be added to the akick list instead of the mask.\n" "All users within that nickgroup will then be akicked.\n"), - source.owner->nick.c_str()); + source.service->nick.c_str()); source.Reply(_( " \n" "The \002AKICK DEL\002 command removes the given nick or mask\n" @@ -484,7 +484,7 @@ class CommandCSAKick : public Command "AKICK mask.\n" " \n" "The \002AKICK CLEAR\002 command clears all entries of the\n" - "akick list."), source.owner->nick.c_str()); + "akick list."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_clearusers.cpp b/modules/commands/cs_clearusers.cpp index 1c26fe382..9a50f70c9 100644 --- a/modules/commands/cs_clearusers.cpp +++ b/modules/commands/cs_clearusers.cpp @@ -69,7 +69,7 @@ class CommandCSClearUsers : public Command source.Reply(_("Tells %s to clear (kick) all users on a channel." " \n" "By default, limited to those with founder access on the\n" - "channel."), source.owner->nick.c_str()); + "channel."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index 99c635c8f..bbc06c7be 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -98,7 +98,7 @@ public: target_ci->last_topic_time = target_ci->c->topic_time; } else - target_ci->last_topic_setter = source.owner->nick; + target_ci->last_topic_setter = source.service->nick; FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(target_ci)); diff --git a/modules/commands/cs_invite.cpp b/modules/commands/cs_invite.cpp index 09c077fc6..32ef87e3e 100644 --- a/modules/commands/cs_invite.cpp +++ b/modules/commands/cs_invite.cpp @@ -94,7 +94,7 @@ class CommandCSInvite : public Command "nick into the given channel.\n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), source.owner->nick.c_str()); + "on the channel."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_register.cpp b/modules/commands/cs_register.cpp index 49c0919c4..7528a96c0 100644 --- a/modules/commands/cs_register.cpp +++ b/modules/commands/cs_register.cpp @@ -70,7 +70,7 @@ class CommandCSRegister : public Command ci->last_topic_time = c->topic_time; } else - ci->last_topic_setter = source.owner->nick; + ci->last_topic_setter = source.service->nick; Log(LOG_COMMAND, source, this, ci); source.Reply(_("Channel \002%s\002 registered under your account: %s"), chan.c_str(), nc->display.c_str()); @@ -125,7 +125,7 @@ class CommandCSRegister : public Command "NOTICE: In order to register a channel, you must have\n" "first registered your nickname. If you haven't,\n" "\002%s%s HELP\002 for information on how to do so."), - source.owner->nick.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); + source.service->nick.c_str(), source.service->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); return true; } }; diff --git a/modules/commands/cs_saset.cpp b/modules/commands/cs_saset.cpp index c2e7b13d5..a4a72ee76 100644 --- a/modules/commands/cs_saset.cpp +++ b/modules/commands/cs_saset.cpp @@ -37,7 +37,7 @@ class CommandCSSASet : public Command " \n" "Available options:")); Anope::string this_name = source.command; - for (BotInfo::command_map::const_iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; @@ -52,7 +52,7 @@ class CommandCSSASet : public Command } } source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "particular option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 0d23b5550..9851a27a1 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -37,7 +37,7 @@ class CommandCSSet : public Command " \n" "Available options:")); Anope::string this_name = source.command; - for (BotInfo::command_map::const_iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; @@ -52,7 +52,7 @@ class CommandCSSet : public Command } } source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + "particular option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_set_keeptopic.cpp b/modules/commands/cs_set_keeptopic.cpp index 1aeedfa0a..d95d4ac2b 100644 --- a/modules/commands/cs_set_keeptopic.cpp +++ b/modules/commands/cs_set_keeptopic.cpp @@ -66,7 +66,7 @@ class CommandCSSetKeepTopic : public Command "channel. When \002%s\002 is set, the topic for the\n" "channel will be remembered by %s even after the\n" "last user leaves the channel, and will be restored the\n" - "next time the channel is created."), this->name.c_str(), source.owner->nick.c_str()); + "next time the channel is created."), this->name.c_str(), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_set_peace.cpp b/modules/commands/cs_set_peace.cpp index 889a0c6ae..f7eb8af6b 100644 --- a/modules/commands/cs_set_peace.cpp +++ b/modules/commands/cs_set_peace.cpp @@ -64,7 +64,7 @@ class CommandCSSetPeace : public Command source.Reply(_("Enables or disables the \002peace\002 option for a channel.\n" "When \002peace\002 is set, a user won't be able to kick,\n" "ban or remove a channel status of a user that has\n" - "a level superior or equal to his via %s commands."), source.owner->nick.c_str()); + "a level superior or equal to his via %s commands."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_set_private.cpp b/modules/commands/cs_set_private.cpp index 37a5dbbc9..45741eb20 100644 --- a/modules/commands/cs_set_private.cpp +++ b/modules/commands/cs_set_private.cpp @@ -65,7 +65,7 @@ class CommandCSSetPrivate : public Command source.Reply(_("Enables or disables the \002private\002 option for a channel.\n" "When \002private\002 is set, a \002%s%s LIST\002 will not\n" "include the channel in any lists."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp index 5badaa12d..3474874d6 100644 --- a/modules/commands/cs_topic.cpp +++ b/modules/commands/cs_topic.cpp @@ -61,7 +61,7 @@ class CommandCSTopic : public Command "is set. This command is most useful in conjunction\n" "with topic lock.\n" "By default, limited to those with founder access on the\n" - "channel."), source.owner->nick.c_str()); + "channel."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_unban.cpp b/modules/commands/cs_unban.cpp index 91776b0c0..aaa336438 100644 --- a/modules/commands/cs_unban.cpp +++ b/modules/commands/cs_unban.cpp @@ -70,7 +70,7 @@ class CommandCSUnban : public Command "user from entering the given channel.\n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), source.owner->nick.c_str()); + "on the channel."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/cs_xop.cpp b/modules/commands/cs_xop.cpp index ae1fe3110..884d7e437 100644 --- a/modules/commands/cs_xop.cpp +++ b/modules/commands/cs_xop.cpp @@ -620,8 +620,8 @@ class CommandCSQOP : public XOPBase "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; @@ -675,8 +675,8 @@ class CommandCSAOP : public XOPBase "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; @@ -729,8 +729,8 @@ class CommandCSHOP : public XOPBase "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; @@ -783,8 +783,8 @@ class CommandCSSOP : public XOPBase "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; @@ -837,8 +837,8 @@ class CommandCSVOP : public XOPBase "available. See \002%s%s HELP ACCESS\002 for information\n" "about the access list, and \002%s%s HELP FLAGS\002 for\n" "information about the flags based system."), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/gl_global.cpp b/modules/commands/gl_global.cpp index 2ec39b3b9..09d44f9a0 100644 --- a/modules/commands/gl_global.cpp +++ b/modules/commands/gl_global.cpp @@ -41,7 +41,7 @@ class CommandGLGlobal : public Command this->SendSyntax(source); source.Reply(" "); source.Reply(_("Allows Administrators to send messages to all users on the \n" - "network. The message will be sent from the nick \002%s\002."), source.owner->nick.c_str()); + "network. The message will be sent from the nick \002%s\002."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/help.cpp b/modules/commands/help.cpp index c0c57dbae..28bf963a8 100644 --- a/modules/commands/help.cpp +++ b/modules/commands/help.cpp @@ -30,18 +30,19 @@ class CommandHelp : public Command if (MOD_RESULT == EVENT_STOP) return; - const BotInfo *bi = source.owner; + const BotInfo *bi = source.service; + const CommandInfo::map &map = source.c ? Config->Fantasy : bi->commands; if (params.empty()) { - for (BotInfo::command_map::const_iterator it = bi->commands.begin(), it_end = bi->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = map.begin(), it_end = map.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; // Smaller command exists Anope::string cmd = myStrGetToken(c_name, ' ', 0); - if (cmd != it->first && bi->commands.count(cmd)) + if (cmd != it->first && map.count(cmd)) continue; service_reference<Command> c("Command", info.name); @@ -64,8 +65,8 @@ class CommandHelp : public Command full_command += " " + params[i]; full_command.erase(full_command.begin()); - BotInfo::command_map::const_iterator it = bi->commands.find(full_command); - if (it == bi->commands.end()) + CommandInfo::map::const_iterator it = map.find(full_command); + if (it == map.end()) continue; const CommandInfo &info = it->second; diff --git a/modules/commands/ms_set.cpp b/modules/commands/ms_set.cpp index 998a5a062..02ce8d32c 100644 --- a/modules/commands/ms_set.cpp +++ b/modules/commands/ms_set.cpp @@ -239,7 +239,7 @@ class CommandMSSet : public Command " receive\n" " \n" "Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str()); } else if (subcommand.equals_ci("NOTIFY")) source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" diff --git a/modules/commands/ns_ghost.cpp b/modules/commands/ns_ghost.cpp index 3362cf408..53082e0a4 100644 --- a/modules/commands/ns_ghost.cpp +++ b/modules/commands/ns_ghost.cpp @@ -13,6 +13,43 @@ #include "module.h" +class NSGhostRequest : public IdentifyRequest +{ + CommandSource source; + Command *cmd; + + public: + NSGhostRequest(Module *o, CommandSource &src, Command *c, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(o, user, pass), source(src), cmd(c) { } + + void OnSuccess() anope_override + { + if (!source.GetUser() || !source.service) + return; + + User *user = source.GetUser(); + if (!user->IsIdentified()) + source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); + else + { + Log(LOG_COMMAND, source, cmd) << "for " << GetAccount(); + Anope::string buf = "GHOST command used by " + source.GetNick(); + user->Kill(source.service->nick, buf); + source.Reply(_("Ghost with your nick has been killed.")); + } + } + + void OnFail() anope_override + { + source.Reply(ACCESS_DENIED); + if (!GetPassword().empty()) + { + Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount(); + if (source.GetUser()) + bad_password(source.GetUser()); + } + } +}; + class CommandNSGhost : public Command { public: @@ -50,37 +87,21 @@ class CommandNSGhost : public Command ok = true; else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint)) ok = true; - else if (!pass.empty()) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); - if (MOD_RESULT == EVENT_STOP) - return; - else if (MOD_RESULT == EVENT_ALLOW) - ok = true; - } - if (ok) + if (ok == false && !pass.empty()) { - if (!user->IsIdentified()) - source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); - else - { - Log(LOG_COMMAND, source, this) << "for " << nick; - Anope::string buf = "GHOST command used by " + source.GetNick(); - user->Kill(Config->NickServ, buf); - source.Reply(_("Ghost with your nick has been killed."), nick.c_str()); - } + NSGhostRequest *req = new NSGhostRequest(owner, source, this, na->nc->display, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req)); + req->Dispatch(); } else { - source.Reply(ACCESS_DENIED); - if (!pass.empty()) - { - Log(LOG_COMMAND, source, this) << "with an invalid password for " << nick; - if (source.GetUser()) - bad_password(source.GetUser()); - } + NSGhostRequest req(owner, source, this, na->nc->display, pass); + + if (ok) + req.OnSuccess(); + else + req.OnFail(); } } diff --git a/modules/commands/ns_group.cpp b/modules/commands/ns_group.cpp index 3df4b3460..58251d76d 100644 --- a/modules/commands/ns_group.cpp +++ b/modules/commands/ns_group.cpp @@ -13,6 +13,61 @@ #include "module.h" +class NSGroupRequest : public IdentifyRequest +{ + CommandSource source; + Command *cmd; + Anope::string nick; + dynamic_reference<NickAlias> target; + + public: + NSGroupRequest(Module *o, CommandSource &src, Command *c, const Anope::string &n, NickAlias *targ, const Anope::string &pass) : IdentifyRequest(o, targ->nc->display, pass), source(src), cmd(c), nick(n), target(targ) { } + + void OnSuccess() anope_override + { + if (!source.GetUser() || source.GetUser()->nick != nick || !target || !target->nc) + return; + + User *u = source.GetUser(); + NickAlias *na = findnick(nick); + /* If the nick is already registered, drop it. */ + if (na) + { + FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(na->nc, u->nick)); + na->destroy(); + } + + na = new NickAlias(nick, target->nc); + + Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); + na->last_usermask = last_usermask; + na->last_realname = u->realname; + na->time_registered = na->last_seen = Anope::CurTime; + + u->Login(target->nc); + ircdproto->SendLogin(u); + if (!Config->NoNicknameOwnership && na->nc == u->Account() && na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target)); + + Log(LOG_COMMAND, source, cmd) << "makes " << nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")"; + source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str()); + + u->lastnickreg = Anope::CurTime; + + } + + void OnFail() anope_override + { + if (!source.GetUser()) + return; + + Log(LOG_COMMAND, source, cmd) << "failed group for " << target->nick; + source.Reply(PASSWORD_INCORRECT); + bad_password(source.GetUser()); + } +}; + class CommandNSGroup : public Command { public: @@ -62,7 +117,7 @@ class CommandNSGroup : public Command source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (Anope::CurTime < u->lastnickreg + Config->NSRegDelay) source.Reply(_("Please wait %d seconds before using the GROUP command again."), (Config->NSRegDelay + u->lastnickreg) - Anope::CurTime); - else if (target && target->nc->HasFlag(NI_SUSPENDED)) + else if (target->nc->HasFlag(NI_SUSPENDED)) { Log(LOG_COMMAND, source, this) << "tried to use GROUP for SUSPENDED nick " << target->nick; source.Reply(NICK_X_SUSPENDED, target->nick.c_str()); @@ -75,6 +130,12 @@ class CommandNSGroup : public Command source.Reply(_("Your nick is already registered.")); else if (Config->NSMaxAliases && (target->nc->aliases.size() >= Config->NSMaxAliases) && !target->nc->IsServicesOper()) source.Reply(_("There are too many nicks in %s's group.")); + else if (u->nick.length() <= Config->NSGuestNickPrefix.length() + 7 && + u->nick.length() >= Config->NSGuestNickPrefix.length() + 1 && + !u->nick.find_ci(Config->NSGuestNickPrefix) && !u->nick.substr(Config->NSGuestNickPrefix.length()).find_first_not_of("1234567890")) + { + source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); + } else { bool ok = false; @@ -82,63 +143,23 @@ class CommandNSGroup : public Command ok = true; else if (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint)) ok = true; - else if (!pass.empty()) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, target->nc->display, pass)); - if (MOD_RESULT == EVENT_STOP) - return; - else if (MOD_RESULT == EVENT_ALLOW) - ok = true; - } - if (ok) - { - /* If the nick is already registered, drop it. - * If not, check that it is valid. - */ - if (na) - { - FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(na->nc, u->nick)); - na->destroy(); - } - else - { - size_t prefixlen = Config->NSGuestNickPrefix.length(); - size_t nicklen = u->nick.length(); - - if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && !u->nick.find_ci(Config->NSGuestNickPrefix) && !u->nick.substr(prefixlen).find_first_not_of("1234567890")) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); - return; - } - } - - na = new NickAlias(u->nick, target->nc); - - Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_usermask = last_usermask; - na->last_realname = u->realname; - na->time_registered = na->last_seen = Anope::CurTime; - - u->Login(target->nc); - ircdproto->SendLogin(u); - if (!Config->NoNicknameOwnership && na->nc == u->Account() && na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target)); - Log(LOG_COMMAND, source, this) << "makes " << u->nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")"; - source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str()); - - u->lastnickreg = Anope::CurTime; + if (ok == false && !pass.empty()) + { + NSGroupRequest *req = new NSGroupRequest(owner, source, this, u->nick, target, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req)); + req->Dispatch(); } else { - Log(LOG_COMMAND, source, this) << "failed group for " << target->nick; - source.Reply(PASSWORD_INCORRECT); - bad_password(u); + NSGroupRequest req(owner, source, this, u->nick, target, pass); + + if (ok) + req.OnSuccess(); + else + req.OnFail(); } } - return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override diff --git a/modules/commands/ns_identify.cpp b/modules/commands/ns_identify.cpp index cce0569dd..dde24d72d 100644 --- a/modules/commands/ns_identify.cpp +++ b/modules/commands/ns_identify.cpp @@ -13,6 +13,47 @@ #include "module.h" +class NSIdentifyRequest : public IdentifyRequest +{ + CommandSource source; + Command *cmd; + + public: + NSIdentifyRequest(Module *o, CommandSource &s, Command *c, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(o, acc, pass), source(s), cmd(c) { } + + void OnSuccess() anope_override + { + if (!source.GetUser()) + return; + + User *u = source.GetUser(); + NickAlias *na = findnick(GetAccount()); + + if (!na) + source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); + else + { + if (u->IsIdentified()) + Log(LOG_COMMAND, source, cmd) << "to log out of account " << u->Account()->display; + + Log(LOG_COMMAND, source, cmd) << "and identified for account " << na->nc->display; + source.Reply(_("Password accepted - you are now recognized.")); + u->Identify(na); + na->Release(); + } + } + + void OnFail() anope_override + { + if (source.GetUser()) + { + Log(LOG_COMMAND, source, cmd) << "and failed to identify"; + source.Reply(PASSWORD_INCORRECT); + bad_password(source.GetUser()); + } + } +}; + class CommandNSIdentify : public Command { public: @@ -40,29 +81,9 @@ class CommandNSIdentify : public Command source.Reply(_("You are already identified.")); else { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na ? na->nc->display : nick, pass)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (!na) - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - else if (MOD_RESULT != EVENT_ALLOW) - { - Log(LOG_COMMAND, source, this) << "and failed to identify"; - source.Reply(PASSWORD_INCORRECT); - bad_password(u); - } - else - { - if (u->IsIdentified()) - Log(LOG_COMMAND, source, this) << "to log out of account " << u->Account()->display; - - Log(LOG_COMMAND, source, this) << "and identified for account " << na->nc->display; - source.Reply(_("Password accepted - you are now recognized.")); - u->Identify(na); - na->Release(); - } + NSIdentifyRequest *req = new NSIdentifyRequest(owner, source, this, na ? na->nc->display : nick, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req)); + req->Dispatch(); } return; } @@ -75,7 +96,7 @@ class CommandNSIdentify : public Command "nick. Many commands require you to authenticate yourself\n" "with this command before you use them. The password\n" "should be the same one you sent with the \002REGISTER\002\n" - "command."), source.owner->nick.c_str()); + "command."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/ns_recover.cpp b/modules/commands/ns_recover.cpp index 7c5b6cbeb..648bbf032 100644 --- a/modules/commands/ns_recover.cpp +++ b/modules/commands/ns_recover.cpp @@ -14,12 +14,23 @@ #include "module.h" -class CommandNSRecover : public Command +class NSRecoverRequest : public IdentifyRequest { - private: - void DoRecover(CommandSource &source, User *u, NickAlias *na, const Anope::string &nick) + CommandSource source; + Command *cmd; + dynamic_reference<NickAlias> na; + + public: + NSRecoverRequest(Module *m, CommandSource &src, Command *c, NickAlias *n, const Anope::string &pass) : IdentifyRequest(m, n->nc->display, pass), source(src), cmd(c), na(n) { } + + void OnSuccess() anope_override { - u->SendMessage(source.owner, FORCENICKCHANGE_NOW); + if (!source.GetUser() || !na) + return; + + User *u = source.GetUser(); + + u->SendMessage(source.service, FORCENICKCHANGE_NOW); if (u->Account() == na->nc) { @@ -31,9 +42,27 @@ class CommandNSRecover : public Command /* Convert Config->NSReleaseTimeout seconds to string format */ Anope::string relstr = duration(Config->NSReleaseTimeout); - source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), nick.c_str(), relstr.c_str()); + source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), na->nick.c_str(), relstr.c_str()); } + void OnFail() anope_override + { + if (!source.GetUser()) + return; + + User *u = source.GetUser(); + + source.Reply(ACCESS_DENIED); + if (!GetPassword().empty()) + { + Log(LOG_COMMAND, source, cmd) << "with invalid password for " << na->nick; + bad_password(u); + } + } +}; + +class CommandNSRecover : public Command +{ public: CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2) { @@ -60,25 +89,6 @@ class CommandNSRecover : public Command source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (nick.equals_ci(source.GetNick())) source.Reply(_("You can't recover yourself!")); - else if (!pass.empty()) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT == EVENT_ALLOW) - { - this->DoRecover(source, u2, na, nick); - } - else - { - source.Reply(ACCESS_DENIED); - Log(LOG_COMMAND, source, this) << "with invalid password for " << nick; - if (source.GetUser()) - bad_password(source.GetUser()); - } - } else { bool ok = false; @@ -88,12 +98,23 @@ class CommandNSRecover : public Command ok = true; else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint)) ok = true; - if (ok) - this->DoRecover(source, u2, na, nick); + + if (ok == false && !pass.empty()) + { + NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, na, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req)); + req->Dispatch(); + } else - source.Reply(ACCESS_DENIED); + { + NSRecoverRequest req(owner, source, this, na, pass); + + if (ok) + req.OnSuccess(); + else + req.OnFail(); + } } - return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp index 2665b2381..4253b672b 100644 --- a/modules/commands/ns_register.cpp +++ b/modules/commands/ns_register.cpp @@ -217,7 +217,7 @@ class CommandNSRegister : public Command else if (Config->NSRegistration.equals_ci("mail")) { nc->SetFlag(NI_UNCONFIRMED); - if (SendRegmail(u, na, source.owner)) + if (SendRegmail(u, na, source.service)) { source.Reply(_("A passcode has been sent to %s, please type %s%s confirm <passcode> to confirm your email address."), email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); source.Reply(_("If you do not confirm your email address within %s your account will expire."), duration(Config->NSUnconfirmedExpire).c_str()); @@ -300,7 +300,7 @@ class CommandNSResend : public Command { if (Anope::CurTime < source.nc->lastmail + Config->NSResendDelay) source.Reply(_("Cannot send mail now; please retry a little later.")); - else if (SendRegmail(source.GetUser(), na, source.owner)) + else if (SendRegmail(source.GetUser(), na, source.service)) { na->nc->lastmail = Anope::CurTime; source.Reply(_("Your passcode has been re-sent to %s."), na->nc->email.c_str()); diff --git a/modules/commands/ns_release.cpp b/modules/commands/ns_release.cpp index 9e12685aa..cd669e707 100644 --- a/modules/commands/ns_release.cpp +++ b/modules/commands/ns_release.cpp @@ -13,6 +13,38 @@ #include "module.h" +class NSReleaseRequest : public IdentifyRequest +{ + CommandSource source; + Command *cmd; + dynamic_reference<NickAlias> na; + + public: + NSReleaseRequest(Module *m, CommandSource &src, Command *c, NickAlias *n, const Anope::string &pass) : IdentifyRequest(m, n->nc->display, pass), source(src), cmd(c), na(n) { } + + void OnSuccess() anope_override + { + if (!source.GetUser() || !na) + return; + + bool override = source.GetAccount() != na->nc && source.HasPriv("nickserv/release"); + Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, cmd) << "for nickname " << na->nick; + na->Release(); + source.Reply(_("Services' hold on \002%s\002 has been released."), na->nick.c_str()); + } + + void OnFail() anope_override + { + source.Reply(ACCESS_DENIED); + if (!GetPassword().empty()) + { + Log(LOG_COMMAND, source, cmd) << "with invalid password for " << na->nick; + if (!source.GetUser()) + bad_password(source.GetUser()); + } + } +}; + class CommandNSRelease : public Command { public: @@ -35,27 +67,6 @@ class CommandNSRelease : public Command source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (!na->HasFlag(NS_HELD)) source.Reply(_("Nick \002%s\002 isn't being held."), nick.c_str()); - else if (!pass.empty()) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT == EVENT_ALLOW) - { - Log(LOG_COMMAND, source, this) << "for nickname " << na->nick; - na->Release(); - source.Reply(_("Services' hold on \002%s\002 has been released."), nick.c_str()); - } - else - { - source.Reply(ACCESS_DENIED); - Log(LOG_COMMAND, source, this) << "invalid password for " << nick; - if (source.GetUser()) - bad_password(source.GetUser()); - } - } else { bool override = source.GetAccount() != na->nc && source.HasPriv("nickserv/release"); @@ -67,14 +78,22 @@ class CommandNSRelease : public Command ok = true; else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint)) ok = true; - if (ok) + + if (ok == false && !pass.empty()) { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this) << "for nickname " << na->nick; - na->Release(); - source.Reply(_("Services' hold on \002%s\002 has been released."), nick.c_str()); + NSReleaseRequest *req = new NSReleaseRequest(owner, source, this, na, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(source.GetUser(), req)); + req->Dispatch(); } else - source.Reply(ACCESS_DENIED); + { + NSReleaseRequest req(owner, source, this, na, pass); + + if (ok) + req.OnSuccess(); + else + req.OnFail(); + } } return; } diff --git a/modules/commands/ns_resetpass.cpp b/modules/commands/ns_resetpass.cpp index 6102c2d85..8965b6a3e 100644 --- a/modules/commands/ns_resetpass.cpp +++ b/modules/commands/ns_resetpass.cpp @@ -35,7 +35,7 @@ class CommandNSResetPass : public Command source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); else { - if (SendResetEmail(source.GetUser(), na, source.owner)) + if (SendResetEmail(source.GetUser(), na, source.service)) { Log(LOG_COMMAND, source, this) << "for " << na->nick << " (group: " << na->nc->display << ")"; source.Reply(_("Password reset email for \002%s\002 has been sent."), na->nick.c_str()); diff --git a/modules/commands/ns_saset.cpp b/modules/commands/ns_saset.cpp index f49af06e9..8d2ba08d9 100644 --- a/modules/commands/ns_saset.cpp +++ b/modules/commands/ns_saset.cpp @@ -33,7 +33,7 @@ class CommandNSSASet : public Command this->SendSyntax(source); source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); Anope::string this_name = source.command; - for (BotInfo::command_map::const_iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; diff --git a/modules/commands/ns_sendpass.cpp b/modules/commands/ns_sendpass.cpp index 6b2b2533b..5d88fd5a4 100644 --- a/modules/commands/ns_sendpass.cpp +++ b/modules/commands/ns_sendpass.cpp @@ -39,7 +39,7 @@ class CommandNSSendPass : public Command Anope::string tmp_pass; if (enc_decrypt(na->nc->pass, tmp_pass) == 1) { - if (SendPassMail(source.GetUser(), na, source.owner, tmp_pass)) + if (SendPassMail(source.GetUser(), na, source.service, tmp_pass)) { Log(Config->RestrictMail ? LOG_ADMIN : LOG_COMMAND, source, this) << "for " << na->nick; source.Reply(_("Password of \002%s\002 has been sent."), nick.c_str()); diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp index 719ddc4f3..0917d45bd 100644 --- a/modules/commands/ns_set.cpp +++ b/modules/commands/ns_set.cpp @@ -34,7 +34,7 @@ class CommandNSSet : public Command source.Reply(" "); source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); Anope::string this_name = source.command; - for (BotInfo::command_map::const_iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) + for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) { const Anope::string &c_name = it->first; const CommandInfo &info = it->second; @@ -50,7 +50,7 @@ class CommandNSSet : public Command } } source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str()); return true; } }; diff --git a/modules/commands/ns_set_email.cpp b/modules/commands/ns_set_email.cpp index 34aa68c5c..6966c2a79 100644 --- a/modules/commands/ns_set_email.cpp +++ b/modules/commands/ns_set_email.cpp @@ -88,7 +88,7 @@ class CommandNSSetEmail : public Command source.nc->Extend("ns_set_email", new ExtensibleItemClass<Anope::string>(param)); Anope::string old = source.nc->email; source.nc->email = param; - if (SendConfirmMail(source.GetUser(), source.owner)) + if (SendConfirmMail(source.GetUser(), source.service)) source.Reply(_("A confirmation email has been sent to \002%s\002. Follow the instructions in it to change your email address."), param.c_str()); source.nc->email = old; } diff --git a/modules/commands/os_kick.cpp b/modules/commands/os_kick.cpp index e3dd8cf8d..0a5165621 100644 --- a/modules/commands/os_kick.cpp +++ b/modules/commands/os_kick.cpp @@ -46,7 +46,7 @@ class CommandOSKick : public Command return; } - c->Kick(source.owner, u2, "%s (%s)", source.GetNick().c_str(), s.c_str()); + c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str()); Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")"; return; } @@ -60,7 +60,7 @@ class CommandOSKick : public Command "command. The kick message will have the nickname of the\n" "IRCop sending the KICK command prepended; for example:\n" " \n" - "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), source.owner->nick.c_str()); + "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/os_login.cpp b/modules/commands/os_login.cpp index 0ceac6428..c282b9662 100644 --- a/modules/commands/os_login.cpp +++ b/modules/commands/os_login.cpp @@ -45,7 +45,7 @@ class CommandOSLogin : public Command } else { - Log(LOG_ADMIN, source, this) << "and successfully identified to " << source.owner->nick; + Log(LOG_ADMIN, source, this) << "and successfully identified to " << source.service->nick; u->Extend("os_login_password_correct", NULL); source.Reply(_("Password accepted.")); } @@ -59,7 +59,7 @@ class CommandOSLogin : public Command source.Reply(" "); source.Reply(_("Logs you in to %s so you gain Services Operator privileges.\n" "This command may be unnecessary if your oper block is\n" - "configured without a password."), source.owner->nick.c_str()); + "configured without a password."), source.service->nick.c_str()); return true; } }; @@ -100,7 +100,7 @@ class CommandOSLogout : public Command source.Reply(" "); source.Reply(_("Logs you out from %s so you lose Services Operator privileges.\n" "This command is only useful if your oper block is configured\n" - "with a password."), source.owner->nick.c_str()); + "with a password."), source.service->nick.c_str()); return true; } }; diff --git a/modules/commands/os_mode.cpp b/modules/commands/os_mode.cpp index 55e5145c2..2fa8e5f69 100644 --- a/modules/commands/os_mode.cpp +++ b/modules/commands/os_mode.cpp @@ -34,7 +34,7 @@ class CommandOSMode : public Command source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); else { - c->SetModes(source.owner, false, modes.c_str()); + c->SetModes(source.service, false, modes.c_str()); Log(LOG_ADMIN, source, this) << modes << " on " << target; } @@ -69,10 +69,10 @@ class CommandOSUMode : public Command source.Reply(NICK_X_NOT_IN_USE, target.c_str()); else { - u2->SetModes(source.owner, "%s", modes.c_str()); + u2->SetModes(source.service, "%s", modes.c_str()); source.Reply(_("Changed usermodes of \002%s\002 to %s."), u2->nick.c_str(), modes.c_str()); - u2->SendMessage(source.owner, _("\002%s\002 changed your usermodes to %s."), source.GetNick().c_str(), modes.c_str()); + u2->SendMessage(source.service, _("\002%s\002 changed your usermodes to %s."), source.GetNick().c_str(), modes.c_str()); Log(LOG_ADMIN, source, this) << modes << " on " << target; } diff --git a/modules/commands/os_modinfo.cpp b/modules/commands/os_modinfo.cpp index 60fe8293f..88748a106 100644 --- a/modules/commands/os_modinfo.cpp +++ b/modules/commands/os_modinfo.cpp @@ -44,7 +44,7 @@ class CommandOSModInfo : public Command { const BotInfo *bi = it->second; - for (BotInfo::command_map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) + for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) { const Anope::string &c_name = cit->first; const CommandInfo &info = cit->second; diff --git a/modules/commands/os_oline.cpp b/modules/commands/os_oline.cpp index ccf053f7e..3fe622c1c 100644 --- a/modules/commands/os_oline.cpp +++ b/modules/commands/os_oline.cpp @@ -33,15 +33,15 @@ class CommandOSOLine : public Command source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (u2 && flag[0] == '+') { - ircdproto->SendSVSO(source.owner, nick, flag); - u2->SetMode(source.owner, UMODE_OPER); - u2->SendMessage(source.owner, _("You are now an IRC Operator.")); + ircdproto->SendSVSO(source.service, nick, flag); + u2->SetMode(source.service, UMODE_OPER); + u2->SendMessage(source.service, _("You are now an IRC Operator.")); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); Log(LOG_ADMIN, source, this) << "for " << nick; } else if (u2 && flag[0] == '-') { - ircdproto->SendSVSO(source.owner, nick, flag); + ircdproto->SendSVSO(source.service, nick, flag); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); Log(LOG_ADMIN, source, this) << "for " << nick; } diff --git a/modules/encryption/enc_md5.cpp b/modules/encryption/enc_md5.cpp index 73bc29557..bcbe4aeed 100644 --- a/modules/encryption/enc_md5.cpp +++ b/modules/encryption/enc_md5.cpp @@ -339,33 +339,31 @@ class EMD5 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override { - const NickAlias *na = findnick(account); + const NickAlias *na = findnick(req->GetAccount()); if (na == NULL) - return EVENT_CONTINUE; + return; NickCore *nc = na->nc; size_t pos = nc->pass.find(':'); if (pos == Anope::string::npos) - return EVENT_CONTINUE; + return; Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); if (!hash_method.equals_cs("md5")) - return EVENT_CONTINUE; + return; Anope::string buf; - this->OnEncrypt(password, buf); + this->OnEncrypt(req->GetPassword(), buf); if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (ModuleManager::FindFirstOf(ENCRYPTION) != this) - enc_encrypt(password, nc->pass); - return EVENT_ALLOW; + enc_encrypt(req->GetPassword(), nc->pass); + req->Success(this); } - - return EVENT_CONTINUE; } }; diff --git a/modules/encryption/enc_none.cpp b/modules/encryption/enc_none.cpp index 778ed6cba..9496939fd 100644 --- a/modules/encryption/enc_none.cpp +++ b/modules/encryption/enc_none.cpp @@ -41,33 +41,31 @@ class ENone : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override { - const NickAlias *na = findnick(account); + const NickAlias *na = findnick(req->GetAccount()); if (na == NULL) - return EVENT_CONTINUE; + return; NickCore *nc = na->nc; size_t pos = nc->pass.find(':'); if (pos == Anope::string::npos) - return EVENT_CONTINUE; + return; Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); if (!hash_method.equals_cs("plain")) - return EVENT_CONTINUE; + return; Anope::string buf; - this->OnEncrypt(password, buf); + this->OnEncrypt(req->GetPassword(), buf); if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (ModuleManager::FindFirstOf(ENCRYPTION) != this) - enc_encrypt(password, nc->pass); - return EVENT_ALLOW; + enc_encrypt(req->GetPassword(), nc->pass); + req->Success(this); } - - return EVENT_CONTINUE; } }; diff --git a/modules/encryption/enc_old.cpp b/modules/encryption/enc_old.cpp index 9fba199dc..b5ce86540 100644 --- a/modules/encryption/enc_old.cpp +++ b/modules/encryption/enc_old.cpp @@ -349,33 +349,31 @@ class EOld : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override { - const NickAlias *na = findnick(account); + const NickAlias *na = findnick(req->GetAccount()); if (na == NULL) - return EVENT_CONTINUE; + return; NickCore *nc = na->nc; size_t pos = nc->pass.find(':'); if (pos == Anope::string::npos) - return EVENT_CONTINUE; + return; Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); if (!hash_method.equals_cs("oldmd5")) - return EVENT_CONTINUE; + return; Anope::string buf; - this->OnEncrypt(password, buf); + this->OnEncrypt(req->GetPassword(), buf); if (nc->pass.equals_cs(buf)) { /* if we are NOT the first module in the list, * we want to re-encrypt the pass with the new encryption */ if (ModuleManager::FindFirstOf(ENCRYPTION) != this) - enc_encrypt(password, nc->pass); - return EVENT_ALLOW; + enc_encrypt(req->GetPassword(), nc->pass); + req->Success(this); } - - return EVENT_CONTINUE; } }; diff --git a/modules/encryption/enc_sha1.cpp b/modules/encryption/enc_sha1.cpp index 3735e65bc..28d216972 100644 --- a/modules/encryption/enc_sha1.cpp +++ b/modules/encryption/enc_sha1.cpp @@ -192,30 +192,28 @@ class ESHA1 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override { - const NickAlias *na = findnick(account); + const NickAlias *na = findnick(req->GetAccount()); if (na == NULL) - return EVENT_CONTINUE; + return; NickCore *nc = na->nc; size_t pos = nc->pass.find(':'); if (pos == Anope::string::npos) - return EVENT_CONTINUE; + return; Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); if (!hash_method.equals_cs("sha1")) - return EVENT_CONTINUE; + return; Anope::string buf; - this->OnEncrypt(password, buf); + this->OnEncrypt(req->GetPassword(), buf); if (nc->pass.equals_cs(buf)) { if (ModuleManager::FindFirstOf(ENCRYPTION) != this) - enc_encrypt(password, nc->pass); - return EVENT_ALLOW; + enc_encrypt(req->GetPassword(), nc->pass); + req->Success(this); } - - return EVENT_CONTINUE; } }; diff --git a/modules/encryption/enc_sha256.cpp b/modules/encryption/enc_sha256.cpp index cee21b01d..36eaa98fc 100644 --- a/modules/encryption/enc_sha256.cpp +++ b/modules/encryption/enc_sha256.cpp @@ -278,24 +278,24 @@ class ESHA256 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override { - const NickAlias *na = findnick(account); + const NickAlias *na = findnick(req->GetAccount()); if (na == NULL) - return EVENT_CONTINUE; + return; NickCore *nc = na->nc; size_t pos = nc->pass.find(':'); if (pos == Anope::string::npos) - return EVENT_CONTINUE; + return; Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); if (!hash_method.equals_cs("sha256")) - return EVENT_CONTINUE; + return; GetIVFromPass(nc->pass); use_iv = true; Anope::string buf; - this->OnEncrypt(password, buf); + this->OnEncrypt(req->GetPassword(), buf); if (nc->pass.equals_cs(buf)) { @@ -303,11 +303,9 @@ class ESHA256 : public Module * we want to re-encrypt the pass with the new encryption */ if (ModuleManager::FindFirstOf(ENCRYPTION) != this) - enc_encrypt(password, nc->pass); - return EVENT_ALLOW; + enc_encrypt(req->GetPassword(), nc->pass); + req->Success(this); } - - return EVENT_CONTINUE; } }; diff --git a/modules/extra/httpd.h b/modules/extra/httpd.h index 684c11512..d9e800d13 100644 --- a/modules/extra/httpd.h +++ b/modules/extra/httpd.h @@ -21,6 +21,23 @@ struct HTTPReply HTTPReply() : error(HTTP_ERROR_OK), length(0) { } + HTTPReply(const HTTPReply& other) : error(other.error), length(other.length) + { + content_type = other.content_type; + headers = other.headers; + cookies = other.cookies; + + for (unsigned i = 0; i < other.out.size(); ++i) + out.push_back(new Data(other.out[i]->buf, other.out[i]->len)); + } + + ~HTTPReply() + { + for (unsigned i = 0; i < out.size(); ++i) + delete out[i]; + out.clear(); + } + struct Data { char *buf; @@ -87,10 +104,10 @@ class HTTPPage : public Base * @param The HTTP header sent from the client to request the page * @param The HTTP header that will be sent back to the client */ - virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0; + virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0; }; -class HTTPClient : public ClientSocket, public BufferedSocket, public BinarySocket +class HTTPClient : public ClientSocket, public BufferedSocket, public BinarySocket, public Base { protected: void WriteClient(const Anope::string &message) diff --git a/modules/extra/m_httpd.cpp b/modules/extra/m_httpd.cpp index 626a62e8c..e802ed055 100644 --- a/modules/extra/m_httpd.cpp +++ b/modules/extra/m_httpd.cpp @@ -35,7 +35,7 @@ static Anope::string GetStatusFromCode(HTTPError err) return "501 Not Implemented"; } -class MyHTTPClient : public HTTPClient, public Base +class MyHTTPClient : public HTTPClient { HTTPProvider *provider; HTTPMessage header; @@ -78,9 +78,8 @@ class MyHTTPClient : public HTTPClient, public Base HTTPReply reply; - this->page->OnRequest(this->provider, this->page_name, this, this->header, reply); - - this->SendReply(&reply); + if (this->page->OnRequest(this->provider, this->page_name, this, this->header, reply)) + this->SendReply(&reply); } public: diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index 7fcd67e5d..2ca08f975 100644 --- a/modules/extra/m_ldap_authentication.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -2,6 +2,8 @@ #include "nickserv.h" #include "ldap.h" +static Module *me; + static Anope::string basedn; static Anope::string search_filter; static Anope::string object_class; @@ -10,17 +12,21 @@ static Anope::string username_attribute; struct IdentifyInfo { - dynamic_reference<Command> command; - CommandSource source; - std::vector<Anope::string> params; - Anope::string account; - Anope::string pass; - Anope::string dn; + dynamic_reference<User> user; + IdentifyRequest *req; service_reference<LDAPProvider> lprov; bool admin_bind; + Anope::string dn; - IdentifyInfo(Command *c, CommandSource &s, const std::vector<Anope::string> &pa, const Anope::string &a, const Anope::string &p, service_reference<LDAPProvider> &lp) : - command(c), source(s), params(pa), account(a), pass(p), lprov(lp), admin_bind(true) { } + IdentifyInfo(User *u, IdentifyRequest *r, service_reference<LDAPProvider> &lp) : user(u), req(r), lprov(lp), admin_bind(true) + { + req->Hold(me); + } + + ~IdentifyInfo() + { + req->Release(me); + } }; class IdentifyInterface : public LDAPInterface @@ -46,9 +52,9 @@ class IdentifyInterface : public LDAPInterface IdentifyInfo *ii = it->second; this->requests.erase(it); - if (!ii->source.GetUser() || !ii->command || !ii->lprov) + if (!ii->lprov) { - delete this; + delete ii; return; } @@ -63,69 +69,55 @@ class IdentifyInterface : public LDAPInterface const LDAPAttributes &attr = r.get(0); ii->dn = attr.get("dn"); Log(LOG_DEBUG) << "m_ldap_authenticationn: binding as " << ii->dn; - LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->pass); + LDAPQuery id = ii->lprov->Bind(this, ii->dn, ii->req->GetPassword()); this->Add(id, ii); + return; } catch (const LDAPException &ex) { Log() << "m_ldap_authentication: Error binding after search: " << ex.GetReason(); - delete ii; } } - else - { - User *u = ii->source.GetUser(); - Command *c = ii->command; - - u->Extend("m_ldap_authentication_error", NULL); - - c->Execute(ii->source, ii->params); - - delete ii; - } break; } case LDAPResult::QUERY_BIND: { if (ii->admin_bind) { - Anope::string sf = search_filter.replace_all_cs("%account", ii->account).replace_all_cs("%object_class", object_class); + Anope::string sf = search_filter.replace_all_cs("%account", ii->req->GetAccount()).replace_all_cs("%object_class", object_class); Log(LOG_DEBUG) << "m_ldap_authentication: searching for " << sf; LDAPQuery id = ii->lprov->Search(this, basedn, sf); this->Add(id, ii); ii->admin_bind = false; + return; } else { - User *u = ii->source.GetUser(); - Command *c = ii->command; - - u->Extend("m_ldap_authentication_authenticated", NULL); - - NickAlias *na = findnick(ii->account); + NickAlias *na = findnick(ii->req->GetAccount()); if (na == NULL) { - na = new NickAlias(ii->account, new NickCore(ii->account)); - if (Config->NSAddAccessOnReg) - na->nc->AddAccess(create_mask(u)); - - BotInfo *bi = findbot(Config->NickServ); - if (bi) - u->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); + na = new NickAlias(ii->req->GetAccount(), new NickCore(ii->req->GetAccount())); + if (ii->user) + { + if (Config->NSAddAccessOnReg) + na->nc->AddAccess(create_mask(ii->user)); + + const BotInfo *bi = findbot(Config->NickServ); + if (bi) + ii->user->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); + } } - na->nc->Extend("m_ldap_authentication_dn", new ExtensibleItemClass<Anope::string>(ii->dn)); - - enc_encrypt(ii->pass, na->nc->pass); - - c->Execute(ii->source, ii->params); - delete ii; + + ii->req->Success(me); } break; } default: - delete ii; + break; } + + delete ii; } void OnError(const LDAPResult &r) anope_override @@ -135,20 +127,6 @@ class IdentifyInterface : public LDAPInterface return; IdentifyInfo *ii = it->second; this->requests.erase(it); - - if (!ii->source.GetUser() || !ii->command) - { - delete ii; - return; - } - - User *u = ii->source.GetUser(); - Command *c = ii->command; - - u->Extend("m_ldap_authentication_error", NULL); - - c->Execute(ii->source, ii->params); - delete ii; } }; @@ -235,6 +213,8 @@ class NSIdentifyLDAP : public Module { this->SetAuthor("Anope"); + me = this; + Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnCheckAuthentication, I_OnNickIdentify, I_OnNickRegister }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); ModuleManager::SetPriority(this, PRIORITY_FIRST); @@ -267,28 +247,12 @@ class NSIdentifyLDAP : public Module return EVENT_CONTINUE; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override { + if (!this->ldap) + return; - if (c == NULL || source == NULL || !this->ldap) - return EVENT_CONTINUE; - - User *u = source->GetUser(); - if (!u) - return EVENT_CONTINUE; - - if (u->HasExt("m_ldap_authentication_authenticated")) - { - u->Shrink("m_ldap_authentication_authenticated"); - return EVENT_ALLOW; - } - else if (u->HasExt("m_ldap_authentication_error")) - { - u->Shrink("m_ldap_authentication_error"); - return EVENT_CONTINUE; - } - - IdentifyInfo *ii = new IdentifyInfo(c, *source, params, account, password, this->ldap); + IdentifyInfo *ii = new IdentifyInfo(u, req, this->ldap); try { LDAPQuery id = this->ldap->BindAsAdmin(&this->iinterface); @@ -298,10 +262,7 @@ class NSIdentifyLDAP : public Module { delete ii; Log() << "ns_identify_ldap: " << ex.GetReason(); - return EVENT_CONTINUE; } - - return EVENT_STOP; } void OnNickIdentify(User *u) anope_override diff --git a/modules/extra/m_sql_authentication.cpp b/modules/extra/m_sql_authentication.cpp index 957258fcb..9375615ee 100644 --- a/modules/extra/m_sql_authentication.cpp +++ b/modules/extra/m_sql_authentication.cpp @@ -1,71 +1,71 @@ #include "module.h" #include "sql.h" +static Module *me; + class SQLAuthenticationResult : public SQLInterface { - dynamic_reference<Command> cmd; - CommandSource source; - std::vector<Anope::string> params; dynamic_reference<User> user; - Anope::string account; + IdentifyRequest *req; public: - SQLAuthenticationResult(Module *m, Command *c, CommandSource &s, const std::vector<Anope::string> &p, User *u, const Anope::string &a) : SQLInterface(m), cmd(c), source(s), params(p), user(u), account(a) { } + SQLAuthenticationResult(User *u, IdentifyRequest *r) : SQLInterface(me), user(u), req(r) + { + req->Hold(me); + } + + ~SQLAuthenticationResult() + { + req->Release(me); + } void OnResult(const SQLResult &r) anope_override { - if (user && cmd) + if (r.Rows() == 0) { - Anope::string email; + Log(LOG_DEBUG) << "m_sql_authentication: Unsuccessful authentication for " << req->GetAccount(); + delete this; + return; + } - if (r.Rows() > 0) - { - user->Extend("m_sql_authentication_success", NULL); + Log(LOG_DEBUG) << "m_sql_authentication: Successful authentication for " << req->GetAccount(); - try - { - email = r.Get(0, "email"); - } - catch (const SQLException &) { } - } - else - user->Extend("m_sql_authentication_failed", NULL); + Anope::string email; + try + { + email = r.Get(0, "email"); + } + catch (const SQLException &) { } - BotInfo *bi = findbot(Config->NickServ); - NickAlias *na = findnick(account); - if (na == NULL) + const BotInfo *bi = findbot(Config->NickServ); + NickAlias *na = findnick(req->GetAccount()); + if (na == NULL) + { + na = new NickAlias(req->GetAccount(), new NickCore(req->GetAccount())); + if (user) { - na = new NickAlias(account, new NickCore(account)); if (Config->NSAddAccessOnReg) na->nc->AddAccess(create_mask(user)); if (bi) user->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); } + } - if (!email.empty() && email != na->nc->email) - { - na->nc->email = email; - if (bi) - user->SendMessage(bi, _("Your email has been updated to \002%s\002."), email.c_str()); - } - - cmd->Execute(source, params); + if (!email.empty() && email != na->nc->email) + { + na->nc->email = email; + if (user && bi) + user->SendMessage(bi, _("Your email has been updated to \002%s\002."), email.c_str()); } + req->Success(me); delete this; } void OnError(const SQLResult &r) anope_override { Log() << "m_sql_authentication: Error executing query " << r.GetQuery().query << ": " << r.GetError(); - - if (user && cmd) - { - user->Extend("m_sql_authentication_failed", NULL); - cmd->Execute(source, params); - } - delete this; } }; @@ -84,6 +84,8 @@ class ModuleSQLAuthentication : public Module { this->SetAuthor("Anope"); + me = this; + Implementation i[] = { I_OnReload, I_OnPreCommand, I_OnCheckAuthentication }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); @@ -113,37 +115,32 @@ class ModuleSQLAuthentication : public Module return EVENT_CONTINUE; } - EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) anope_override + void OnCheckAuthentication(User *u, IdentifyRequest *req) anope_override { - if (!source || !source->GetUser()) - return EVENT_CONTINUE; - else if (!this->SQL) + if (!this->SQL) { Log() << "m_sql_authentication: Unable to find SQL engine"; - return EVENT_CONTINUE; + return; } - else if (source->GetUser()->HasExt("m_sql_authentication_success")) + + SQLQuery q(this->query); + q.setValue("a", req->GetAccount()); + q.setValue("p", req->GetPassword()); + if (u) { - source->GetUser()->Shrink("m_sql_authentication_success"); - return EVENT_ALLOW; + q.setValue("n", u->nick); + q.setValue("i", u->ip); } - else if (source->GetUser()->HasExt("m_sql_authentication_failed")) + else { - source->GetUser()->Shrink("m_sql_authentication_failed"); - return EVENT_CONTINUE; + q.setValue("n", ""); + q.setValue("i", ""); } - SQLQuery q(this->query); - q.setValue("a", account); - q.setValue("p", password); - q.setValue("n", source->GetNick()); - q.setValue("i", source->GetUser()->ip); - - this->SQL->Run(new SQLAuthenticationResult(this, c, *source, params, source->GetUser(), account), q); - Log(LOG_DEBUG) << "m_sql_authentication: Checking authentication for " << account; + this->SQL->Run(new SQLAuthenticationResult(u, req), q); - return EVENT_STOP; + Log(LOG_DEBUG) << "m_sql_authentication: Checking authentication for " << req->GetAccount(); } }; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index dc12d565e..94b655ad7 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -1,6 +1,39 @@ #include "module.h" #include "xmlrpc.h" +static Module *me; + +class XMLRPCIdentifyRequest : public IdentifyRequest +{ + XMLRPCRequest request; + dynamic_reference<XMLRPCServiceInterface> xinterface; + dynamic_reference<XMLRPCClientSocket> source; + + public: + XMLRPCIdentifyRequest(Module *m, XMLRPCRequest& req, XMLRPCServiceInterface* iface, XMLRPCClientSocket* s, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(m, acc, pass), request(req), xinterface(iface), source(s) { } + + void OnSuccess() anope_override + { + if (!xinterface || !source) + return; + + request.reply("result", "Success"); + request.reply("account", GetAccount()); + + xinterface->Reply(source, &request); + } + + void OnFail() anope_override + { + if (!xinterface || !source) + return; + + request.reply("error", "Invalid password"); + + xinterface->Reply(source, &request); + } +}; + class MyXMLRPCEvent : public XMLRPCEvent { public: @@ -55,11 +88,7 @@ class MyXMLRPCEvent : public XMLRPCEvent } reply(out); - CommandSource source(user, NULL, na ? *na->nc : NULL, &reply); - source.c = NULL; - source.owner = bi; - source.service = bi; - + CommandSource source(user, NULL, na ? *na->nc : NULL, &reply, bi); RunCommand(source, command); if (!out.empty()) @@ -77,22 +106,9 @@ class MyXMLRPCEvent : public XMLRPCEvent request->reply("error", "Invalid parameters"); else { - const NickAlias *na = findnick(username); - - if (!na) - request->reply("error", "Invalid account"); - else - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, password)); - if (MOD_RESULT == EVENT_ALLOW) - { - request->reply("result", "Success"); - request->reply("account", na->nc->display); - } - else - request->reply("error", "Invalid password"); - } + XMLRPCIdentifyRequest *req = new XMLRPCIdentifyRequest(me, *request, iface, source, username, password); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req)); + req->Dispatch(); } } @@ -234,6 +250,8 @@ class ModuleXMLRPCMain : public Module if (!xmlrpc) throw ModuleException("Unable to find xmlrpc reference, is m_xmlrpc loaded?"); + me = this; + xmlrpc->Register(&stats); } diff --git a/modules/extra/webcpanel/pages/chanserv/access.cpp b/modules/extra/webcpanel/pages/chanserv/access.cpp index d3ec2ad99..71fe1a7e9 100644 --- a/modules/extra/webcpanel/pages/chanserv/access.cpp +++ b/modules/extra/webcpanel/pages/chanserv/access.cpp @@ -11,7 +11,7 @@ WebCPanel::ChanServ::Access::Access(const Anope::string &cat, const Anope::strin { } -void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { const Anope::string &chname = message.get_data["channel"]; @@ -19,19 +19,19 @@ void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s { reply.error = HTTP_FOUND; reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info"; - return; + return true; } ChannelInfo *ci = cs_findchan(chname); if (!ci) - return; + return true; AccessGroup u_access = ci->AccessFor(na->nc); bool has_priv = na->nc->IsServicesOper() && na->nc->o->ot->HasPriv("chanserv/access/modify"); if (!u_access.HasPriv("ACCESS_LIST") && !has_priv) - return; + return true; const ChanAccess *highest = u_access.Highest(); @@ -136,6 +136,7 @@ void WebCPanel::ChanServ::Access::OnRequest(HTTPProvider *server, const Anope::s TemplateFileServer page("chanserv/access.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } std::set<Anope::string> WebCPanel::ChanServ::Access::GetData() anope_override diff --git a/modules/extra/webcpanel/pages/chanserv/access.h b/modules/extra/webcpanel/pages/chanserv/access.h index 50425aa40..d5fbbf68c 100644 --- a/modules/extra/webcpanel/pages/chanserv/access.h +++ b/modules/extra/webcpanel/pages/chanserv/access.h @@ -16,7 +16,7 @@ class Access : public WebPanelProtectedPage public: Access(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; std::set<Anope::string> GetData() anope_override; }; diff --git a/modules/extra/webcpanel/pages/chanserv/akick.cpp b/modules/extra/webcpanel/pages/chanserv/akick.cpp index bc80437cc..bb38c5e06 100644 --- a/modules/extra/webcpanel/pages/chanserv/akick.cpp +++ b/modules/extra/webcpanel/pages/chanserv/akick.cpp @@ -11,7 +11,7 @@ WebCPanel::ChanServ::Akick::Akick(const Anope::string &cat, const Anope::string { } -void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { const Anope::string &chname = message.get_data["channel"]; @@ -19,19 +19,19 @@ void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st { reply.error = HTTP_FOUND; reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info"; - return; + return true; } ChannelInfo *ci = cs_findchan(chname); if (!ci) - return; + return true; AccessGroup u_access = ci->AccessFor(na->nc); bool has_priv = na->nc->IsServicesOper() && na->nc->o->ot->HasPriv("chanserv/access/modify"); if (!u_access.HasPriv("akick") && !has_priv) - return; + return true; if (message.get_data["del"].empty() == false && message.get_data["mask"].empty() == false) { @@ -70,6 +70,7 @@ void WebCPanel::ChanServ::Akick::OnRequest(HTTPProvider *server, const Anope::st TemplateFileServer page("chanserv/akick.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } std::set<Anope::string> WebCPanel::ChanServ::Akick::GetData() anope_override diff --git a/modules/extra/webcpanel/pages/chanserv/akick.h b/modules/extra/webcpanel/pages/chanserv/akick.h index ff4a4653e..cd8408934 100644 --- a/modules/extra/webcpanel/pages/chanserv/akick.h +++ b/modules/extra/webcpanel/pages/chanserv/akick.h @@ -16,7 +16,7 @@ class Akick : public WebPanelProtectedPage public: Akick(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; std::set<Anope::string> GetData() anope_override; }; diff --git a/modules/extra/webcpanel/pages/chanserv/info.cpp b/modules/extra/webcpanel/pages/chanserv/info.cpp index 8db88f496..44ae98537 100644 --- a/modules/extra/webcpanel/pages/chanserv/info.cpp +++ b/modules/extra/webcpanel/pages/chanserv/info.cpp @@ -11,7 +11,7 @@ WebCPanel::ChanServ::Info::Info(const Anope::string &cat, const Anope::string &u { } -void WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { // XXX this is slightly inefficient for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) @@ -25,8 +25,8 @@ void WebCPanel::ChanServ::Info::OnRequest(HTTPProvider *server, const Anope::str } } - TemplateFileServer page("chanserv/main.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/chanserv/info.h b/modules/extra/webcpanel/pages/chanserv/info.h index 87dc9836b..c55e1b1eb 100644 --- a/modules/extra/webcpanel/pages/chanserv/info.h +++ b/modules/extra/webcpanel/pages/chanserv/info.h @@ -16,7 +16,7 @@ class Info : public WebPanelProtectedPage public: Info(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/chanserv/set.cpp b/modules/extra/webcpanel/pages/chanserv/set.cpp index 764eb13ac..7d144c6de 100644 --- a/modules/extra/webcpanel/pages/chanserv/set.cpp +++ b/modules/extra/webcpanel/pages/chanserv/set.cpp @@ -11,7 +11,7 @@ WebCPanel::ChanServ::Set::Set(const Anope::string &cat, const Anope::string &u) { } -void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { const Anope::string &chname = message.get_data["channel"]; @@ -19,13 +19,13 @@ void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri { reply.error = HTTP_FOUND; reply.headers["Location"] = "http://" + message.headers["Host"] + "/chanserv/info"; - return; + return true; } ChannelInfo *ci = cs_findchan(chname); if (!ci || !ci->AccessFor(na->nc).HasPriv("SET")) - return; + return true; if (message.post_data.empty() == false) { @@ -125,6 +125,7 @@ void WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri TemplateFileServer page("chanserv/set.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } std::set<Anope::string> WebCPanel::ChanServ::Set::GetData() anope_override diff --git a/modules/extra/webcpanel/pages/chanserv/set.h b/modules/extra/webcpanel/pages/chanserv/set.h index 67e817493..4d4113b5a 100644 --- a/modules/extra/webcpanel/pages/chanserv/set.h +++ b/modules/extra/webcpanel/pages/chanserv/set.h @@ -16,7 +16,7 @@ class Set : public WebPanelProtectedPage public: Set(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; std::set<Anope::string> GetData() anope_override; }; diff --git a/modules/extra/webcpanel/pages/confirm.cpp b/modules/extra/webcpanel/pages/confirm.cpp index f18d28129..18e2004b5 100644 --- a/modules/extra/webcpanel/pages/confirm.cpp +++ b/modules/extra/webcpanel/pages/confirm.cpp @@ -7,7 +7,7 @@ #include "../webcpanel.h" -void WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) +bool WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) { TemplateFileServer::Replacements replacements; const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"], &email = message.post_data["email"]; @@ -27,5 +27,6 @@ void WebCPanel::Confirm::OnRequest(HTTPProvider *server, const Anope::string &pa TemplateFileServer page("confirm.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/confirm.h b/modules/extra/webcpanel/pages/confirm.h index d4d19d9c6..c6a5d180d 100644 --- a/modules/extra/webcpanel/pages/confirm.h +++ b/modules/extra/webcpanel/pages/confirm.h @@ -15,7 +15,7 @@ class Confirm : public WebPanelPage public: Confirm(const Anope::string &u) : WebPanelPage(u) { } - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/index.cpp b/modules/extra/webcpanel/pages/index.cpp index e0db8f8de..357d3ec3b 100644 --- a/modules/extra/webcpanel/pages/index.cpp +++ b/modules/extra/webcpanel/pages/index.cpp @@ -7,67 +7,93 @@ #include "../webcpanel.h" -void WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) +class WebpanelRequest : public IdentifyRequest { + HTTPReply reply; + HTTPMessage message; + dynamic_reference<HTTPProvider> server; + Anope::string page_name; + dynamic_reference<HTTPClient> client; TemplateFileServer::Replacements replacements; - const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"]; - replacements["TITLE"] = page_title; + public: + WebpanelRequest(Module *o, HTTPReply &r, HTTPMessage &m, HTTPProvider *s, const Anope::string &p_n, HTTPClient *c, TemplateFileServer::Replacements &re, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(o, user, pass), reply(r), message(m), server(s), page_name(p_n), client(c), replacements(re) { } - if (!user.empty() && !pass.empty()) + void OnSuccess() anope_override { - // Rate limit check. - - NickAlias *na = findnick(user); - - EventReturn MOD_RESULT = EVENT_CONTINUE; - - if (na) + if (!client) + return; + NickAlias *na = findnick(this->GetAccount()); + if (!na) { - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(NULL, NULL, std::vector<Anope::string>(), na->nc->display, pass)); + this->OnFail(); + return; } - if (MOD_RESULT == EVENT_ALLOW) + Anope::string id; + for (int i = 0; i < 64; ++i) { - Anope::string id; - for (int i = 0; i < 64; ++i) - { - char c; - do - c = 48 + (rand() % 75); - while (!isalnum(c)); - id += c; - } - - na->Extend("webcpanel_id", new ExtensibleItemClass<Anope::string>(id)); - na->Extend("webcpanel_ip", new ExtensibleItemClass<Anope::string>(client->GetIP())); - - { - HTTPReply::cookie c; - c.push_back(std::make_pair("account", na->nick)); - c.push_back(std::make_pair("Path", "/")); - reply.cookies.push_back(c); - } - - { - HTTPReply::cookie c; - c.push_back(std::make_pair("id", id)); - c.push_back(std::make_pair("Path", "/")); - reply.cookies.push_back(c); - } - - reply.error = HTTP_FOUND; - reply.headers["Location"] = "http://" + message.headers["Host"] + "/nickserv/info"; - return; + char c; + do + c = 48 + (rand() % 75); + while (!isalnum(c)); + id += c; } - else + + na->Extend("webcpanel_id", new ExtensibleItemClass<Anope::string>(id)); + na->Extend("webcpanel_ip", new ExtensibleItemClass<Anope::string>(client->GetIP())); + { - replacements["INVALID_LOGIN"] = "Invalid username or password"; + HTTPReply::cookie c; + c.push_back(std::make_pair("account", na->nick)); + c.push_back(std::make_pair("Path", "/")); + reply.cookies.push_back(c); + } + + { + HTTPReply::cookie c; + c.push_back(std::make_pair("id", id)); + c.push_back(std::make_pair("Path", "/")); + reply.cookies.push_back(c); } + + reply.error = HTTP_FOUND; + reply.headers["Location"] = "http://" + message.headers["Host"] + "/nickserv/info"; + + client->SendReply(&reply); } - TemplateFileServer page("login.html"); + void OnFail() anope_override + { + if (!client) + return; + replacements["INVALID_LOGIN"] = "Invalid username or password"; + TemplateFileServer page("login.html"); + page.Serve(server, page_name, client, message, reply, replacements); + client->SendReply(&reply); + } +}; + +bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) +{ + TemplateFileServer::Replacements replacements; + const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"]; + + replacements["TITLE"] = page_title; + + if (!user.empty() && !pass.empty()) + { + // Rate limit check. + + WebpanelRequest *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass); + FOREACH_MOD(I_OnCheckAuthentication, OnCheckAuthentication(NULL, req)); + req->Dispatch(); + return false; + } + + TemplateFileServer page("login.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/index.h b/modules/extra/webcpanel/pages/index.h index 2f4d9c400..e67d7181a 100644 --- a/modules/extra/webcpanel/pages/index.h +++ b/modules/extra/webcpanel/pages/index.h @@ -15,7 +15,7 @@ class Index : public WebPanelPage public: Index(const Anope::string &u) : WebPanelPage(u) { } - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/logout.cpp b/modules/extra/webcpanel/pages/logout.cpp index 90a6a8a9b..efa93ab4f 100644 --- a/modules/extra/webcpanel/pages/logout.cpp +++ b/modules/extra/webcpanel/pages/logout.cpp @@ -11,12 +11,13 @@ WebCPanel::Logout::Logout(const Anope::string &u) : WebPanelProtectedPage("", u) { } -void WebCPanel::Logout::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::Logout::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { na->Shrink("webcpanel_id"); na->Shrink("webcpanel_ip"); reply.error = HTTP_FOUND; reply.headers["Location"] = "http://" + message.headers["Host"]; + return true; } diff --git a/modules/extra/webcpanel/pages/logout.h b/modules/extra/webcpanel/pages/logout.h index 4f31e4a00..d00a83733 100644 --- a/modules/extra/webcpanel/pages/logout.h +++ b/modules/extra/webcpanel/pages/logout.h @@ -13,7 +13,7 @@ class Logout : public WebPanelProtectedPage public: Logout(const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/memoserv/memos.cpp b/modules/extra/webcpanel/pages/memoserv/memos.cpp index eafbde3a5..00b913ef0 100644 --- a/modules/extra/webcpanel/pages/memoserv/memos.cpp +++ b/modules/extra/webcpanel/pages/memoserv/memos.cpp @@ -11,7 +11,7 @@ WebCPanel::MemoServ::Memos::Memos(const Anope::string &cat, const Anope::string { } -void WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { const Anope::string &chname = message.get_data["channel"]; ChannelInfo *ci; @@ -117,5 +117,6 @@ void WebCPanel::MemoServ::Memos::OnRequest(HTTPProvider *server, const Anope::st TemplateFileServer page("memoserv/memos.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/memoserv/memos.h b/modules/extra/webcpanel/pages/memoserv/memos.h index 00c4c346b..32942147f 100644 --- a/modules/extra/webcpanel/pages/memoserv/memos.h +++ b/modules/extra/webcpanel/pages/memoserv/memos.h @@ -16,7 +16,7 @@ class Memos : public WebPanelProtectedPage public: Memos(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/nickserv/access.cpp b/modules/extra/webcpanel/pages/nickserv/access.cpp index c18c5ccb0..40128f47e 100644 --- a/modules/extra/webcpanel/pages/nickserv/access.cpp +++ b/modules/extra/webcpanel/pages/nickserv/access.cpp @@ -11,7 +11,7 @@ WebCPanel::NickServ::Access::Access(const Anope::string &cat, const Anope::strin { } -void WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { if (message.post_data.count("access") > 0) { @@ -35,5 +35,6 @@ void WebCPanel::NickServ::Access::OnRequest(HTTPProvider *server, const Anope::s TemplateFileServer page("nickserv/access.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/nickserv/access.h b/modules/extra/webcpanel/pages/nickserv/access.h index 3f4059aa4..068757877 100644 --- a/modules/extra/webcpanel/pages/nickserv/access.h +++ b/modules/extra/webcpanel/pages/nickserv/access.h @@ -16,7 +16,7 @@ class Access : public WebPanelProtectedPage public: Access(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/nickserv/alist.cpp b/modules/extra/webcpanel/pages/nickserv/alist.cpp index d3c92dcf4..2fd184dbb 100644 --- a/modules/extra/webcpanel/pages/nickserv/alist.cpp +++ b/modules/extra/webcpanel/pages/nickserv/alist.cpp @@ -11,7 +11,7 @@ WebCPanel::NickServ::Alist::Alist(const Anope::string &cat, const Anope::string { } -void WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { int chan_count = 0; @@ -45,5 +45,6 @@ void WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st TemplateFileServer page("nickserv/alist.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/nickserv/alist.h b/modules/extra/webcpanel/pages/nickserv/alist.h index 5e4b31724..93ec85d03 100644 --- a/modules/extra/webcpanel/pages/nickserv/alist.h +++ b/modules/extra/webcpanel/pages/nickserv/alist.h @@ -16,7 +16,7 @@ class Alist : public WebPanelProtectedPage public: Alist(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/nickserv/cert.cpp b/modules/extra/webcpanel/pages/nickserv/cert.cpp index e354addca..5c799d2f6 100644 --- a/modules/extra/webcpanel/pages/nickserv/cert.cpp +++ b/modules/extra/webcpanel/pages/nickserv/cert.cpp @@ -11,7 +11,7 @@ WebCPanel::NickServ::Cert::Cert(const Anope::string &cat, const Anope::string &u { } -void WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { if (message.post_data.count("certfp") > 0) { @@ -35,5 +35,6 @@ void WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str TemplateFileServer page("nickserv/cert.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/nickserv/cert.h b/modules/extra/webcpanel/pages/nickserv/cert.h index 1f9f1b4ad..bcc148132 100644 --- a/modules/extra/webcpanel/pages/nickserv/cert.h +++ b/modules/extra/webcpanel/pages/nickserv/cert.h @@ -16,7 +16,7 @@ class Cert : public WebPanelProtectedPage public: Cert(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/nickserv/info.cpp b/modules/extra/webcpanel/pages/nickserv/info.cpp index 7ae07ad28..3ec61b03f 100644 --- a/modules/extra/webcpanel/pages/nickserv/info.cpp +++ b/modules/extra/webcpanel/pages/nickserv/info.cpp @@ -11,7 +11,7 @@ WebCPanel::NickServ::Info::Info(const Anope::string &cat, const Anope::string &u { } -void WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { if (message.post_data.empty() == false) { @@ -107,5 +107,6 @@ void WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str TemplateFileServer page("nickserv/info.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/nickserv/info.h b/modules/extra/webcpanel/pages/nickserv/info.h index 05fc981ac..45ffbc882 100644 --- a/modules/extra/webcpanel/pages/nickserv/info.h +++ b/modules/extra/webcpanel/pages/nickserv/info.h @@ -16,7 +16,7 @@ class Info : public WebPanelProtectedPage public: Info(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/operserv/akill.cpp b/modules/extra/webcpanel/pages/operserv/akill.cpp index 8a66b8d9b..3d66b5c6a 100644 --- a/modules/extra/webcpanel/pages/operserv/akill.cpp +++ b/modules/extra/webcpanel/pages/operserv/akill.cpp @@ -11,7 +11,7 @@ WebCPanel::OperServ::Akill::Akill(const Anope::string &cat, const Anope::string { } -void WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) +bool WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements) { static service_reference<XLineManager> akills("XLineManager","xlinemanager/sgline"); @@ -59,5 +59,6 @@ void WebCPanel::OperServ::Akill::OnRequest(HTTPProvider *server, const Anope::st TemplateFileServer page("operserv/akill.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/operserv/akill.h b/modules/extra/webcpanel/pages/operserv/akill.h index 4b5f8f1dd..270ae84a7 100644 --- a/modules/extra/webcpanel/pages/operserv/akill.h +++ b/modules/extra/webcpanel/pages/operserv/akill.h @@ -16,7 +16,7 @@ class Akill : public WebPanelProtectedPage public: Akill(const Anope::string &cat, const Anope::string &u); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) anope_override; }; } diff --git a/modules/extra/webcpanel/pages/register.cpp b/modules/extra/webcpanel/pages/register.cpp index 84efb3fc0..e8ed84303 100644 --- a/modules/extra/webcpanel/pages/register.cpp +++ b/modules/extra/webcpanel/pages/register.cpp @@ -7,7 +7,7 @@ #include "../webcpanel.h" -void WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) +bool WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) { TemplateFileServer::Replacements replacements; @@ -19,5 +19,6 @@ void WebCPanel::Register::OnRequest(HTTPProvider *server, const Anope::string &p TemplateFileServer page("register.html"); page.Serve(server, page_name, client, message, reply, replacements); + return true; } diff --git a/modules/extra/webcpanel/pages/register.h b/modules/extra/webcpanel/pages/register.h index 0651bfba6..deb46c950 100644 --- a/modules/extra/webcpanel/pages/register.h +++ b/modules/extra/webcpanel/pages/register.h @@ -15,7 +15,7 @@ class Register : public WebPanelPage public: Register(const Anope::string &u) : WebPanelPage(u) { } - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; }; } diff --git a/modules/extra/webcpanel/static_fileserver.cpp b/modules/extra/webcpanel/static_fileserver.cpp index 6e6d5ccd4..1fbf46ee8 100644 --- a/modules/extra/webcpanel/static_fileserver.cpp +++ b/modules/extra/webcpanel/static_fileserver.cpp @@ -17,7 +17,7 @@ StaticFileServer::StaticFileServer(const Anope::string &f_n, const Anope::string { } -void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) +bool StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) { int fd = open((template_base + "/" + this->file_name).c_str(), O_RDONLY); if (fd < 0) @@ -25,7 +25,7 @@ void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page Log(LOG_NORMAL, "httpd") << "Error serving file " << page_name << " (" << (template_base + "/" + this->file_name) << "): " << strerror(errno); client->SendError(HTTP_PAGE_NOT_FOUND, "Page not found"); - return; + return true; } reply.content_type = this->GetContentType(); @@ -37,5 +37,6 @@ void StaticFileServer::OnRequest(HTTPProvider *server, const Anope::string &page reply.Write(buffer, i); close(fd); + return true; } diff --git a/modules/extra/webcpanel/static_fileserver.h b/modules/extra/webcpanel/static_fileserver.h index 17fa7d6b2..238614610 100644 --- a/modules/extra/webcpanel/static_fileserver.h +++ b/modules/extra/webcpanel/static_fileserver.h @@ -14,6 +14,6 @@ class StaticFileServer : public HTTPPage public: StaticFileServer(const Anope::string &f_n, const Anope::string &u, const Anope::string &c_t); - void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; + bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) anope_override; }; diff --git a/modules/extra/webcpanel/template_fileserver.cpp b/modules/extra/webcpanel/template_fileserver.cpp index 45dc4dadd..b1881b811 100644 --- a/modules/extra/webcpanel/template_fileserver.cpp +++ b/modules/extra/webcpanel/template_fileserver.cpp @@ -239,5 +239,6 @@ void TemplateFileServer::Serve(HTTPProvider *server, const Anope::string &page_n } reply.Write(finished); + return; } diff --git a/modules/extra/webcpanel/webcpanel.cpp b/modules/extra/webcpanel/webcpanel.cpp index 460efba3a..c23b6efbf 100644 --- a/modules/extra/webcpanel/webcpanel.cpp +++ b/modules/extra/webcpanel/webcpanel.cpp @@ -7,6 +7,7 @@ #include "webcpanel.h" +Module *me; Anope::string provider_name, template_name, template_base, page_title; class ModuleWebCPanel : public Module @@ -45,6 +46,8 @@ class ModuleWebCPanel : public Module { this->SetAuthor("Anope"); + me = this; + ConfigReader reader; provider_name = reader.ReadValue("webcpanel", "server", "httpd/main", 0); template_name = reader.ReadValue("webcpanel", "template", "template", 0); @@ -214,10 +217,7 @@ namespace WebPanel } my_reply(r); - CommandSource source(user, NULL, nc, &my_reply); - source.owner = bi; - source.service = bi; - + CommandSource source(user, NULL, nc, &my_reply, bi); cmd->Execute(source, params); } } diff --git a/modules/extra/webcpanel/webcpanel.h b/modules/extra/webcpanel/webcpanel.h index 9573bbb6c..926feaf53 100644 --- a/modules/extra/webcpanel/webcpanel.h +++ b/modules/extra/webcpanel/webcpanel.h @@ -11,6 +11,8 @@ #include "static_fileserver.h" #include "template_fileserver.h" +extern Module *me; + extern Anope::string provider_name, template_name, template_base, page_title; struct SubSection @@ -66,7 +68,7 @@ class WebPanelPage : public HTTPPage { } - virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0; + virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &) = 0; }; class WebPanelProtectedPage : public WebPanelPage @@ -78,14 +80,14 @@ class WebPanelProtectedPage : public WebPanelPage { } - void OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override anope_final + bool OnRequest(HTTPProvider *provider, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply) anope_override anope_final { service_reference<Panel> panel("Panel", "webcpanel"); NickAlias *na; if (!panel || !(na = panel->GetNickFromSession(client, message))) { - return; // Access denied + return true; // Access denied } TemplateFileServer::Replacements replacements; @@ -123,10 +125,10 @@ class WebPanelProtectedPage : public WebPanelPage } } - this->OnRequest(provider, page_name, client, message, reply, na, replacements); + return this->OnRequest(provider, page_name, client, message, reply, na, replacements); } - virtual void OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) = 0; + virtual bool OnRequest(HTTPProvider *, const Anope::string &, HTTPClient *, HTTPMessage &, HTTPReply &, NickAlias *, TemplateFileServer::Replacements &) = 0; /* What get data should be appended to links in the navbar */ virtual std::set<Anope::string> GetData() { return std::set<Anope::string>(); } diff --git a/modules/extra/xmlrpc.h b/modules/extra/xmlrpc.h index baff9b18d..bc3ba893d 100644 --- a/modules/extra/xmlrpc.h +++ b/modules/extra/xmlrpc.h @@ -3,7 +3,7 @@ class XMLRPCClientSocket; class XMLRPCListenSocket; class XMLRPCServiceInterface; -class XMLRPCClientSocket : public ClientSocket, public BufferedSocket +class XMLRPCClientSocket : public ClientSocket, public BufferedSocket, public Base { protected: Anope::string query; diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp index d792f74da..f165423fc 100644 --- a/modules/pseudoclients/botserv.cpp +++ b/modules/pseudoclients/botserv.cpp @@ -15,9 +15,8 @@ class BotServCore : public Module { - Channel *fantasy_channel; public: - BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), fantasy_channel(NULL) + BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) { this->SetAuthor("Anope"); @@ -25,7 +24,7 @@ class BotServCore : public Module if (BotServ == NULL) throw ModuleException("No bot named " + Config->BotServ); - Implementation i[] = { I_OnPrivmsg, I_OnPreCommand, I_OnJoinChannel, I_OnLeaveChannel, + Implementation i[] = { I_OnPrivmsg, I_OnJoinChannel, I_OnLeaveChannel, I_OnPreHelp, I_OnPostHelp, I_OnChannelModeSet }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); @@ -45,79 +44,109 @@ class BotServCore : public Module ircdproto->SendCTCP(c->ci->bi, u->nick, "%s", ctcp.c_str()); } - Anope::string realbuf = msg; - bool was_action = false; if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1') { realbuf.erase(0, 8); realbuf.erase(realbuf.length() - 1); - was_action = true; + return; } - if (realbuf.empty()) + if (realbuf.empty() || !c->ci->botflags.HasFlag(BS_FANTASY)) return; - /* Fantaisist commands */ - if (c->ci->botflags.HasFlag(BS_FANTASY) && (Config->BSFantasyCharacter.empty() || realbuf.find_first_of(Config->BSFantasyCharacter) == 0) && !was_action) + std::vector<Anope::string> params = BuildStringVector(realbuf); + + if (!realbuf.find_first_of(c->ci->bi->nick)) + params.erase(params.begin()); + else if (Config->BSFantasyCharacter.empty()) + ; + else if (!realbuf.find_first_of(Config->BSFantasyCharacter)) + params[0].erase(params[0].begin()); + else + return; + + if (params.empty()) + return; + + CommandInfo::map::const_iterator it = Config->Fantasy.end(); + unsigned count = 0; + for (unsigned max = params.size(); it == Config->Fantasy.end() && max > 0; --max) { - /* Strip off the fantasy character */ - if (!Config->BSFantasyCharacter.empty()) - realbuf.erase(realbuf.begin()); + Anope::string full_command; + for (unsigned i = 0; i < max; ++i) + full_command += " " + params[i]; + full_command.erase(full_command.begin()); - size_t space = realbuf.find(' '); - Anope::string command, rest; - if (space == Anope::string::npos) - command = realbuf; - else - { - command = realbuf.substr(0, space); - rest = realbuf.substr(space + 1); - } + ++count; + it = Config->Fantasy.find(full_command); + } - if (c->ci->AccessFor(u).HasPriv("FANTASIA")) - { - FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, c->ci, rest)); - } - else - { - FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, c->ci, rest)); - } + if (it == Config->Fantasy.end()) + return; - BotInfo *bi = findbot(Config->ChanServ); - if (bi == NULL) - bi = findbot(Config->BotServ); - if (bi == NULL || !bi->commands.count(command)) - return; + const CommandInfo &info = it->second; + service_reference<Command> cmd("Command", info.name); + if (!cmd) + { + Log(LOG_DEBUG) << "Fantasy command " << it->first << " exists for nonexistant service " << info.name << "!"; + return; + } - if (c->ci->AccessFor(u).HasPriv("FANTASIA")) - { - this->fantasy_channel = c; - bi->OnMessage(u, realbuf); - this->fantasy_channel = NULL; - } + for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i) + params.erase(params.begin()); + + while (cmd->MaxParams > 0 && params.size() > cmd->MaxParams) + { + params[cmd->MaxParams - 1] += " " + params[cmd->MaxParams]; + params.erase(params.begin() + cmd->MaxParams); } - } - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override - { - if (this->fantasy_channel != NULL) + /* All ChanServ commands take the channel as a first parameter */ + if (cmd->name.find("chanserv/") == 0 && !cmd->HasFlag(CFLAG_STRIP_CHANNEL)) + params.insert(params.begin(), c->ci->name); + + // Command requires registered users only + if (!cmd->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->Account()) + return; + + if (params.size() < cmd->MinParams) + return; + + CommandSource source(u->nick, u, u->Account(), u, c->ci->bi); + source.c = c; + source.command = it->first; + source.permission = info.permission; + + EventReturn MOD_RESULT; + if (c->ci->AccessFor(u).HasPriv("FANTASIA")) { - if (!command->HasFlag(CFLAG_STRIP_CHANNEL)) - { - params.insert(params.begin(), this->fantasy_channel->name); - if (command->MaxParams && params.size() > command->MaxParams) - { - params[params.size() - 2] += " " + params[params.size() - 1]; - params.erase(params.end() - 1); - } - } - source.c = this->fantasy_channel; - source.service = this->fantasy_channel->ci->WhoSends(); + FOREACH_RESULT(I_OnBotFantasy, OnBotFantasy(source, cmd, c->ci, params)); + } + else + { + FOREACH_RESULT(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(source, cmd, c->ci, params)); } - return EVENT_CONTINUE; + if (MOD_RESULT == EVENT_STOP || !c->ci->AccessFor(u).HasPriv("FANTASIA")) + return; + + if (MOD_RESULT != EVENT_ALLOW && !info.permission.empty() && !source.HasCommand(info.permission)) + return; + + FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, cmd, params)); + if (MOD_RESULT == EVENT_STOP) + return; + + dynamic_reference<User> user_reference(u); + dynamic_reference<NickCore> nc_reference(u->Account()); + cmd->Execute(source, params); + + if (user_reference && nc_reference) + { + FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, cmd, params)); + } } void OnJoinChannel(User *user, Channel *c) anope_override @@ -172,24 +201,43 @@ class BotServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->BotServ) + if (!params.empty()) return EVENT_CONTINUE; - source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n" - "It has been created for users that can't host or\n" - "configure a bot, or for use on networks that don't\n" - "allow user bots. Available commands are listed \n" - "below; to use them, type \002%s%s \037command\037\002. For\n" - "more information on a specific command, type\n" - "\002%s%s %s \037command\037\002.\n "), - Config->BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), source.command.c_str()); + + if (source.c) + { + source.Reply(_("\2%s\2 allows you to execute \"fantasy\" commands in the channel.\n" + "Fantasy commands are tied to existing commands, usually on \2%s\2,\n" + "and provide a more convenient way to execute commands. Commands that\n" + "require a channel as a parameter will automatically have that parameter\n" + "given.\n"), source.service->nick.c_str(), Config->ChanServ.c_str()); + if (!Config->BSFantasyCharacter.empty()) + source.Reply(_(" \n" + "Fantasy commands may be prefixed with one of the following characters: %s\n"), Config->BSFantasyCharacter.c_str()); + source.Reply(_(" \n" + "Available commands are:")); + } + else if (source.service->nick == Config->BotServ) + { + source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n" + "It has been created for users that can't host or\n" + "configure a bot, or for use on networks that don't\n" + "allow user bots. Available commands are listed \n" + "below; to use them, type \002%s%s \037command\037\002. For\n" + "more information on a specific command, type\n" + "\002%s%s %s \037command\037\002.\n "), + Config->BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), source.command.c_str()); + } + return EVENT_CONTINUE; } void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->BotServ) + if (!params.empty() || source.c || source.service->nick != Config->BotServ) return; + source.Reply(_(" \n" "Bot will join a channel whenever there is at least\n" "\002%d\002 user(s) on it."), Config->BSMinUsers); diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index 181baa7b8..c3a6e6479 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -151,7 +151,7 @@ class ChanServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->ChanServ) + if (!params.empty() || source.c || source.service->nick != Config->ChanServ) return EVENT_CONTINUE; source.Reply(_("\002%s\002 allows you to register and control various\n" "aspects of channels. %s can often prevent\n" @@ -166,7 +166,7 @@ class ChanServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->ChanServ) + if (!params.empty() || source.c || source.service->nick != Config->ChanServ) return; if (Config->CSExpire >= 86400) source.Reply(_(" \n" diff --git a/modules/pseudoclients/global.cpp b/modules/pseudoclients/global.cpp index 3fdfbf4e0..13e7570ce 100644 --- a/modules/pseudoclients/global.cpp +++ b/modules/pseudoclients/global.cpp @@ -81,7 +81,7 @@ class GlobalCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->Global) + if (!params.empty() || source.c || source.service->nick != Config->Global) return EVENT_CONTINUE; source.Reply(_("%s commands:"), Config->Global.c_str()); return EVENT_CONTINUE; diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp index 33d183b9a..d0d078a79 100644 --- a/modules/pseudoclients/hostserv.cpp +++ b/modules/pseudoclients/hostserv.cpp @@ -67,7 +67,7 @@ class HostServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->HostServ) + if (!params.empty() || source.c || source.service->nick != Config->HostServ) return EVENT_CONTINUE; source.Reply(_("%s commands:"), Config->HostServ.c_str()); return EVENT_CONTINUE; diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp index f24b69edf..faeeae1fc 100644 --- a/modules/pseudoclients/memoserv.cpp +++ b/modules/pseudoclients/memoserv.cpp @@ -202,7 +202,7 @@ class MemoServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->MemoServ) + if (!params.empty() || source.c || source.service->nick != Config->MemoServ) return EVENT_CONTINUE; source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" "messages to other IRC users, whether they are online at\n" @@ -215,7 +215,7 @@ class MemoServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->MemoServ) + if (!params.empty() || source.c || source.service->nick != Config->MemoServ) return; source.Reply(_(" \n" "Type \002%s%s HELP \037command\037\002 for help on any of the\n" diff --git a/modules/pseudoclients/nickserv.cpp b/modules/pseudoclients/nickserv.cpp index cda719a33..caffd74d4 100644 --- a/modules/pseudoclients/nickserv.cpp +++ b/modules/pseudoclients/nickserv.cpp @@ -320,7 +320,7 @@ class NickServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->NickServ) + if (!params.empty() || source.c || source.service->nick != Config->NickServ) return EVENT_CONTINUE; source.Reply(_("\002%s\002 allows you to \"register\" a nickname and\n" "prevent others from using it. The following\n" @@ -333,7 +333,7 @@ class NickServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->NickServ) + if (!params.empty() || source.c || source.service->nick != Config->NickServ) return; if (source.IsServicesOper()) source.Reply(_(" \n" diff --git a/modules/pseudoclients/operserv.cpp b/modules/pseudoclients/operserv.cpp index b02120e91..cc051d685 100644 --- a/modules/pseudoclients/operserv.cpp +++ b/modules/pseudoclients/operserv.cpp @@ -249,7 +249,7 @@ class OperServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.owner->nick != Config->OperServ) + if (!params.empty() || source.c || source.service->nick != Config->OperServ) return EVENT_CONTINUE; source.Reply(_("%s commands:"), Config->OperServ.c_str()); return EVENT_CONTINUE; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13a88bf51..f1f383397 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -47,7 +47,7 @@ foreach(SRC ${SRC_SRCS}) # Create unused skip variable set(SKIP) # Calculate the header file dependencies for the given source file - calculate_depends(${SRC} SKIP TEMP_INCLUDES) + calculate_depends(${SRC} SKIP TRUE TEMP_INCLUDES) # If there were some extra include directories, add them to the list if(TEMP_INCLUDES) append_to_list(EXTRA_INCLUDES ${TEMP_INCLUDES}) diff --git a/src/bots.cpp b/src/bots.cpp index 38f37c41d..bc7fc3cb0 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -230,10 +230,7 @@ void BotInfo::OnMessage(User *u, const Anope::string &message) if (this->commands.empty()) return; - CommandSource source(u->nick, u, u->Account(), u); - source.owner = this; - source.service = this; - + CommandSource source(u->nick, u, u->Account(), u, this); RunCommand(source, message); } @@ -256,7 +253,7 @@ void BotInfo::SetCommand(const Anope::string &cname, const Anope::string &sname, */ CommandInfo *BotInfo::GetCommand(const Anope::string &cname) { - command_map::iterator it = this->commands.find(cname); + CommandInfo::map::iterator it = this->commands.find(cname); if (it != this->commands.end()) return &it->second; return NULL; diff --git a/src/command.cpp b/src/command.cpp index 9f1b26fa4..6ae9275ca 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -17,8 +17,8 @@ #include "regchannel.h" #include "channels.h" -CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r) : nick(n), u(user), nc(core), reply(r), - c(NULL), owner(NULL), service(NULL) +CommandSource::CommandSource(const Anope::string &n, User *user, NickCore *core, CommandReply *r, BotInfo *bi) : nick(n), u(user), nc(core), reply(r), + c(NULL), service(bi) { } @@ -153,7 +153,7 @@ void Command::SendSyntax(CommandSource &source) void Command::SendSyntax(CommandSource &source, const Anope::string &syn) { source.Reply(_("Syntax: \002%s %s\002"), source.command.c_str(), syn.c_str()); - source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str()); } const Anope::string &Command::GetDesc() const @@ -171,7 +171,7 @@ bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { r void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { this->SendSyntax(source); - source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.service->nick.c_str(), source.command.c_str()); } void RunCommand(CommandSource &source, const Anope::string &message) @@ -179,7 +179,7 @@ void RunCommand(CommandSource &source, const Anope::string &message) std::vector<Anope::string> params = BuildStringVector(message); bool has_help = source.service->commands.find("HELP") != source.service->commands.end(); - BotInfo::command_map::const_iterator it = source.service->commands.end(); + CommandInfo::map::const_iterator it = source.service->commands.end(); unsigned count = 0; for (unsigned max = params.size(); it == source.service->commands.end() && max > 0; --max) { @@ -239,7 +239,6 @@ void RunCommand(CommandSource &source, const Anope::string &message) if (MOD_RESULT == EVENT_STOP) return; - if (params.size() < c->MinParams) { c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : ""); diff --git a/src/config.cpp b/src/config.cpp index e0cd21b68..b90c8598a 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -890,6 +890,8 @@ static bool DoneCommands(ServerConfig *config, const Anope::string &) return true; } +/*************************************************************************/ + static bool InitPrivileges(ServerConfig *config, const Anope::string &) { PrivilegeManager::ClearPrivileges(); @@ -1040,6 +1042,30 @@ static bool DoneServices(ServerConfig *config, const Anope::string &) /*************************************************************************/ +static bool InitFantasy(ServerConfig *config, const Anope::string &) +{ + config->Fantasy.clear(); + return true; +} + +static bool DoFantasy(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +{ + Anope::string name = values[0].GetValue(); + Anope::string service = values[1].GetValue(); + Anope::string permission = values[2].GetValue(); + + config->Fantasy[name].name = service; + config->Fantasy[name].permission = permission; + return true; +} + +static bool DoneFantasy(ServerConfig *config, const Anope::string &) +{ + return true; +} + +/*************************************************************************/ + ConfigurationFile::ConfigurationFile(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL) { } @@ -1359,6 +1385,11 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"", "", "", ""}, {DT_STRING, DT_STRING, DT_INTEGER, DT_STRING}, InitPrivileges, DoPrivileges, DonePrivileges}, + {"fantasy", + {"name", "command", "permission", ""}, + {"", "", "", ""}, + {DT_STRING, DT_STRING, DT_STRING}, + InitFantasy, DoFantasy, DoneFantasy}, {"", {""}, {""}, diff --git a/src/init.cpp b/src/init.cpp index ee36cb39a..4f0f8bac3 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -384,7 +384,7 @@ void Init(int ac, char **av) if (GetCommandLineArgument("dbdir", 0, Arg)) { if (Arg.empty()) - throw FatalException("The --confdir option requires a path"); + throw FatalException("The --dbdir option requires a path"); db_dir = Arg; } diff --git a/src/module.cpp b/src/module.cpp index 2f70cb96b..e69b7c6a3 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -52,6 +52,7 @@ Module::~Module() ModuleManager::DetachAll(this); /* Clear any active callbacks this module has */ ModuleManager::ClearCallBacks(this); + IdentifyRequest::ModuleUnload(this); std::list<Module *>::iterator it = std::find(Modules.begin(), Modules.end(), this); if (it != Modules.end()) diff --git a/src/nickserv.cpp b/src/nickserv.cpp index 65126b987..b6455447a 100644 --- a/src/nickserv.cpp +++ b/src/nickserv.cpp @@ -93,3 +93,64 @@ void change_core_display(NickCore *nc) change_core_display(nc, na->nick); } +std::set<IdentifyRequest *> IdentifyRequest::requests; + +IdentifyRequest::IdentifyRequest(Module *o, const Anope::string &acc, const Anope::string &pass) : owner(o), account(acc), password(pass), dispatched(false), success(false) +{ + requests.insert(this); +} + +IdentifyRequest::~IdentifyRequest() +{ + requests.erase(this); +} + +void IdentifyRequest::Hold(Module *m) +{ + holds.insert(m); +} + +void IdentifyRequest::Release(Module *m) +{ + holds.erase(m); + if (holds.empty() && dispatched) + { + if (!success) + this->OnFail(); + delete this; + } +} + +void IdentifyRequest::Success(Module *m) +{ + if (!success) + { + this->OnSuccess(); + success = true; + } +} + +void IdentifyRequest::Dispatch() +{ + if (holds.empty()) + { + if (!success) + this->OnFail(); + delete this; + } + else + dispatched = true; +} + +void IdentifyRequest::ModuleUnload(Module *m) +{ + for (std::set<IdentifyRequest *>::iterator it = requests.begin(), it_end = requests.end(); it != it_end;) + { + IdentifyRequest *ir = *it; + ++it; + + ir->Release(m); + if (ir->owner == m) + delete ir; + } +} diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index c69c2fa7d..88fc37ffc 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -12,7 +12,7 @@ foreach(SRC ${TOOLS_SRCS}) # Create skip variable set(SKIP) # Calculate the header file dependencies for the given source file - calculate_depends(${SRC} SKIP) + calculate_depends(${SRC} SKIP TRUE) # Only continue if this file isn't skipped if(NOT SKIP) # Generate the executable and set its linker flags, also set it to depend on the main Anope executable to be built beforehand diff --git a/src/users.cpp b/src/users.cpp index a68c03739..603c22745 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -299,9 +299,9 @@ void User::SendMessage(const BotInfo *source, const Anope::string &msg) while (sep.GetToken(tok)) { if (Config->UsePrivmsg && ((!this->nc && Config->NSDefFlags.HasFlag(NI_MSG)) || (this->nc && this->nc->HasFlag(NI_MSG)))) - ircdproto->SendPrivmsg(source, this->nick, "%s", tok.c_str()); + ircdproto->SendPrivmsg(source, this->GetUID(), "%s", tok.c_str()); else - ircdproto->SendNotice(source, this->nick, "%s", tok.c_str()); + ircdproto->SendNotice(source, this->GetUID(), "%s", tok.c_str()); } } |