diff options
| author | rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b <rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864> | 2005-05-02 19:02:12 +0000 |
|---|---|---|
| committer | rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b <rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864> | 2005-05-02 19:02:12 +0000 |
| commit | e0583918834a3f8683e430adf3923ea89d2a449a (patch) | |
| tree | ff36ada734c3874d3be1a806e3a2b994386b54ed /src/core | |
| parent | 49491770383e66f1b8074d8b0f80026e3086e9d8 (diff) | |
BUILD : 1.7.8 (753) BUGS : N/a NOTES : Merged anope-dev with trunk
git-svn-id: svn://svn.anope.org/anope/trunk@753 31f1291d-b8d6-0310-a050-a5561fc1590b
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@516 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src/core')
126 files changed, 21287 insertions, 0 deletions
diff --git a/src/core/Makefile b/src/core/Makefile new file mode 100644 index 000000000..e73fd7e7c --- /dev/null +++ b/src/core/Makefile @@ -0,0 +1,45 @@ +include ./Makefile.inc + +MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \ + 'LDFLAGS=${LDFLAGS}' 'BINDEST=${BINDEST}' 'INSTALL=${INSTALL}' \ + 'INCLUDEDIR=${INCLUDEDIR}' 'RM=${RM}' 'CP=${CP}' \ + 'TOUCH=${TOUCH}' 'SHELL=${SHELL}' 'DATDEST=${DATDEST}' \ + 'RUNGROUP=${RUNGROUP}' 'MODULE_PATH=${MODULE_PATH}' \ + 'PROFILE=${PROFILE}' 'SHARED=${SHARED}' + +OBJECTS= $(SRCS:.c=.o) +SO_FILES=$(OBJECTS:.o=.s) +CDEFS= -g -rdynamic -Wall +CFLAGS=$(CFLAGS) $(CDEFS) + +all: modules subs + +modules: $(OBJECTS) $(SO_FILES) + +install: + $(CP) ./*.so $(MODULE_PATH) + +distclean: clean spotless + +.c.o: + $(CC) $(CFLAGS) -I../${INCLUDEDIR} -c $< + +.o.s: + $(CC) ${SHARED} $< -o $*.so ${PROFILE} + +subs: + @for i in $(SUBS); do \ + echo "make all in $$i..."; \ + (cd $$i; $(MAKE) $(MAKEARGS) all); done + +subs_clean: + @for i in $(SUBS); do \ + echo "cleaning in $$i..."; \ + (cd $$i; $(MAKE) $(MAKEARGS) clean); done + +clean: subs_clean + rm -f *.o *.so *.c~ core + +spotless: clean + rm -f *.so Makefile.inc + diff --git a/src/core/Makefile.sub b/src/core/Makefile.sub new file mode 100644 index 000000000..b060ca5b6 --- /dev/null +++ b/src/core/Makefile.sub @@ -0,0 +1,30 @@ +MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \ + 'LDFLAGS=${LDFLAGS}' 'BINDEST=${BINDEST}' 'INSTALL=${INSTALL}' \ + 'INCLUDEDIR=${INCLUDEDIR}' 'RM=${RM}' 'CP=${CP}' \ + 'TOUCH=${TOUCH}' 'SHELL=${SHELL}' 'DATDEST=${DATDEST}' \ + 'RUNGROUP=${RUNGROUP}' 'MODULE_PATH=${MODULE_PATH}' \ + 'PROFILE=${PROFILE}' 'SHARED=${SHARED}' + +OBJECTS= $(SRCS:.c=.o) +SO_FILES=$(OBJECTS:.o=.s) +CDEFS= -g -rdynamic -Wall +CFLAGS=$(CFLAGS) $(CDEFS) + +all: module + +module: $(OBJECTS) so + +distclean: clean spotless + +.c.o: + $(CC) $(CFLAGS) -I../ -I../../${INCLUDEDIR} -c $< + +so: + $(CC) ${SHARED} $(OBJECTS) -o ../$(TARGET).so ${PROFILE} + +clean: + rm -f *.o *.so *.c~ core + +spotless: clean + rm -f *~ + diff --git a/src/core/Makefile.win32 b/src/core/Makefile.win32 new file mode 100644 index 000000000..e1f4301a3 --- /dev/null +++ b/src/core/Makefile.win32 @@ -0,0 +1,25 @@ +include ../../Makefile.inc.win32 + +SRCS=bs_act.c bs_assign.c bs_badwords.c bs_bot.c bs_botlist.c bs_fantasy.c bs_fantasy_kick.c bs_fantasy_kickban.c bs_fantasy_owner.c bs_fantasy_seen.c bs_fantasy_unban.c bs_help.c bs_info.c bs_kick.c bs_say.c bs_set.c bs_unassign.c cs_access.c cs_akick.c cs_ban.c cs_clear.c cs_drop.c cs_forbid.c cs_getkey.c cs_getpass.c cs_help.c cs_identify.c cs_info.c cs_invite.c cs_kick.c cs_list.c cs_logout.c cs_modes.c cs_register.c cs_sendpass.c cs_set.c cs_status.c cs_suspend.c cs_topic.c cs_xop.c he_help.c hs_del.c hs_delall.c hs_group.c hs_help.c hs_list.c hs_off.c hs_on.c hs_set.c hs_setall.c ms_cancel.c ms_check.c ms_del.c ms_help.c ms_info.c ms_list.c ms_read.c ms_rsend.c ms_send.c ms_sendall.c ms_set.c ms_staff.c ns_access.c ns_alist.c ns_drop.c ns_forbid.c ns_getemail.c ns_getpass.c ns_ghost.c ns_group.c ns_help.c ns_identify.c ns_info.c ns_list.c ns_logout.c ns_recover.c ns_register.c ns_release.c ns_sendpass.c ns_set.c ns_status.c ns_suspend.c ns_update.c os_admin.c os_akill.c os_chankill.c os_chanlist.c os_clearmodes.c os_defcon.c os_global.c os_help.c os_ignore.c os_jupe.c os_kick.c os_killclones.c \ + os_logonnews.c os_mode.c os_modinfo.c os_modlist.c os_modload.c os_modunload.c os_noop.c os_oline.c os_oper.c os_opernews.c os_quit.c os_randomnews.c os_raw.c os_reload.c os_restart.c os_session.c os_set.c os_sgline.c os_shutdown.c os_sqline.c os_staff.c os_stats.c os_svsnick.c os_szline.c os_umode.c os_update.c os_userlist.c +OBJECTS= $(SRCS:.c=.dll) +CFLAGS=/LD /MD /D MODULE_COMPILE $(CFLAGS) /I"../../include" +LFLAGS=/link ../anope.lib wsock32.lib $(LIBS) $(LFLAGS) $(MYSQL_LIB_PATH) /export:AnopeInit /export:AnopeFini + +all: $(OBJECTS) + +distclean: clean spotless + +.c.dll: + $(CC) $(CFLAGS) $< $(LFLAGS) + +clean: + -@del *.obj + +spotless: clean + -@del *.dll *.lib *.exp + +install: + -@mkdir ..\..\$(DATDEST)\modules + -@mkdir ..\..\$(DATDEST)\modules\runtime + -@copy *.dll ..\..\$(DATDEST)\modules diff --git a/src/core/bs_act.c b/src/core/bs_act.c new file mode 100644 index 000000000..0929ba716 --- /dev/null +++ b/src/core/bs_act.c @@ -0,0 +1,93 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_act(User * u); +void myBotServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("ACT", do_act, NULL, BOT_HELP_ACT, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_ACT); +} + +/** + * The /bs act command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_act(User * u) +{ + ChannelInfo *ci; + + char *chan = strtok(NULL, " "); + char *text = strtok(NULL, ""); + + if (!chan || !text) + syntax_error(s_BotServ, u, "ACT", BOT_ACT_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!ci->bi) + notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); + else if (!ci->c || ci->c->usercount < BSMinUsers) + notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); + else if (!check_access(u, ci, CA_SAY)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + strnrepl(text, BUFSIZE, "\001", ""); + anope_cmd_privmsg(ci->bi->nick, ci->name, "%cACTION %s %c", 1, + text, 1); + ci->bi->lastmsg = time(NULL); + if (logchan && LogBot) + anope_cmd_privmsg(ci->bi->nick, LogChannel, "ACT %s %s %s", + u->nick, ci->name, text); + } + return MOD_CONT; +} diff --git a/src/core/bs_assign.c b/src/core/bs_assign.c new file mode 100644 index 000000000..320a615fc --- /dev/null +++ b/src/core/bs_assign.c @@ -0,0 +1,102 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_assign(User * u); +void myBotServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("ASSIGN", do_assign, NULL, BOT_HELP_ASSIGN, -1, -1, + -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_ASSIGN); +} + +/** + * The /bs assign command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_assign(User * u) +{ + char *chan = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + BotInfo *bi; + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); + else if (!chan || !nick) + syntax_error(s_BotServ, u, "ASSIGN", BOT_ASSIGN_SYNTAX); + else if (!(bi = findbot(nick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + else if (bi->flags & BI_PRIVATE && !is_oper(u)) + notice_lang(s_BotServ, u, PERMISSION_DENIED); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) + notice_lang(s_BotServ, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); + else if ((ci->botflags & BS_NOBOT) + || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) + notice_lang(s_BotServ, u, PERMISSION_DENIED); + else { + if (ci->bi) + unassign(u, ci); + ci->bi = bi; + bi->chancount++; + if (ci->c && ci->c->usercount >= BSMinUsers) { + bot_join(ci); + } + notice_lang(s_BotServ, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); + send_event(EVENT_BOT_ASSIGN, 2, ci->name, bi->nick); + } + return MOD_CONT; +} diff --git a/src/core/bs_badwords.c b/src/core/bs_badwords.c new file mode 100644 index 000000000..de42f6355 --- /dev/null +++ b/src/core/bs_badwords.c @@ -0,0 +1,290 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_badwords(User * u); +void myBotServHelp(User * u); +int badwords_del_callback(User * u, int num, va_list args); +int badwords_list(User * u, int index, ChannelInfo * ci, int *sent_header); +int badwords_list_callback(User * u, int num, va_list args); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("BADWORDS", do_badwords, NULL, BOT_HELP_BADWORDS, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_BADWORDS); +} + +/** + * The /bs badwords command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_badwords(User * u) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *word = strtok(NULL, ""); + ChannelInfo *ci; + BadWord *bw; + + int i; + int need_args = (cmd + && (!stricmp(cmd, "LIST") || !stricmp(cmd, "CLEAR"))); + + if (!cmd || (need_args ? 0 : !word)) { + syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!check_access(u, ci, CA_BADWORDS) + && (!need_args || !is_services_admin(u))) { + notice_lang(s_BotServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "ADD") == 0) { + + char *opt, *pos; + int type = BW_ANY; + + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + pos = strrchr(word, ' '); + if (pos) { + opt = pos + 1; + if (*opt) { + if (!stricmp(opt, "SINGLE")) + type = BW_SINGLE; + else if (!stricmp(opt, "START")) + type = BW_START; + else if (!stricmp(opt, "END")) + type = BW_END; + if (type != BW_ANY) + *pos = 0; + } + } + + for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) { + if (bw->word && ((BSCaseSensitive && (!strcmp(bw->word, word))) + || (!BSCaseSensitive + && (!stricmp(bw->word, word))))) { + notice_lang(s_BotServ, u, BOT_BADWORDS_ALREADY_EXISTS, + bw->word, ci->name); + return MOD_CONT; + } + } + + for (i = 0; i < ci->bwcount; i++) { + if (!ci->badwords[i].in_use) + break; + } + if (i == ci->bwcount) { + if (i < BSBadWordsMax) { + ci->bwcount++; + ci->badwords = + srealloc(ci->badwords, sizeof(BadWord) * ci->bwcount); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_REACHED_LIMIT, + BSBadWordsMax); + return MOD_CONT; + } + } + bw = &ci->badwords[i]; + bw->in_use = 1; + bw->word = sstrdup(word); + bw->type = type; + + notice_lang(s_BotServ, u, BOT_BADWORDS_ADDED, bw->word, ci->name); + + } else if (stricmp(cmd, "DEL") == 0) { + + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + /* Special case: is it a number/list? Only do search if it isn't. */ + if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) { + int count, deleted, last = -1; + deleted = + process_numlist(word, &count, badwords_del_callback, u, ci, + &last); + if (!deleted) { + if (count == 1) { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, + last, ci->name); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, + ci->name); + } + } else if (deleted == 1) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_ONE, + ci->name); + } else { + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED_SEVERAL, + deleted, ci->name); + } + } else { + for (i = 0; i < ci->bwcount; i++) { + if (ci->badwords[i].in_use + && !stricmp(ci->badwords[i].word, word)) + break; + } + if (i == ci->bwcount) { + notice_lang(s_BotServ, u, BOT_BADWORDS_NOT_FOUND, word, + chan); + return MOD_CONT; + } + bw = &ci->badwords[i]; + notice_lang(s_BotServ, u, BOT_BADWORDS_DELETED, bw->word, + ci->name); + if (bw->word) + free(bw->word); + bw->word = NULL; + bw->in_use = 0; + } + + } else if (stricmp(cmd, "LIST") == 0) { + int sent_header = 0; + + if (ci->bwcount == 0) { + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_EMPTY, chan); + return MOD_CONT; + } + if (word && strspn(word, "1234567890,-") == strlen(word)) { + process_numlist(word, NULL, badwords_list_callback, u, ci, + &sent_header); + } else { + for (i = 0; i < ci->bwcount; i++) { + if (!(ci->badwords[i].in_use)) + continue; + if (word && ci->badwords[i].word + && !match_wild_nocase(word, ci->badwords[i].word)) + continue; + badwords_list(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, chan); + + } else if (stricmp(cmd, "CLEAR") == 0) { + + if (readonly) { + notice_lang(s_BotServ, u, BOT_BADWORDS_DISABLED); + return MOD_CONT; + } + + for (i = 0; i < ci->bwcount; i++) + if (ci->badwords[i].word) + free(ci->badwords[i].word); + + free(ci->badwords); + ci->badwords = NULL; + ci->bwcount = 0; + + notice_lang(s_BotServ, u, BOT_BADWORDS_CLEAR); + + } else { + syntax_error(s_BotServ, u, "BADWORDS", BOT_BADWORDS_SYNTAX); + } + return MOD_CONT; +} + +int badwords_del_callback(User * u, int num, va_list args) +{ + BadWord *bw; + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + if (num < 1 || num > ci->bwcount) + return 0; + *last = num; + + bw = &ci->badwords[num - 1]; + if (bw->word) + free(bw->word); + bw->word = NULL; + bw->in_use = 0; + + return 1; +} + +int badwords_list(User * u, int index, ChannelInfo * ci, int *sent_header) +{ + BadWord *bw = &ci->badwords[index]; + + if (!bw->in_use) + return 0; + if (!*sent_header) { + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_HEADER, ci->name); + *sent_header = 1; + } + + notice_lang(s_BotServ, u, BOT_BADWORDS_LIST_FORMAT, index + 1, + bw->word, + ((bw->type == + BW_SINGLE) ? "(SINGLE)" : ((bw->type == + BW_START) ? "(START)" + : ((bw->type == + BW_END) ? "(END)" : ""))) + ); + return 1; +} + +int badwords_list_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + if (num < 1 || num > ci->bwcount) + return 0; + return badwords_list(u, num - 1, ci, sent_header); +} diff --git a/src/core/bs_bot.c b/src/core/bs_bot.c new file mode 100644 index 000000000..0e604a410 --- /dev/null +++ b/src/core/bs_bot.c @@ -0,0 +1,372 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +/** + * RFC: defination of a valid nick + * nickname = ( letter / special ) *8( letter / digit / special / "-" ) + * letter = %x41-5A / %x61-7A ; A-Z / a-z + * digit = %x30-39 ; 0-9 + * special = %x5B-60 / %x7B-7D ; "[", "]", "\", "`", "_", "^", "{", "|", "}" + **/ +#define isvalidnick(c) ( isalnum(c) || ((c) >='\x5B' && (c) <='\x60') || ((c) >='\x7B' && (c) <='\x7D') || (c)=='-' ) + + +int do_bot(User * u); +int delbot(BotInfo * bi); +void myBotServHelp(User * u); +void change_bot_nick(BotInfo * bi, char *newnick); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("BOT", do_bot, is_services_admin, -1, -1, -1, + BOT_SERVADMIN_HELP_BOT, BOT_SERVADMIN_HELP_BOT); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_BotServ, u, BOT_HELP_CMD_BOT); + } +} + +/** + * The /bs bot command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_bot(User * u) +{ + BotInfo *bi; + char *cmd = strtok(NULL, " "); + char *ch = NULL; + + if (!cmd) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (!stricmp(cmd, "ADD")) { + char *nick = strtok(NULL, " "); + char *user = strtok(NULL, " "); + char *host = strtok(NULL, " "); + char *real = strtok(NULL, ""); + + if (!nick || !user || !host || !real) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (findbot(nick)) + notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + else { + NickAlias *na; + + /** + * Check the nick is valid re RFC 2812 + **/ + if (isdigit(nick[0]) || nick[0] == '-') { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { + if (!isvalidnick(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + + /* check for hardcored ircd forbidden nicks */ + if (!anope_valid_nick(nick)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + if (!isValidHost(host, 3)) { + notice_lang(s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + for (ch = user; *ch && (ch - user) < USERMAX; ch++) { + if (!isalnum(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_IDENT); + return MOD_CONT; + } + } + + /** + * Check the host is valid re RFC 2812 + **/ + + /* Check whether it's a services client's nick and return if so - Certus */ + /* use nickIsServices reduce the total number lines of code - TSL */ + + if (nickIsServices(nick, 0)) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + /* We check whether the nick is registered, and inform the user + * if so. You need to drop the nick manually before you can use + * it as a bot nick from now on -GD + */ + if ((na = findnick(nick))) { + notice_lang(s_BotServ, u, NICK_ALREADY_REGISTERED, nick); + return MOD_CONT; + } + + bi = makebot(nick); + if (!bi) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + bi->user = sstrdup(user); + bi->host = sstrdup(host); + bi->real = sstrdup(real); + bi->created = time(NULL); + bi->chancount = 0; + + /* We check whether user with this nick is online, and kill it if so */ + EnforceQlinedNick(nick, s_BotServ); + + /* We make the bot online, ready to serve */ + anope_cmd_bot_nick(bi->nick, bi->user, bi->host, bi->real, + ircd->botserv_bot_mode); + + notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user, + bi->host, bi->real); + + send_event(EVENT_BOT_CREATE, 1, bi->nick); + } + } else if (!stricmp(cmd, "CHANGE")) { + char *oldnick = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + char *user = strtok(NULL, " "); + char *host = strtok(NULL, " "); + char *real = strtok(NULL, ""); + + if (!oldnick || !nick) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (!(bi = findbot(oldnick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); + else { + NickAlias *na; + + /* Checks whether there *are* changes. + * Case sensitive because we may want to change just the case. + * And we must finally check that the nick is not already + * taken by another bot. + */ + if (!strcmp(bi->nick, nick) + && ((user) ? !strcmp(bi->user, user) : 1) + && ((host) ? !strcmp(bi->host, host) : 1) + && ((real) ? !strcmp(bi->real, real) : 1)) { + notice_lang(s_BotServ, u, BOT_BOT_ANY_CHANGES); + return MOD_CONT; + } + + /* Check whether it's a services client's nick and return if so - Certus */ + /* use nickIsServices() to reduce the number of lines of code - TSL */ + if (nickIsServices(nick, 0)) { + notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + /** + * Check the nick is valid re RFC 2812 + **/ + if (isdigit(nick[0]) || nick[0] == '-') { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { + if (!isvalidnick(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + + /* check for hardcored ircd forbidden nicks */ + if (!anope_valid_nick(nick)) { + notice_lang(s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + if (!isValidHost(host, 3)) { + notice_lang(s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + + for (ch = user; *ch && (ch - user) < USERMAX; ch++) { + if (!isalnum(*ch)) { + notice_lang(s_BotServ, u, BOT_BAD_IDENT); + return MOD_CONT; + } + } + + if (stricmp(bi->nick, nick) && findbot(nick)) { + notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + return MOD_CONT; + } + + if (stricmp(bi->nick, nick)) { + /* We check whether the nick is registered, and inform the user + * if so. You need to drop the nick manually before you can use + * it as a bot nick from now on -GD + */ + if ((na = findnick(nick))) { + notice_lang(s_BotServ, u, NICK_ALREADY_REGISTERED, + nick); + return MOD_CONT; + } + + /* The new nick is really different, so we remove the Q line for + the old nick. */ + if (ircd->sqline) { + anope_cmd_unsqline(bi->nick); + } + + /* We check whether user with this nick is online, and kill it if so */ + EnforceQlinedNick(nick, s_BotServ); + } + + if (strcmp(nick, bi->nick)) + change_bot_nick(bi, nick); + + if (user && strcmp(user, bi->user)) { + free(bi->user); + bi->user = sstrdup(user); + } + if (host && strcmp(host, bi->host)) { + free(bi->host); + bi->host = sstrdup(host); + } + if (real && strcmp(real, bi->real)) { + free(bi->real); + bi->real = sstrdup(real); + } + + /* If only the nick changes, we just make the bot change his nick, + else we must make it quit and rejoin. */ + if (!user) + anope_cmd_chg_nick(oldnick, bi->nick); + else { + anope_cmd_quit(oldnick, "Quit: Be right back"); + + anope_cmd_bot_nick(bi->nick, bi->user, bi->host, bi->real, + ircd->botserv_bot_mode); + bot_rejoin_all(bi); + } + + notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick, + bi->user, bi->host, bi->real); + + send_event(EVENT_BOT_CHANGE, 1, bi->nick); + } + } else if (!stricmp(cmd, "DEL")) { + char *nick = strtok(NULL, " "); + + if (!nick) + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + else if (readonly) + notice_lang(s_BotServ, u, BOT_BOT_READONLY); + else if (!(bi = findbot(nick))) + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + else { + send_event(EVENT_BOT_DEL, 1, bi->nick); + anope_cmd_quit(bi->nick, + "Quit: Help! I'm being deleted by %s!", + u->nick); + if (ircd->sqline) { + anope_cmd_unsqline(bi->nick); + } + delbot(bi); + + notice_lang(s_BotServ, u, BOT_BOT_DELETED, nick); + } + } else + syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + + return MOD_CONT; +} + +int delbot(BotInfo * bi) +{ + cs_remove_bot(bi); + + if (bi->next) + bi->next->prev = bi->prev; + if (bi->prev) + bi->prev->next = bi->next; + else + botlists[tolower(*bi->nick)] = bi->next; + + nbots--; + + free(bi->nick); + free(bi->user); + free(bi->host); + free(bi->real); + + free(bi); + + return 1; +} + +void change_bot_nick(BotInfo * bi, char *newnick) +{ + if (bi->next) + bi->next->prev = bi->prev; + if (bi->prev) + bi->prev->next = bi->next; + else + botlists[tolower(*bi->nick)] = bi->next; + + if (bi->nick) + free(bi->nick); + bi->nick = sstrdup(newnick); + + insert_bot(bi); +} diff --git a/src/core/bs_botlist.c b/src/core/bs_botlist.c new file mode 100644 index 000000000..cc510aec0 --- /dev/null +++ b/src/core/bs_botlist.c @@ -0,0 +1,108 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_botlist(User * u); +void myBotServHelp(User * u); + +/** + * Create the botlist command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("BOTLIST", do_botlist, NULL, BOT_HELP_BOTLIST, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_BOTLIST); +} + +/** + * The /bs botlist command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_botlist(User * u) +{ + int i, count = 0; + BotInfo *bi; + + if (!nbots) { + notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); + return MOD_CONT; + } + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + if (!(bi->flags & BI_PRIVATE)) { + if (!count) + notice_lang(s_BotServ, u, BOT_BOTLIST_HEADER); + count++; + notice_user(s_BotServ, u, " %-15s (%s@%s)", bi->nick, + bi->user, bi->host); + } + } + } + + if (is_oper(u) && count < nbots) { + notice_lang(s_BotServ, u, BOT_BOTLIST_PRIVATE_HEADER); + + for (i = 0; i < 256; i++) { + for (bi = botlists[i]; bi; bi = bi->next) { + if (bi->flags & BI_PRIVATE) { + notice_user(s_BotServ, u, " %-15s (%s@%s)", + bi->nick, bi->user, bi->host); + count++; + } + } + } + } + + if (!count) + notice_lang(s_BotServ, u, BOT_BOTLIST_EMPTY); + else + notice_lang(s_BotServ, u, BOT_BOTLIST_FOOTER, count); + return MOD_CONT; +} diff --git a/src/core/bs_fantasy.c b/src/core/bs_fantasy.c new file mode 100644 index 000000000..9ea3fe402 --- /dev/null +++ b/src/core/bs_fantasy.c @@ -0,0 +1,80 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle all csmodeutils fantasy commands. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + CSModeUtil *util = csmodeutils; + char *target; + + if (argc < 3) + return MOD_CONT; + + do { + if (stricmp(argv[0], util->bsname) == 0) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + target = ((argc == 4) ? argv[3] : NULL); + + if (!target && check_access(u, ci, util->levelself)) + bot_raw_mode(u, ci, util->mode, u->nick); + else if (target && check_access(u, ci, util->level)) + bot_raw_mode(u, ci, util->mode, target); + } + } while ((++util)->name != NULL); + + return MOD_CONT; +} diff --git a/src/core/bs_fantasy_kick.c b/src/core/bs_fantasy_kick.c new file mode 100644 index 000000000..ec1e78ae6 --- /dev/null +++ b/src/core/bs_fantasy_kick.c @@ -0,0 +1,87 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle kick/k fantasy commands. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + char *target = NULL; + char *reason = NULL; + + if (argc < 3) + return MOD_CONT; + + if ((stricmp(argv[0], "!kick") == 0) || (stricmp(argv[0], "!k") == 0)) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + if (argc >= 4) { + target = myStrGetToken(argv[3], ' ', 0); + reason = myStrGetTokenRemainder(argv[3], ' ', 1); + } + if (!target && check_access(u, ci, CA_KICKME)) { + bot_raw_kick(u, ci, u->nick, "Requested"); + } else if (target && check_access(u, ci, CA_KICK)) { + if (!stricmp(target, ci->bi->nick)) + bot_raw_kick(u, ci, u->nick, "Oops!"); + else if (!reason) + bot_raw_kick(u, ci, target, "Requested"); + else + bot_raw_kick(u, ci, target, reason); + } + } + + return MOD_CONT; +} diff --git a/src/core/bs_fantasy_kickban.c b/src/core/bs_fantasy_kickban.c new file mode 100644 index 000000000..651b0113d --- /dev/null +++ b/src/core/bs_fantasy_kickban.c @@ -0,0 +1,90 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle kickban/kb fantasy commands. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + char *target = NULL; + char *reason = NULL; + + if (argc < 3) + return MOD_CONT; + + if ((stricmp(argv[0], "!kickban") == 0) + || (stricmp(argv[0], "!kb") == 0)) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + if (argc >= 4) { + target = myStrGetToken(argv[3], ' ', 0); + reason = myStrGetTokenRemainder(argv[3], ' ', 1); + } + if (!target && check_access(u, ci, CA_BANME)) { + bot_raw_ban(u, ci, u->nick, "Requested"); + } else if (target && check_access(u, ci, CA_BAN)) { + if (stricmp(target, ci->bi->nick) == 0) { + bot_raw_ban(u, ci, u->nick, "Oops!"); + } else { + if (!reason) + bot_raw_ban(u, ci, target, "Requested"); + else + bot_raw_ban(u, ci, target, reason); + } + } + } + + return MOD_CONT; +} diff --git a/src/core/bs_fantasy_owner.c b/src/core/bs_fantasy_owner.c new file mode 100644 index 000000000..ec88c966b --- /dev/null +++ b/src/core/bs_fantasy_owner.c @@ -0,0 +1,87 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + /* No need to load of we don't support owner */ + if (!ircd->owner) { + alog("Your ircd doesn't support the owner channelmode; bs_fantasy_owner won't be loaded"); + return MOD_STOP; + } + + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle owner/deowner fantasy commands. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + + if (argc < 3) + return MOD_CONT; + + if (stricmp(argv[0], "!deowner") == 0) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + if (is_founder(u, ci)) + bot_raw_mode(u, ci, ircd->ownerunset, u->nick); + } else if (stricmp(argv[0], "!owner") == 0) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + if (is_founder(u, ci)) + bot_raw_mode(u, ci, ircd->ownerset, u->nick); + } + + return MOD_CONT; +} diff --git a/src/core/bs_fantasy_seen.c b/src/core/bs_fantasy_seen.c new file mode 100644 index 000000000..e218576d6 --- /dev/null +++ b/src/core/bs_fantasy_seen.c @@ -0,0 +1,136 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle seen fantasy command. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + User *u2; + NickAlias *na; + ChanAccess *access; + char buf[BUFSIZE]; + char *target = NULL; + + if (argc < 4) + return MOD_CONT; + + if (stricmp(argv[0], "!seen") == 0) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci) + return MOD_CONT; + + target = myStrGetToken(argv[3], ' ', 0); + + if (stricmp(ci->bi->nick, target) == 0) { + /* If we look for the bot */ + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_BOT), + u->nick); + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } else if (!(na = findnick(target)) || (na->status & NS_VERBOTEN)) { + /* If the nick is not registered or forbidden */ + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_UNKNOWN), + target); + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } else if ((u2 = nc_on_chan(ci->c, na->nc))) { + /* If the nick we're looking for is on the channel, + * there are three possibilities: it's yourself, + * it's the nick we look for, it's an alias of the + * nick we look for. + */ + if (u == u2 || (u->na && u->na->nc == na->nc)) + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_YOU), + u->nick); + else if (!stricmp(u2->nick, target)) + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_ON_CHANNEL), u2->nick); + else + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_ON_CHANNEL_AS), target, + u2->nick); + + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } else if ((access = get_access_entry(na->nc, ci))) { + /* User is on the access list but not present actually. + Special case: if access->last_seen is 0 it's that we + never seen the user. + */ + if (access->last_seen) { + char durastr[192]; + duration(u->na, durastr, sizeof(durastr), + time(NULL) - access->last_seen); + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_ON), + target, durastr); + } else { + snprintf(buf, sizeof(buf), + getstring(u->na, BOT_SEEN_NEVER), target); + } + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } else if (na->nc == ci->founder) { + /* User is the founder of the channel */ + char durastr[192]; + duration(u->na, durastr, sizeof(durastr), + time(NULL) - na->last_seen); + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_ON), + target, durastr); + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } else { + /* All other cases */ + snprintf(buf, sizeof(buf), getstring(u->na, BOT_SEEN_UNKNOWN), + target); + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", buf); + } + } + + return MOD_CONT; +} diff --git a/src/core/bs_fantasy_unban.c b/src/core/bs_fantasy_unban.c new file mode 100644 index 000000000..412b36099 --- /dev/null +++ b/src/core/bs_fantasy_unban.c @@ -0,0 +1,78 @@ +/* BotServ core fantasy functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_fantasy(int argc, char **argv); + +/** + * Create the hook, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + EvtHook *hook; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + hook = createEventHook(EVENT_BOT_FANTASY, do_fantasy); + moduleAddEventHook(hook); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Handle unban fantasy command. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT or MOD_STOP + **/ +int do_fantasy(int argc, char **argv) +{ + User *u; + ChannelInfo *ci; + char *target = NULL; + + if (argc < 3) + return MOD_CONT; + + if (stricmp(argv[0], "!unban") == 0) { + u = finduser(argv[1]); + ci = cs_findchan(argv[2]); + if (!u || !ci || !check_access(u, ci, CA_UNBAN)) + return MOD_CONT; + + if (argc >= 4) + target = myStrGetToken(argv[3], ' ', 0); + if (!target) + common_unban(ci, u->nick); + else + common_unban(ci, target); + } + + return MOD_CONT; +} diff --git a/src/core/bs_help.c b/src/core/bs_help.c new file mode 100644 index 000000000..8fea7a5ad --- /dev/null +++ b/src/core/bs_help.c @@ -0,0 +1,67 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the help command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * The /bs help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_BotServ, u, BOT_HELP); + moduleDisplayHelp(4, u); + notice_help(s_BotServ, u, BOT_HELP_FOOTER, BSMinUsers); + } else { + mod_help_cmd(s_BotServ, u, BOTSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/bs_info.c b/src/core/bs_info.c new file mode 100644 index 000000000..3665b2054 --- /dev/null +++ b/src/core/bs_info.c @@ -0,0 +1,282 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_info(User * u); +void send_bot_channels(User * u, BotInfo * bi); +void myBotServHelp(User * u); + +/** + * Create the info command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("INFO", do_info, NULL, BOT_HELP_INFO, -1, -1, -1, + -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_INFO); +} + +/** + * The /bs info command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_info(User * u) +{ + BotInfo *bi; + ChannelInfo *ci; + char *query = strtok(NULL, " "); + + int need_comma = 0, is_servadmin = is_services_admin(u); + char buf[BUFSIZE], *end; + const char *commastr = getstring(u->na, COMMA_SPACE); + + if (!query) + syntax_error(s_BotServ, u, "INFO", BOT_INFO_SYNTAX); + else if ((bi = findbot(query))) { + char buf[BUFSIZE]; + struct tm *tm; + + notice_lang(s_BotServ, u, BOT_INFO_BOT_HEADER, bi->nick); + notice_lang(s_BotServ, u, BOT_INFO_BOT_MASK, bi->user, bi->host); + notice_lang(s_BotServ, u, BOT_INFO_BOT_REALNAME, bi->real); + tm = localtime(&bi->created); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_BotServ, u, BOT_INFO_BOT_CREATED, buf); + notice_lang(s_BotServ, u, BOT_INFO_BOT_OPTIONS, + getstring(u->na, + (bi-> + flags & BI_PRIVATE) ? BOT_INFO_OPT_PRIVATE : + BOT_INFO_OPT_NONE)); + notice_lang(s_BotServ, u, BOT_INFO_BOT_USAGE, bi->chancount); + + if (is_services_admin(u)) + send_bot_channels(u, bi); + } else if ((ci = cs_findchan(query))) { + if (!is_servadmin && !is_founder(u, ci)) { + notice_lang(s_BotServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + if (ci->flags & CI_VERBOTEN) { + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, query); + return MOD_CONT; + } + + notice_lang(s_BotServ, u, BOT_INFO_CHAN_HEADER, ci->name); + if (ci->bi) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT, ci->bi->nick); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_BOT_NONE); + + if (ci->botflags & BS_KICK_BADWORDS) { + if (ci->ttb[TTB_BADWORDS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_BADWORDS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BADWORDS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_BOLDS) { + if (ci->ttb[TTB_BOLDS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_BOLDS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_BOLDS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_CAPS) { + if (ci->ttb[TTB_CAPS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_CAPS], ci->capsmin, + ci->capspercent); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_ON, + getstring(u->na, BOT_INFO_ACTIVE), ci->capsmin, + ci->capspercent); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_CAPS_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_COLORS) { + if (ci->ttb[TTB_COLORS]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_COLORS]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_COLORS, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_FLOOD) { + if (ci->ttb[TTB_FLOOD]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_FLOOD], ci->floodlines, + ci->floodsecs); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_ON, + getstring(u->na, BOT_INFO_ACTIVE), + ci->floodlines, ci->floodsecs); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_FLOOD_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_REPEAT) { + if (ci->ttb[TTB_REPEAT]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_REPEAT], ci->repeattimes); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_ON, + getstring(u->na, BOT_INFO_ACTIVE), + ci->repeattimes); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REPEAT_OFF, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_REVERSES) { + if (ci->ttb[TTB_REVERSES]) + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_REVERSES]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_REVERSES, + getstring(u->na, BOT_INFO_INACTIVE)); + if (ci->botflags & BS_KICK_UNDERLINES) { + if (ci->ttb[TTB_UNDERLINES]) + notice_lang(s_BotServ, u, + BOT_INFO_CHAN_KICK_UNDERLINES_BAN, + getstring(u->na, BOT_INFO_ACTIVE), + ci->ttb[TTB_UNDERLINES]); + else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, + getstring(u->na, BOT_INFO_ACTIVE)); + } else + notice_lang(s_BotServ, u, BOT_INFO_CHAN_KICK_UNDERLINES, + getstring(u->na, BOT_INFO_INACTIVE)); + + end = buf; + *end = 0; + if (ci->botflags & BS_DONTKICKOPS) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s", + getstring(u->na, BOT_INFO_OPT_DONTKICKOPS)); + need_comma = 1; + } + if (ci->botflags & BS_DONTKICKVOICES) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_DONTKICKVOICES)); + need_comma = 1; + } + if (ci->botflags & BS_FANTASY) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_FANTASY)); + need_comma = 1; + } + if (ci->botflags & BS_GREET) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_GREET)); + need_comma = 1; + } + if (ci->botflags & BS_NOBOT) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_NOBOT)); + need_comma = 1; + } + if (ci->botflags & BS_SYMBIOSIS) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, BOT_INFO_OPT_SYMBIOSIS)); + need_comma = 1; + } + notice_lang(s_BotServ, u, BOT_INFO_CHAN_OPTIONS, + *buf ? buf : getstring(u->na, BOT_INFO_OPT_NONE)); + + } else + notice_lang(s_BotServ, u, BOT_INFO_NOT_FOUND, query); + return MOD_CONT; +} + +void send_bot_channels(User * u, BotInfo * bi) +{ + int i; + ChannelInfo *ci; + char buf[307], *end; + + *buf = 0; + end = buf; + + for (i = 0; i < 256; i++) { + for (ci = chanlists[i]; ci; ci = ci->next) { + if (ci->bi == bi) { + if (strlen(buf) + strlen(ci->name) > 300) { + notice_user(s_BotServ, u, buf); + *buf = 0; + end = buf; + } + end += + snprintf(end, sizeof(buf) - (end - buf), " %s ", + ci->name); + } + } + } + + if (*buf) + notice_user(s_BotServ, u, buf); + return; +} diff --git a/src/core/bs_kick.c b/src/core/bs_kick.c new file mode 100644 index 000000000..abedbd550 --- /dev/null +++ b/src/core/bs_kick.c @@ -0,0 +1,377 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_kickcmd(User * u); + +void myBotServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("KICK", do_kickcmd, NULL, BOT_HELP_KICK, -1, -1, -1, + -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK BADWORDS", NULL, NULL, BOT_HELP_KICK_BADWORDS, + -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK BOLDS", NULL, NULL, BOT_HELP_KICK_BOLDS, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK CAPS", NULL, NULL, BOT_HELP_KICK_CAPS, -1, -1, + -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK COLORS", NULL, NULL, BOT_HELP_KICK_COLORS, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK FLOOD", NULL, NULL, BOT_HELP_KICK_FLOOD, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK REPEAT", NULL, NULL, BOT_HELP_KICK_REPEAT, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK REVERSES", NULL, NULL, BOT_HELP_KICK_REVERSES, + -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("KICK UNDERLINES", NULL, NULL, + BOT_HELP_KICK_UNDERLINES, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_KICK); +} + +/** + * The /bs kick command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_kickcmd(User * u) +{ + char *chan = strtok(NULL, " "); + char *option = strtok(NULL, " "); + char *value = strtok(NULL, " "); + char *ttb = strtok(NULL, " "); + + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_KICK_DISABLED); + else if (!chan || !option || !value) + syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); + else if (stricmp(value, "ON") && stricmp(value, "OFF")) + syntax_error(s_BotServ, u, "KICK", BOT_KICK_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!is_services_admin(u) && !check_access(u, ci, CA_SET)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (!stricmp(option, "BADWORDS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_BADWORDS] = + strtol(ttb, (char **) NULL, 10); + /* Only error if errno returns ERANGE or EINVAL or we are less then 0 - TSL */ + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_BADWORDS] < 0) { + /* leaving the debug behind since we might want to know what these are */ + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_BADWORDS]); + } + /* reset the value back to 0 - TSL */ + ci->ttb[TTB_BADWORDS] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else { + ci->ttb[TTB_BADWORDS] = 0; + } + ci->botflags |= BS_KICK_BADWORDS; + if (ci->ttb[TTB_BADWORDS]) + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON_BAN, + ci->ttb[TTB_BADWORDS]); + else + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_ON); + } else { + ci->botflags &= ~BS_KICK_BADWORDS; + notice_lang(s_BotServ, u, BOT_KICK_BADWORDS_OFF); + } + } else if (!stricmp(option, "BOLDS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_BOLDS] = strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_BOLDS] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_BOLDS]); + } + ci->ttb[TTB_BOLDS] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_BOLDS] = 0; + ci->botflags |= BS_KICK_BOLDS; + if (ci->ttb[TTB_BOLDS]) + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON_BAN, + ci->ttb[TTB_BOLDS]); + else + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_ON); + } else { + ci->botflags &= ~BS_KICK_BOLDS; + notice_lang(s_BotServ, u, BOT_KICK_BOLDS_OFF); + } + } else if (!stricmp(option, "CAPS")) { + if (!stricmp(value, "ON")) { + char *min = strtok(NULL, " "); + char *percent = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_CAPS] = strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_CAPS] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_CAPS]); + } + ci->ttb[TTB_CAPS] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_CAPS] = 0; + + if (!min) + ci->capsmin = 10; + else + ci->capsmin = atol(min); + if (ci->capsmin < 1) + ci->capsmin = 10; + + if (!percent) + ci->capspercent = 25; + else + ci->capspercent = atol(percent); + if (ci->capspercent < 1 || ci->capspercent > 100) + ci->capspercent = 25; + + ci->botflags |= BS_KICK_CAPS; + if (ci->ttb[TTB_CAPS]) + notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON_BAN, + ci->capsmin, ci->capspercent, + ci->ttb[TTB_CAPS]); + else + notice_lang(s_BotServ, u, BOT_KICK_CAPS_ON, + ci->capsmin, ci->capspercent); + } else { + ci->botflags &= ~BS_KICK_CAPS; + notice_lang(s_BotServ, u, BOT_KICK_CAPS_OFF); + } + } else if (!stricmp(option, "COLORS")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_COLORS] = strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_COLORS] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_COLORS]); + } + ci->ttb[TTB_COLORS] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_COLORS] = 0; + ci->botflags |= BS_KICK_COLORS; + if (ci->ttb[TTB_COLORS]) + notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON_BAN, + ci->ttb[TTB_COLORS]); + else + notice_lang(s_BotServ, u, BOT_KICK_COLORS_ON); + } else { + ci->botflags &= ~BS_KICK_COLORS; + notice_lang(s_BotServ, u, BOT_KICK_COLORS_OFF); + } + } else if (!stricmp(option, "FLOOD")) { + if (!stricmp(value, "ON")) { + char *lines = strtok(NULL, " "); + char *secs = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_FLOOD] = strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_FLOOD] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_FLOOD]); + } + ci->ttb[TTB_FLOOD] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_FLOOD] = 0; + + if (!lines) + ci->floodlines = 6; + else + ci->floodlines = atol(lines); + if (ci->floodlines < 2) + ci->floodlines = 6; + + if (!secs) + ci->floodsecs = 10; + else + ci->floodsecs = atol(secs); + if (ci->floodsecs < 1 || ci->floodsecs > BSKeepData) + ci->floodsecs = 10; + + ci->botflags |= BS_KICK_FLOOD; + if (ci->ttb[TTB_FLOOD]) + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON_BAN, + ci->floodlines, ci->floodsecs, + ci->ttb[TTB_FLOOD]); + else + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_ON, + ci->floodlines, ci->floodsecs); + } else { + ci->botflags &= ~BS_KICK_FLOOD; + notice_lang(s_BotServ, u, BOT_KICK_FLOOD_OFF); + } + } else if (!stricmp(option, "REPEAT")) { + if (!stricmp(value, "ON")) { + char *times = strtok(NULL, " "); + + if (ttb) { + ci->ttb[TTB_REPEAT] = strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_REPEAT] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_REPEAT]); + } + ci->ttb[TTB_REPEAT] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_REPEAT] = 0; + + if (!times) + ci->repeattimes = 3; + else + ci->repeattimes = atol(times); + if (ci->repeattimes < 2) + ci->repeattimes = 3; + + ci->botflags |= BS_KICK_REPEAT; + if (ci->ttb[TTB_REPEAT]) + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON_BAN, + ci->repeattimes, ci->ttb[TTB_REPEAT]); + else + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_ON, + ci->repeattimes); + } else { + ci->botflags &= ~BS_KICK_REPEAT; + notice_lang(s_BotServ, u, BOT_KICK_REPEAT_OFF); + } + } else if (!stricmp(option, "REVERSES")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_REVERSES] = + strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_REVERSES] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_REVERSES]); + } + ci->ttb[TTB_REVERSES] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_REVERSES] = 0; + ci->botflags |= BS_KICK_REVERSES; + if (ci->ttb[TTB_REVERSES]) + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON_BAN, + ci->ttb[TTB_REVERSES]); + else + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_ON); + } else { + ci->botflags &= ~BS_KICK_REVERSES; + notice_lang(s_BotServ, u, BOT_KICK_REVERSES_OFF); + } + } else if (!stricmp(option, "UNDERLINES")) { + if (!stricmp(value, "ON")) { + if (ttb) { + ci->ttb[TTB_UNDERLINES] = + strtol(ttb, (char **) NULL, 10); + if (errno == ERANGE || errno == EINVAL + || ci->ttb[TTB_UNDERLINES] < 0) { + if (debug) { + alog("debug: errno is %d ERANGE %d EINVAL %d ttb %d", errno, ERANGE, EINVAL, ci->ttb[TTB_UNDERLINES]); + } + ci->ttb[TTB_UNDERLINES] = 0; + notice_lang(s_BotServ, u, BOT_KICK_BAD_TTB, ttb); + return MOD_CONT; + } + } else + ci->ttb[TTB_UNDERLINES] = 0; + ci->botflags |= BS_KICK_UNDERLINES; + if (ci->ttb[TTB_UNDERLINES]) + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON_BAN, + ci->ttb[TTB_UNDERLINES]); + else + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_ON); + } else { + ci->botflags &= ~BS_KICK_UNDERLINES; + notice_lang(s_BotServ, u, BOT_KICK_UNDERLINES_OFF); + } + } else + notice_help(s_BotServ, u, BOT_KICK_UNKNOWN, option); + } + return MOD_CONT; +} diff --git a/src/core/bs_say.c b/src/core/bs_say.c new file mode 100644 index 000000000..0330a812d --- /dev/null +++ b/src/core/bs_say.c @@ -0,0 +1,97 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_say(User * u); +void myBotServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("SAY", do_say, NULL, BOT_HELP_SAY, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_SAY); +} + +/** + * The /bs say command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_say(User * u) +{ + ChannelInfo *ci; + + char *chan = strtok(NULL, " "); + char *text = strtok(NULL, ""); + + if (!chan || !text) + syntax_error(s_BotServ, u, "SAY", BOT_SAY_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!ci->bi) + notice_help(s_BotServ, u, BOT_NOT_ASSIGNED); + else if (!ci->c || ci->c->usercount < BSMinUsers) + notice_lang(s_BotServ, u, BOT_NOT_ON_CHANNEL, ci->name); + else if (!check_access(u, ci, CA_SAY)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (text[0] != '\001') { + anope_cmd_privmsg(ci->bi->nick, ci->name, "%s", text); + ci->bi->lastmsg = time(NULL); + if (logchan && LogBot) + anope_cmd_privmsg(ci->bi->nick, LogChannel, + "SAY %s %s %s", u->nick, ci->name, text); + } else { + syntax_error(s_BotServ, u, "SAY", BOT_SAY_SYNTAX); + } + } + return MOD_CONT; +} diff --git a/src/core/bs_set.c b/src/core/bs_set.c new file mode 100644 index 000000000..5312b0f6c --- /dev/null +++ b/src/core/bs_set.c @@ -0,0 +1,207 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_set(User * u); +void myBotServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", do_set, NULL, BOT_HELP_SET, -1, -1, + BOT_SERVADMIN_HELP_SET, BOT_SERVADMIN_HELP_SET); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET DONTKICKOPS", NULL, NULL, + BOT_HELP_SET_DONTKICKOPS, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET DONTKICKVOICES", NULL, NULL, + BOT_HELP_SET_DONTKICKVOICES, -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET FANTASY", NULL, NULL, BOT_HELP_SET_FANTASY, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET GREET", NULL, NULL, BOT_HELP_SET_GREET, -1, -1, + -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET SYMBIOSIS", NULL, NULL, BOT_HELP_SET_SYMBIOSIS, + -1, -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET NOBOT", NULL, NULL, -1, -1, -1, + BOT_SERVADMIN_HELP_SET_NOBOT, + BOT_SERVADMIN_HELP_SET_NOBOT); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + c = createCommand("SET PRIVATE", NULL, NULL, -1, -1, -1, + BOT_SERVADMIN_HELP_SET_PRIVATE, + BOT_SERVADMIN_HELP_SET_PRIVATE); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_SET); +} + +/** + * The /bs set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set(User * u) +{ + char *chan = strtok(NULL, " "); + char *option = strtok(NULL, " "); + char *value = strtok(NULL, " "); + int is_servadmin = is_services_admin(u); + + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_SET_DISABLED); + else if (!chan || !option || !value) + syntax_error(s_BotServ, u, "SET", BOT_SET_SYNTAX); + else if (is_servadmin && !stricmp(option, "PRIVATE")) { + BotInfo *bi; + + if ((bi = findbot(chan))) { + if (!stricmp(value, "ON")) { + bi->flags |= BI_PRIVATE; + notice_lang(s_BotServ, u, BOT_SET_PRIVATE_ON, bi->nick); + } else if (!stricmp(value, "OFF")) { + bi->flags &= ~BI_PRIVATE; + notice_lang(s_BotServ, u, BOT_SET_PRIVATE_OFF, bi->nick); + } else { + syntax_error(s_BotServ, u, "SET PRIVATE", + BOT_SET_PRIVATE_SYNTAX); + } + } else { + notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, chan); + } + return MOD_CONT; + } else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!is_servadmin && !check_access(u, ci, CA_SET)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (!stricmp(option, "DONTKICKOPS")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_DONTKICKOPS; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_ON, + ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_DONTKICKOPS; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKOPS_OFF, + ci->name); + } else { + syntax_error(s_BotServ, u, "SET DONTKICKOPS", + BOT_SET_DONTKICKOPS_SYNTAX); + } + } else if (!stricmp(option, "DONTKICKVOICES")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_DONTKICKVOICES; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_ON, + ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_DONTKICKVOICES; + notice_lang(s_BotServ, u, BOT_SET_DONTKICKVOICES_OFF, + ci->name); + } else { + syntax_error(s_BotServ, u, "SET DONTKICKVOICES", + BOT_SET_DONTKICKVOICES_SYNTAX); + } + } else if (!stricmp(option, "FANTASY")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_FANTASY; + notice_lang(s_BotServ, u, BOT_SET_FANTASY_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_FANTASY; + notice_lang(s_BotServ, u, BOT_SET_FANTASY_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET FANTASY", + BOT_SET_FANTASY_SYNTAX); + } + } else if (!stricmp(option, "GREET")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_GREET; + notice_lang(s_BotServ, u, BOT_SET_GREET_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_GREET; + notice_lang(s_BotServ, u, BOT_SET_GREET_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET GREET", + BOT_SET_GREET_SYNTAX); + } + } else if (is_servadmin && !stricmp(option, "NOBOT")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_NOBOT; + if (ci->bi) + unassign(u, ci); + notice_lang(s_BotServ, u, BOT_SET_NOBOT_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_NOBOT; + notice_lang(s_BotServ, u, BOT_SET_NOBOT_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET NOBOT", + BOT_SET_NOBOT_SYNTAX); + } + } else if (!stricmp(option, "SYMBIOSIS")) { + if (!stricmp(value, "ON")) { + ci->botflags |= BS_SYMBIOSIS; + notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_ON, ci->name); + } else if (!stricmp(value, "OFF")) { + ci->botflags &= ~BS_SYMBIOSIS; + notice_lang(s_BotServ, u, BOT_SET_SYMBIOSIS_OFF, ci->name); + } else { + syntax_error(s_BotServ, u, "SET SYMBIOSIS", + BOT_SET_SYMBIOSIS_SYNTAX); + } + } else { + notice_help(s_BotServ, u, BOT_SET_UNKNOWN, option); + } + } + return MOD_CONT; +} diff --git a/src/core/bs_unassign.c b/src/core/bs_unassign.c new file mode 100644 index 000000000..1789189ba --- /dev/null +++ b/src/core/bs_unassign.c @@ -0,0 +1,88 @@ +/* BotServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_unassign(User * u); +void myBotServHelp(User * u); + +/** + * Create the unassign command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("UNASSIGN", do_unassign, NULL, BOT_HELP_UNASSIGN, -1, + -1, -1, -1); + moduleAddCommand(BOTSERV, c, MOD_UNIQUE); + + moduleSetBotHelp(myBotServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to Anopes /bs help output. + * @param u The user who is requesting help + **/ +void myBotServHelp(User * u) +{ + notice_lang(s_BotServ, u, BOT_HELP_CMD_UNASSIGN); +} + +/** + * The /bs unassign command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_unassign(User * u) +{ + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + + if (readonly) + notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); + else if (!chan) + syntax_error(s_BotServ, u, "UNASSIGN", BOT_UNASSIGN_SYNTAX); + else if (!(ci = cs_findchan(chan))) + notice_lang(s_BotServ, u, CHAN_X_NOT_REGISTERED, chan); + else if (ci->flags & CI_VERBOTEN) + notice_lang(s_BotServ, u, CHAN_X_FORBIDDEN, chan); + else if (!is_services_admin(u) && !check_access(u, ci, CA_ASSIGN)) + notice_lang(s_BotServ, u, ACCESS_DENIED); + else { + if (ci->bi) + unassign(u, ci); + notice_lang(s_BotServ, u, BOT_UNASSIGN_UNASSIGNED, ci->name); + } + return MOD_CONT; +} diff --git a/src/core/configure b/src/core/configure new file mode 100755 index 000000000..119c7c887 --- /dev/null +++ b/src/core/configure @@ -0,0 +1,35 @@ +#!/bin/sh + +echo -n "SRCS=" > ./Makefile.inc +FIRST=1 +for oldfile in *.c +do + if [ "$FIRST" = 1 ] ; then + echo -n " "$oldfile >> ./Makefile.inc + else + echo "\\" >> ./Makefile.inc + echo -n " " $oldfile >> ./Makefile.inc + fi + FIRST=0 +done +echo "" >> ./Makefile.inc + +echo -n "SUBS=" >> ./Makefile.inc +FIRST=1 +for dir in * +do + if [ -d $dir ] ; then + if [ -f $dir/Makefile ] ; then + if [ "$FIRST" = 1 ] ; then + echo -n " "$dir >> ./Makefile.inc + else + echo "\\" >> ./Makefile.inc + echo -n " " $dir >> ./Makefile.inc + fi + FIRST=0 + fi + fi +done + +exit 0 + diff --git a/src/core/cs_access.c b/src/core/cs_access.c new file mode 100644 index 000000000..e5d621972 --- /dev/null +++ b/src/core/cs_access.c @@ -0,0 +1,507 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + + +int do_access(User * u); +int do_levels(User * u); + +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ACCESS", do_access, NULL, CHAN_HELP_ACCESS, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("ACCESS LEVELS", NULL, NULL, CHAN_HELP_ACCESS_LEVELS, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("LEVELS", do_levels, NULL, CHAN_HELP_LEVELS, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_ACCESS); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_LEVELS); +} + + +static int access_del(User * u, ChanAccess * access, int *perm, int uacc) +{ + if (!access->in_use) + return 0; + if (!is_services_admin(u) && uacc <= access->level) { + (*perm)++; + return 0; + } + access->nc = NULL; + access->in_use = 0; + return 1; +} + +static int access_del_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + int *perm = va_arg(args, int *); + int uacc = va_arg(args, int); + if (num < 1 || num > ci->accesscount) + return 0; + *last = num; + return access_del(u, &ci->access[num - 1], perm, uacc); +} + + +static int access_list(User * u, int index, ChannelInfo * ci, + int *sent_header) +{ + ChanAccess *access = &ci->access[index]; + char *xop; + + if (!access->in_use) + return 0; + + if (!*sent_header) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_HEADER, ci->name); + *sent_header = 1; + } + + if (ci->flags & CI_XOP) { + xop = get_xop_level(access->level); + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_XOP_FORMAT, index + 1, + xop, access->nc->display); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_AXS_FORMAT, index + 1, + access->level, access->nc->display); + } + return 1; +} + +static int access_list_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + if (num < 1 || num > ci->accesscount) + return 0; + return access_list(u, num - 1, ci, sent_header); +} + + +/** + * The /cs access command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_access(User * u) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + char *s = strtok(NULL, " "); + + ChannelInfo *ci; + NickAlias *na; + NickCore *nc; + ChanAccess *access; + + int i; + int level = 0, ulev; + int is_list = (cmd && stricmp(cmd, "LIST") == 0); + int is_servadmin = is_services_admin(u); + + /* If LIST, we don't *require* any parameters, but we can take any. + * If DEL, we require a nick and no level. + * Else (ADD), we require a level (which implies a nick). */ + if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : + (stricmp(cmd, "DEL") == 0) ? (!nick || s) : !s)) { + syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + /* We still allow LIST in xOP mode, but not others */ + } else if ((ci->flags & CI_XOP) && !is_list) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_XOP, s_ChanServ); + } else if (((is_list && !check_access(u, ci, CA_ACCESS_LIST)) + || (!is_list && !check_access(u, ci, CA_ACCESS_CHANGE))) + && !is_servadmin) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "ADD") == 0) { + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + level = atoi(s); + ulev = get_access(u, ci); + + if (!is_servadmin && level >= ulev) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (level == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_NONZERO); + return MOD_CONT; + } else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_RANGE, + ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + return MOD_CONT; + } + + na = findnick(nick); + if (!na) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NICKS_ONLY); + return MOD_CONT; + } + if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + nc = na->nc; + for (access = ci->access, i = 0; i < ci->accesscount; + access++, i++) { + if (access->nc == nc) { + /* Don't allow lowering from a level >= ulev */ + if (!is_servadmin && access->level >= ulev) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + if (access->level == level) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_UNCHANGED, + access->nc->display, chan, level); + return MOD_CONT; + } + access->level = level; + alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); + notice_lang(s_ChanServ, u, CHAN_ACCESS_LEVEL_CHANGED, + access->nc->display, chan, level); + return MOD_CONT; + } + } + + for (i = 0; i < ci->accesscount; i++) { + if (!ci->access[i].in_use) + break; + } + if (i == ci->accesscount) { + if (i < CSAccessMax) { + ci->accesscount++; + ci->access = + srealloc(ci->access, + sizeof(ChanAccess) * ci->accesscount); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_REACHED_LIMIT, + CSAccessMax); + return MOD_CONT; + } + } + + access = &ci->access[i]; + access->nc = nc; + access->in_use = 1; + access->level = level; + access->last_seen = 0; + + alog("%s: %s!%s@%s (level %d) set access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, access->level, na->nick, nc->display, ci->name); + notice_lang(s_ChanServ, u, CHAN_ACCESS_ADDED, nc->display, + ci->name, access->level); + } else if (stricmp(cmd, "DEL") == 0) { + int deleted, a, b; + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + return MOD_CONT; + } + + /* Special case: is it a number/list? Only do search if it isn't. */ + if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { + int count, last = -1, perm = 0; + deleted = process_numlist(nick, &count, access_del_callback, u, + ci, &last, &perm, get_access(u, ci)); + if (!deleted) { + if (perm) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (count == 1) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_SUCH_ENTRY, + last, ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, + ci->name); + } + } else if (deleted == 1) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_ONE, + ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED_SEVERAL, + deleted, ci->name); + } + } else { + na = findnick(nick); + if (!na) { + notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + nc = na->nc; + for (i = 0; i < ci->accesscount; i++) { + if (ci->access[i].nc == nc) + break; + } + if (i == ci->accesscount) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NOT_FOUND, nick, + chan); + return MOD_CONT; + } + access = &ci->access[i]; + if (!is_servadmin && get_access(u, ci) <= access->level) { + deleted = 0; + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DELETED, + access->nc->display, ci->name); + alog("%s: %s!%s@%s (level %d) deleted access of %s (group %s) on %s", s_ChanServ, u->nick, u->username, u->host, get_access(u, ci), na->nick, access->nc->display, chan); + access->nc = NULL; + access->in_use = 0; + deleted = 1; + } + } + + if (deleted) { + /* Reordering - DrStein */ + for (b = 0; b < ci->accesscount; b++) { + if (ci->access[b].in_use) { + for (a = 0; a < ci->accesscount; a++) { + if (a > b) + break; + if (!ci->access[a].in_use) { + ci->access[a].in_use = 1; + ci->access[a].level = ci->access[b].level; + ci->access[a].nc = ci->access[b].nc; + ci->access[a].last_seen = + ci->access[b].last_seen; + ci->access[b].nc = NULL; + ci->access[b].in_use = 0; + break; + } + } + } + } + } + } else if (stricmp(cmd, "LIST") == 0) { + int sent_header = 0; + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + return MOD_CONT; + } + if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { + process_numlist(nick, NULL, access_list_callback, u, ci, + &sent_header); + } else { + for (i = 0; i < ci->accesscount; i++) { + if (nick && ci->access[i].nc + && !match_wild_nocase(nick, ci->access[i].nc->display)) + continue; + access_list(u, i, ci, &sent_header); + } + } + if (!sent_header) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_NO_MATCH, chan); + } else { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_FOOTER, ci->name); + } + } else if (stricmp(cmd, "CLEAR") == 0) { + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + if (!is_servadmin && !is_founder(u, ci)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + free(ci->access); + ci->access = NULL; + ci->accesscount = 0; + + notice_lang(s_ChanServ, u, CHAN_ACCESS_CLEAR, ci->name); + alog("%s: %s!%s@%s (level %d) cleared access list on %s", + s_ChanServ, u->nick, u->username, u->host, + get_access(u, ci), chan); + + } else { + syntax_error(s_ChanServ, u, "ACCESS", CHAN_ACCESS_SYNTAX); + } + return MOD_CONT; +} + + +int do_levels(User * u) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *what = strtok(NULL, " "); + char *s = strtok(NULL, " "); + char *error; + + ChannelInfo *ci; + int level; + int i; + + /* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only + * one; else, we want none. + */ + if (!cmd + || ((stricmp(cmd, "SET") == 0) ? !s + : ((strnicmp(cmd, "DIS", 3) == 0)) ? (!what || s) : !!what)) { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (ci->flags & CI_XOP) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_XOP); + } else if (!is_founder(u, ci) && !is_services_admin(u)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "SET") == 0) { + level = strtol(s, &error, 10); + + if (*error != '\0') { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + return MOD_CONT; + } + + if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_RANGE, + ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + return MOD_CONT; + } + + for (i = 0; levelinfo[i].what >= 0; i++) { + if (stricmp(levelinfo[i].name, what) == 0) { + ci->levels[levelinfo[i].what] = level; + + alog("%s: %s!%s@%s set level %s on channel %s to %d", + s_ChanServ, u->nick, u->username, u->host, + levelinfo[i].name, ci->name, level); + notice_lang(s_ChanServ, u, CHAN_LEVELS_CHANGED, + levelinfo[i].name, chan, level); + return MOD_CONT; + } + } + + notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); + + } else if (stricmp(cmd, "DIS") == 0 || stricmp(cmd, "DISABLE") == 0) { + for (i = 0; levelinfo[i].what >= 0; i++) { + if (stricmp(levelinfo[i].name, what) == 0) { + ci->levels[levelinfo[i].what] = ACCESS_INVALID; + + alog("%s: %s!%s@%s disabled level %s on channel %s", + s_ChanServ, u->nick, u->username, u->host, + levelinfo[i].name, ci->name); + notice_lang(s_ChanServ, u, CHAN_LEVELS_DISABLED, + levelinfo[i].name, chan); + return MOD_CONT; + } + } + + notice_lang(s_ChanServ, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); + } else if (stricmp(cmd, "LIST") == 0) { + int i; + + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_HEADER, chan); + + if (!levelinfo_maxwidth) { + for (i = 0; levelinfo[i].what >= 0; i++) { + int len = strlen(levelinfo[i].name); + if (len > levelinfo_maxwidth) + levelinfo_maxwidth = len; + } + } + + for (i = 0; levelinfo[i].what >= 0; i++) { + int j = ci->levels[levelinfo[i].what]; + + if (j == ACCESS_INVALID) { + j = levelinfo[i].what; + + if (j == CA_AUTOOP || j == CA_AUTODEOP || j == CA_AUTOVOICE + || j == CA_NOJOIN) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, + levelinfo_maxwidth, levelinfo[i].name); + } else { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_DISABLED, + levelinfo_maxwidth, levelinfo[i].name); + } + } else if (j == ACCESS_FOUNDER) { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_FOUNDER, + levelinfo_maxwidth, levelinfo[i].name); + } else { + notice_lang(s_ChanServ, u, CHAN_LEVELS_LIST_NORMAL, + levelinfo_maxwidth, levelinfo[i].name, j); + } + } + + } else if (stricmp(cmd, "RESET") == 0) { + reset_levels(ci); + + alog("%s: %s!%s@%s reset levels definitions on channel %s", + s_ChanServ, u->nick, u->username, u->host, ci->name); + notice_lang(s_ChanServ, u, CHAN_LEVELS_RESET, chan); + } else { + syntax_error(s_ChanServ, u, "LEVELS", CHAN_LEVELS_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/cs_akick.c b/src/core/cs_akick.c new file mode 100644 index 000000000..dd729da98 --- /dev/null +++ b/src/core/cs_akick.c @@ -0,0 +1,584 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + + +int do_akick(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("AKICK", do_akick, NULL, CHAN_HELP_AKICK, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AKICK); +} + +/** + * The /cs akick command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ + /* `last' is set to the last index this routine was called with */ +int akick_del(User * u, AutoKick * akick) +{ + if (!(akick->flags & AK_USED)) + return 0; + if (akick->flags & AK_ISNICK) { + akick->u.nc = NULL; + } else { + free(akick->u.mask); + akick->u.mask = NULL; + } + if (akick->reason) { + free(akick->reason); + akick->reason = NULL; + } + if (akick->creator) { + free(akick->creator); + akick->creator = NULL; + } + akick->addtime = 0; + akick->flags = 0; + return 1; +} + +int akick_del_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + if (num < 1 || num > ci->akickcount) + return 0; + *last = num; + return akick_del(u, &ci->akick[num - 1]); +} + + +int akick_list(User * u, int index, ChannelInfo * ci, int *sent_header) +{ + AutoKick *akick = &ci->akick[index]; + + if (!(akick->flags & AK_USED)) + return 0; + if (!*sent_header) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name); + *sent_header = 1; + } + + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_FORMAT, index + 1, + ((akick->flags & AK_ISNICK) ? akick->u.nc-> + display : akick->u.mask), + (akick->reason ? akick-> + reason : getstring(u->na, NO_REASON))); + return 1; +} + +int akick_list_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + if (num < 1 || num > ci->akickcount) + return 0; + return akick_list(u, num - 1, ci, sent_header); +} + +int akick_view(User * u, int index, ChannelInfo * ci, int *sent_header) +{ + AutoKick *akick = &ci->akick[index]; + char timebuf[64]; + struct tm tm; + + if (!(akick->flags & AK_USED)) + return 0; + if (!*sent_header) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_HEADER, ci->name); + *sent_header = 1; + } + + if (akick->addtime) { + tm = *localtime(&akick->addtime); + strftime_lang(timebuf, sizeof(timebuf), u, + STRFTIME_SHORT_DATE_FORMAT, &tm); + } else { + snprintf(timebuf, sizeof(timebuf), getstring(u->na, UNKNOWN)); + } + + notice_lang(s_ChanServ, u, + ((akick-> + flags & AK_STUCK) ? CHAN_AKICK_VIEW_FORMAT_STUCK : + CHAN_AKICK_VIEW_FORMAT), index + 1, + ((akick->flags & AK_ISNICK) ? akick->u.nc-> + display : akick->u.mask), + akick->creator ? akick->creator : getstring(u->na, + UNKNOWN), + timebuf, + (akick->reason ? akick-> + reason : getstring(u->na, NO_REASON))); + return 1; +} + +int akick_view_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + if (num < 1 || num > ci->akickcount) + return 0; + return akick_view(u, num - 1, ci, sent_header); +} + + + +int do_akick(User * u) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *mask = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + ChannelInfo *ci; + AutoKick *akick; + int i; + Channel *c; + struct c_userlist *cu = NULL; + struct c_userlist *next; + char *argv[3]; + int count = 0; + + if (!cmd || (!mask && (!stricmp(cmd, "ADD") || !stricmp(cmd, "STICK") + || !stricmp(cmd, "UNSTICK") + || !stricmp(cmd, "DEL")))) { + + syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!check_access(u, ci, CA_AKICK) && !is_services_admin(u)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "ADD") == 0) { + + NickAlias *na = findnick(mask); + NickCore *nc = NULL; + char *nick, *user, *host; + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + return MOD_CONT; + } + + if (!na) { + split_usermask(mask, &nick, &user, &host); + mask = + scalloc(strlen(nick) + strlen(user) + strlen(host) + 3, 1); + sprintf(mask, "%s!%s@%s", nick, user, host); + free(nick); + free(user); + free(host); + } else { + if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, mask); + return MOD_CONT; + } + nc = na->nc; + } + + /* Check excepts BEFORE we get this far */ + if (ircd->except) { + if (is_excepted_mask(ci, mask) == 1) { + notice_lang(s_ChanServ, u, CHAN_EXCEPTED, mask, chan); + return MOD_CONT; + } + } + + for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + if (!(akick->flags & AK_USED)) + continue; + if ((akick->flags & AK_ISNICK) ? akick->u.nc == nc + : stricmp(akick->u.mask, mask) == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_ALREADY_EXISTS, + (akick->flags & AK_ISNICK) ? akick->u.nc-> + display : akick->u.mask, chan); + return MOD_CONT; + } + } + + for (i = 0; i < ci->akickcount; i++) { + if (!(ci->akick[i].flags & AK_USED)) + break; + } + if (i == ci->akickcount) { + if (ci->akickcount >= CSAutokickMax) { + notice_lang(s_ChanServ, u, CHAN_AKICK_REACHED_LIMIT, + CSAutokickMax); + return MOD_CONT; + } + ci->akickcount++; + ci->akick = + srealloc(ci->akick, sizeof(AutoKick) * ci->akickcount); + } + akick = &ci->akick[i]; + akick->flags = AK_USED; + if (nc) { + akick->flags |= AK_ISNICK; + akick->u.nc = nc; + } else { + akick->u.mask = mask; + } + akick->creator = sstrdup(u->nick); + akick->addtime = time(NULL); + if (reason) { + if (strlen(reason) > 200) + reason[200] = '\0'; + akick->reason = sstrdup(reason); + } else { + akick->reason = NULL; + } + + /* Auto ENFORCE #63 */ + c = findchan(ci->name); + if (c) { + cu = c->users; + while (cu) { + next = cu->next; + if (check_kick(cu->user, c->name)) { + argv[0] = sstrdup(c->name); + argv[1] = sstrdup(cu->user->nick); + if (akick->reason) + argv[2] = sstrdup(akick->reason); + else + argv[2] = sstrdup("none"); + + do_kick(s_ChanServ, 3, argv); + + free(argv[2]); + free(argv[1]); + free(argv[0]); + count++; + + } + cu = next; + } + } + notice_lang(s_ChanServ, u, CHAN_AKICK_ADDED, mask, chan); + + if (count) + notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan, + count); + + } else if (stricmp(cmd, "STICK") == 0) { + NickAlias *na; + NickCore *nc; + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + return MOD_CONT; + } + + if (ci->akickcount == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return MOD_CONT; + } + + na = findnick(mask); + nc = (na ? na->nc : NULL); + + for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) + continue; + if (!stricmp(akick->u.mask, mask)) + break; + } + + if (i == ci->akickcount) { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, + ci->name); + return MOD_CONT; + } + + akick->flags |= AK_STUCK; + notice_lang(s_ChanServ, u, CHAN_AKICK_STUCK, akick->u.mask, + ci->name); + + if (ci->c) + stick_mask(ci, akick); + } else if (stricmp(cmd, "UNSTICK") == 0) { + NickAlias *na; + NickCore *nc; + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + return MOD_CONT; + } + + if (ci->akickcount == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, ci->name); + return MOD_CONT; + } + + na = findnick(mask); + nc = (na ? na->nc : NULL); + + for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) + continue; + if (!stricmp(akick->u.mask, mask)) + break; + } + + if (i == ci->akickcount) { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, + ci->name); + return MOD_CONT; + } + + akick->flags &= ~AK_STUCK; + notice_lang(s_ChanServ, u, CHAN_AKICK_UNSTUCK, akick->u.mask, + ci->name); + + } else if (stricmp(cmd, "DEL") == 0) { + int deleted, a, b; + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + return MOD_CONT; + } + + if (ci->akickcount == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); + return MOD_CONT; + } + + /* Special case: is it a number/list? Only do search if it isn't. */ + if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { + int count, last = -1; + deleted = process_numlist(mask, &count, akick_del_callback, u, + ci, &last); + if (!deleted) { + if (count == 1) { + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_SUCH_ENTRY, + last, ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, + ci->name); + } + } else if (deleted == 1) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_ONE, + ci->name); + } else { + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED_SEVERAL, + deleted, ci->name); + } + } else { + NickAlias *na = findnick(mask); + NickCore *nc = (na ? na->nc : NULL); + + for (akick = ci->akick, i = 0; i < ci->akickcount; + akick++, i++) { + if (!(akick->flags & AK_USED)) + continue; + if (((akick->flags & AK_ISNICK) && akick->u.nc == nc) + || (!(akick->flags & AK_ISNICK) + && stricmp(akick->u.mask, mask) == 0)) + break; + } + if (i == ci->akickcount) { + notice_lang(s_ChanServ, u, CHAN_AKICK_NOT_FOUND, mask, + chan); + return MOD_CONT; + } + notice_lang(s_ChanServ, u, CHAN_AKICK_DELETED, mask, chan); + akick_del(u, akick); + deleted = 1; + } + if (deleted) { + /* Reordering - DrStein */ + for (b = 0; b < ci->akickcount; b++) { + if (ci->akick[b].flags & AK_USED) { + for (a = 1; a < ci->akickcount; a++) { + if (a > b) + break; + if (!(ci->akick[a].flags & AK_USED)) { + ci->akick[a].flags = ci->akick[b].flags; + if (ci->akick[b].flags & AK_ISNICK) { + ci->akick[a].u.nc = ci->akick[b].u.nc; + } else { + ci->akick[a].u.mask = + sstrdup(ci->akick[b].u.mask); + } + ci->akick[a].reason = + sstrdup(ci->akick[b].reason); + ci->akick[a].creator = + sstrdup(ci->akick[b].creator); + ci->akick[a].addtime = ci->akick[b].addtime; + + akick_del(u, &ci->akick[b]); + break; + } + } + } + } + } + } else if (stricmp(cmd, "LIST") == 0) { + int sent_header = 0; + + if (ci->akickcount == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); + return MOD_CONT; + } + if (mask && isdigit(*mask) && + strspn(mask, "1234567890,-") == strlen(mask)) { + process_numlist(mask, NULL, akick_list_callback, u, ci, + &sent_header); + } else { + for (akick = ci->akick, i = 0; i < ci->akickcount; + akick++, i++) { + if (!(akick->flags & AK_USED)) + continue; + if (mask) { + if (!(akick->flags & AK_ISNICK) + && !match_wild_nocase(mask, akick->u.mask)) + continue; + if ((akick->flags & AK_ISNICK) + && !match_wild_nocase(mask, akick->u.nc->display)) + continue; + } + akick_list(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan); + + } else if (stricmp(cmd, "VIEW") == 0) { + int sent_header = 0; + + if (ci->akickcount == 0) { + notice_lang(s_ChanServ, u, CHAN_AKICK_LIST_EMPTY, chan); + return MOD_CONT; + } + if (mask && isdigit(*mask) && + strspn(mask, "1234567890,-") == strlen(mask)) { + process_numlist(mask, NULL, akick_view_callback, u, ci, + &sent_header); + } else { + for (akick = ci->akick, i = 0; i < ci->akickcount; + akick++, i++) { + if (!(akick->flags & AK_USED)) + continue; + if (mask) { + if (!(akick->flags & AK_ISNICK) + && !match_wild_nocase(mask, akick->u.mask)) + continue; + if ((akick->flags & AK_ISNICK) + && !match_wild_nocase(mask, akick->u.nc->display)) + continue; + } + akick_view(u, i, ci, &sent_header); + } + } + if (!sent_header) + notice_lang(s_ChanServ, u, CHAN_AKICK_NO_MATCH, chan); + + } else if (stricmp(cmd, "ENFORCE") == 0) { + Channel *c = findchan(ci->name); + struct c_userlist *cu = NULL; + struct c_userlist *next; + char *argv[3]; + int count = 0; + + if (!c) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, ci->name); + return MOD_CONT; + } + + cu = c->users; + + while (cu) { + next = cu->next; + if (check_kick(cu->user, c->name)) { + argv[0] = sstrdup(c->name); + argv[1] = sstrdup(cu->user->nick); + argv[2] = sstrdup(CSAutokickReason); + + do_kick(s_ChanServ, 3, argv); + + free(argv[2]); + free(argv[1]); + free(argv[0]); + + count++; + } + cu = next; + } + + notice_lang(s_ChanServ, u, CHAN_AKICK_ENFORCE_DONE, chan, count); + + } else if (stricmp(cmd, "CLEAR") == 0) { + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); + return MOD_CONT; + } + + for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { + if (!(akick->flags & AK_USED)) + continue; + akick_del(u, akick); + } + + free(ci->akick); + ci->akick = NULL; + ci->akickcount = 0; + + notice_lang(s_ChanServ, u, CHAN_AKICK_CLEAR, ci->name); + + } else { + syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/cs_ban.c b/src/core/cs_ban.c new file mode 100644 index 000000000..eaf25597d --- /dev/null +++ b/src/core/cs_ban.c @@ -0,0 +1,227 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_unban(User * u); +int do_ban(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("BAN", do_ban, NULL, CHAN_HELP_BAN, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("UNBAN", do_unban, NULL, CHAN_HELP_UNBAN, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_BAN); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_UNBAN); +} + +/** + * The /cs ban command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_ban(User * u) +{ + char *chan = strtok(NULL, " "); + char *params = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + Channel *c; + ChannelInfo *ci; + User *u2; + + int is_same; + + if (!reason) { + reason = "Requested"; + } else { + if (strlen(reason) > 200) + reason[200] = '\0'; + } + + if (!chan) { + struct u_chanlist *uc, *next; + + /* Bans the user on every channels he is on. */ + + for (uc = u->chans; uc; uc = next) { + next = uc->next; + if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) + && check_access(u, ci, CA_BANME)) { + char *av[3]; + char mask[BUFSIZE]; + + /* + * Dont ban/kick the user on channels where he is excepted + * to prevent services <-> server wars. + */ + if (ircd->except) { + if (is_excepted(ci, u)) + notice_lang(s_ChanServ, u, CHAN_EXCEPTED, + u->nick, ci->name); + continue; + } + if (is_protected(u)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + continue; + } + + av[0] = sstrdup("+b"); + get_idealban(ci, u, mask, sizeof(mask)); + av[1] = mask; + anope_cmd_mode(whosends(ci), uc->chan->name, "+b %s", + av[1]); + chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); + free(av[0]); + + if ((ci->flags & CI_SIGNKICK) + || ((ci->flags & CI_SIGNKICK_LEVEL) + && !check_access(u, ci, CA_SIGNKICK))) + anope_cmd_kick(whosends(ci), ci->name, u->nick, + "%s (%s)", reason, u->nick); + else + anope_cmd_kick(whosends(ci), ci->name, u->nick, "%s", + reason); + av[0] = ci->name; + av[1] = u->nick; + av[2] = reason; + do_kick(s_ChanServ, 3, av); + } + } + + return MOD_CONT; + } else if (!params) { + params = u->nick; + } + + is_same = (params == u->nick) ? 1 : (stricmp(params, u->nick) == 0); + + if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (is_same ? !(u2 = u) : !(u2 = finduser(params))) { + notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, params); + } else if (!is_same ? !check_access(u, ci, CA_BAN) : + !check_access(u, ci, CA_BANME)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (!is_same && (ci->flags & CI_PEACE) + && (get_access(u2, ci) >= get_access(u, ci))) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + /* + * Dont ban/kick the user on channels where he is excepted + * to prevent services <-> server wars. + */ + } else if (ircd->except && is_excepted(ci, u2)) { + notice_lang(s_ChanServ, u, CHAN_EXCEPTED, u2->nick, ci->name); + } else if (ircd->protectedumode && is_protected(u2)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + char *av[3]; + char mask[BUFSIZE]; + + av[0] = sstrdup("+b"); + get_idealban(ci, u2, mask, sizeof(mask)); + av[1] = mask; + anope_cmd_mode(whosends(ci), c->name, "+b %s", av[1]); + chan_set_modes(s_ChanServ, c, 2, av, 1); + free(av[0]); + + /* We still allow host banning while not allowing to kick */ + if (!is_on_chan(c, u2)) + return MOD_CONT; + + if ((ci->flags & CI_SIGNKICK) + || ((ci->flags & CI_SIGNKICK_LEVEL) + && !check_access(u, ci, CA_SIGNKICK))) + anope_cmd_kick(whosends(ci), ci->name, params, "%s (%s)", + reason, u->nick); + else + anope_cmd_kick(whosends(ci), ci->name, params, "%s", reason); + + av[0] = ci->name; + av[1] = params; + av[2] = reason; + do_kick(s_ChanServ, 3, av); + } + return MOD_CONT; +} + +/** + * The /cs unban command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_unban(User * u) +{ + char *chan = strtok(NULL, " "); + Channel *c; + ChannelInfo *ci; + + if (!chan) { + syntax_error(s_ChanServ, u, "UNBAN", CHAN_UNBAN_SYNTAX); + } else if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!check_access(u, ci, CA_UNBAN)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + common_unban(ci, u->nick); + notice_lang(s_ChanServ, u, CHAN_UNBANNED, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_clear.c b/src/core/cs_clear.c new file mode 100644 index 000000000..8bf4c8e67 --- /dev/null +++ b/src/core/cs_clear.c @@ -0,0 +1,375 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_clear(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("CLEAR", do_clear, NULL, CHAN_HELP_CLEAR, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_CLEAR); +} + +/** + * The /cs clear command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_clear(User * u) +{ + char *chan = strtok(NULL, " "); + char *what = strtok(NULL, " "); + char tmp[BUFSIZE]; + Channel *c; + ChannelInfo *ci; + + if (!what) { + syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX); + } else if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!u || !check_access(u, ci, CA_CLEAR)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (stricmp(what, "bans") == 0) { + char *av[2]; + int i; + + /* Save original ban info */ + int count = c->bancount; + char **bans = scalloc(sizeof(char *) * count, 1); + for (i = 0; i < count; i++) + bans[i] = sstrdup(c->bans[i]); + + for (i = 0; i < count; i++) { + av[0] = sstrdup("-b"); + av[1] = bans[i]; + anope_cmd_mode(whosends(ci), chan, "%s %s", av[0], av[1]); + chan_set_modes(whosends(ci), c, 2, av, 0); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_BANS, chan); + free(bans); + } else if (ircd->except && stricmp(what, "excepts") == 0) { + char *av[2]; + int i; + + /* Save original except info */ + int count = c->exceptcount; + char **excepts = scalloc(sizeof(char *) * count, 1); + for (i = 0; i < count; i++) + excepts[i] = sstrdup(c->excepts[i]); + + for (i = 0; i < count; i++) { + av[0] = sstrdup("-e"); + av[1] = excepts[i]; + anope_cmd_mode(whosends(ci), chan, "%s %s", av[0], av[1]); + chan_set_modes(whosends(ci), c, 2, av, 0); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_EXCEPTS, chan); + free(excepts); + + } else if (ircd->invitemode && stricmp(what, "invites") == 0) { + char *av[2]; + int i; + + /* Save original except info */ + int count = c->invitecount; + char **invites = scalloc(sizeof(char *) * count, 1); + for (i = 0; i < count; i++) + invites[i] = sstrdup(c->invite[i]); + + for (i = 0; i < count; i++) { + av[0] = sstrdup("-I"); + av[1] = invites[i]; + anope_cmd_mode(whosends(ci), chan, "%s %s", av[0], av[1]); + chan_set_modes(whosends(ci), c, 2, av, 0); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_INVITES, chan); + free(invites); + + } else if (stricmp(what, "modes") == 0) { + char buf[BUFSIZE], *end = buf; + char *argv[2]; + + if (c->mode) { + /* Clear modes the bulk of the modes */ + anope_cmd_mode(whosends(ci), c->name, "%s", + ircd->modestoremove); + argv[0] = sstrdup(ircd->modestoremove); + chan_set_modes(whosends(ci), c, 1, argv, 0); + free(argv[0]); + + /* to prevent the internals from complaining send -k, -L, -f by themselves if we need + to send them - TSL */ + if (c->key) { + anope_cmd_mode(whosends(ci), c->name, "-k %s", c->key); + argv[0] = sstrdup("-k"); + argv[1] = c->key; + chan_set_modes(whosends(ci), c, 2, argv, 0); + free(argv[0]); + } + if (ircd->Lmode && c->redirect) { + anope_cmd_mode(whosends(ci), c->name, "-L %s", + c->redirect); + argv[0] = sstrdup("-L"); + argv[1] = c->redirect; + chan_set_modes(whosends(ci), c, 2, argv, 0); + free(argv[0]); + } + if (ircd->fmode && c->flood) { + if (flood_mode_char_remove) { + anope_cmd_mode(whosends(ci), c->name, "%s %s", + flood_mode_char_remove, c->flood); + argv[0] = sstrdup(flood_mode_char_remove); + argv[1] = c->flood; + chan_set_modes(whosends(ci), c, 2, argv, 0); + free(argv[0]); + } else { + if (debug) { + alog("debug: flood_mode_char_remove was not set unable to remove flood/throttle modes"); + } + } + } + check_modes(c); + } + + + + /* TODO: decide if the above implementation is better than this one. */ + + if (0) { + CBModeInfo *cbmi = cbmodeinfos; + CBMode *cbm; + + do { + if (c->mode & cbmi->flag) + *end++ = cbmi->mode; + } while ((++cbmi)->flag != 0); + + cbmi = cbmodeinfos; + + do { + if (cbmi->getvalue && (c->mode & cbmi->flag) + && !(cbmi->flags & CBM_MINUS_NO_ARG)) { + char *value = cbmi->getvalue(c); + + if (value) { + *end++ = ' '; + while (*value) + *end++ = *value++; + + /* Free the value */ + cbm = &cbmodes[(int) cbmi->mode]; + cbm->setvalue(c, NULL); + } + } + } while ((++cbmi)->flag != 0); + + *end = 0; + + anope_cmd_mode(whosends(ci), c->name, "-%s", buf); + c->mode = 0; + check_modes(c); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_MODES, chan); + } else if (stricmp(what, "ops") == 0) { + char *av[3]; + struct c_userlist *cu, *next; + + if (ircd->svsmode_ucmode) { + av[0] = sstrdup(chan); + anope_cmd_svsmode_chan(av[0], "-o", NULL); + if (ircd->owner) { + anope_cmd_svsmode_chan(av[0], ircd->ownerunset, NULL); + } + if (ircd->protect || ircd->admin) { + anope_cmd_svsmode_chan(av[0], ircd->adminunset, NULL); + } + for (cu = c->users; cu; cu = next) { + next = cu->next; + av[0] = sstrdup(chan); + if (!chan_has_user_status(c, cu->user, CUS_OP)) { + if (!chan_has_user_status(c, cu->user, CUS_PROTECT)) { + if (!chan_has_user_status(c, cu->user, CUS_OWNER)) { + continue; + } else { + snprintf(tmp, BUFSIZE, "%so", + ircd->ownerunset); + av[1] = sstrdup(tmp); + + } + } else { + snprintf(tmp, BUFSIZE, "%so", ircd->adminunset); + av[1] = sstrdup(tmp); + } + } else { + av[1] = sstrdup("-o"); + } + av[2] = sstrdup(cu->user->nick); + do_cmode(s_ChanServ, 3, av); + free(av[2]); + free(av[1]); + free(av[0]); + } + } else { + for (cu = c->users; cu; cu = next) { + next = cu->next; + av[0] = sstrdup(chan); + if (!chan_has_user_status(c, cu->user, CUS_OP)) { + if (!chan_has_user_status(c, cu->user, CUS_PROTECT)) { + if (!chan_has_user_status(c, cu->user, CUS_OWNER)) { + continue; + } else { + snprintf(tmp, BUFSIZE, "%so", + ircd->ownerunset); + av[1] = sstrdup(tmp); + } + } else { + snprintf(tmp, BUFSIZE, "%so", ircd->adminunset); + av[1] = sstrdup(tmp); + } + } else { + av[1] = sstrdup("-o"); + } + av[2] = sstrdup(cu->user->nick); + anope_cmd_mode(whosends(ci), av[0], "%s :%s", av[1], + av[2]); + do_cmode(s_ChanServ, 3, av); + free(av[2]); + free(av[1]); + free(av[0]); + } + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_OPS, chan); + } else if (ircd->halfop && stricmp(what, "hops") == 0) { + char *av[3]; + struct c_userlist *cu, *next; + + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_HALFOP)) + continue; + av[0] = sstrdup(chan); + av[1] = sstrdup("-h"); + av[2] = sstrdup(cu->user->nick); + if (ircd->svsmode_ucmode) { + anope_cmd_svsmode_chan(av[0], av[1], NULL); + do_cmode(s_ChanServ, 3, av); + break; + } else { + anope_cmd_mode(whosends(ci), av[0], "%s :%s", av[1], + av[2]); + } + do_cmode(s_ChanServ, 3, av); + free(av[2]); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_HOPS, chan); + } else if (stricmp(what, "voices") == 0) { + char *av[3]; + struct c_userlist *cu, *next; + + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_VOICE)) + continue; + av[0] = sstrdup(chan); + av[1] = sstrdup("-v"); + av[2] = sstrdup(cu->user->nick); + if (ircd->svsmode_ucmode) { + anope_cmd_svsmode_chan(av[0], av[1], NULL); + do_cmode(s_ChanServ, 3, av); + break; + } else { + anope_cmd_mode(whosends(ci), av[0], "%s :%s", av[1], + av[2]); + } + do_cmode(s_ChanServ, 3, av); + free(av[2]); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_VOICES, chan); + } else if (stricmp(what, "users") == 0) { + char *av[3]; + struct c_userlist *cu, *next; + char buf[256]; + + snprintf(buf, sizeof(buf), "CLEAR USERS command from %s", u->nick); + + for (cu = c->users; cu; cu = next) { + next = cu->next; + av[0] = sstrdup(chan); + av[1] = sstrdup(cu->user->nick); + av[2] = sstrdup(buf); + anope_cmd_kick(whosends(ci), av[0], av[1], av[2]); + do_kick(s_ChanServ, 3, av); + free(av[2]); + free(av[1]); + free(av[0]); + } + notice_lang(s_ChanServ, u, CHAN_CLEARED_USERS, chan); + } else { + syntax_error(s_ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/cs_drop.c b/src/core/cs_drop.c new file mode 100644 index 000000000..e53aa2037 --- /dev/null +++ b/src/core/cs_drop.c @@ -0,0 +1,128 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_drop(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("DROP", do_drop, NULL, -1, CHAN_HELP_DROP, -1, + CHAN_SERVADMIN_HELP_DROP, CHAN_SERVADMIN_HELP_DROP); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DROP); +} + +/** + * The /cs command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_drop(User * u) +{ + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + int is_servadmin = is_services_admin(u); + + if (readonly && !is_servadmin) { + notice_lang(s_ChanServ, u, CHAN_DROP_DISABLED); + return MOD_CONT; + } + + if (!chan) { + syntax_error(s_ChanServ, u, "DROP", CHAN_DROP_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (!is_servadmin && (ci->flags & CI_VERBOTEN)) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!is_servadmin && (ci->flags & CI_SUSPENDED)) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!is_servadmin + && (ci-> + flags & CI_SECUREFOUNDER ? !is_real_founder(u, + ci) : + !is_founder(u, ci))) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + int level = get_access(u, ci); + + if (readonly) /* in this case we know they're a Services admin */ + notice_lang(s_ChanServ, u, READ_ONLY_MODE); + + if (ci->c) { + if (ircd->regmode) { + ci->c->mode &= ~ircd->regmode; + anope_cmd_mode(whosends(ci), ci->name, "-r"); + } + } + + if (ircd->chansqline && (ci->flags & CI_VERBOTEN)) { + anope_cmd_unsqline(ci->name); + } + + alog("%s: Channel %s dropped by %s!%s@%s (founder: %s)", + s_ChanServ, ci->name, u->nick, u->username, + u->host, (ci->founder ? ci->founder->display : "(none)")); + + delchan(ci); + + /* We must make sure that the Services admin has not normally the right to + * drop the channel before issuing the wallops. + */ + if (WallDrop && is_servadmin && level < ACCESS_FOUNDER) + anope_cmd_global(s_ChanServ, + "\2%s\2 used DROP on channel \2%s\2", u->nick, + chan); + + notice_lang(s_ChanServ, u, CHAN_DROPPED, chan); + send_event(EVENT_CHAN_DROP, 1, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_forbid.c b/src/core/cs_forbid.c new file mode 100644 index 000000000..e7efd39d5 --- /dev/null +++ b/src/core/cs_forbid.c @@ -0,0 +1,132 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_forbid(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("FORBID", do_forbid, is_services_admin, -1, -1, -1, + CHAN_SERVADMIN_HELP_FORBID, + CHAN_SERVADMIN_HELP_FORBID); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_FORBID); + } +} + +/** + * The /cs forbid command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_forbid(User * u) +{ + ChannelInfo *ci; + char *chan = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + Channel *c; + + /* Assumes that permission checking has already been done. */ + if (!chan || (ForceForbidReason && !reason)) { + syntax_error(s_ChanServ, u, "FORBID", + (ForceForbidReason ? CHAN_FORBID_SYNTAX_REASON : + CHAN_FORBID_SYNTAX)); + return MOD_CONT; + } + if (readonly) + notice_lang(s_ChanServ, u, READ_ONLY_MODE); + if ((ci = cs_findchan(chan)) != NULL) + delchan(ci); + ci = makechan(chan); + if (ci) { + ci->flags |= CI_VERBOTEN; + ci->forbidby = sstrdup(u->nick); + if (reason) + ci->forbidreason = sstrdup(reason); + + if ((c = findchan(ci->name))) { + struct c_userlist *cu, *next; + char *av[3]; + + for (cu = c->users; cu; cu = next) { + next = cu->next; + + if (is_oper(cu->user)) + continue; + + av[0] = c->name; + av[1] = cu->user->nick; + av[2] = reason ? reason : "CHAN_FORBID_REASON"; + anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]); + do_kick(s_ChanServ, 3, av); + } + } + + if (WallForbid) + anope_cmd_global(s_ChanServ, + "\2%s\2 used FORBID on channel \2%s\2", + u->nick, ci->name); + + if (ircd->chansqline) { + anope_cmd_sqline(ci->name, ((reason) ? reason : "Forbidden")); + } + + alog("%s: %s set FORBID for channel %s", s_ChanServ, u->nick, + ci->name); + notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan); + send_event(EVENT_CHAN_FORBIDDEN, 1, chan); + } else { + alog("%s: Valid FORBID for %s by %s failed", s_ChanServ, ci->name, + u->nick); + notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_getkey.c b/src/core/cs_getkey.c new file mode 100644 index 000000000..c7ff77fea --- /dev/null +++ b/src/core/cs_getkey.c @@ -0,0 +1,88 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_getkey(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GETKEY", do_getkey, NULL, CHAN_HELP_GETKEY, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_GETKEY); +} + +/** + * The /cs getkey command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_getkey(User * u) +{ + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + + if (!chan) { + syntax_error(s_ChanServ, u, "GETKEY", CHAN_GETKEY_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!check_access(u, ci, CA_GETKEY)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (!ci->c || !ci->c->key) { + notice_lang(s_ChanServ, u, CHAN_GETKEY_NOKEY, chan); + } else { + notice_lang(s_ChanServ, u, CHAN_GETKEY_KEY, chan, ci->c->key); + } + + return MOD_CONT; +} diff --git a/src/core/cs_getpass.c b/src/core/cs_getpass.c new file mode 100644 index 000000000..403b21403 --- /dev/null +++ b/src/core/cs_getpass.c @@ -0,0 +1,100 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_getpass(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GETPASS", do_getpass, is_services_admin, -1, -1, -1, + CHAN_SERVADMIN_HELP_GETPASS, + CHAN_SERVADMIN_HELP_GETPASS); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); +#ifdef USE_ENCRYPTION + +#else + return MOD_CONT; +#endif +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_GETPASS); + } +} + +/** + * The /cs getpass command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ + +int do_getpass(User * u) +{ + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + + if (!chan) { + syntax_error(s_ChanServ, u, "GETPASS", CHAN_GETPASS_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (CSRestrictGetPass && !is_services_root(u)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + alog("%s: %s!%s@%s used GETPASS on %s", + s_ChanServ, u->nick, u->username, u->host, ci->name); + if (WallGetpass) { + anope_cmd_global(s_ChanServ, + "\2%s\2 used GETPASS on channel \2%s\2", + u->nick, chan); + } + notice_lang(s_ChanServ, u, CHAN_GETPASS_PASSWORD_IS, + chan, ci->founderpass); + } + return MOD_CONT; +} diff --git a/src/core/cs_help.c b/src/core/cs_help.c new file mode 100644 index 000000000..8f1910d2a --- /dev/null +++ b/src/core/cs_help.c @@ -0,0 +1,84 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * The /cs help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_ChanServ, u, CHAN_HELP); + moduleDisplayHelp(2, u); + if (CSExpire >= 86400) + notice_help(s_ChanServ, u, CHAN_HELP_EXPIRES, + CSExpire / 86400); + if (is_services_oper(u)) + notice_help(s_ChanServ, u, CHAN_SERVADMIN_HELP); + } else if (stricmp(cmd, "LEVELS DESC") == 0) { + int i; + notice_help(s_ChanServ, u, CHAN_HELP_LEVELS_DESC); + if (!levelinfo_maxwidth) { + for (i = 0; levelinfo[i].what >= 0; i++) { + int len = strlen(levelinfo[i].name); + if (len > levelinfo_maxwidth) + levelinfo_maxwidth = len; + } + } + for (i = 0; levelinfo[i].what >= 0; i++) { + notice_help(s_ChanServ, u, CHAN_HELP_LEVELS_DESC_FORMAT, + levelinfo_maxwidth, levelinfo[i].name, + getstring(u->na, levelinfo[i].desc)); + } + } else { + mod_help_cmd(s_ChanServ, u, CHANSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/cs_identify.c b/src/core/cs_identify.c new file mode 100644 index 000000000..0df40f127 --- /dev/null +++ b/src/core/cs_identify.c @@ -0,0 +1,118 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_identify(User * u); +void myChanServHelp(User * u); +extern MDE int check_password(const char *plaintext, const char *password); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("IDENTIFY", do_identify, NULL, CHAN_HELP_IDENTIFY, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + c = createCommand("ID", do_identify, NULL, CHAN_HELP_IDENTIFY, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_IDENTIFY); +} + +/** + * The /cs command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_identify(User * u) +{ + char *chan = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + ChannelInfo *ci; + struct u_chaninfolist *uc; + + if (!pass) { + syntax_error(s_ChanServ, u, "IDENTIFY", CHAN_IDENTIFY_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!nick_identified(u)) { + notice_lang(s_ChanServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (is_founder(u, ci)) { + notice_lang(s_ChanServ, u, NICK_ALREADY_IDENTIFIED); + } else { + int res; + + if ((res = check_password(pass, ci->founderpass)) == 1) { + if (!is_identified(u, ci)) { + uc = scalloc(sizeof(*uc), 1); + uc->next = u->founder_chans; + if (u->founder_chans) + u->founder_chans->prev = uc; + u->founder_chans = uc; + uc->chan = ci; + alog("%s: %s!%s@%s identified for %s", s_ChanServ, u->nick, + u->username, u->host, ci->name); + } + + notice_lang(s_ChanServ, u, CHAN_IDENTIFY_SUCCEEDED, chan); + } else if (res < 0) { + alog("%s: check_password failed for %s", s_ChanServ, ci->name); + notice_lang(s_ChanServ, u, CHAN_IDENTIFY_FAILED); + } else { + alog("%s: Failed IDENTIFY for %s by %s!%s@%s", + s_ChanServ, ci->name, u->nick, u->username, u->host); + notice_lang(s_ChanServ, u, PASSWORD_INCORRECT); + bad_password(u); + } + + } + return MOD_CONT; +} diff --git a/src/core/cs_info.c b/src/core/cs_info.c new file mode 100644 index 000000000..5450980de --- /dev/null +++ b/src/core/cs_info.c @@ -0,0 +1,249 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_info(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("INFO", do_info, NULL, CHAN_HELP_INFO, -1, + CHAN_SERVADMIN_HELP_INFO, CHAN_SERVADMIN_HELP_INFO, + CHAN_SERVADMIN_HELP_INFO); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_INFO); +} + +/** + * The /cs info command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_info(User * u) +{ +/* SADMINS and users, who have identified for a channel, can now cause it's + * Enstry Message and Successor to be displayed by supplying the ALL parameter. + * Syntax: INFO channel [ALL] + * -TheShadow (29 Mar 1999) + */ + char *chan = strtok(NULL, " "); + char *param = strtok(NULL, " "); + ChannelInfo *ci; + char buf[BUFSIZE], *end; + struct tm *tm; + int need_comma = 0; + const char *commastr = getstring(u->na, COMMA_SPACE); + int is_servadmin = is_services_admin(u); + int show_all = 0; + time_t expt; + + if (!chan) { + syntax_error(s_ChanServ, u, "INFO", CHAN_INFO_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + if (is_oper(u) && ci->forbidby) + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN_OPER, chan, + ci->forbidby, + (ci->forbidreason ? ci-> + forbidreason : getstring(u->na, NO_REASON))); + else + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!ci->founder) { + /* Paranoia... this shouldn't be able to happen */ + delchan(ci); + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else { + + /* Should we show all fields? Only for sadmins and identified users */ + if (param && stricmp(param, "ALL") == 0 && + (check_access(u, ci, CA_INFO) || is_servadmin)) + show_all = 1; + + notice_lang(s_ChanServ, u, CHAN_INFO_HEADER, chan); + notice_lang(s_ChanServ, u, CHAN_INFO_NO_FOUNDER, + ci->founder->display); + + if (show_all && ci->successor) + notice_lang(s_ChanServ, u, CHAN_INFO_NO_SUCCESSOR, + ci->successor->display); + + notice_lang(s_ChanServ, u, CHAN_INFO_DESCRIPTION, ci->desc); + tm = localtime(&ci->time_registered); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_ChanServ, u, CHAN_INFO_TIME_REGGED, buf); + tm = localtime(&ci->last_used); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_ChanServ, u, CHAN_INFO_LAST_USED, buf); + if (ci->last_topic + && (show_all || (!(ci->mlock_on & anope_get_secret_mode()) + && (!ci->c + || !(ci->c-> + mode & anope_get_secret_mode()))))) { + notice_lang(s_ChanServ, u, CHAN_INFO_LAST_TOPIC, + ci->last_topic); + notice_lang(s_ChanServ, u, CHAN_INFO_TOPIC_SET_BY, + ci->last_topic_setter); + } + + if (ci->entry_message && show_all) + notice_lang(s_ChanServ, u, CHAN_INFO_ENTRYMSG, + ci->entry_message); + if (ci->url) + notice_lang(s_ChanServ, u, CHAN_INFO_URL, ci->url); + if (ci->email) + notice_lang(s_ChanServ, u, CHAN_INFO_EMAIL, ci->email); + + if (show_all) { + notice_lang(s_ChanServ, u, CHAN_INFO_BANTYPE, ci->bantype); + + end = buf; + *end = 0; + if (ci->flags & CI_KEEPTOPIC) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s", + getstring(u->na, CHAN_INFO_OPT_KEEPTOPIC)); + need_comma = 1; + } + if (ci->flags & CI_OPNOTICE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_OPNOTICE)); + need_comma = 1; + } + if (ci->flags & CI_PEACE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_PEACE)); + need_comma = 1; + } + if (ci->flags & CI_PRIVATE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_PRIVATE)); + need_comma = 1; + } + if (ci->flags & CI_RESTRICTED) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, + CHAN_INFO_OPT_RESTRICTED)); + need_comma = 1; + } + if (ci->flags & CI_SECURE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_SECURE)); + need_comma = 1; + } + if (ci->flags & CI_SECUREOPS) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_SECUREOPS)); + need_comma = 1; + } + if (ci->flags & CI_SECUREFOUNDER) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, + CHAN_INFO_OPT_SECUREFOUNDER)); + need_comma = 1; + } + if ((ci->flags & CI_SIGNKICK) + || (ci->flags & CI_SIGNKICK_LEVEL)) { + end += + snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", getstring(u->na, + CHAN_INFO_OPT_SIGNKICK)); + need_comma = 1; + } + if (ci->flags & CI_TOPICLOCK) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_TOPICLOCK)); + need_comma = 1; + } + if (ci->flags & CI_XOP) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, CHAN_INFO_OPT_XOP)); + need_comma = 1; + } + notice_lang(s_ChanServ, u, CHAN_INFO_OPTIONS, + *buf ? buf : getstring(u->na, CHAN_INFO_OPT_NONE)); + notice_lang(s_ChanServ, u, CHAN_INFO_MODE_LOCK, + get_mlock_modes(ci, 1)); + + } + if (show_all) { + if (ci->flags & CI_NO_EXPIRE) { + notice_lang(s_ChanServ, u, CHAN_INFO_NO_EXPIRE); + } else { + if (is_servadmin) { + expt = ci->last_used + CSExpire; + tm = localtime(&expt); + strftime_lang(buf, sizeof(buf), u, + STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_ChanServ, u, CHAN_INFO_EXPIRE, buf); + } + } + } + if (ci->flags & CI_SUSPENDED) { + notice_lang(s_ChanServ, u, CHAN_X_SUSPENDED, ci->forbidby, + (ci->forbidreason ? ci-> + forbidreason : getstring(u->na, NO_REASON))); + } + + if (!show_all && (check_access(u, ci, CA_INFO) || is_servadmin)) + notice_lang(s_ChanServ, u, NICK_INFO_FOR_MORE, s_ChanServ, + ci->name); + + } + return MOD_CONT; +} diff --git a/src/core/cs_invite.c b/src/core/cs_invite.c new file mode 100644 index 000000000..bd3bb8e2b --- /dev/null +++ b/src/core/cs_invite.c @@ -0,0 +1,88 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myChanServHelp(User * u); +int do_invite(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("INVITE", do_invite, NULL, CHAN_HELP_INVITE, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_INVITE); +} + +/** + * The /cs invite command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_invite(User * u) +{ + char *chan = strtok(NULL, " "); + Channel *c; + ChannelInfo *ci; + + if (!chan) { + syntax_error(s_ChanServ, u, "INVITE", CHAN_INVITE_SYNTAX); + } else if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!u || !check_access(u, ci, CA_INVITE)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + anope_cmd_invite(whosends(ci), chan, u->nick); + } + return MOD_CONT; +} diff --git a/src/core/cs_kick.c b/src/core/cs_kick.c new file mode 100644 index 000000000..caaf6b9a9 --- /dev/null +++ b/src/core/cs_kick.c @@ -0,0 +1,152 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_cs_kick(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("KICK", do_cs_kick, NULL, CHAN_HELP_KICK, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_KICK); +} + +/** + * The /cs kick command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_cs_kick(User * u) +{ + char *chan = strtok(NULL, " "); + char *params = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + Channel *c; + ChannelInfo *ci; + User *u2; + + int is_same; + + if (!reason) { + reason = "Requested"; + } else { + if (strlen(reason) > 200) + reason[200] = '\0'; + } + + if (!chan) { + struct u_chanlist *uc, *next; + + /* Kicks the user on every channels he is on. */ + + for (uc = u->chans; uc; uc = next) { + next = uc->next; + if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) + && check_access(u, ci, CA_KICKME)) { + char *av[3]; + + if ((ci->flags & CI_SIGNKICK) + || ((ci->flags & CI_SIGNKICK_LEVEL) + && !check_access(u, ci, CA_SIGNKICK))) + anope_cmd_kick(whosends(ci), ci->name, u->nick, + "%s (%s)", reason, u->nick); + else + anope_cmd_kick(whosends(ci), ci->name, u->nick, "%s", + reason); + av[0] = ci->name; + av[1] = u->nick; + av[2] = reason; + do_kick(s_ChanServ, 3, av); + } + } + + return MOD_CONT; + } else if (!params) { + params = u->nick; + } + + is_same = (params == u->nick) ? 1 : (stricmp(params, u->nick) == 0); + + if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (is_same ? !(u2 = u) : !(u2 = finduser(params))) { + notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, params); + } else if (!is_on_chan(c, u2)) { + notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN, u2->nick, c->name); + } else if (!is_same ? !check_access(u, ci, CA_KICK) : + !check_access(u, ci, CA_KICKME)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (!is_same && (ci->flags & CI_PEACE) + && (get_access(u2, ci) >= get_access(u, ci))) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (is_protected(u2)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + char *av[3]; + + if ((ci->flags & CI_SIGNKICK) + || ((ci->flags & CI_SIGNKICK_LEVEL) + && !check_access(u, ci, CA_SIGNKICK))) + anope_cmd_kick(whosends(ci), ci->name, params, "%s (%s)", + reason, u->nick); + else + anope_cmd_kick(whosends(ci), ci->name, params, "%s", reason); + av[0] = ci->name; + av[1] = params; + av[2] = reason; + do_kick(s_ChanServ, 3, av); + } + return MOD_CONT; +} diff --git a/src/core/cs_list.c b/src/core/cs_list.c new file mode 100644 index 000000000..fa33f2947 --- /dev/null +++ b/src/core/cs_list.c @@ -0,0 +1,172 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_list(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("LIST", do_list, NULL, -1, CHAN_HELP_LIST, + CHAN_SERVADMIN_HELP_LIST, CHAN_SERVADMIN_HELP_LIST, + CHAN_SERVADMIN_HELP_LIST); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_LIST); +} + +/** + * The /cs list command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_list(User * u) +{ + char *pattern = strtok(NULL, " "); + ChannelInfo *ci; + int nchans, i; + char buf[BUFSIZE]; + int is_servadmin = is_services_admin(u); + int count = 0, from = 0, to = 0; + char *tmp = NULL; + char *s = NULL; + char *keyword; + int32 matchflags = 0; + + + if (CSListOpersOnly && (!u || !is_oper(u))) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (!pattern) { + syntax_error(s_ChanServ, u, "LIST", + is_servadmin ? CHAN_LIST_SERVADMIN_SYNTAX : + CHAN_LIST_SYNTAX); + } else { + + if (pattern) { + if (pattern[0] == '#') { + tmp = myStrGetOnlyToken((pattern + 1), '-', 0); /* Read FROM out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + from = atoi(tmp); + tmp = myStrGetTokenRemainder(pattern, '-', 1); /* Read TO out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + to = atoi(tmp); + pattern = sstrdup("*"); + } + } + + nchans = 0; + + while (is_servadmin && (keyword = strtok(NULL, " "))) { + if (stricmp(keyword, "FORBIDDEN") == 0) + matchflags |= CI_VERBOTEN; + if (stricmp(keyword, "SUSPENDED") == 0) + matchflags |= CI_SUSPENDED; + if (stricmp(keyword, "NOEXPIRE") == 0) + matchflags |= CI_NO_EXPIRE; + } + + notice_lang(s_ChanServ, u, CHAN_LIST_HEADER, pattern); + for (i = 0; i < 256; i++) { + for (ci = chanlists[i]; ci; ci = ci->next) { + if (!is_servadmin && ((ci->flags & CI_PRIVATE) + || (ci->flags & CI_VERBOTEN))) + continue; + if ((matchflags != 0) && !(ci->flags & matchflags)) + continue; + + if (stricmp(pattern, ci->name) == 0 + || match_wild_nocase(pattern, ci->name)) { + if ((((count + 1 >= from) && (count + 1 <= to)) + || ((from == 0) && (to == 0))) + && (++nchans <= CSListMax)) { + char noexpire_char = ' '; + if (is_servadmin && (ci->flags & CI_NO_EXPIRE)) + noexpire_char = '!'; + + if (ci->flags & CI_VERBOTEN) { + snprintf(buf, sizeof(buf), + "%-20s [Forbidden]", ci->name); + } else if (ci->flags & CI_SUSPENDED) { + snprintf(buf, sizeof(buf), + "%-20s [Suspended]", ci->name); + } else { + snprintf(buf, sizeof(buf), "%-20s %s", + ci->name, ci->desc ? ci->desc : ""); + } + + notice_user(s_ChanServ, u, " %c%s", + noexpire_char, buf); + } + count++; + } + } + } + notice_lang(s_ChanServ, u, CHAN_LIST_END, + nchans > CSListMax ? CSListMax : nchans, nchans); + } + return MOD_CONT; + +} diff --git a/src/core/cs_logout.c b/src/core/cs_logout.c new file mode 100644 index 000000000..2d143fc4b --- /dev/null +++ b/src/core/cs_logout.c @@ -0,0 +1,128 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_logout(User * u); +void myChanServHelp(User * u); +void make_unidentified(User * u, ChannelInfo * ci); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("LOGOUT", do_logout, NULL, -1, CHAN_HELP_LOGOUT, -1, + CHAN_SERVADMIN_HELP_LOGOUT, + CHAN_SERVADMIN_HELP_LOGOUT); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_LOGOUT); +} + +/** + * The /cs command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_logout(User * u) +{ + char *chan = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + ChannelInfo *ci; + User *u2 = NULL; + int is_servadmin = is_services_admin(u); + + if (!chan || (!nick && !is_servadmin)) { + syntax_error(s_ChanServ, u, "LOGOUT", + (!is_servadmin ? CHAN_LOGOUT_SYNTAX : + CHAN_LOGOUT_SERVADMIN_SYNTAX)); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (!is_servadmin && (ci->flags & CI_VERBOTEN)) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (nick && !(u2 = finduser(nick))) { + notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, nick); + } else if (!is_servadmin && u2 != u && !is_real_founder(u, ci)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + if (u2) { + make_unidentified(u2, ci); + notice_lang(s_ChanServ, u, CHAN_LOGOUT_SUCCEEDED, nick, chan); + alog("%s: User %s!%s@%s has been logged out of channel %s.", + s_ChanServ, u2->nick, u2->username, u2->host, chan); + } else { + int i; + for (i = 0; i < 1024; i++) + for (u2 = userlist[i]; u2; u2 = u2->next) + make_unidentified(u2, ci); + notice_lang(s_ChanServ, u, CHAN_LOGOUT_ALL_SUCCEEDED, chan); + alog("%s: All users identified have been logged out of channel %s.", s_ChanServ, chan); + } + + } + return MOD_CONT; +} + +void make_unidentified(User * u, ChannelInfo * ci) +{ + struct u_chaninfolist *uci; + + if (!u || !ci) + return; + + for (uci = u->founder_chans; uci; uci = uci->next) { + if (uci->chan == ci) { + if (uci->next) + uci->next->prev = uci->prev; + if (uci->prev) + uci->prev->next = uci->next; + else + u->founder_chans = uci->next; + free(uci); + break; + } + } +} diff --git a/src/core/cs_modes.c b/src/core/cs_modes.c new file mode 100644 index 000000000..c2696a108 --- /dev/null +++ b/src/core/cs_modes.c @@ -0,0 +1,392 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myChanServHelp(User * u); +int do_util(User * u, CSModeUtil * util); +int do_op(User * u); +int do_deop(User * u); +int do_voice(User * u); +int do_devoice(User * u); +int do_halfop(User * u); +int do_dehalfop(User * u); +int do_protect(User * u); +int do_deprotect(User * u); +int do_owner(User * u); +int do_deowner(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("OP", do_op, NULL, CHAN_HELP_OP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEOP", do_deop, NULL, CHAN_HELP_DEOP, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("VOICE", do_voice, NULL, CHAN_HELP_VOICE, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEVOICE", do_devoice, NULL, CHAN_HELP_DEVOICE, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + if (ircd->halfop) { + c = createCommand("HALFOP", do_halfop, NULL, CHAN_HELP_HALFOP, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEHALFOP", do_dehalfop, NULL, + CHAN_HELP_DEHALFOP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + } + if (ircd->protect) { + c = createCommand("PROTECT", do_protect, NULL, CHAN_HELP_PROTECT, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEPROTECT", do_deprotect, NULL, + CHAN_HELP_DEPROTECT, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + } + if (ircd->owner) { + c = createCommand("OWNER", do_owner, NULL, CHAN_HELP_OWNER, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEOWNER", do_deowner, NULL, CHAN_HELP_DEOWNER, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + } + if (ircd->admin) { + c = createCommand("ADMIN", do_protect, NULL, CHAN_HELP_PROTECT, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("DEADMIN", do_deprotect, NULL, + CHAN_HELP_DEPROTECT, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + } + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + if (ircd->owner) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_OWNER); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEOWNER); + } + if (ircd->protect) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_PROTECT); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEPROTECT); + } else if (ircd->admin) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_ADMIN); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEADMIN); + } + + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_OP); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEOP); + if (ircd->halfop) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_HALFOP); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEHALFOP); + } + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_VOICE); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_DEVOICE); +} + +/** + * The /cs op/deop/voice/devoice etc.. commands. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ + +int do_op(User * u) +{ + return do_util(u, &csmodeutils[MUT_OP]); +} + +/*************************************************************************/ + +int do_deop(User * u) +{ + return do_util(u, &csmodeutils[MUT_DEOP]); +} + +/*************************************************************************/ + +int do_voice(User * u) +{ + return do_util(u, &csmodeutils[MUT_VOICE]); +} + +/*************************************************************************/ + +int do_devoice(User * u) +{ + return do_util(u, &csmodeutils[MUT_DEVOICE]); +} + +/*************************************************************************/ + +int do_halfop(User * u) +{ + if (ircd->halfop) { + return do_util(u, &csmodeutils[MUT_HALFOP]); + } else { + return MOD_CONT; + } +} + +/*************************************************************************/ + +int do_dehalfop(User * u) +{ + if (ircd->halfop) { + return do_util(u, &csmodeutils[MUT_DEHALFOP]); + } else { + return MOD_CONT; + } +} + +/*************************************************************************/ + +int do_protect(User * u) +{ + if (ircd->protect || ircd->admin) { + return do_util(u, &csmodeutils[MUT_PROTECT]); + } else { + return MOD_CONT; + } +} + +/*************************************************************************/ + +int do_deprotect(User * u) +{ + if (ircd->protect || ircd->admin) { + return do_util(u, &csmodeutils[MUT_DEPROTECT]); + } else { + return MOD_CONT; + } +} + +/*************************************************************************/ + +int do_owner(User * u) +{ + char *av[2]; + char *chan = strtok(NULL, " "); + + Channel *c; + ChannelInfo *ci; + struct u_chanlist *uc; + + if (!ircd->owner) { + return MOD_CONT; + } + + if (!chan) { + av[0] = sstrdup(ircd->ownerset); + av[1] = u->nick; + + /* Sets the mode to the user on every channels he is on. */ + + for (uc = u->chans; uc; uc = uc->next) { + if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) + && is_founder(u, ci)) { + anope_cmd_mode(whosends(ci), uc->chan->name, "%s %s", + av[0], u->nick); + chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); + } + } + + free(av[0]); + return MOD_CONT; + } + + if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, c->name); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, ci->name); + } else if (!is_on_chan(c, u)) { + notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN, u->nick, c->name); + } else if (!is_founder(u, ci)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + anope_cmd_mode(whosends(ci), c->name, "%s %s", ircd->ownerset, + u->nick); + + av[0] = sstrdup(ircd->ownerset); + av[1] = u->nick; + chan_set_modes(s_ChanServ, c, 2, av, 1); + free(av[0]); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_deowner(User * u) +{ + char *av[2]; + char *chan = strtok(NULL, " "); + + Channel *c; + ChannelInfo *ci; + struct u_chanlist *uc; + + if (!ircd->owner) { + return MOD_CONT; + } + + if (!chan) { + av[0] = sstrdup(ircd->ownerunset); + av[1] = u->nick; + + /* Sets the mode to the user on every channels he is on. */ + + for (uc = u->chans; uc; uc = uc->next) { + if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) + && is_founder(u, ci)) { + anope_cmd_mode(whosends(ci), uc->chan->name, "%s %s", + av[0], u->nick); + chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); + } + } + + free(av[0]); + return MOD_CONT; + } + + if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, c->name); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, ci->name); + } else if (!is_on_chan(c, u)) { + notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN, u->nick, c->name); + } else if (!is_founder(u, ci)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + anope_cmd_mode(whosends(ci), c->name, "%s %s", ircd->ownerunset, + u->nick); + + av[0] = sstrdup(ircd->ownerunset); + av[1] = u->nick; + chan_set_modes(s_ChanServ, c, 2, av, 1); + free(av[0]); + } + return MOD_CONT; +} + +/* do_util: not a command, but does the job of other */ + +int do_util(User * u, CSModeUtil * util) +{ + char *av[2]; + char *chan = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + + Channel *c; + ChannelInfo *ci; + User *u2; + + int is_same; + + if (!chan) { + struct u_chanlist *uc; + + av[0] = util->mode; + av[1] = u->nick; + + /* Sets the mode to the user on every channels he is on. */ + + for (uc = u->chans; uc; uc = uc->next) { + if ((ci = uc->chan->ci) && !(ci->flags & CI_VERBOTEN) + && check_access(u, ci, util->levelself)) { + anope_cmd_mode(whosends(ci), uc->chan->name, "%s %s", + util->mode, u->nick); + chan_set_modes(s_ChanServ, uc->chan, 2, av, 1); + + if (util->notice && ci->flags & util->notice) + notice(whosends(ci), uc->chan->name, + "%s command used for %s by %s", util->name, + u->nick, u->nick); + } + } + + return MOD_CONT; + } else if (!nick) { + nick = u->nick; + } + + is_same = (nick == u->nick) ? 1 : (stricmp(nick, u->nick) == 0); + + if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, c->name); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, ci->name); + } else if (is_same ? !(u2 = u) : !(u2 = finduser(nick))) { + notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, nick); + } else if (!is_on_chan(c, u2)) { + notice_lang(s_ChanServ, u, NICK_X_NOT_ON_CHAN, u2->nick, c->name); + } else if (is_same ? !check_access(u, ci, util->levelself) : + !check_access(u, ci, util->level)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (*util->mode == '-' && !is_same && (ci->flags & CI_PEACE) + && (get_access(u2, ci) >= get_access(u, ci))) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (*util->mode == '-' && is_protected(u2)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + anope_cmd_mode(whosends(ci), c->name, "%s %s", util->mode, + u2->nick); + + av[0] = util->mode; + av[1] = u2->nick; + chan_set_modes(s_ChanServ, c, 2, av, 1); + + if (util->notice && ci->flags & util->notice) + notice(whosends(ci), c->name, "%s command used for %s by %s", + util->name, u2->nick, u->nick); + } + return MOD_CONT; +} diff --git a/src/core/cs_register.c b/src/core/cs_register.c new file mode 100644 index 000000000..892f51290 --- /dev/null +++ b/src/core/cs_register.c @@ -0,0 +1,199 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_register(User * u); +void myChanServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("REGISTER", do_register, NULL, CHAN_HELP_REGISTER, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_REGISTER); +} + +/** + * The /cs register command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_register(User * u) +{ + char *chan = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + char *desc = strtok(NULL, ""); + NickCore *nc; + Channel *c; + ChannelInfo *ci; + struct u_chaninfolist *uc; + int is_servadmin = is_services_admin(u); +#ifdef USE_ENCRYPTION + char founderpass[PASSMAX + 1]; +#endif + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_REGISTER_DISABLED); + return MOD_CONT; + } + + if (checkDefCon(DEFCON_NO_NEW_CHANNELS)) { + notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } + + if (!desc) { + syntax_error(s_ChanServ, u, "REGISTER", CHAN_REGISTER_SYNTAX); + } else if (*chan == '&') { + notice_lang(s_ChanServ, u, CHAN_REGISTER_NOT_LOCAL); + } else if (*chan != '#') { + notice_lang(s_ChanServ, u, CHAN_SYMBOL_REQUIRED); + } else if (!u->na || !(nc = u->na->nc)) { + notice_lang(s_ChanServ, u, CHAN_MUST_REGISTER_NICK, s_NickServ); + } else if (!nick_recognized(u)) { + notice_lang(s_ChanServ, u, CHAN_MUST_IDENTIFY_NICK, s_NickServ, + s_NickServ); + } else if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_REGISTER_NONE_CHANNEL, chan); + } else if ((ci = cs_findchan(chan)) != NULL) { + if (ci->flags & CI_VERBOTEN) { + alog("%s: Attempt to register FORBIDden channel %s by %s!%s@%s", s_ChanServ, ci->name, u->nick, u->username, u->host); + notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan); + } else { + notice_lang(s_ChanServ, u, CHAN_ALREADY_REGISTERED, chan); + } + } else if (!stricmp(chan, "#")) { + notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan); + } else if (!chan_has_user_status(c, u, CUS_OP)) { + notice_lang(s_ChanServ, u, CHAN_MUST_BE_CHANOP); + + } else if (!is_servadmin && nc->channelmax > 0 + && nc->channelcount >= nc->channelmax) { + notice_lang(s_ChanServ, u, + nc->channelcount > + nc-> + channelmax ? CHAN_EXCEEDED_CHANNEL_LIMIT : + CHAN_REACHED_CHANNEL_LIMIT, nc->channelmax); + } else if (stricmp(u->nick, pass) == 0 + || (StrictPasswords && strlen(pass) < 5)) { + notice_lang(s_ChanServ, u, MORE_OBSCURE_PASSWORD); + } else if (!(ci = makechan(chan))) { + alog("%s: makechan() failed for REGISTER %s", s_ChanServ, chan); + notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED); + +#ifdef USE_ENCRYPTION + } else if (strscpy(founderpass, pass, PASSMAX + 1), + encrypt_in_place(founderpass, PASSMAX) < 0) { + alog("%s: Couldn't encrypt password for %s (REGISTER)", + s_ChanServ, chan); + notice_lang(s_ChanServ, u, CHAN_REGISTRATION_FAILED); + delchan(ci); +#endif + + } else { + c->ci = ci; + ci->c = c; + ci->bantype = CSDefBantype; + ci->flags = CSDefFlags; + ci->mlock_on = ircd->defmlock; + ci->memos.memomax = MSMaxMemos; + ci->last_used = ci->time_registered; + ci->founder = nc; +#ifdef USE_ENCRYPTION + if (strlen(pass) > PASSMAX) + notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX); + memset(pass, 0, strlen(pass)); + memcpy(ci->founderpass, founderpass, PASSMAX); + ci->flags |= CI_ENCRYPTEDPW; +#else + if (strlen(pass) > PASSMAX - 1) /* -1 for null byte */ + notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX - 1); + strscpy(ci->founderpass, pass, PASSMAX); +#endif + ci->desc = sstrdup(desc); + if (c->topic) { + ci->last_topic = sstrdup(c->topic); + strscpy(ci->last_topic_setter, c->topic_setter, NICKMAX); + ci->last_topic_time = c->topic_time; + } else { + /* Set this to something, otherwise it will maliform the topic */ + strscpy(ci->last_topic_setter, s_ChanServ, NICKMAX); + } + ci->bi = NULL; + ci->botflags = BSDefFlags; + ci->founder->channelcount++; + alog("%s: Channel '%s' registered by %s!%s@%s", s_ChanServ, chan, + u->nick, u->username, u->host); + notice_lang(s_ChanServ, u, CHAN_REGISTERED, chan, u->nick); +#ifndef USE_ENCRYPTION + notice_lang(s_ChanServ, u, CHAN_PASSWORD_IS, ci->founderpass); +#endif + uc = scalloc(sizeof(*uc), 1); + uc->next = u->founder_chans; + uc->prev = NULL; + if (u->founder_chans) + u->founder_chans->prev = uc; + u->founder_chans = uc; + uc->chan = ci; + /* Implement new mode lock */ + check_modes(c); + /* On most ircds you do not receive the admin/owner mode till its registered */ + if (ircd->admin) { + anope_cmd_mode(s_ChanServ, chan, "%s %s", ircd->adminset, + u->nick); + } + if (ircd->owner && ircd->ownerset) { + anope_cmd_mode(s_ChanServ, chan, "%s %s", ircd->ownerset, + u->nick); + } + send_event(EVENT_CHAN_REGISTERED, 1, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_sendpass.c b/src/core/cs_sendpass.c new file mode 100644 index 000000000..61eb70524 --- /dev/null +++ b/src/core/cs_sendpass.c @@ -0,0 +1,123 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_sendpass(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SENDPASS", do_sendpass, NULL, CHAN_HELP_SENDPASS, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); +#ifdef USE_ENCRYPTION + return MOD_STOP; +#else + if (UseMail) { + return MOD_CONT; + } else { + return MOD_STOP; + } +#endif +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SENDPASS); +} + +/** + * The /cs sendpass command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_sendpass(User * u) +{ + + char *chan = strtok(NULL, " "); + ChannelInfo *ci; + NickCore *founder; + + if (!chan) { + syntax_error(s_ChanServ, u, "SENDPASS", CHAN_SENDPASS_SYNTAX); + } else if (RestrictMail && !is_oper(u)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (!(ci = cs_findchan(chan)) || !(founder = ci->founder)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else { + char buf[BUFSIZE]; + MailInfo *mail; + + snprintf(buf, sizeof(buf), + getstring2(founder, CHAN_SENDPASS_SUBJECT), ci->name); + mail = MailBegin(u, founder, buf, s_ChanServ); + if (!mail) + return MOD_CONT; + + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_HEAD)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_LINE_1), + ci->name); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_LINE_2), + ci->founderpass); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_LINE_3)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_LINE_4)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(founder, CHAN_SENDPASS_LINE_5), + NetworkName); + fprintf(mail->pipe, "\n.\n"); + + MailEnd(mail); + + alog("%s: %s!%s@%s used SENDPASS on %s", s_ChanServ, u->nick, + u->username, u->host, chan); + notice_lang(s_ChanServ, u, CHAN_SENDPASS_OK, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_set.c b/src/core/cs_set.c new file mode 100644 index 000000000..7916a93b4 --- /dev/null +++ b/src/core/cs_set.c @@ -0,0 +1,839 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_set(User * u); +int do_set_founder(User * u, ChannelInfo * ci, char *param); +int do_set_successor(User * u, ChannelInfo * ci, char *param); +int do_set_password(User * u, ChannelInfo * ci, char *param); +int do_set_desc(User * u, ChannelInfo * ci, char *param); +int do_set_url(User * u, ChannelInfo * ci, char *param); +int do_set_email(User * u, ChannelInfo * ci, char *param); +int do_set_entrymsg(User * u, ChannelInfo * ci, char *param); +int do_set_bantype(User * u, ChannelInfo * ci, char *param); +int do_set_mlock(User * u, ChannelInfo * ci, char *param); +int do_set_keeptopic(User * u, ChannelInfo * ci, char *param); +int do_set_topiclock(User * u, ChannelInfo * ci, char *param); +int do_set_private(User * u, ChannelInfo * ci, char *param); +int do_set_secureops(User * u, ChannelInfo * ci, char *param); +int do_set_securefounder(User * u, ChannelInfo * ci, char *param); +int do_set_restricted(User * u, ChannelInfo * ci, char *param); +int do_set_secure(User * u, ChannelInfo * ci, char *param); +int do_set_signkick(User * u, ChannelInfo * ci, char *param); +int do_set_opnotice(User * u, ChannelInfo * ci, char *param); +int do_set_xop(User * u, ChannelInfo * ci, char *param); +int do_set_peace(User * u, ChannelInfo * ci, char *param); +int do_set_noexpire(User * u, ChannelInfo * ci, char *param); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", do_set, NULL, CHAN_HELP_SET, -1, -1, + CHAN_SERVADMIN_HELP_SET, CHAN_SERVADMIN_HELP_SET); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET FOUNDER", NULL, NULL, CHAN_HELP_SET_FOUNDER, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET SUCCESSOR", NULL, NULL, CHAN_HELP_SET_SUCCESSOR, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET PASSWORD", NULL, NULL, CHAN_HELP_SET_PASSWORD, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET DESC", NULL, NULL, CHAN_HELP_SET_DESC, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET URL", NULL, NULL, CHAN_HELP_SET_URL, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET EMAIL", NULL, NULL, CHAN_HELP_SET_EMAIL, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET ENTRYMSG", NULL, NULL, CHAN_HELP_SET_ENTRYMSG, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET BANTYPE", NULL, NULL, CHAN_HELP_SET_BANTYPE, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET PRIVATE", NULL, NULL, CHAN_HELP_SET_PRIVATE, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET KEEPTOPIC", NULL, NULL, CHAN_HELP_SET_KEEPTOPIC, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET TOPICLOCK", NULL, NULL, CHAN_HELP_SET_TOPICLOCK, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET MLOCK", NULL, NULL, CHAN_HELP_SET_MLOCK, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET RESTRICTED", NULL, NULL, + CHAN_HELP_SET_RESTRICTED, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET SECURE", NULL, NULL, CHAN_HELP_SET_SECURE, -1, + -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET SECUREOPS", NULL, NULL, CHAN_HELP_SET_SECUREOPS, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET SECUREFOUNDER", NULL, NULL, + CHAN_HELP_SET_SECUREFOUNDER, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET SIGNKICK", NULL, NULL, CHAN_HELP_SET_SIGNKICK, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET OPNOTICE", NULL, NULL, CHAN_HELP_SET_OPNOTICE, + -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET XOP", NULL, NULL, CHAN_HELP_SET_XOP, -1, -1, -1, + -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET PEACE", NULL, NULL, CHAN_HELP_SET_PEACE, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SET NOEXPIRE", NULL, NULL, -1, -1, -1, + CHAN_SERVADMIN_HELP_SET_NOEXPIRE, + CHAN_SERVADMIN_HELP_SET_NOEXPIRE); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SET); +} + +/** + * The /cs set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ + +/* Main SET routine. Calls other routines as follows: + * do_set_command(User *command_sender, ChannelInfo *ci, char *param); + * The parameter passed is the first space-delimited parameter after the + * option name, except in the case of DESC, TOPIC, and ENTRYMSG, in which + * it is the entire remainder of the line. Additional parameters beyond + * the first passed in the function call can be retrieved using + * strtok(NULL, toks). + */ +int do_set(User * u) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *param; + ChannelInfo *ci; + int is_servadmin = is_services_admin(u); + + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_SET_DISABLED); + return MOD_CONT; + } + + if (cmd) { + if (stricmp(cmd, "DESC") == 0 || stricmp(cmd, "ENTRYMSG") == 0) + param = strtok(NULL, ""); + else + param = strtok(NULL, " "); + } else { + param = NULL; + } + + if (!param && (!cmd || (stricmp(cmd, "SUCCESSOR") != 0 && + stricmp(cmd, "URL") != 0 && + stricmp(cmd, "EMAIL") != 0 && + stricmp(cmd, "ENTRYMSG") != 0))) { + syntax_error(s_ChanServ, u, "SET", CHAN_SET_SYNTAX); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!is_servadmin && !check_access(u, ci, CA_SET)) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else if (stricmp(cmd, "FOUNDER") == 0) { + if (!is_servadmin + && (ci-> + flags & CI_SECUREFOUNDER ? !is_real_founder(u, + ci) : + !is_founder(u, ci))) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + do_set_founder(u, ci, param); + } + } else if (stricmp(cmd, "SUCCESSOR") == 0) { + if (!is_servadmin + && (ci-> + flags & CI_SECUREFOUNDER ? !is_real_founder(u, + ci) : + !is_founder(u, ci))) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + do_set_successor(u, ci, param); + } + } else if (stricmp(cmd, "PASSWORD") == 0) { + if (!is_servadmin + && (ci-> + flags & CI_SECUREFOUNDER ? !is_real_founder(u, + ci) : + !is_founder(u, ci))) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + do_set_password(u, ci, param); + } + } else if (stricmp(cmd, "DESC") == 0) { + do_set_desc(u, ci, param); + } else if (stricmp(cmd, "URL") == 0) { + do_set_url(u, ci, param); + } else if (stricmp(cmd, "EMAIL") == 0) { + do_set_email(u, ci, param); + } else if (stricmp(cmd, "ENTRYMSG") == 0) { + do_set_entrymsg(u, ci, param); + } else if (stricmp(cmd, "TOPIC") == 0) { + notice_lang(s_ChanServ, u, OBSOLETE_COMMAND, "TOPIC"); + } else if (stricmp(cmd, "BANTYPE") == 0) { + do_set_bantype(u, ci, param); + } else if (stricmp(cmd, "MLOCK") == 0) { + do_set_mlock(u, ci, param); + } else if (stricmp(cmd, "KEEPTOPIC") == 0) { + do_set_keeptopic(u, ci, param); + } else if (stricmp(cmd, "TOPICLOCK") == 0) { + do_set_topiclock(u, ci, param); + } else if (stricmp(cmd, "PRIVATE") == 0) { + do_set_private(u, ci, param); + } else if (stricmp(cmd, "SECUREOPS") == 0) { + do_set_secureops(u, ci, param); + } else if (stricmp(cmd, "SECUREFOUNDER") == 0) { + if (!is_servadmin + && (ci-> + flags & CI_SECUREFOUNDER ? !is_real_founder(u, + ci) : + !is_founder(u, ci))) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + } else { + do_set_securefounder(u, ci, param); + } + } else if (stricmp(cmd, "RESTRICTED") == 0) { + do_set_restricted(u, ci, param); + } else if (stricmp(cmd, "SECURE") == 0) { + do_set_secure(u, ci, param); + } else if (stricmp(cmd, "SIGNKICK") == 0) { + do_set_signkick(u, ci, param); + } else if (stricmp(cmd, "OPNOTICE") == 0) { + do_set_opnotice(u, ci, param); + } else if (stricmp(cmd, "XOP") == 0) { + do_set_xop(u, ci, param); + } else if (stricmp(cmd, "PEACE") == 0) { + do_set_peace(u, ci, param); + } else if (stricmp(cmd, "NOEXPIRE") == 0) { + do_set_noexpire(u, ci, param); + } else { + notice_lang(s_ChanServ, u, CHAN_SET_UNKNOWN_OPTION, cmd); + notice_lang(s_ChanServ, u, MORE_INFO, s_ChanServ, "SET"); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_founder(User * u, ChannelInfo * ci, char *param) +{ + NickAlias *na = findnick(param); + NickCore *nc, *nc0 = ci->founder; + + if (!na) { + notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param); + return MOD_CONT; + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param); + return MOD_CONT; + } + + nc = na->nc; + if (nc->channelmax > 0 && nc->channelcount >= nc->channelmax + && !is_services_admin(u)) { + notice_lang(s_ChanServ, u, CHAN_SET_FOUNDER_TOO_MANY_CHANS, param); + return MOD_CONT; + } + + alog("%s: Changing founder of %s from %s to %s by %s!%s@%s", + s_ChanServ, ci->name, ci->founder->display, nc->display, u->nick, + u->username, u->host); + + /* Founder and successor must not be the same group */ + if (nc == ci->successor) + ci->successor = NULL; + + nc0->channelcount--; + ci->founder = nc; + nc->channelcount++; + + notice_lang(s_ChanServ, u, CHAN_FOUNDER_CHANGED, ci->name, param); + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_successor(User * u, ChannelInfo * ci, char *param) +{ + NickAlias *na; + NickCore *nc; + + if (param) { + na = findnick(param); + + if (!na) { + notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param); + return MOD_CONT; + } + if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param); + return MOD_CONT; + } + if (na->nc == ci->founder) { + notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_IS_FOUNDER, param, + ci->name); + return MOD_CONT; + } + nc = na->nc; + + } else { + nc = NULL; + } + + alog("%s: Changing successor of %s from %s to %s by %s!%s@%s", + s_ChanServ, ci->name, + (ci->successor ? ci->successor->display : "none"), + (nc ? nc->display : "none"), u->nick, u->username, u->host); + + ci->successor = nc; + + if (nc) + notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_CHANGED, ci->name, + param); + else + notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_UNSET, ci->name); + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_password(User * u, ChannelInfo * ci, char *param) +{ + int len = strlen(param); + + if (stricmp(u->nick, param) == 0 || (StrictPasswords && len < 5)) { + notice_lang(s_ChanServ, u, MORE_OBSCURE_PASSWORD); + return MOD_CONT; + } +#ifdef USE_ENCRYPTION + if (len > PASSMAX) { + len = PASSMAX; + param[len] = 0; + notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX); + } + + if (encrypt(param, len, ci->founderpass, PASSMAX) < 0) { + memset(param, 0, strlen(param)); + alog("%s: Failed to encrypt password for %s (set)", s_ChanServ, + ci->name); + notice_lang(s_ChanServ, u, CHAN_SET_PASSWORD_FAILED); + return MOD_CONT; + } + + memset(param, 0, strlen(param)); + notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED, ci->name); + +#else /* !USE_ENCRYPTION */ + if (strlen(param) > PASSMAX - 1) /* -1 for null byte */ + notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX - 1); + strscpy(ci->founderpass, param, PASSMAX); + notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED_TO, ci->name, + ci->founderpass); +#endif /* USE_ENCRYPTION */ + + if (get_access(u, ci) < ACCESS_FOUNDER) { + alog("%s: %s!%s@%s set password as Services admin for %s", + s_ChanServ, u->nick, u->username, u->host, ci->name); + if (WallSetpass) + anope_cmd_global(s_ChanServ, + "\2%s\2 set password as Services admin for channel \2%s\2", + u->nick, ci->name); + } else { + alog("%s: %s!%s@%s changed password of %s (founder: %s)", + s_ChanServ, u->nick, u->username, u->host, + ci->name, ci->founder->display); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_desc(User * u, ChannelInfo * ci, char *param) +{ + if (ci->desc) + free(ci->desc); + ci->desc = sstrdup(param); + notice_lang(s_ChanServ, u, CHAN_DESC_CHANGED, ci->name, param); + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_url(User * u, ChannelInfo * ci, char *param) +{ + if (ci->url) + free(ci->url); + if (param) { + ci->url = sstrdup(param); + notice_lang(s_ChanServ, u, CHAN_URL_CHANGED, ci->name, param); + } else { + ci->url = NULL; + notice_lang(s_ChanServ, u, CHAN_URL_UNSET, ci->name); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_email(User * u, ChannelInfo * ci, char *param) +{ + if (ci->email) + free(ci->email); + if (param) { + ci->email = sstrdup(param); + notice_lang(s_ChanServ, u, CHAN_EMAIL_CHANGED, ci->name, param); + } else { + ci->email = NULL; + notice_lang(s_ChanServ, u, CHAN_EMAIL_UNSET, ci->name); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_entrymsg(User * u, ChannelInfo * ci, char *param) +{ + if (ci->entry_message) + free(ci->entry_message); + if (param) { + ci->entry_message = sstrdup(param); + notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_CHANGED, ci->name, + param); + } else { + ci->entry_message = NULL; + notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_UNSET, ci->name); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_mlock(User * u, ChannelInfo * ci, char *param) +{ + int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ + unsigned char mode; + CBMode *cbm; + + if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) { + notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } + + /* Reinitialize everything */ + if (ircd->chanreg) { + ci->mlock_on = ircd->regmode; + } else { + ci->mlock_on = 0; + } + ci->mlock_off = ci->mlock_limit = 0; + ci->mlock_key = NULL; + if (ircd->fmode) { + ci->mlock_flood = NULL; + } + if (ircd->Lmode) { + ci->mlock_redirect = NULL; + } + + while ((mode = *param++)) { + switch (mode) { + case '+': + add = 1; + continue; + case '-': + add = 0; + continue; + default: + if (add < 0) + continue; + } + + if ((int) mode < 128 && (cbm = &cbmodes[(int) mode])->flag != 0) { + if ((cbm->flags & CBM_NO_MLOCK) + || ((cbm->flags & CBM_NO_USER_MLOCK) && !is_oper(u))) { + notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_IMPOSSIBLE_CHAR, + mode); + } else if (add) { + ci->mlock_on |= cbm->flag; + ci->mlock_off &= ~cbm->flag; + if (cbm->cssetvalue) + cbm->cssetvalue(ci, strtok(NULL, " ")); + } else { + ci->mlock_off |= cbm->flag; + if (ci->mlock_on & cbm->flag) { + ci->mlock_on &= ~cbm->flag; + if (cbm->cssetvalue) + cbm->cssetvalue(ci, NULL); + } + } + } else { + notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_UNKNOWN_CHAR, mode); + } + } /* while (*param) */ + + if (ircd->Lmode) { + /* We can't mlock +L if +l is not mlocked as well. */ + if ((ci->mlock_on & ircd->chan_lmode) + && !(ci->mlock_on & anope_get_limit_mode())) { + ci->mlock_on &= ~ircd->chan_lmode; + free(ci->mlock_redirect); + notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_L_REQUIRED); + } + } + + /* Some ircd we can't set NOKNOCK without INVITE */ + /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */ + if (ircd->noknock && ircd->knock_needs_i) { + if ((ci->mlock_on & ircd->noknock) + && !(ci->mlock_on & anope_get_invite_mode())) { + ci->mlock_on &= ~ircd->noknock; + notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_K_REQUIRED); + } + } + + /* Since we always enforce mode r there is no way to have no + * mode lock at all. + */ + if (get_mlock_modes(ci, 0)) { + notice_lang(s_ChanServ, u, CHAN_MLOCK_CHANGED, ci->name, + get_mlock_modes(ci, 0)); + } + + /* Implement the new lock. */ + if (ci->c) + check_modes(ci->c); + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_bantype(User * u, ChannelInfo * ci, char *param) +{ + char *endptr; + + int16 bantype = strtol(param, &endptr, 10); + + if (*endptr != 0 || bantype < 0 || bantype > 3) { + notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_INVALID, param); + } else { + ci->bantype = bantype; + notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_CHANGED, ci->name, + ci->bantype); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_keeptopic(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_KEEPTOPIC; + notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_KEEPTOPIC; + notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET KEEPTOPIC", + CHAN_SET_KEEPTOPIC_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_topiclock(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_TOPICLOCK; + notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_TOPICLOCK; + notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET TOPICLOCK", + CHAN_SET_TOPICLOCK_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_private(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_PRIVATE; + notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_PRIVATE; + notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET PRIVATE", + CHAN_SET_PRIVATE_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_secureops(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_SECUREOPS; + notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_SECUREOPS; + notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET SECUREOPS", + CHAN_SET_SECUREOPS_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_securefounder(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_SECUREFOUNDER; + notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_SECUREFOUNDER; + notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET SECUREFOUNDER", + CHAN_SET_SECUREFOUNDER_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_restricted(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_RESTRICTED; + if (ci->levels[CA_NOJOIN] < 0) + ci->levels[CA_NOJOIN] = 0; + notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_RESTRICTED; + if (ci->levels[CA_NOJOIN] >= 0) + ci->levels[CA_NOJOIN] = -2; + notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET RESTRICTED", + CHAN_SET_RESTRICTED_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_secure(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_SECURE; + notice_lang(s_ChanServ, u, CHAN_SET_SECURE_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_SECURE; + notice_lang(s_ChanServ, u, CHAN_SET_SECURE_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET SECURE", CHAN_SET_SECURE_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_signkick(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_SIGNKICK; + ci->flags &= ~CI_SIGNKICK_LEVEL; + notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_ON, ci->name); + } else if (stricmp(param, "LEVEL") == 0) { + ci->flags |= CI_SIGNKICK_LEVEL; + ci->flags &= ~CI_SIGNKICK; + notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_LEVEL, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~(CI_SIGNKICK | CI_SIGNKICK_LEVEL); + notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET SIGNKICK", + CHAN_SET_SIGNKICK_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_opnotice(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_OPNOTICE; + notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_OPNOTICE; + notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET OPNOTICE", + CHAN_SET_OPNOTICE_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +#define CHECKLEV(lev) ((ci->levels[(lev)] != ACCESS_INVALID) && (access->level >= ci->levels[(lev)])) + +int do_set_xop(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + if (!(ci->flags & CI_XOP)) { + int i; + ChanAccess *access; + + for (access = ci->access, i = 0; i < ci->accesscount; + access++, i++) { + if (!access->in_use) + continue; + /* This will probably cause wrong levels to be set, but hey, + * it's better than losing it altogether. + */ + if (CHECKLEV(CA_AKICK) || CHECKLEV(CA_SET)) { + access->level = ACCESS_SOP; + } else if (CHECKLEV(CA_AUTOOP) || CHECKLEV(CA_OPDEOP) + || CHECKLEV(CA_OPDEOPME)) { + access->level = ACCESS_AOP; + } else if (ircd->halfop) { + if (CHECKLEV(CA_AUTOHALFOP) || CHECKLEV(CA_HALFOP) + || CHECKLEV(CA_HALFOPME)) { + access->level = ACCESS_HOP; + } + } else if (CHECKLEV(CA_AUTOVOICE) || CHECKLEV(CA_VOICE) + || CHECKLEV(CA_VOICEME)) { + access->level = ACCESS_VOP; + } else { + access->in_use = 0; + access->nc = NULL; + } + } + + reset_levels(ci); + ci->flags |= CI_XOP; + } + + alog("%s: %s!%s@%s enabled XOP for %s", s_ChanServ, u->nick, + u->username, u->host, ci->name); + notice_lang(s_ChanServ, u, CHAN_SET_XOP_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_XOP; + + alog("%s: %s!%s@%s disabled XOP for %s", s_ChanServ, u->nick, + u->username, u->host, ci->name); + notice_lang(s_ChanServ, u, CHAN_SET_XOP_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET XOP", CHAN_SET_XOP_SYNTAX); + } + return MOD_CONT; +} + +#undef CHECKLEV + +/*************************************************************************/ + +int do_set_peace(User * u, ChannelInfo * ci, char *param) +{ + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_PEACE; + notice_lang(s_ChanServ, u, CHAN_SET_PEACE_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_PEACE; + notice_lang(s_ChanServ, u, CHAN_SET_PEACE_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET PEACE", CHAN_SET_PEACE_SYNTAX); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_set_noexpire(User * u, ChannelInfo * ci, char *param) +{ + if (!is_services_admin(u)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + if (stricmp(param, "ON") == 0) { + ci->flags |= CI_NO_EXPIRE; + notice_lang(s_ChanServ, u, CHAN_SET_NOEXPIRE_ON, ci->name); + } else if (stricmp(param, "OFF") == 0) { + ci->flags &= ~CI_NO_EXPIRE; + notice_lang(s_ChanServ, u, CHAN_SET_NOEXPIRE_OFF, ci->name); + } else { + syntax_error(s_ChanServ, u, "SET NOEXPIRE", + CHAN_SET_NOEXPIRE_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/cs_status.c b/src/core/cs_status.c new file mode 100644 index 000000000..a8a847ff1 --- /dev/null +++ b/src/core/cs_status.c @@ -0,0 +1,102 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_status(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("STATUS", do_status, is_services_admin, -1, -1, -1, + CHAN_SERVADMIN_HELP_STATUS, + CHAN_SERVADMIN_HELP_STATUS); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_STATUS); + } +} + +/** + * The /cs status command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_status(User * u) +{ + ChannelInfo *ci; + User *u2; + char *nick, *chan; + char *temp; + + chan = strtok(NULL, " "); + nick = strtok(NULL, " "); + if (!nick || strtok(NULL, " ")) { + notice_lang(s_ChanServ, u, CHAN_STATUS_SYNTAX); + return MOD_CONT; + } + if (!(ci = cs_findchan(chan))) { + temp = chan; + chan = nick; + nick = temp; + ci = cs_findchan(chan); + } + if (!ci) { + notice_lang(s_ChanServ, u, CHAN_STATUS_NOT_REGGED, temp); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_STATUS_FORBIDDEN, chan); + return MOD_CONT; + } else if ((u2 = finduser(nick)) != NULL) { + notice_lang(s_ChanServ, u, CHAN_STATUS_INFO, chan, nick, + get_access(u2, ci)); + } else { /* !u2 */ + notice_lang(s_ChanServ, u, CHAN_STATUS_NOTONLINE, nick); + } + return MOD_CONT; +} diff --git a/src/core/cs_suspend.c b/src/core/cs_suspend.c new file mode 100644 index 000000000..7abf9e730 --- /dev/null +++ b/src/core/cs_suspend.c @@ -0,0 +1,188 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_suspend(User * u); +int do_unsuspend(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SUSPEND", do_suspend, is_services_admin, -1, -1, -1, + CHAN_SERVADMIN_HELP_SUSPEND, + CHAN_SERVADMIN_HELP_SUSPEND); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("UNSUSPEND", do_unsuspend, is_services_admin, -1, -1, + -1, CHAN_SERVADMIN_HELP_UNSUSPEND, + CHAN_SERVADMIN_HELP_UNSUSPEND); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SUSPEND); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_UNSUSPEND); + } +} + +/** + * The /cs (un)suspend command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_suspend(User * u) +{ + ChannelInfo *ci; + char *chan = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + Channel *c; + + /* Assumes that permission checking has already been done. */ + if (!chan || (ForceForbidReason && !reason)) { + syntax_error(s_ChanServ, u, "SUSPEND", + (ForceForbidReason ? CHAN_SUSPEND_SYNTAX_REASON : + CHAN_SUSPEND_SYNTAX)); + return MOD_CONT; + } + + /* Only SUSPEND existing channels, otherwise use FORBID (bug #54) */ + if ((ci = cs_findchan(chan)) == NULL) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } + + /* You should not SUSPEND a FORBIDEN channel */ + if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_MAY_NOT_BE_REGISTERED, chan); + return MOD_CONT; + } + + if (readonly) + notice_lang(s_ChanServ, u, READ_ONLY_MODE); + + if (ci) { + ci->flags |= CI_SUSPENDED; + ci->forbidby = sstrdup(u->nick); + if (reason) + ci->forbidreason = sstrdup(reason); + + if ((c = findchan(ci->name))) { + struct c_userlist *cu, *next; + char *av[3]; + + for (cu = c->users; cu; cu = next) { + next = cu->next; + + if (is_oper(cu->user)) + continue; + + av[0] = c->name; + av[1] = cu->user->nick; + av[2] = reason ? reason : "CHAN_SUSPEND_REASON"; + anope_cmd_kick(s_ChanServ, av[0], av[1], av[2]); + do_kick(s_ChanServ, 3, av); + } + } + + if (WallForbid) + anope_cmd_global(s_ChanServ, + "\2%s\2 used SUSPEND on channel \2%s\2", + u->nick, ci->name); + + alog("%s: %s set SUSPEND for channel %s", s_ChanServ, u->nick, + ci->name); + notice_lang(s_ChanServ, u, CHAN_SUSPEND_SUCCEEDED, chan); + send_event(EVENT_CHAN_SUSPENDED, 1, chan); + } else { + alog("%s: Valid SUSPEND for %s by %s failed", s_ChanServ, ci->name, + u->nick); + notice_lang(s_ChanServ, u, CHAN_SUSPEND_FAILED, chan); + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_unsuspend(User * u) +{ + ChannelInfo *ci; + char *chan = strtok(NULL, " "); + + /* Assumes that permission checking has already been done. */ + if (!chan) { + syntax_error(s_ChanServ, u, "UNSUSPEND", CHAN_UNSUSPEND_SYNTAX); + return MOD_CONT; + } + if (chan[0] != '#') { + notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_ERROR); + return MOD_CONT; + } + if (readonly) + notice_lang(s_ChanServ, u, READ_ONLY_MODE); + + ci = cs_findchan(chan); + + if (ci) { + ci->flags &= ~CI_SUSPENDED; + ci->forbidreason = NULL; + ci->forbidby = NULL; + + if (WallForbid) + anope_cmd_global(s_ChanServ, + "\2%s\2 used UNSUSPEND on channel \2%s\2", + u->nick, ci->name); + + alog("%s: %s set UNSUSPEND for channel %s", s_ChanServ, u->nick, + ci->name); + notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_SUCCEEDED, chan); + send_event(EVENT_CHAN_UNSUSPEND, 1, chan); + } else { + alog("%s: Valid UNSUSPEND for %s by %s failed", s_ChanServ, + chan, u->nick); + notice_lang(s_ChanServ, u, CHAN_UNSUSPEND_FAILED, chan); + } + return MOD_CONT; +} diff --git a/src/core/cs_topic.c b/src/core/cs_topic.c new file mode 100644 index 000000000..bd175cafe --- /dev/null +++ b/src/core/cs_topic.c @@ -0,0 +1,119 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_cs_topic(User * u); +void myChanServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("TOPIC", do_cs_topic, NULL, CHAN_HELP_TOPIC, -1, -1, + -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_TOPIC); +} + +/** + * The /cs topic command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_cs_topic(User * u) +{ + char *chan = strtok(NULL, " "); + char *topic = strtok(NULL, ""); + + Channel *c; + ChannelInfo *ci; + + if (!chan) { + syntax_error(s_ChanServ, u, "TOPIC", CHAN_TOPIC_SYNTAX); + } else if (!(c = findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (!(ci = c->ci)) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, c->name); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, ci->name); + } else if (!is_services_admin(u) && !check_access(u, ci, CA_TOPIC)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + if (ci->last_topic) + free(ci->last_topic); + ci->last_topic = topic ? sstrdup(topic) : NULL; + strscpy(ci->last_topic_setter, u->nick, NICKMAX); + ci->last_topic_time = time(NULL); + + if (c->topic) + free(c->topic); + c->topic = topic ? sstrdup(topic) : NULL; + strscpy(c->topic_setter, u->nick, NICKMAX); + if (ircd->topictsbackward) { + c->topic_time = c->topic_time - 1; + } else { + c->topic_time = ci->last_topic_time; + } + + if (is_services_admin(u) && !check_access(u, ci, CA_TOPIC)) + alog("%s: %s!%s@%s changed topic of %s as services admin.", + s_ChanServ, u->nick, u->username, u->host, c->name); + if (ircd->join2set) { + if (whosends(ci) == s_ChanServ) { + anope_cmd_join(s_ChanServ, c->name, time(NULL)); + anope_cmd_mode(NULL, c->name, "+o %s", s_ChanServ); + } + } + anope_cmd_topic(whosends(ci), c->name, u->nick, topic ? topic : "", + c->topic_time); + if (ircd->join2set) { + if (whosends(ci) == s_ChanServ) { + anope_cmd_part(s_ChanServ, c->name, NULL); + } + } + } + return MOD_CONT; +} diff --git a/src/core/cs_xop.c b/src/core/cs_xop.c new file mode 100644 index 000000000..9116d165c --- /dev/null +++ b/src/core/cs_xop.c @@ -0,0 +1,474 @@ +/* ChanServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_xop(User * u, char *xname, int xlev, int *xmsgs); +int do_aop(User * u); +int do_hop(User * u); +int do_sop(User * u); +int do_vop(User * u); + +void myChanServHelp(User * u); + +int xop_msgs[4][14] = { + {CHAN_AOP_SYNTAX, + CHAN_AOP_DISABLED, + CHAN_AOP_NICKS_ONLY, + CHAN_AOP_ADDED, + CHAN_AOP_MOVED, + CHAN_AOP_NO_SUCH_ENTRY, + CHAN_AOP_NOT_FOUND, + CHAN_AOP_NO_MATCH, + CHAN_AOP_DELETED, + CHAN_AOP_DELETED_ONE, + CHAN_AOP_DELETED_SEVERAL, + CHAN_AOP_LIST_EMPTY, + CHAN_AOP_LIST_HEADER, + CHAN_AOP_CLEAR}, + {CHAN_SOP_SYNTAX, + CHAN_SOP_DISABLED, + CHAN_SOP_NICKS_ONLY, + CHAN_SOP_ADDED, + CHAN_SOP_MOVED, + CHAN_SOP_NO_SUCH_ENTRY, + CHAN_SOP_NOT_FOUND, + CHAN_SOP_NO_MATCH, + CHAN_SOP_DELETED, + CHAN_SOP_DELETED_ONE, + CHAN_SOP_DELETED_SEVERAL, + CHAN_SOP_LIST_EMPTY, + CHAN_SOP_LIST_HEADER, + CHAN_SOP_CLEAR}, + {CHAN_VOP_SYNTAX, + CHAN_VOP_DISABLED, + CHAN_VOP_NICKS_ONLY, + CHAN_VOP_ADDED, + CHAN_VOP_MOVED, + CHAN_VOP_NO_SUCH_ENTRY, + CHAN_VOP_NOT_FOUND, + CHAN_VOP_NO_MATCH, + CHAN_VOP_DELETED, + CHAN_VOP_DELETED_ONE, + CHAN_VOP_DELETED_SEVERAL, + CHAN_VOP_LIST_EMPTY, + CHAN_VOP_LIST_HEADER, + CHAN_VOP_CLEAR}, + {CHAN_HOP_SYNTAX, + CHAN_HOP_DISABLED, + CHAN_HOP_NICKS_ONLY, + CHAN_HOP_ADDED, + CHAN_HOP_MOVED, + CHAN_HOP_NO_SUCH_ENTRY, + CHAN_HOP_NOT_FOUND, + CHAN_HOP_NO_MATCH, + CHAN_HOP_DELETED, + CHAN_HOP_DELETED_ONE, + CHAN_HOP_DELETED_SEVERAL, + CHAN_HOP_LIST_EMPTY, + CHAN_HOP_LIST_HEADER, + CHAN_HOP_CLEAR} +}; + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("AOP", do_aop, NULL, CHAN_HELP_AOP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("HOP", do_hop, NULL, CHAN_HELP_HOP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("SOP", do_sop, NULL, CHAN_HELP_SOP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + c = createCommand("VOP", do_vop, NULL, CHAN_HELP_VOP, -1, -1, -1, -1); + moduleAddCommand(CHANSERV, c, MOD_UNIQUE); + + moduleSetChanHelp(myChanServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /cs help output. + * @param u The user who is requesting help + **/ +void myChanServHelp(User * u) +{ + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SOP); + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_AOP); + if (ircd->halfop) { + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_HOP); + } + notice_lang(s_ChanServ, u, CHAN_HELP_CMD_VOP); +} + +/** + * The /cs xop command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_aop(User * u) +{ + return do_xop(u, "AOP", ACCESS_AOP, xop_msgs[0]); +} + +/*************************************************************************/ + +int do_hop(User * u) +{ + return do_xop(u, "HOP", ACCESS_HOP, xop_msgs[3]); +} + +/*************************************************************************/ + +int do_sop(User * u) +{ + return do_xop(u, "SOP", ACCESS_SOP, xop_msgs[1]); +} + +/*************************************************************************/ + +int do_vop(User * u) +{ + return do_xop(u, "VOP", ACCESS_VOP, xop_msgs[2]); +} + +/* `last' is set to the last index this routine was called with + * `perm' is incremented whenever a permission-denied error occurs + */ + +int xop_del(User * u, ChanAccess * access, int *perm, int uacc, int xlev) +{ + if (!access->in_use || access->level != xlev) + return 0; + if (!is_services_admin(u) && uacc <= access->level) { + (*perm)++; + return 0; + } + access->nc = NULL; + access->in_use = 0; + return 1; +} + +int xop_del_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *last = va_arg(args, int *); + int *perm = va_arg(args, int *); + int uacc = va_arg(args, int); + int xlev = va_arg(args, int); + + if (num < 1 || num > ci->accesscount) + return 0; + *last = num; + + return xop_del(u, &ci->access[num - 1], perm, uacc, xlev); +} + + +int xop_list(User * u, int index, ChannelInfo * ci, + int *sent_header, int xlev, int xmsg) +{ + ChanAccess *access = &ci->access[index]; + + if (!access->in_use || access->level != xlev) + return 0; + + if (!*sent_header) { + notice_lang(s_ChanServ, u, xmsg, ci->name); + *sent_header = 1; + } + + notice_lang(s_ChanServ, u, CHAN_XOP_LIST_FORMAT, index + 1, + access->nc->display); + return 1; +} + +int xop_list_callback(User * u, int num, va_list args) +{ + ChannelInfo *ci = va_arg(args, ChannelInfo *); + int *sent_header = va_arg(args, int *); + int xlev = va_arg(args, int); + int xmsg = va_arg(args, int); + + if (num < 1 || num > ci->accesscount) + return 0; + + return xop_list(u, num - 1, ci, sent_header, xlev, xmsg); +} + + +int do_xop(User * u, char *xname, int xlev, int *xmsgs) +{ + char *chan = strtok(NULL, " "); + char *cmd = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + + ChannelInfo *ci; + NickAlias *na; + NickCore *nc; + + int i; + int change = 0; + short ulev; + int is_list = (cmd && stricmp(cmd, "LIST") == 0); + int is_servadmin = is_services_admin(u); + ChanAccess *access; + + /* If CLEAR, we don't need any parameters. + * If LIST, we don't *require* any parameters, but we can take any. + * If DEL or ADD we require a nick. */ + if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : !nick)) { + syntax_error(s_ChanServ, u, xname, xmsgs[0]); + } else if (!(ci = cs_findchan(chan))) { + notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); + } else if (!(ci->flags & CI_XOP)) { + notice_lang(s_ChanServ, u, CHAN_XOP_ACCESS, s_ChanServ); + } else if (stricmp(cmd, "ADD") == 0) { + if (readonly) { + notice_lang(s_ChanServ, u, xmsgs[1]); + return MOD_CONT; + } + + ulev = get_access(u, ci); + + if ((xlev >= ulev || ulev < ACCESS_AOP) && !is_servadmin) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + na = findnick(nick); + if (!na) { + notice_lang(s_ChanServ, u, xmsgs[2]); + return MOD_CONT; + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, na->nick); + return MOD_CONT; + } + + nc = na->nc; + for (access = ci->access, i = 0; i < ci->accesscount; + access++, i++) { + if (access->nc == nc) { + /** + * Patch provided by PopCorn to prevert AOP's reducing SOP's levels + **/ + if ((access->level >= ulev) && (!is_servadmin)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + change++; + break; + } + } + + if (!change) { + for (i = 0; i < ci->accesscount; i++) + if (!ci->access[i].in_use) + break; + + if (i == ci->accesscount) { + if (i < CSAccessMax) { + ci->accesscount++; + ci->access = + srealloc(ci->access, + sizeof(ChanAccess) * ci->accesscount); + } else { + notice_lang(s_ChanServ, u, CHAN_XOP_REACHED_LIMIT, + CSAccessMax); + return MOD_CONT; + } + } + + access = &ci->access[i]; + access->nc = nc; + } + + access->in_use = 1; + access->level = xlev; + access->last_seen = 0; + + alog("%s: %s!%s@%s (level %d) %s access level %d to %s (group %s) on channel %s", s_ChanServ, u->nick, u->username, u->host, ulev, change ? "changed" : "set", access->level, na->nick, nc->display, ci->name); + + if (!change) { + notice_lang(s_ChanServ, u, xmsgs[3], access->nc->display, + ci->name); + } else { + notice_lang(s_ChanServ, u, xmsgs[4], access->nc->display, + ci->name); + } + + } else if (stricmp(cmd, "DEL") == 0) { + int deleted, a, b; + if (readonly) { + notice_lang(s_ChanServ, u, xmsgs[1]); + return MOD_CONT; + } + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, xmsgs[11], chan); + return MOD_CONT; + } + + ulev = get_access(u, ci); + + /* Special case: is it a number/list? Only do search if it isn't. */ + if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { + int count, last = -1, perm = 0; + deleted = + process_numlist(nick, &count, xop_del_callback, u, ci, + &last, &perm, ulev, xlev); + if (!deleted) { + if (perm) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else if (count == 1) { + notice_lang(s_ChanServ, u, xmsgs[5], last, ci->name); + } else { + notice_lang(s_ChanServ, u, xmsgs[7], ci->name); + } + } else if (deleted == 1) { + notice_lang(s_ChanServ, u, xmsgs[9], ci->name); + } else { + notice_lang(s_ChanServ, u, xmsgs[10], deleted, ci->name); + } + } else { + na = findnick(nick); + if (!na) { + notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + nc = na->nc; + + for (i = 0; i < ci->accesscount; i++) + if (ci->access[i].nc == nc && ci->access[i].level == xlev) + break; + + if (i == ci->accesscount) { + notice_lang(s_ChanServ, u, xmsgs[6], nick, chan); + return MOD_CONT; + } + + access = &ci->access[i]; + if (!is_servadmin && ulev <= access->level) { + deleted = 0; + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + } else { + notice_lang(s_ChanServ, u, xmsgs[8], access->nc->display, + ci->name); + access->nc = NULL; + access->in_use = 0; + deleted = 1; + } + } + if (deleted) { + /* Reordering - DrStein */ + for (b = 0; b < ci->accesscount; b++) { + if (ci->access[b].in_use) { + for (a = 0; a < ci->accesscount; a++) { + if (a > b) + break; + if (!ci->access[a].in_use) { + ci->access[a].in_use = 1; + ci->access[a].level = ci->access[b].level; + ci->access[a].nc = ci->access[b].nc; + ci->access[a].last_seen = + ci->access[b].last_seen; + ci->access[b].nc = NULL; + ci->access[b].in_use = 0; + break; + } + } + } + } + } + } else if (stricmp(cmd, "LIST") == 0) { + int sent_header = 0; + + ulev = get_access(u, ci); + + if (!is_servadmin && ulev < ACCESS_AOP) { + notice_lang(s_ChanServ, u, ACCESS_DENIED); + return MOD_CONT; + } + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, xmsgs[11], ci->name); + return MOD_CONT; + } + + if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { + process_numlist(nick, NULL, xop_list_callback, u, ci, + &sent_header, xlev, xmsgs[12]); + } else { + for (i = 0; i < ci->accesscount; i++) { + if (nick && ci->access[i].nc + && !match_wild_nocase(nick, ci->access[i].nc->display)) + continue; + xop_list(u, i, ci, &sent_header, xlev, xmsgs[12]); + } + } + if (!sent_header) + notice_lang(s_ChanServ, u, xmsgs[7], chan); + } else if (stricmp(cmd, "CLEAR") == 0) { + if (readonly) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_DISABLED); + return MOD_CONT; + } + + if (ci->accesscount == 0) { + notice_lang(s_ChanServ, u, CHAN_ACCESS_LIST_EMPTY, chan); + return MOD_CONT; + } + + if (!is_servadmin && !is_founder(u, ci)) { + notice_lang(s_ChanServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + for (i = 0; i < ci->accesscount; i++) { + if (ci->access[i].in_use && ci->access[i].level == xlev) { + ci->access[i].nc = NULL; + ci->access[i].in_use = 0; + } + } + + notice_lang(s_ChanServ, u, xmsgs[13], ci->name); + } else { + syntax_error(s_ChanServ, u, xname, xmsgs[0]); + } + return MOD_CONT; +} diff --git a/src/core/he_help.c b/src/core/he_help.c new file mode 100644 index 000000000..0a96507ab --- /dev/null +++ b/src/core/he_help.c @@ -0,0 +1,76 @@ +/* HelpServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the help command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(HELPSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Display the HelpServ help. + * This core function has been embed in the source for a long time, but + * it moved into it's own file so we now all can enjoy the joy of + * modules for HelpServ. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + */ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_HelpServ, u, HELP_HELP, s_NickServ, s_ChanServ, + s_MemoServ); + if (s_BotServ) { + notice_help(s_HelpServ, u, HELP_HELP_BOT, s_BotServ); + } + if (s_HostServ) { + notice_help(s_HelpServ, u, HELP_HELP_HOST, s_HostServ); + } + moduleDisplayHelp(7, u); + } else { + mod_help_cmd(s_HelpServ, u, HELPSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/hs_del.c b/src/core/hs_del.c new file mode 100644 index 000000000..93bc09551 --- /dev/null +++ b/src/core/hs_del.c @@ -0,0 +1,91 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_del(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("DEL", do_del, is_host_remover, HOST_HELP_DEL, -1, + -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + if (is_host_remover(u)) { + notice_lang(s_HostServ, u, HOST_HELP_CMD_DEL); + } +} + +/** + * The /hs del command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_del(User * u) +{ + NickAlias *na; + char *nick = strtok(NULL, " "); + if (nick) { + if ((na = findnick(nick))) { + if (na->status & NS_VERBOTEN) { + notice_lang(s_HostServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + alog("vHost for user \002%s\002 deleted by oper \002%s\002", + nick, u->nick); + delHostCore(nick); + notice_lang(s_HostServ, u, HOST_DEL, nick); + } else { + notice_lang(s_HostServ, u, HOST_NOREG, nick); + } + } else { + notice_lang(s_HostServ, u, HOST_DEL_SYNTAX, s_HostServ); + } + return MOD_CONT; +} diff --git a/src/core/hs_delall.c b/src/core/hs_delall.c new file mode 100644 index 000000000..4571c5aca --- /dev/null +++ b/src/core/hs_delall.c @@ -0,0 +1,96 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_delall(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("DELALL", do_delall, is_host_remover, + HOST_HELP_DELALL, -1, -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + if (is_host_remover(u)) { + notice_lang(s_HostServ, u, HOST_HELP_CMD_DELALL); + } +} + +/** + * The /hs delall command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_delall(User * u) +{ + int i; + char *nick = strtok(NULL, " "); + NickAlias *na; + NickCore *nc; + if (!nick) { + notice_lang(s_HostServ, u, HOST_DELALL_SYNTAX, s_HostServ); + return MOD_CONT; + } + if ((na = findnick(nick))) { + if (na->status & NS_VERBOTEN) { + notice_lang(s_HostServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + nc = na->nc; + for (i = 0; i < nc->aliases.count; i++) { + na = nc->aliases.list[i]; + delHostCore(na->nick); + } + alog("vHosts for all nicks in group \002%s\002 deleted by oper \002%s\002", nc->display, u->nick); + notice_lang(s_HostServ, u, HOST_DELALL, nc->display); + } else { + notice_lang(s_HostServ, u, HOST_NOREG, nick); + } + return MOD_CONT; +} diff --git a/src/core/hs_group.c b/src/core/hs_group.c new file mode 100644 index 000000000..db034a948 --- /dev/null +++ b/src/core/hs_group.c @@ -0,0 +1,121 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_group(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GROUP", do_group, NULL, HOST_HELP_GROUP, -1, -1, -1, + -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + notice_lang(s_HostServ, u, HOST_HELP_CMD_GROUP); +} + +/** + * The /hs group command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_group(User * u) +{ + NickAlias *na; + HostCore *tmp; + char *vHost = NULL; + char *vIdent = NULL; + char *creator = NULL; + HostCore *head = NULL; + time_t time; + boolean found = false; + + head = hostCoreListHead(); + + if ((na = findnick(u->nick))) { + if (na->status & NS_IDENTIFIED) { + + tmp = findHostCore(head, u->nick, &found); + if (found) { + if (tmp == NULL) { + tmp = head; /* incase first in list */ + } else if (tmp->next) { /* we dont want the previous entry were not inserting! */ + tmp = tmp->next; /* jump to the next */ + } + + vHost = sstrdup(tmp->vHost); + if (tmp->vIdent) + vIdent = sstrdup(tmp->vIdent); + creator = sstrdup(tmp->creator); + time = tmp->time; + + do_hs_sync(na->nc, vIdent, vHost, creator, time); + if (tmp->vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_GROUP, + na->nc->display, vIdent, vHost); + } else { + notice_lang(s_HostServ, u, HOST_GROUP, na->nc->display, + vHost); + } + free(vHost); + if (vIdent) + free(vIdent); + free(creator); + + } else { + notice_lang(s_HostServ, u, HOST_NOT_ASSIGNED); + } + } else { + notice_lang(s_HostServ, u, HOST_ID); + } + } else { + notice_lang(s_HostServ, u, HOST_NOT_REGED); + } + return MOD_CONT; +} diff --git a/src/core/hs_help.c b/src/core/hs_help.c new file mode 100644 index 000000000..084bd3434 --- /dev/null +++ b/src/core/hs_help.c @@ -0,0 +1,66 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the help command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * The /hs help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_HostServ, u, HOST_HELP, s_HostServ); + moduleDisplayHelp(6, u); + } else { + mod_help_cmd(s_HostServ, u, HOSTSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/hs_list.c b/src/core/hs_list.c new file mode 100644 index 000000000..c8d096db7 --- /dev/null +++ b/src/core/hs_list.c @@ -0,0 +1,179 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int listOut(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("LIST", listOut, is_services_oper, -1, -1, + HOST_HELP_LIST, HOST_HELP_LIST, HOST_HELP_LIST); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_HostServ, u, HOST_HELP_CMD_LIST); + } +} + +/** + * The /hs list command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int listOut(User * u) +{ + char *key = strtok(NULL, ""); + struct tm *tm; + char buf[BUFSIZE]; + int counter = 1; + int from = 0, to = 0; + char *tmp = NULL; + char *s = NULL; + int display_counter = 0; + HostCore *head = NULL; + HostCore *current; + + head = hostCoreListHead(); + + current = head; + if (current == NULL) + notice_lang(s_HostServ, u, HOST_EMPTY); + else { + /** + * Do a check for a range here, then in the next loop + * we'll only display what has been requested.. + **/ + if (key) { + if (key[0] == '#') { + tmp = myStrGetOnlyToken((key + 1), '-', 0); /* Read FROM out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + from = atoi(tmp); + tmp = myStrGetTokenRemainder(key, '-', 1); /* Read TO out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + to = atoi(tmp); + key = NULL; + } + } + + while (current != NULL) { + if (key) { + if (((match_wild_nocase(key, current->nick)) + || (match_wild_nocase(key, current->vHost))) + && (display_counter < NSListMax)) { + display_counter++; + tm = localtime(¤t->time); + strftime_lang(buf, sizeof(buf), u, + STRFTIME_DATE_TIME_FORMAT, tm); + if (current->vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_ENTRY, + counter, current->nick, + current->vIdent, current->vHost, + current->creator, buf); + } else { + notice_lang(s_HostServ, u, HOST_ENTRY, counter, + current->nick, current->vHost, + current->creator, buf); + } + } + } else { + /** + * List the host if its in the display range, and not more + * than NSListMax records have been displayed... + **/ + if ((((counter >= from) && (counter <= to)) + || ((from == 0) && (to == 0))) + && (display_counter < NSListMax)) { + display_counter++; + tm = localtime(¤t->time); + strftime_lang(buf, sizeof(buf), u, + STRFTIME_DATE_TIME_FORMAT, tm); + if (current->vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_ENTRY, + counter, current->nick, + current->vIdent, current->vHost, + current->creator, buf); + } else { + notice_lang(s_HostServ, u, HOST_ENTRY, counter, + current->nick, current->vHost, + current->creator, buf); + } + } + } + counter++; + current = current->next; + } + if (key) { + notice_lang(s_HostServ, u, HOST_LIST_KEY_FOOTER, key, + display_counter); + } else { + if (from != 0) { + notice_lang(s_HostServ, u, HOST_LIST_RANGE_FOOTER, from, + to); + } else { + notice_lang(s_HostServ, u, HOST_LIST_FOOTER, + display_counter); + } + } + } + return MOD_CONT; +} diff --git a/src/core/hs_off.c b/src/core/hs_off.c new file mode 100644 index 000000000..e3785e7ad --- /dev/null +++ b/src/core/hs_off.c @@ -0,0 +1,87 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_off(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("OFF", do_off, NULL, HOST_HELP_OFF, -1, -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + notice_lang(s_HostServ, u, HOST_HELP_CMD_OFF); +} + +/** + * The /hs off command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_off(User * u) +{ + NickAlias *na; + char *vhost; + char *vident = NULL; + if ((na = findnick(u->nick))) { + if (na->status & NS_IDENTIFIED) { + vhost = getvHost(u->nick); + vident = getvIdent(u->nick); + if (vhost == NULL && vident == NULL) + notice_lang(s_HostServ, u, HOST_NOT_ASSIGNED); + else + anope_cmd_vhost_off(u); + } else { + notice_lang(s_HostServ, u, HOST_ID); + } + } else { + notice_lang(s_HostServ, u, HOST_NOT_REGED); + } + return MOD_CONT; +} diff --git a/src/core/hs_on.c b/src/core/hs_on.c new file mode 100644 index 000000000..7421eec7d --- /dev/null +++ b/src/core/hs_on.c @@ -0,0 +1,102 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_on(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ON", do_on, NULL, HOST_HELP_ON, -1, -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + notice_lang(s_HostServ, u, HOST_HELP_CMD_ON); +} + +/** + * The /hs on command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_on(User * u) +{ + NickAlias *na; + char *vHost; + char *vIdent = NULL; + if ((na = findnick(u->nick))) { + if (na->status & NS_IDENTIFIED) { + vHost = getvHost(u->nick); + vIdent = getvIdent(u->nick); + if (vHost == NULL) { + notice_lang(s_HostServ, u, HOST_NOT_ASSIGNED); + } else { + if (vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_ACTIVATED, + vIdent, vHost); + } else { + notice_lang(s_HostServ, u, HOST_ACTIVATED, vHost); + } + anope_cmd_vhost_on(u->nick, vIdent, vHost); + if (ircd->vhost) { + u->vhost = sstrdup(vHost); + } + if (ircd->vident) { + if (vIdent) + u->vident = sstrdup(vIdent); + } + set_lastmask(u); + } + } else { + notice_lang(s_HostServ, u, HOST_ID); + } + } else { + notice_lang(s_HostServ, u, HOST_NOT_REGED); + } + return MOD_CONT; +} diff --git a/src/core/hs_set.c b/src/core/hs_set.c new file mode 100644 index 000000000..f62491414 --- /dev/null +++ b/src/core/hs_set.c @@ -0,0 +1,147 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int myDoSet(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", myDoSet, is_host_setter, HOST_HELP_SET, -1, + -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + if (is_host_setter(u)) { + notice_lang(s_HostServ, u, HOST_HELP_CMD_SET); + } +} + +/** + * The /hs set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int myDoSet(User * u) +{ + char *nick = strtok(NULL, " "); + char *rawhostmask = strtok(NULL, " "); + char *hostmask = smalloc(HOSTMAX); + + NickAlias *na; + int32 tmp_time; + char *s; + + char *vIdent = NULL; + + if (!nick || !rawhostmask) { + notice_lang(s_HostServ, u, HOST_SET_SYNTAX, s_HostServ); + return MOD_CONT; + } + + vIdent = myStrGetOnlyToken(rawhostmask, '@', 0); /* Get the first substring, @ as delimiter */ + if (vIdent) { + rawhostmask = myStrGetTokenRemainder(rawhostmask, '@', 1); /* get the remaining string */ + if (!rawhostmask) { + notice_lang(s_HostServ, u, HOST_SET_SYNTAX, s_HostServ); + return MOD_CONT; + } + if (strlen(vIdent) > USERMAX - 1) { + notice_lang(s_HostServ, u, HOST_SET_IDENTTOOLONG, USERMAX); + return MOD_CONT; + } else { + for (s = vIdent; *s; s++) { + if (!isvalidchar(*s)) { + notice_lang(s_HostServ, u, HOST_SET_IDENT_ERROR); + return MOD_CONT; + } + } + } + if (!ircd->vident) { + notice_lang(s_HostServ, u, HOST_NO_VIDENT); + return MOD_CONT; + } + } + if (strlen(rawhostmask) < HOSTMAX - 1) + snprintf(hostmask, HOSTMAX - 1, "%s", rawhostmask); + else { + notice_lang(s_HostServ, u, HOST_SET_TOOLONG, HOSTMAX); + return MOD_CONT; + } + + if (!isValidHost(hostmask, 3)) { + notice_lang(s_HostServ, u, HOST_SET_ERROR); + return MOD_CONT; + } + + + tmp_time = time(NULL); + + if ((na = findnick(nick))) { + if (na->status & NS_VERBOTEN) { + notice_lang(s_HostServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + if (vIdent && ircd->vident) { + alog("vHost for user \002%s\002 set to \002%s@%s\002 by oper \002%s\002", nick, vIdent, hostmask, u->nick); + } else { + alog("vHost for user \002%s\002 set to \002%s\002 by oper \002%s\002", nick, hostmask, u->nick); + } + addHostCore(nick, vIdent, hostmask, u->nick, tmp_time); + if (vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_SET, nick, vIdent, + hostmask); + } else { + notice_lang(s_HostServ, u, HOST_SET, nick, hostmask); + } + } else { + notice_lang(s_HostServ, u, HOST_NOREG, nick); + } + free(hostmask); + return MOD_CONT; +} diff --git a/src/core/hs_setall.c b/src/core/hs_setall.c new file mode 100644 index 000000000..a0685a89f --- /dev/null +++ b/src/core/hs_setall.c @@ -0,0 +1,150 @@ +/* HostServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_setall(User * u); +void myHostServHelp(User * u); + +/** + * Create the off command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SETALL", do_setall, is_host_setter, + HOST_HELP_SETALL, -1, -1, -1, -1); + moduleAddCommand(HOSTSERV, c, MOD_UNIQUE); + moduleSetHostHelp(myHostServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myHostServHelp(User * u) +{ + if (is_host_setter(u)) { + notice_lang(s_HostServ, u, HOST_HELP_CMD_SETALL); + } +} + +/** + * The /hs setall command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_setall(User * u) +{ + + char *nick = strtok(NULL, " "); + char *rawhostmask = strtok(NULL, " "); + char *hostmask = smalloc(HOSTMAX); + + NickAlias *na; + int32 tmp_time; + char *s; + + char *vIdent = NULL; + + if (!nick || !rawhostmask) { + notice_lang(s_HostServ, u, HOST_SETALL_SYNTAX, s_HostServ); + return MOD_CONT; + } + + vIdent = myStrGetOnlyToken(rawhostmask, '@', 0); /* Get the first substring, @ as delimiter */ + if (vIdent) { + rawhostmask = myStrGetTokenRemainder(rawhostmask, '@', 1); /* get the remaining string */ + if (!rawhostmask) { + notice_lang(s_HostServ, u, HOST_SETALL_SYNTAX, s_HostServ); + return MOD_CONT; + } + if (strlen(vIdent) > USERMAX - 1) { + notice_lang(s_HostServ, u, HOST_SET_IDENTTOOLONG, USERMAX); + return MOD_CONT; + } else { + for (s = vIdent; *s; s++) { + if (!isvalidchar(*s)) { + notice_lang(s_HostServ, u, HOST_SET_IDENT_ERROR); + return MOD_CONT; + } + } + } + if (!ircd->vident) { + notice_lang(s_HostServ, u, HOST_NO_VIDENT); + return MOD_CONT; + } + } + + if (strlen(rawhostmask) < HOSTMAX - 1) + snprintf(hostmask, HOSTMAX - 1, "%s", rawhostmask); + else { + notice_lang(s_HostServ, u, HOST_SET_TOOLONG, HOSTMAX); + return MOD_CONT; + } + + if (!isValidHost(hostmask, 3)) { + notice_lang(s_HostServ, u, HOST_SET_ERROR); + free(hostmask); + return MOD_CONT; + } + + tmp_time = time(NULL); + + if ((na = findnick(nick))) { + if (na->status & NS_VERBOTEN) { + notice_lang(s_HostServ, u, NICK_X_FORBIDDEN, nick); + free(hostmask); + return MOD_CONT; + } + if (vIdent && ircd->vident) { + alog("vHost for all nicks in group \002%s\002 set to \002%s@%s\002 by oper \002%s\002", nick, vIdent, hostmask, u->nick); + } else { + alog("vHost for all nicks in group \002%s\002 set to \002%s\002 by oper \002%s\002", nick, hostmask, u->nick); + } + do_hs_sync(na->nc, vIdent, hostmask, u->nick, tmp_time); + if (vIdent) { + notice_lang(s_HostServ, u, HOST_IDENT_SETALL, nick, vIdent, + hostmask); + } else { + notice_lang(s_HostServ, u, HOST_SETALL, nick, hostmask); + } + } else { + notice_lang(s_HostServ, u, HOST_NOREG, nick); + } + + free(hostmask); + return MOD_CONT; +} diff --git a/src/core/ms_cancel.c b/src/core/ms_cancel.c new file mode 100644 index 000000000..8def3b2da --- /dev/null +++ b/src/core/ms_cancel.c @@ -0,0 +1,105 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_cancel(User * u); +void myMemoServHelp(User * u); + +/** + * Create the cancel command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("CANCEL", do_cancel, NULL, MEMO_HELP_CANCEL, -1, -1, + -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_CANCEL); +} + +/** + * The /ms cancel command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_cancel(User * u) +{ + int ischan; + int isforbid; + char *name = strtok(NULL, " "); + MemoInfo *mi; + + if (!name) { + syntax_error(s_MemoServ, u, "CANCEL", MEMO_CANCEL_SYNTAX); + + } else if (!nick_recognized(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + + } else if (!(mi = getmemoinfo(name, &ischan, &isforbid))) { + if (isforbid) { + notice_lang(s_MemoServ, u, + ischan ? CHAN_X_FORBIDDEN : + NICK_X_FORBIDDEN, name); + } else { + notice_lang(s_MemoServ, u, + ischan ? CHAN_X_NOT_REGISTERED : + NICK_X_NOT_REGISTERED, name); + } + } else { + int i; + + for (i = mi->memocount - 1; i >= 0; i--) { + if ((mi->memos[i].flags & MF_UNREAD) + && !stricmp(mi->memos[i].sender, u->na->nc->display) + && (!(mi->memos[i].flags & MF_NOTIFYS))) { + delmemo(mi, mi->memos[i].number); + notice_lang(s_MemoServ, u, MEMO_CANCELLED, name); + return MOD_CONT; + } + } + + notice_lang(s_MemoServ, u, MEMO_CANCEL_NONE); + } + return MOD_CONT; +} diff --git a/src/core/ms_check.c b/src/core/ms_check.c new file mode 100644 index 000000000..a236ae0a5 --- /dev/null +++ b/src/core/ms_check.c @@ -0,0 +1,118 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_memocheck(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("CHECK", do_memocheck, NULL, MEMO_HELP_CHECK, -1, -1, + -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_CHECK); +} + +/** + * The /ms check command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_memocheck(User * u) +{ + NickAlias *na = NULL; + MemoInfo *mi = NULL; + int i, found = 0; + char *recipient = strtok(NULL, ""); + struct tm *tm; + char timebuf[64]; + + if (!recipient) { + syntax_error(s_MemoServ, u, "CHECK", MEMO_CHECK_SYNTAX); + return MOD_CONT; + } else if (!nick_recognized(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } else if (!(na = findnick(recipient))) { + notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, recipient); + return MOD_CONT; + } + + if ((na->status & NS_VERBOTEN)) { + notice_lang(s_MemoServ, u, NICK_X_FORBIDDEN, recipient); + return MOD_CONT; + } + + mi = &na->nc->memos; + +/* Okay, I know this looks strange but we wanna get the LAST memo, so we + have to loop backwards */ + + for (i = (mi->memocount - 1); i >= 0; i--) { + if (!stricmp(mi->memos[i].sender, u->na->nc->display)) { + found = 1; /* Yes, we've found the memo */ + + tm = localtime(&mi->memos[i].time); + strftime_lang(timebuf, sizeof(timebuf), u, + STRFTIME_DATE_TIME_FORMAT, tm); + + if (mi->memos[i].flags & MF_UNREAD) + notice_lang(s_MemoServ, u, MEMO_CHECK_NOT_READ, na->nick, + timebuf); + else + notice_lang(s_MemoServ, u, MEMO_CHECK_READ, na->nick, + timebuf); + break; + } + } + + if (!found) + notice_lang(s_MemoServ, u, MEMO_CHECK_NO_MEMO, na->nick); + + return MOD_CONT; +} diff --git a/src/core/ms_del.c b/src/core/ms_del.c new file mode 100644 index 000000000..1fc3557c0 --- /dev/null +++ b/src/core/ms_del.c @@ -0,0 +1,199 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_del(User * u); +int del_memo_callback(User * u, int num, va_list args); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("DEL", do_del, NULL, MEMO_HELP_DEL, -1, -1, -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_DEL); +} + +/** + * The /ms del command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_del(User * u) +{ + MemoInfo *mi; + ChannelInfo *ci; + char *numstr = strtok(NULL, ""), *chan = NULL; + int last, last0, i; + char buf[BUFSIZE], *end; + int delcount, count, left; + + if (numstr && *numstr == '#') { + chan = strtok(numstr, " "); + numstr = strtok(NULL, ""); + if (!(ci = cs_findchan(chan))) { + notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } else if (!check_access(u, ci, CA_MEMO)) { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } + mi = &ci->memos; + } else { + if (!nick_identified(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } + mi = &u->na->nc->memos; + } + if (!numstr + || (!isdigit(*numstr) && stricmp(numstr, "ALL") != 0 + && stricmp(numstr, "LAST") != 0)) { + syntax_error(s_MemoServ, u, "DEL", MEMO_DEL_SYNTAX); + } else if (mi->memocount == 0) { + if (chan) + notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan); + else + notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS); + } else { + if (isdigit(*numstr)) { + /* Delete a specific memo or memos. */ + last = -1; /* Last memo deleted */ + last0 = -1; /* Beginning of range of last memos deleted */ + end = buf; + left = sizeof(buf); + delcount = + process_numlist(numstr, &count, del_memo_callback, u, mi, + &last, &last0, &end, &left); + if (last != -1) { + /* Some memos got deleted; tell them which ones. */ + if (delcount > 1) { + if (last0 != last) + end += snprintf(end, sizeof(buf) - (end - buf), + ",%d-%d", last0, last); + else + end += snprintf(end, sizeof(buf) - (end - buf), + ",%d", last); + /* "buf+1" here because *buf == ',' */ + notice_lang(s_MemoServ, u, MEMO_DELETED_SEVERAL, + buf + 1); + } else { + notice_lang(s_MemoServ, u, MEMO_DELETED_ONE, last); + } + } else { + /* No memos were deleted. Tell them so. */ + if (count == 1) + notice_lang(s_MemoServ, u, MEMO_DOES_NOT_EXIST, + atoi(numstr)); + else + notice_lang(s_MemoServ, u, MEMO_DELETED_NONE); + } + } else if (stricmp(numstr, "LAST") == 0) { + /* Delete last memo. */ + for (i = 0; i < mi->memocount; i++) + last = mi->memos[i].number; + delmemo(mi, last); + notice_lang(s_MemoServ, u, MEMO_DELETED_ONE, last); + } else { + /* Delete all memos. */ + for (i = 0; i < mi->memocount; i++) { + free(mi->memos[i].text); + moduleCleanStruct(&mi->memos[i].moduleData); + } + free(mi->memos); + mi->memos = NULL; + mi->memocount = 0; + if (chan) + notice_lang(s_MemoServ, u, MEMO_CHAN_DELETED_ALL, chan); + else + notice_lang(s_MemoServ, u, MEMO_DELETED_ALL); + } + + /* Reset the order */ + for (i = 0; i < mi->memocount; i++) + mi->memos[i].number = i + 1; + } + return MOD_CONT; +} + +/** + * Delete a single memo from a MemoInfo. callback function + * @param u User Struct + * @param int Number + * @param va_list Variable Arguemtns + * @return 1 if successful, 0 if it fails + */ +int del_memo_callback(User * u, int num, va_list args) +{ + MemoInfo *mi = va_arg(args, MemoInfo *); + int *last = va_arg(args, int *); + int *last0 = va_arg(args, int *); + char **end = va_arg(args, char **); + int *left = va_arg(args, int *); + + if (delmemo(mi, num)) { + if (num != (*last) + 1) { + if (*last != -1) { + int len; + if (*last0 != *last) + len = snprintf(*end, *left, ",%d-%d", *last0, *last); + else + len = snprintf(*end, *left, ",%d", *last); + *end += len; + *left -= len; + } + *last0 = num; + } + *last = num; + return 1; + } else { + return 0; + } +} diff --git a/src/core/ms_help.c b/src/core/ms_help.c new file mode 100644 index 000000000..d4e3bb4d2 --- /dev/null +++ b/src/core/ms_help.c @@ -0,0 +1,66 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the help command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * The /ms help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_MemoServ, u, MEMO_HELP_HEADER); + moduleDisplayHelp(3, u); + notice_help(s_MemoServ, u, MEMO_HELP_FOOTER, s_ChanServ); + } else { + mod_help_cmd(s_MemoServ, u, MEMOSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/ms_info.c b/src/core/ms_info.c new file mode 100644 index 000000000..92255256a --- /dev/null +++ b/src/core/ms_info.c @@ -0,0 +1,231 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_info(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("INFO", do_info, NULL, -1, MEMO_HELP_INFO, -1, + MEMO_SERVADMIN_HELP_INFO, MEMO_SERVADMIN_HELP_INFO); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_INFO); +} + +/** + * The /ms info command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_info(User * u) +{ + MemoInfo *mi; + NickAlias *na = NULL; + ChannelInfo *ci = NULL; + char *name = strtok(NULL, " "); + int is_servadmin = is_services_admin(u); + int hardmax = 0; + + if (is_servadmin && name && *name != '#') { + na = findnick(name); + if (!na) { + notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, name); + return MOD_CONT; + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_MemoServ, u, NICK_X_FORBIDDEN, name); + return MOD_CONT; + } + mi = &na->nc->memos; + hardmax = na->nc->flags & NI_MEMO_HARDMAX ? 1 : 0; + } else if (name && *name == '#') { + ci = cs_findchan(name); + if (!ci) { + notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, name); + return MOD_CONT; + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, name); + return MOD_CONT; + } else if (!check_access(u, ci, CA_MEMO)) { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } + mi = &ci->memos; + hardmax = ci->flags & CI_MEMO_HARDMAX ? 1 : 0; + } else if (name) { /* It's not a chan and we aren't services admin */ + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } else { /* !name */ + if (!nick_identified(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } + mi = &u->na->nc->memos; + hardmax = u->na->nc->flags & NI_MEMO_HARDMAX ? 1 : 0; + } + + if (name && (ci || na->nc != u->na->nc)) { + + if (!mi->memocount) { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NO_MEMOS, name); + } else if (mi->memocount == 1) { + if (mi->memos[0].flags & MF_UNREAD) + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMO_UNREAD, name); + else + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMO, name); + } else { + int count = 0, i; + for (i = 0; i < mi->memocount; i++) { + if (mi->memos[i].flags & MF_UNREAD) + count++; + } + if (count == mi->memocount) + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_ALL_UNREAD, + name, count); + else if (count == 0) + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS, name, + mi->memocount); + else if (count == 1) + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_ONE_UNREAD, + name, mi->memocount); + else + notice_lang(s_MemoServ, u, MEMO_INFO_X_MEMOS_SOME_UNREAD, + name, mi->memocount, count); + } + if (mi->memomax == 0) { + if (hardmax) + notice_lang(s_MemoServ, u, MEMO_INFO_X_HARD_LIMIT, name, + mi->memomax); + else + notice_lang(s_MemoServ, u, MEMO_INFO_X_LIMIT, name, + mi->memomax); + } else if (mi->memomax > 0) { + if (hardmax) + notice_lang(s_MemoServ, u, MEMO_INFO_X_HARD_LIMIT, name, + mi->memomax); + else + notice_lang(s_MemoServ, u, MEMO_INFO_X_LIMIT, name, + mi->memomax); + } else { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NO_LIMIT, name); + } + + /* I ripped this code out of ircservices 4.4.5, since I didn't want + to rewrite the whole thing (it pisses me off). */ + if (na) { + if ((na->nc->flags & NI_MEMO_RECEIVE) + && (na->nc->flags & NI_MEMO_SIGNON)) { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_ON, name); + } else if (na->nc->flags & NI_MEMO_RECEIVE) { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_RECEIVE, + name); + } else if (na->nc->flags & NI_MEMO_SIGNON) { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_SIGNON, + name); + } else { + notice_lang(s_MemoServ, u, MEMO_INFO_X_NOTIFY_OFF, name); + } + } + + } else { /* !name || (!ci || na->nc == u->na->nc) */ + + if (!mi->memocount) { + notice_lang(s_MemoServ, u, MEMO_INFO_NO_MEMOS); + } else if (mi->memocount == 1) { + if (mi->memos[0].flags & MF_UNREAD) + notice_lang(s_MemoServ, u, MEMO_INFO_MEMO_UNREAD); + else + notice_lang(s_MemoServ, u, MEMO_INFO_MEMO); + } else { + int count = 0, i; + for (i = 0; i < mi->memocount; i++) { + if (mi->memos[i].flags & MF_UNREAD) + count++; + } + if (count == mi->memocount) + notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_ALL_UNREAD, + count); + else if (count == 0) + notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS, mi->memocount); + else if (count == 1) + notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_ONE_UNREAD, + mi->memocount); + else + notice_lang(s_MemoServ, u, MEMO_INFO_MEMOS_SOME_UNREAD, + mi->memocount, count); + } + + if (mi->memomax == 0) { + if (!is_servadmin && hardmax) + notice_lang(s_MemoServ, u, MEMO_INFO_HARD_LIMIT_ZERO); + else + notice_lang(s_MemoServ, u, MEMO_INFO_LIMIT_ZERO); + } else if (mi->memomax > 0) { + if (!is_servadmin && hardmax) + notice_lang(s_MemoServ, u, MEMO_INFO_HARD_LIMIT, + mi->memomax); + else + notice_lang(s_MemoServ, u, MEMO_INFO_LIMIT, mi->memomax); + } else { + notice_lang(s_MemoServ, u, MEMO_INFO_NO_LIMIT); + } + + /* Ripped too. But differently because of a seg fault (loughs) */ + if ((u->na->nc->flags & NI_MEMO_RECEIVE) + && (u->na->nc->flags & NI_MEMO_SIGNON)) { + notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_ON); + } else if (u->na->nc->flags & NI_MEMO_RECEIVE) { + notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_RECEIVE); + } else if (u->na->nc->flags & NI_MEMO_SIGNON) { + notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_SIGNON); + } else { + notice_lang(s_MemoServ, u, MEMO_INFO_NOTIFY_OFF); + } + } + return MOD_CONT; /* if (name && (ci || na->nc != u->na->nc)) */ +} diff --git a/src/core/ms_list.c b/src/core/ms_list.c new file mode 100644 index 000000000..fa6a9f95b --- /dev/null +++ b/src/core/ms_list.c @@ -0,0 +1,197 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" +int do_list(User * u); +int list_memo_callback(User * u, int num, va_list args); +int list_memo(User * u, int index, MemoInfo * mi, int *sent_header, + int new, const char *chan); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("LIST", do_list, NULL, MEMO_HELP_LIST, -1, -1, -1, + -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_LIST); +} + +/** + * List the memos (if any) for the source nick or given channel. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_list(User * u) +{ + char *param = strtok(NULL, " "), *chan = NULL; + ChannelInfo *ci; + MemoInfo *mi; + Memo *m; + int i; + + if (param && *param == '#') { + chan = param; + param = strtok(NULL, " "); + if (!(ci = cs_findchan(chan))) { + notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } else if (!check_access(u, ci, CA_MEMO)) { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } + mi = &ci->memos; + } else { + if (!nick_identified(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } + mi = &u->na->nc->memos; + } + if (param && !isdigit(*param) && stricmp(param, "NEW") != 0) { + syntax_error(s_MemoServ, u, "LIST", MEMO_LIST_SYNTAX); + } else if (mi->memocount == 0) { + if (chan) + notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan); + else + notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS); + } else { + int sent_header = 0; + if (param && isdigit(*param)) { + process_numlist(param, NULL, list_memo_callback, u, + mi, &sent_header, chan); + } else { + if (param) { + for (i = 0, m = mi->memos; i < mi->memocount; i++, m++) { + if (m->flags & MF_UNREAD) + break; + } + if (i == mi->memocount) { + if (chan) + notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_NEW_MEMOS, + chan); + else + notice_lang(s_MemoServ, u, MEMO_HAVE_NO_NEW_MEMOS); + return MOD_CONT; + } + } + for (i = 0, m = mi->memos; i < mi->memocount; i++, m++) { + if (param && !(m->flags & MF_UNREAD)) + continue; + list_memo(u, i, mi, &sent_header, param != NULL, chan); + } + } + } + return MOD_CONT; +} + +/** + * list memno callback function + * @param u User Struct + * @param int Memo number + * @param va_list List of arguements + * @return result form list_memo() + */ +int list_memo_callback(User * u, int num, va_list args) +{ + MemoInfo *mi = va_arg(args, MemoInfo *); + int *sent_header = va_arg(args, int *); + const char *chan = va_arg(args, const char *); + int i; + + for (i = 0; i < mi->memocount; i++) { + if (mi->memos[i].number == num) + break; + } + /* Range checking done by list_memo() */ + return list_memo(u, i, mi, sent_header, 0, chan); +} + +/** + * Display a single memo entry, possibly printing the header first. + * @param u User Struct + * @param int Memo index + * @param mi MemoInfo Struct + * @param send_header If we are to send the headers + * @param new If we are listing new memos + * @param chan Channel name + * @return MOD_CONT + */ +int list_memo(User * u, int index, MemoInfo * mi, int *sent_header, + int new, const char *chan) +{ + Memo *m; + char timebuf[64]; + struct tm tm; + + if (index < 0 || index >= mi->memocount) + return 0; + if (!*sent_header) { + if (chan) { + notice_lang(s_MemoServ, u, + new ? MEMO_LIST_CHAN_NEW_MEMOS : + MEMO_LIST_CHAN_MEMOS, chan, s_MemoServ, chan); + } else { + notice_lang(s_MemoServ, u, + new ? MEMO_LIST_NEW_MEMOS : MEMO_LIST_MEMOS, + u->nick, s_MemoServ); + } + notice_lang(s_MemoServ, u, MEMO_LIST_HEADER); + *sent_header = 1; + } + m = &mi->memos[index]; + tm = *localtime(&m->time); + strftime_lang(timebuf, sizeof(timebuf), + u, STRFTIME_DATE_TIME_FORMAT, &tm); + timebuf[sizeof(timebuf) - 1] = 0; /* just in case */ + notice_lang(s_MemoServ, u, MEMO_LIST_FORMAT, + (m->flags & MF_UNREAD) ? '*' : ' ', + m->number, m->sender, timebuf); + return 1; +} diff --git a/src/core/ms_read.c b/src/core/ms_read.c new file mode 100644 index 000000000..4c650f5e1 --- /dev/null +++ b/src/core/ms_read.c @@ -0,0 +1,201 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_read(User * u); +int read_memo_callback(User * u, int num, va_list args); +int read_memo(User * u, int index, MemoInfo * mi, const char *chan); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("READ", do_read, NULL, MEMO_HELP_READ, -1, -1, -1, + -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_READ); +} + +/** + * The /ms read command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_read(User * u) +{ + MemoInfo *mi; + ChannelInfo *ci; + char *numstr = strtok(NULL, " "), *chan = NULL; + int num, count; + + if (numstr && *numstr == '#') { + chan = numstr; + numstr = strtok(NULL, " "); + if (!(ci = cs_findchan(chan))) { + notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } else if (!check_access(u, ci, CA_MEMO)) { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } + mi = &ci->memos; + } else { + if (!nick_identified(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } + mi = &u->na->nc->memos; + } + num = numstr ? atoi(numstr) : -1; + if (!numstr + || (stricmp(numstr, "LAST") != 0 && stricmp(numstr, "NEW") != 0 + && num <= 0)) { + syntax_error(s_MemoServ, u, "READ", MEMO_READ_SYNTAX); + + } else if (mi->memocount == 0) { + if (chan) + notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_MEMOS, chan); + else + notice_lang(s_MemoServ, u, MEMO_HAVE_NO_MEMOS); + + } else { + int i; + + if (stricmp(numstr, "NEW") == 0) { + int readcount = 0; + for (i = 0; i < mi->memocount; i++) { + if (mi->memos[i].flags & MF_UNREAD) { + read_memo(u, i, mi, chan); + readcount++; + } + } + if (!readcount) { + if (chan) + notice_lang(s_MemoServ, u, MEMO_X_HAS_NO_NEW_MEMOS, + chan); + else + notice_lang(s_MemoServ, u, MEMO_HAVE_NO_NEW_MEMOS); + } + } else if (stricmp(numstr, "LAST") == 0) { + for (i = 0; i < mi->memocount - 1; i++); + read_memo(u, i, mi, chan); + } else { /* number[s] */ + if (!process_numlist(numstr, &count, read_memo_callback, u, + mi, chan)) { + if (count == 1) + notice_lang(s_MemoServ, u, MEMO_DOES_NOT_EXIST, num); + else + notice_lang(s_MemoServ, u, MEMO_LIST_NOT_FOUND, + numstr); + } + } + + } + return MOD_CONT; +} + +/** + * Read a memo callback function + * @param u User Struct + * @param int Index number + * @param va_list variable arguements + * @return result of read_memo() + */ +int read_memo_callback(User * u, int num, va_list args) +{ + MemoInfo *mi = va_arg(args, MemoInfo *); + const char *chan = va_arg(args, const char *); + int i; + + for (i = 0; i < mi->memocount; i++) { + if (mi->memos[i].number == num) + break; + } + /* Range check done in read_memo */ + return read_memo(u, i, mi, chan); +} + +/** + * Read a memo + * @param u User Struct + * @param int Index number + * @param mi MemoInfo struct + * @param chan Channel Name + * @return 1 on success, 0 if failed + */ +int read_memo(User * u, int index, MemoInfo * mi, const char *chan) +{ + Memo *m; + char timebuf[64]; + struct tm tm; + + if (index < 0 || index >= mi->memocount) + return 0; + m = &mi->memos[index]; + tm = *localtime(&m->time); + strftime_lang(timebuf, sizeof(timebuf), + u, STRFTIME_DATE_TIME_FORMAT, &tm); + timebuf[sizeof(timebuf) - 1] = 0; + if (chan) + notice_lang(s_MemoServ, u, MEMO_CHAN_HEADER, m->number, + m->sender, timebuf, s_MemoServ, chan, m->number); + else + notice_lang(s_MemoServ, u, MEMO_HEADER, m->number, + m->sender, timebuf, s_MemoServ, m->number); + notice_lang(s_MemoServ, u, MEMO_TEXT, m->text); + m->flags &= ~MF_UNREAD; + + /* Check if a receipt notification was requested */ + if (m->flags & MF_RECEIPT) { + rsend_notify(u, m, chan); + } + + return 1; +} diff --git a/src/core/ms_rsend.c b/src/core/ms_rsend.c new file mode 100644 index 000000000..b712f4af1 --- /dev/null +++ b/src/core/ms_rsend.c @@ -0,0 +1,119 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_rsend(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("RSEND", do_rsend, NULL, MEMO_HELP_RSEND, -1, -1, -1, + -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + if (!MSMemoReceipt) { + return MOD_STOP; + } + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + if (((MSMemoReceipt == 1) && (is_services_oper(u))) + || (MSMemoReceipt == 2)) { + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_RSEND); + } +} + +/** + * The /ms rsend command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_rsend(User * u) +{ + char *name = strtok(NULL, " "); + char *text = strtok(NULL, ""); + NickAlias *na = NULL; + int z = 3; + + + + /* check if the variables are here */ + if (!name || !text) { + notice_lang(s_MemoServ, u, MEMO_RSEND_SYNTAX); + return MOD_CONT; + } + + /* prevent user from rsend to themselves */ + if ((na = findnick(name))) { + if (u->na) { + if (stricmp(na->nc->display, u->na->nc->display) == 0) { + notice_lang(s_MemoServ, u, MEMO_NO_RSEND_SELF); + return MOD_CONT; + } + } else { + notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, name); + return MOD_CONT; + } + } + + if (MSMemoReceipt == 1) { + /* Services opers and above can use rsend */ + if (is_services_oper(u)) { + memo_send(u, name, text, z); + } else { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + } + } else if (MSMemoReceipt == 2) { + /* Everybody can use rsend */ + memo_send(u, name, text, z); + } else { + /* rsend has been disabled */ + if (debug) { + alog("debug: MSMemoReceipt is set misconfigured to %d", + MSMemoReceipt); + } + notice_lang(s_MemoServ, u, MEMO_RSEND_DISABLED); + } + + return MOD_CONT; +} diff --git a/src/core/ms_send.c b/src/core/ms_send.c new file mode 100644 index 000000000..c366072a4 --- /dev/null +++ b/src/core/ms_send.c @@ -0,0 +1,73 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_send(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("SEND", do_send, NULL, MEMO_HELP_SEND, -1, -1, -1, + -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_SEND); +} + +/** + * The /ms send command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_send(User * u) +{ + char *name = strtok(NULL, " "); + char *text = strtok(NULL, ""); + int z = 0; + memo_send(u, name, text, z); + return MOD_CONT; +} diff --git a/src/core/ms_sendall.c b/src/core/ms_sendall.c new file mode 100644 index 000000000..36eae983f --- /dev/null +++ b/src/core/ms_sendall.c @@ -0,0 +1,95 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_sendall(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("SENDALL", do_sendall, is_services_admin, -1, -1, -1, + MEMO_HELP_SENDALL, MEMO_HELP_SENDALL); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_SENDALL); + } +} + +/** + * The /ms sendall command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_sendall(User * u) +{ + int i, z = 1; + NickCore *nc; + char *text = strtok(NULL, ""); + + if (readonly) { + notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED); + return MOD_CONT; + } else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) { + notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } else if (!text) { + syntax_error(s_MemoServ, u, "SENDALL", MEMO_SEND_SYNTAX); + return MOD_CONT; + } + + + for (i = 0; i < 1024; i++) { + for (nc = nclists[i]; nc; nc = nc->next) { + if (stricmp(u->nick, nc->display) != 0) + memo_send(u, nc->display, text, z); + } /* /nc */ + } /* /i */ + + notice_lang(s_MemoServ, u, MEMO_MASS_SENT); + return MOD_CONT; +} diff --git a/src/core/ms_set.c b/src/core/ms_set.c new file mode 100644 index 000000000..6d89818ba --- /dev/null +++ b/src/core/ms_set.c @@ -0,0 +1,265 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_set(User * u); +int do_set_notify(User * u, MemoInfo * mi, char *param); +int do_set_limit(User * u, MemoInfo * mi, char *param); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", do_set, NULL, MEMO_HELP_SET, -1, -1, -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + + c = createCommand("SET NOTIFY", NULL, NULL, MEMO_HELP_SET_NOTIFY, -1, + -1, -1, -1); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + + c = createCommand("SET LIMIT", NULL, NULL, -1, MEMO_HELP_SET_LIMIT, + MEMO_SERVADMIN_HELP_SET_LIMIT, + MEMO_SERVADMIN_HELP_SET_LIMIT, + MEMO_SERVADMIN_HELP_SET_LIMIT); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /hs help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_SET); +} + +/** + * The /ms set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set(User * u) +{ + char *cmd = strtok(NULL, " "); + char *param = strtok(NULL, ""); + MemoInfo *mi = &u->na->nc->memos; + + if (readonly) { + notice_lang(s_MemoServ, u, MEMO_SET_DISABLED); + return MOD_CONT; + } + if (!param) { + syntax_error(s_MemoServ, u, "SET", MEMO_SET_SYNTAX); + } else if (!nick_identified(u)) { + notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + return MOD_CONT; + } else if (stricmp(cmd, "NOTIFY") == 0) { + do_set_notify(u, mi, param); + } else if (stricmp(cmd, "LIMIT") == 0) { + do_set_limit(u, mi, param); + } else { + notice_lang(s_MemoServ, u, MEMO_SET_UNKNOWN_OPTION, cmd); + notice_lang(s_MemoServ, u, MORE_INFO, s_MemoServ, "SET"); + } + return MOD_CONT; +} + +/** + * The /ms set notify command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set_notify(User * u, MemoInfo * mi, char *param) +{ + if (stricmp(param, "ON") == 0) { + u->na->nc->flags |= NI_MEMO_SIGNON | NI_MEMO_RECEIVE; + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_ON, s_MemoServ); + } else if (stricmp(param, "LOGON") == 0) { + u->na->nc->flags |= NI_MEMO_SIGNON; + u->na->nc->flags &= ~NI_MEMO_RECEIVE; + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_LOGON, s_MemoServ); + } else if (stricmp(param, "NEW") == 0) { + u->na->nc->flags &= ~NI_MEMO_SIGNON; + u->na->nc->flags |= NI_MEMO_RECEIVE; + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_NEW, s_MemoServ); + } else if (stricmp(param, "MAIL") == 0) { + if (u->na->nc->email) { + u->na->nc->flags |= NI_MEMO_MAIL; + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_MAIL); + } else { + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_INVALIDMAIL); + } + } else if (stricmp(param, "NOMAIL") == 0) { + u->na->nc->flags &= ~NI_MEMO_MAIL; + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_NOMAIL); + } else if (stricmp(param, "OFF") == 0) { + u->na->nc->flags &= ~(NI_MEMO_SIGNON | NI_MEMO_RECEIVE); + notice_lang(s_MemoServ, u, MEMO_SET_NOTIFY_OFF, s_MemoServ); + } else { + syntax_error(s_MemoServ, u, "SET NOTIFY", MEMO_SET_NOTIFY_SYNTAX); + } + return MOD_CONT; +} + +/** + * The /ms set limit command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set_limit(User * u, MemoInfo * mi, char *param) +{ + char *p1 = strtok(param, " "); + char *p2 = strtok(NULL, " "); + char *p3 = strtok(NULL, " "); + char *user = NULL, *chan = NULL; + int32 limit; + NickAlias *na = u->na; + ChannelInfo *ci = NULL; + int is_servadmin = is_services_admin(u); + + if (p1 && *p1 == '#') { + chan = p1; + p1 = p2; + p2 = p3; + p3 = strtok(NULL, " "); + if (!(ci = cs_findchan(chan))) { + notice_lang(s_MemoServ, u, CHAN_X_NOT_REGISTERED, chan); + return MOD_CONT; + } else if (ci->flags & CI_VERBOTEN) { + notice_lang(s_MemoServ, u, CHAN_X_FORBIDDEN, chan); + return MOD_CONT; + } else if (!is_servadmin && !check_access(u, ci, CA_MEMO)) { + notice_lang(s_MemoServ, u, ACCESS_DENIED); + return MOD_CONT; + } + mi = &ci->memos; + } + if (is_servadmin) { + if (p2 && stricmp(p2, "HARD") != 0 && !chan) { + if (!(na = findnick(p1))) { + notice_lang(s_MemoServ, u, NICK_X_NOT_REGISTERED, p1); + return MOD_CONT; + } + user = p1; + mi = &na->nc->memos; + p1 = p2; + p2 = p3; + } else if (!p1) { + syntax_error(s_MemoServ, u, "SET LIMIT", + MEMO_SET_LIMIT_SERVADMIN_SYNTAX); + return MOD_CONT; + } + if ((!isdigit(*p1) && stricmp(p1, "NONE") != 0) || + (p2 && stricmp(p2, "HARD") != 0)) { + syntax_error(s_MemoServ, u, "SET LIMIT", + MEMO_SET_LIMIT_SERVADMIN_SYNTAX); + return MOD_CONT; + } + if (chan) { + if (p2) + ci->flags |= CI_MEMO_HARDMAX; + else + ci->flags &= ~CI_MEMO_HARDMAX; + } else { + if (p2) + na->nc->flags |= NI_MEMO_HARDMAX; + else + na->nc->flags &= ~NI_MEMO_HARDMAX; + } + limit = atoi(p1); + if (limit < 0 || limit > 32767) { + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_OVERFLOW, 32767); + limit = 32767; + } + if (stricmp(p1, "NONE") == 0) + limit = -1; + } else { + if (!p1 || p2 || !isdigit(*p1)) { + syntax_error(s_MemoServ, u, "SET LIMIT", + MEMO_SET_LIMIT_SYNTAX); + return MOD_CONT; + } + if (chan && (ci->flags & CI_MEMO_HARDMAX)) { + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_FORBIDDEN, chan); + return MOD_CONT; + } else if (!chan && (na->nc->flags & NI_MEMO_HARDMAX)) { + notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_FORBIDDEN); + return MOD_CONT; + } + limit = atoi(p1); + /* The first character is a digit, but we could still go negative + * from overflow... watch out! */ + if (limit < 0 || (MSMaxMemos > 0 && limit > MSMaxMemos)) { + if (chan) { + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_TOO_HIGH, + chan, MSMaxMemos); + } else { + notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_TOO_HIGH, + MSMaxMemos); + } + return MOD_CONT; + } else if (limit > 32767) { + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_OVERFLOW, 32767); + limit = 32767; + } + } + mi->memomax = limit; + if (limit > 0) { + if (!chan && na->nc == u->na->nc) + notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT, limit); + else + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT, + chan ? chan : user, limit); + } else if (limit == 0) { + if (!chan && na->nc == u->na->nc) + notice_lang(s_MemoServ, u, MEMO_SET_YOUR_LIMIT_ZERO); + else + notice_lang(s_MemoServ, u, MEMO_SET_LIMIT_ZERO, + chan ? chan : user); + } else { + if (!chan && na->nc == u->na->nc) + notice_lang(s_MemoServ, u, MEMO_UNSET_YOUR_LIMIT); + else + notice_lang(s_MemoServ, u, MEMO_UNSET_LIMIT, + chan ? chan : user); + } + return MOD_CONT; +} diff --git a/src/core/ms_staff.c b/src/core/ms_staff.c new file mode 100644 index 000000000..091a23ce5 --- /dev/null +++ b/src/core/ms_staff.c @@ -0,0 +1,92 @@ +/* MemoServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_staff(User * u); +void myMemoServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("STAFF", do_staff, is_services_oper, -1, -1, + MEMO_HELP_STAFF, MEMO_HELP_STAFF, MEMO_HELP_STAFF); + moduleAddCommand(MEMOSERV, c, MOD_UNIQUE); + moduleSetMemoHelp(myMemoServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ms help output. + * @param u The user who is requesting help + **/ +void myMemoServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_MemoServ, u, MEMO_HELP_CMD_STAFF); + } +} + +/** + * The /ms staff command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_staff(User * u) +{ + NickCore *nc; + int i, z = 0; + char *text = strtok(NULL, ""); + + if (readonly) { + notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED); + return MOD_CONT; + } else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) { + notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } else if (text == NULL) { + syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX); + return MOD_CONT; + } + + for (i = 0; i < 1024; i++) { + for (nc = nclists[i]; nc; nc = nc->next) { + if (nick_is_services_oper(nc)) + memo_send(u, nc->display, text, z); + } + } + return MOD_CONT; +} diff --git a/src/core/ns_access.c b/src/core/ns_access.c new file mode 100644 index 000000000..25c6bf8cd --- /dev/null +++ b/src/core/ns_access.c @@ -0,0 +1,189 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_access(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ACCESS", do_access, NULL, NICK_HELP_ACCESS, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_ACCESS); +} + +/** + * The /ns access command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_access(User * u) +{ + char *cmd = strtok(NULL, " "); + char *mask = strtok(NULL, " "); + NickAlias *na; + int i; + char **access; + + if (cmd && stricmp(cmd, "LIST") == 0 && mask && is_services_admin(u) + && (na = findnick(mask))) { + + if (na->nc->accesscount == 0) { + notice_lang(s_NickServ, u, NICK_ACCESS_LIST_X_EMPTY, na->nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + return MOD_CONT; + } + + if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + return MOD_CONT; + } + + + notice_lang(s_NickServ, u, NICK_ACCESS_LIST_X, mask); + mask = strtok(NULL, " "); + for (access = na->nc->access, i = 0; i < na->nc->accesscount; + access++, i++) { + if (mask && !match_wild(mask, *access)) + continue; + notice_user(s_NickServ, u, " %s", *access); + } + + } else if (!cmd || ((stricmp(cmd, "LIST") == 0) ? !!mask : !mask)) { + syntax_error(s_NickServ, u, "ACCESS", NICK_ACCESS_SYNTAX); + + } else if (mask && !strchr(mask, '@')) { + notice_lang(s_NickServ, u, BAD_USERHOST_MASK); + notice_lang(s_NickServ, u, MORE_INFO, s_NickServ, "ACCESS"); + + } else if (!(na = u->na)) { + notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); + + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + + } else if (!nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + + } else if (stricmp(cmd, "ADD") == 0) { + if (na->nc->accesscount >= NSAccessMax) { + notice_lang(s_NickServ, u, NICK_ACCESS_REACHED_LIMIT, + NSAccessMax); + return MOD_CONT; + } + + for (access = na->nc->access, i = 0; i < na->nc->accesscount; + access++, i++) { + if (strcmp(*access, mask) == 0) { + notice_lang(s_NickServ, u, NICK_ACCESS_ALREADY_PRESENT, + *access); + return MOD_CONT; + } + } + + na->nc->accesscount++; + na->nc->access = + srealloc(na->nc->access, sizeof(char *) * na->nc->accesscount); + na->nc->access[na->nc->accesscount - 1] = sstrdup(mask); + notice_lang(s_NickServ, u, NICK_ACCESS_ADDED, mask); + + } else if (stricmp(cmd, "DEL") == 0) { + + for (access = na->nc->access, i = 0; i < na->nc->accesscount; + access++, i++) { + if (stricmp(*access, mask) == 0) + break; + } + if (i == na->nc->accesscount) { + notice_lang(s_NickServ, u, NICK_ACCESS_NOT_FOUND, mask); + return MOD_CONT; + } + + notice_lang(s_NickServ, u, NICK_ACCESS_DELETED, *access); + free(*access); + na->nc->accesscount--; + if (i < na->nc->accesscount) /* if it wasn't the last entry... */ + memmove(access, access + 1, + (na->nc->accesscount - i) * sizeof(char *)); + if (na->nc->accesscount) /* if there are any entries left... */ + na->nc->access = + srealloc(na->nc->access, + na->nc->accesscount * sizeof(char *)); + else { + free(na->nc->access); + na->nc->access = NULL; + } + } else if (stricmp(cmd, "LIST") == 0) { + if (na->nc->accesscount == 0) { + notice_lang(s_NickServ, u, NICK_ACCESS_LIST_EMPTY, u->nick); + return MOD_CONT; + } + + notice_lang(s_NickServ, u, NICK_ACCESS_LIST); + for (access = na->nc->access, i = 0; i < na->nc->accesscount; + access++, i++) { + if (mask && !match_wild(mask, *access)) + continue; + notice_user(s_NickServ, u, " %s", *access); + } + } else { + syntax_error(s_NickServ, u, "ACCESS", NICK_ACCESS_SYNTAX); + + } + return MOD_CONT; +} diff --git a/src/core/ns_alist.c b/src/core/ns_alist.c new file mode 100644 index 000000000..f7a913f8f --- /dev/null +++ b/src/core/ns_alist.c @@ -0,0 +1,186 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_alist(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ALIST", do_alist, NULL, -1, NICK_HELP_ALIST, -1, + NICK_SERVADMIN_HELP_ALIST, + NICK_SERVADMIN_HELP_ALIST); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_ALIST); +} + +/** + * The /ns alist command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_alist(User * u) +{ + +/* + * List the channels that the given nickname has access on + * + * /ns ALIST [level] + * /ns ALIST [nickname] [level] + * + * -jester + */ + + char *nick = NULL; + char *lev = NULL; + + NickAlias *na; + + int min_level = 0; + int is_servadmin = is_services_admin(u); + + if (!is_servadmin) { + /* Non service admins can only see their own levels */ + na = u->na; + } else { + /* Services admins can request ALIST on nicks. + * The first argument for service admins must + * always be a nickname. + */ + nick = strtok(NULL, " "); + + /* If an argument was passed, use it as the nick to see levels + * for, else check levels for the user calling the command */ + if (nick) { + na = findnick(nick); + } else { + na = u->na; + } + } + + /* If available, get level from arguments */ + lev = strtok(NULL, " "); + + /* if a level was given, make sure it's an int for later */ + if (lev) { + if (stricmp(lev, "FOUNDER") == 0) { + min_level = ACCESS_FOUNDER; + } else if (stricmp(lev, "SOP") == 0) { + min_level = ACCESS_SOP; + } else if (stricmp(lev, "AOP") == 0) { + min_level = ACCESS_AOP; + } else if (stricmp(lev, "HOP") == 0) { + min_level = ACCESS_HOP; + } else if (stricmp(lev, "VOP") == 0) { + min_level = ACCESS_VOP; + } else { + min_level = atoi(lev); + } + } + + if (!nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (is_servadmin && nick && !na) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (min_level <= ACCESS_INVALID || min_level >= ACCESS_FOUNDER) { + notice_lang(s_NickServ, u, CHAN_ACCESS_LEVEL_RANGE, + ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + } else { + int i, level; + int chan_count = 0; + int match_count = 0; + ChannelInfo *ci; + + notice_lang(s_NickServ, u, (is_servadmin ? NICK_ALIST_HEADER_X : + NICK_ALIST_HEADER), na->nick); + + for (i = 0; i < 256; i++) { + for ((ci = chanlists[i]); ci; (ci = ci->next)) { + + if ((level = get_access_level(ci, na))) { + chan_count++; + + if (min_level > level) { + continue; + } + + match_count++; + + if ((ci->flags & CI_XOP) || (level == ACCESS_FOUNDER)) { + char *xop; + + xop = get_xop_level(level); + + notice_lang(s_NickServ, u, NICK_ALIST_XOP_FORMAT, + match_count, + ((ci-> + flags & CI_NO_EXPIRE) ? '!' : ' '), + ci->name, xop, + (ci->desc ? ci->desc : "")); + } else { + notice_lang(s_NickServ, u, + NICK_ALIST_ACCESS_FORMAT, match_count, + ((ci-> + flags & CI_NO_EXPIRE) ? '!' : ' '), + ci->name, level, + (ci->desc ? ci->desc : "")); + + } + } + } + } + + notice_lang(s_NickServ, u, NICK_ALIST_FOOTER, match_count, + chan_count); + } + return MOD_CONT; +} diff --git a/src/core/ns_drop.c b/src/core/ns_drop.c new file mode 100644 index 000000000..e48849dff --- /dev/null +++ b/src/core/ns_drop.c @@ -0,0 +1,156 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_drop(User * u); +int do_unlink(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("DROP", do_drop, NULL, -1, NICK_HELP_DROP, -1, + NICK_SERVADMIN_HELP_DROP, NICK_SERVADMIN_HELP_DROP); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("UNLINK", do_unlink, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_DROP); +} + +/** + * The /ns drop command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_drop(User * u) +{ + char *nick = strtok(NULL, " "); + NickAlias *na; + NickRequest *nr = NULL; + int is_servadmin = is_services_admin(u); + int is_mine; /* Does the nick being dropped belong to the user that is dropping? */ + char *my_nick = NULL; + + if (readonly && !is_servadmin) { + notice_lang(s_NickServ, u, NICK_DROP_DISABLED); + return MOD_CONT; + } + + if (!(na = (nick ? findnick(nick) : u->na))) { + if (nick) { + if ((nr = findrequestnick(nick)) && is_servadmin) { + if (readonly) + notice_lang(s_NickServ, u, READ_ONLY_MODE); + if (WallDrop) + anope_cmd_global(s_NickServ, + "\2%s\2 used DROP on \2%s\2", u->nick, + nick); + alog("%s: %s!%s@%s dropped nickname %s (e-mail: %s)", + s_NickServ, u->nick, u->username, u->host, + nr->nick, nr->email); + delnickrequest(nr); + notice_lang(s_NickServ, u, NICK_X_DROPPED, nick); + } else { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } + } else + notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); + return MOD_CONT; + } + + is_mine = (u->na && (u->na->nc == na->nc)); + if (is_mine && !nick) + my_nick = sstrdup(na->nick); + + if (is_mine && !nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (!is_mine && !is_servadmin) { + notice_lang(s_NickServ, u, ACCESS_DENIED); + } else if (NSSecureAdmins && !is_mine && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + } else { + if (readonly) + notice_lang(s_NickServ, u, READ_ONLY_MODE); + + if (ircd->sqline && (na->status & NS_VERBOTEN)) { + anope_cmd_unsqline(na->nick); + } + + alog("%s: %s!%s@%s dropped nickname %s (group %s) (e-mail: %s)", + s_NickServ, u->nick, u->username, u->host, + na->nick, na->nc->display, + (na->nc->email ? na->nc->email : "none")); + delnick(na); + send_event(EVENT_NICK_DROPPED, 1, (my_nick ? my_nick : nick)); + + if (!is_mine) { + if (WallDrop) + anope_cmd_global(s_NickServ, "\2%s\2 used DROP on \2%s\2", + u->nick, nick); + notice_lang(s_NickServ, u, NICK_X_DROPPED, nick); + } else { + if (nick) + notice_lang(s_NickServ, u, NICK_X_DROPPED, nick); + else + notice_lang(s_NickServ, u, NICK_DROPPED); + if (my_nick) { + free(my_nick); + } + } + } + return MOD_CONT; +} + + +int do_unlink(User * u) +{ + notice_lang(s_NickServ, u, OBSOLETE_COMMAND, "DROP"); + return MOD_CONT; +} diff --git a/src/core/ns_forbid.c b/src/core/ns_forbid.c new file mode 100644 index 000000000..adf620ff4 --- /dev/null +++ b/src/core/ns_forbid.c @@ -0,0 +1,151 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_forbid(User * u); +void myNickServHelp(User * u); +NickAlias *makenick(const char *nick); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("FORBID", do_forbid, is_services_admin, -1, -1, -1, + NICK_SERVADMIN_HELP_FORBID, + NICK_SERVADMIN_HELP_FORBID); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_FORBID); + } +} + +/** + * The /ns forbid command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_forbid(User * u) +{ + NickAlias *na; + char *nick = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + /* Assumes that permission checking has already been done. */ + if (!nick || (ForceForbidReason && !reason)) { + syntax_error(s_NickServ, u, "FORBID", + (ForceForbidReason ? NICK_FORBID_SYNTAX_REASON : + NICK_FORBID_SYNTAX)); + return MOD_CONT; + } + + if (readonly) + notice_lang(s_NickServ, u, READ_ONLY_MODE); + if ((na = findnick(nick)) != NULL) { + if (NSSecureAdmins && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + delnick(na); + } + na = makenick(nick); + if (na) { + na->status |= NS_VERBOTEN; + na->last_usermask = sstrdup(u->nick); + if (reason) + na->last_realname = sstrdup(reason); + + na->u = finduser(na->nick); + if (na->u) + na->u->na = na; + + if (na->u) { + notice_lang(s_NickServ, na->u, FORCENICKCHANGE_NOW); + collide(na, 0); + } + + + if (ircd->sqline) { + anope_cmd_sqline(na->nick, ((reason) ? reason : "Forbidden")); + } + + if (WallForbid) + anope_cmd_global(s_NickServ, "\2%s\2 used FORBID on \2%s\2", + u->nick, nick); + + alog("%s: %s set FORBID for nick %s", s_NickServ, u->nick, nick); + notice_lang(s_NickServ, u, NICK_FORBID_SUCCEEDED, nick); + send_event(EVENT_NICK_FORBIDDEN, 1, nick); + } else { + alog("%s: Valid FORBID for %s by %s failed", s_NickServ, nick, + u->nick); + notice_lang(s_NickServ, u, NICK_FORBID_FAILED, nick); + } + return MOD_CONT; +} + +NickAlias *makenick(const char *nick) +{ + NickAlias *na; + NickCore *nc; + + /* First make the core */ + nc = scalloc(1, sizeof(NickCore)); + nc->display = sstrdup(nick); + slist_init(&nc->aliases); + insert_core(nc); + alog("%s: group %s has been created", s_NickServ, nc->display); + + /* Then make the alias */ + na = scalloc(1, sizeof(NickAlias)); + na->nick = sstrdup(nick); + na->nc = nc; + slist_add(&nc->aliases, na); + alpha_insert_alias(na); + return na; +} diff --git a/src/core/ns_getemail.c b/src/core/ns_getemail.c new file mode 100644 index 000000000..24d463bb6 --- /dev/null +++ b/src/core/ns_getemail.c @@ -0,0 +1,102 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * + * A simple call to check for all emails that a user may have registered + * with. It returns the nicks that match the email you provide. Wild + * Cards are not excepted. Must use user@email-host. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_getemail(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GETEMAIL", do_getemail, is_services_admin, -1, -1, + -1, NICK_SERVADMIN_HELP_GETEMAIL, + NICK_SERVADMIN_HELP_GETEMAIL); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_GETEMAIL); + } +} + +/** + * The /ns getemail command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_getemail(User * u) +{ + char *email = strtok(NULL, " "); + int i, j = 0; + NickCore *nc; + + if (!email) { + syntax_error(s_NickServ, u, "GETMAIL", NICK_GETEMAIL_SYNTAX); + return MOD_CONT; + } + alog("%s: %s!%s@%s used GETEMAIL on %s", s_NickServ, u->nick, + u->username, u->host, email); + for (i = 0; i < 1024; i++) { + for (nc = nclists[i]; nc; nc = nc->next) { + if (nc->email) { + if (stricmp(nc->email, email) == 0) { + j++; + notice_lang(s_NickServ, u, NICK_GETEMAIL_EMAILS_ARE, + nc->display, email); + } + } + } + } + if (j <= 0) { + notice_lang(s_NickServ, u, NICK_GETEMAIL_NOT_USED, email); + return MOD_CONT; + } + return MOD_CONT; +} diff --git a/src/core/ns_getpass.c b/src/core/ns_getpass.c new file mode 100644 index 000000000..afacd63a9 --- /dev/null +++ b/src/core/ns_getpass.c @@ -0,0 +1,111 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_getpass(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GETPASS", do_getpass, is_services_admin, -1, -1, -1, + NICK_SERVADMIN_HELP_GETPASS, + NICK_SERVADMIN_HELP_GETPASS); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + +#ifdef USE_ENCRYPTION + return MOD_STOP; +#else + return MOD_CONT; +#endif +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_GETPASS); + } +} + +/** + * The /ns getpass command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_getpass(User * u) +{ + char *nick = strtok(NULL, " "); + NickAlias *na; + NickRequest *nr = NULL; + + if (!nick) { + syntax_error(s_NickServ, u, "GETPASS", NICK_GETPASS_SYNTAX); + } else if (!(na = findnick(nick))) { + if ((nr = findrequestnick(nick))) { + alog("%s: %s!%s@%s used GETPASS on %s", s_NickServ, u->nick, + u->username, u->host, nick); + if (WallGetpass) + anope_cmd_global(s_NickServ, + "\2%s\2 used GETPASS on \2%s\2", u->nick, + nick); + notice_lang(s_NickServ, u, NICK_GETPASS_PASSCODE_IS, nick, + nr->passcode); + } else { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (NSSecureAdmins && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + } else if (NSRestrictGetPass && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + } else { + alog("%s: %s!%s@%s used GETPASS on %s", s_NickServ, u->nick, + u->username, u->host, nick); + if (WallGetpass) + anope_cmd_global(s_NickServ, "\2%s\2 used GETPASS on \2%s\2", + u->nick, nick); + notice_lang(s_NickServ, u, NICK_GETPASS_PASSWORD_IS, nick, + na->nc->pass); + } + return MOD_CONT; +} diff --git a/src/core/ns_ghost.c b/src/core/ns_ghost.c new file mode 100644 index 000000000..d97cc39ff --- /dev/null +++ b/src/core/ns_ghost.c @@ -0,0 +1,122 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_ghost(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GHOST", do_ghost, NULL, NICK_HELP_GHOST, -1, -1, -1, + -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_GHOST); +} + +/** + * The /ns ghost command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_ghost(User * u) +{ + char *nick = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + NickAlias *na; + User *u2; + + if (!nick) { + syntax_error(s_NickServ, u, "GHOST", NICK_GHOST_SYNTAX); + } else if (!(u2 = finduser(nick))) { + notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick); + } else if (!(na = u2->na)) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + } else if (stricmp(nick, u->nick) == 0) { + notice_lang(s_NickServ, u, NICK_NO_GHOST_SELF); + } else if (pass) { + int res = check_password(pass, na->nc->pass); + if (res == 1) { + char buf[NICKMAX + 32]; + snprintf(buf, sizeof(buf), "GHOST command used by %s", + u->nick); + if (LimitSessions) { + del_session(u2->host); + } + kill_user(s_NickServ, nick, buf); + notice_lang(s_NickServ, u, NICK_GHOST_KILLED, nick); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + if (res == 0) { + alog("%s: GHOST: invalid password for %s by %s!%s@%s", + s_NickServ, nick, u->nick, u->username, u->host); + bad_password(u); + } + } + } else { + if (group_identified(u, na->nc) + || (!(na->nc->flags & NI_SECURE) && is_on_access(u, na->nc))) { + char buf[NICKMAX + 32]; + snprintf(buf, sizeof(buf), "GHOST command used by %s", + u->nick); + if (LimitSessions) { + del_session(u2->host); + } + kill_user(s_NickServ, nick, buf); + notice_lang(s_NickServ, u, NICK_GHOST_KILLED, nick); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + } + } + return MOD_CONT; +} diff --git a/src/core/ns_group.c b/src/core/ns_group.c new file mode 100644 index 000000000..f652547a9 --- /dev/null +++ b/src/core/ns_group.c @@ -0,0 +1,326 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_group(User * u); +void myNickServHelp(User * u); +int do_glist(User * u); +int do_listlinks(User * u); + +NickAlias *makealias(const char *nick, NickCore * nc); + +/* Obsolete commands */ +int do_link(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GROUP", do_group, NULL, NICK_HELP_GROUP, -1, -1, -1, + -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + c = createCommand("LINK", do_link, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + c = createCommand("GLIST", do_glist, NULL, -1, NICK_HELP_GLIST, -1, + NICK_SERVADMIN_HELP_GLIST, + NICK_SERVADMIN_HELP_GLIST); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + c = createCommand("LISTLINKS", do_listlinks, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_GROUP); + notice_lang(s_NickServ, u, NICK_HELP_CMD_GLIST); +} + +/** + * The /ns group command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +/* Register a nick in a specified group. */ + +int do_group(User * u) +{ + NickAlias *na, *target; + NickCore *nc; + char *nick = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + int i; + char tsbuf[16]; + + if (NSEmailReg && (findrequestnick(u->nick))) { + notice_lang(s_NickServ, u, NICK_REQUESTED); + return MOD_CONT; + } + + if (readonly) { + notice_lang(s_NickServ, u, NICK_GROUP_DISABLED); + return MOD_CONT; + } + if (checkDefCon(DEFCON_NO_NEW_NICKS)) { + notice_lang(s_NickServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } + + if (RestrictOperNicks) { + for (i = 0; i < RootNumber; i++) { + if (stristr(u->nick, ServicesRoots[i]) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + for (i = 0; i < servadmins.count && (nc = servadmins.list[i]); i++) { + if (stristr(u->nick, nc->display) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + for (i = 0; i < servopers.count && (nc = servopers.list[i]); i++) { + if (stristr(u->nick, nc->display) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + } + + if (!nick || !pass) { + syntax_error(s_NickServ, u, "GROUP", NICK_GROUP_SYNTAX); + } else if (!(target = findnick(nick))) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (time(NULL) < u->lastnickreg + NSRegDelay) { + notice_lang(s_NickServ, u, NICK_GROUP_PLEASE_WAIT, NSRegDelay); + } else if (u->na && (u->na->status & NS_VERBOTEN)) { + alog("%s: %s@%s tried to use GROUP from FORBIDden nick %s", + s_NickServ, u->username, u->host, u->nick); + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u->nick); + } else if (u->na && (u->na->nc->flags & NI_SUSPENDED)) { + alog("%s: %s!%s@%s tried to use GROUP from SUSPENDED nick %s", + s_NickServ, u->nick, u->username, u->host, target->nick); + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, u->nick); + } else if (u->na && NSNoGroupChange) { + notice_lang(s_NickServ, u, NICK_GROUP_CHANGE_DISABLED, s_NickServ); + } else if (u->na && !nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (target && (target->nc->flags & NI_SUSPENDED)) { + alog("%s: %s!%s@%s tried to use GROUP from SUSPENDED nick %s", + s_NickServ, u->nick, u->username, u->host, target->nick); + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, target->nick); + } else if (target->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick); + } else if (u->na && target->nc == u->na->nc) { + notice_lang(s_NickServ, u, NICK_GROUP_SAME, target->nick); + } else if (NSMaxAliases && (target->nc->aliases.count >= NSMaxAliases) + && !nick_is_services_admin(target->nc)) { + notice_lang(s_NickServ, u, NICK_GROUP_TOO_MANY, target->nick, + s_NickServ, s_NickServ); + } else if (check_password(pass, target->nc->pass) != 1) { + alog("%s: Failed GROUP for %s!%s@%s (invalid password)", + s_NickServ, u->nick, u->username, u->host); + notice_lang(s_NickServ, u, PASSWORD_INCORRECT); + bad_password(u); + } else { + /* If the nick is already registered, drop it. + * If not, check that it is valid. + */ + if (u->na) { + delnick(u->na); + } else { + int prefixlen = strlen(NSGuestNickPrefix); + int nicklen = strlen(u->nick); + + if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 + && stristr(u->nick, NSGuestNickPrefix) == u->nick + && strspn(u->nick + prefixlen, + "1234567890") == nicklen - prefixlen) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + na = makealias(u->nick, target->nc); + + if (na) { + na->last_usermask = + scalloc(strlen(common_get_vident(u)) + + strlen(common_get_vhost(u)) + 2, 1); + sprintf(na->last_usermask, "%s@%s", common_get_vident(u), + common_get_vhost(u)); + na->last_realname = sstrdup(u->realname); + na->time_registered = na->last_seen = time(NULL); + na->status = (int16) (NS_IDENTIFIED | NS_RECOGNIZED); + + if (!(na->nc->flags & NI_SERVICES_ROOT)) { + for (i = 0; i < RootNumber; i++) { + if (!stricmp(ServicesRoots[i], u->nick)) { + na->nc->flags |= NI_SERVICES_ROOT; + break; + } + } + } + + u->na = na; + na->u = u; + +#ifdef USE_RDB + /* Is this really needed? Since this is a new alias it will get + * its unique id on the next update, since it was previously + * deleted by delnick. Must observe... + */ + if (rdb_open()) { + rdb_save_ns_alias(na); + rdb_close(); + } +#endif + send_event(EVENT_GROUP, 1, u->nick); + alog("%s: %s!%s@%s makes %s join group of %s (%s) (e-mail: %s)", s_NickServ, u->nick, u->username, u->host, u->nick, target->nick, target->nc->display, (target->nc->email ? target->nc->email : "none")); + notice_lang(s_NickServ, u, NICK_GROUP_JOINED, target->nick); + + u->lastnickreg = time(NULL); + snprintf(tsbuf, sizeof(tsbuf), "%lu", + (unsigned long int) u->timestamp); + if (ircd->modeonreg) { + if (ircd->tsonmode) { + common_svsmode(u, ircd->modeonreg, tsbuf); + } else { + common_svsmode(u, ircd->modeonreg, NULL); + } + } + + check_memos(u); + } else { + alog("%s: makealias(%s) failed", s_NickServ, u->nick); + notice_lang(s_NickServ, u, NICK_GROUP_FAILED); + } + } + return MOD_CONT; +} + + +/* Creates a new alias in NickServ database. */ + +NickAlias *makealias(const char *nick, NickCore * nc) +{ + NickAlias *na; + + /* Just need to make the alias */ + na = scalloc(1, sizeof(NickAlias)); + na->nick = sstrdup(nick); + na->nc = nc; + slist_add(&nc->aliases, na); + alpha_insert_alias(na); + return na; +} + + +int do_link(User * u) +{ + notice_lang(s_NickServ, u, OBSOLETE_COMMAND, "GROUP"); + return MOD_CONT; +} + +int do_glist(User * u) +{ + char *nick = strtok(NULL, " "); + + NickAlias *na, *na2; + int is_servadmin = is_services_admin(u); + int nick_ided = nick_identified(u); + int i; + + if ((nick ? (stricmp(nick, u->nick) ? !is_servadmin : !nick_ided) + : !nick_ided)) { + notice_lang(s_NickServ, u, + (nick_ided ? ACCESS_DENIED : + NICK_IDENTIFY_REQUIRED), s_NickServ); + } else if ((!nick ? !(na = u->na) : !(na = findnick(nick)))) { + notice_lang(s_NickServ, u, + (!nick ? NICK_NOT_REGISTERED : NICK_X_NOT_REGISTERED), + nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else { + time_t expt; + struct tm *tm; + char buf[BUFSIZE]; + int wont_expire; + + notice_lang(s_NickServ, u, + nick ? NICK_GLIST_HEADER_X : NICK_GLIST_HEADER, + na->nc->display); + for (i = 0; i < na->nc->aliases.count; i++) { + na2 = na->nc->aliases.list[i]; + if (na2->nc == na->nc) { + if (!(wont_expire = na2->status & NS_NO_EXPIRE)) { + expt = na2->last_seen + NSExpire; + tm = localtime(&expt); + strftime_lang(buf, sizeof(buf), na2->u, + STRFTIME_DATE_TIME_FORMAT, tm); + } + notice_lang(s_NickServ, u, + ((is_services_admin(u) && !wont_expire) + ? NICK_GLIST_REPLY_ADMIN : NICK_GLIST_REPLY), + (wont_expire ? '!' : ' '), na2->nick, buf); + } + } + notice_lang(s_NickServ, u, NICK_GLIST_FOOTER, + na->nc->aliases.count); + } + return MOD_CONT; +} + + +int do_listlinks(User * u) +{ + notice_lang(s_NickServ, u, OBSOLETE_COMMAND, "GLIST"); + return MOD_CONT; +} diff --git a/src/core/ns_help.c b/src/core/ns_help.c new file mode 100644 index 000000000..579dfec7c --- /dev/null +++ b/src/core/ns_help.c @@ -0,0 +1,77 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("HELP", do_help, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * The /ns help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_NickServ, u, NICK_HELP); + moduleDisplayHelp(1, u); + if (is_services_admin(u)) { + notice_help(s_NickServ, u, NICK_SERVADMIN_HELP); + } + if (NSExpire >= 86400) + notice_help(s_NickServ, u, NICK_HELP_EXPIRES, + NSExpire / 86400); + notice_help(s_NickServ, u, NICK_HELP_FOOTER); + } else if (stricmp(cmd, "SET LANGUAGE") == 0) { + int i; + notice_help(s_NickServ, u, NICK_HELP_SET_LANGUAGE); + for (i = 0; i < NUM_LANGS && langlist[i] >= 0; i++) + notice_user(s_NickServ, u, " %2d) %s", i + 1, + langnames[langlist[i]]); + } else { + mod_help_cmd(s_NickServ, u, NICKSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/ns_identify.c b/src/core/ns_identify.c new file mode 100644 index 000000000..362cd4488 --- /dev/null +++ b/src/core/ns_identify.c @@ -0,0 +1,160 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +#define TO_COLLIDE 0 /* Collide the user with this nick */ +#define TO_RELEASE 1 /* Release a collided nick */ + +int do_identify(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ID", do_identify, NULL, NICK_HELP_IDENTIFY, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("IDENTIFY", do_identify, NULL, NICK_HELP_IDENTIFY, + -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SIDENTIFY", do_identify, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_IDENTIFY); +} + +/** + * The /ns identify command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_identify(User * u) +{ + char *pass = strtok(NULL, " "); + NickAlias *na; + NickRequest *nr; + int res; + char tsbuf[16]; + + if (!pass) { + syntax_error(s_NickServ, u, "IDENTIFY", NICK_IDENTIFY_SYNTAX); + } else if (!(na = u->na)) { + if ((nr = findrequestnick(u->nick))) { + notice_lang(s_NickServ, u, NICK_IS_PREREG); + } else { + notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); + } + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + } else if (nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_ALREADY_IDENTIFIED); + } else if (!(res = check_password(pass, na->nc->pass))) { + alog("%s: Failed IDENTIFY for %s!%s@%s", s_NickServ, u->nick, + u->username, u->host); + notice_lang(s_NickServ, u, PASSWORD_INCORRECT); + bad_password(u); + } else if (res == -1) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_FAILED); + } else { + if (!(na->status & NS_IDENTIFIED) && !(na->status & NS_RECOGNIZED)) { + if (na->last_usermask) + free(na->last_usermask); + na->last_usermask = + scalloc(strlen(common_get_vident(u)) + + strlen(common_get_vhost(u)) + 2, 1); + sprintf(na->last_usermask, "%s@%s", common_get_vident(u), + common_get_vhost(u)); + if (na->last_realname) + free(na->last_realname); + na->last_realname = sstrdup(u->realname); + } + + na->status |= NS_IDENTIFIED; + na->last_seen = time(NULL); + snprintf(tsbuf, sizeof(tsbuf), "%lu", + (unsigned long int) u->timestamp); + + if (ircd->modeonreg) { + if (ircd->tsonmode) { + common_svsmode(u, ircd->modeonreg, tsbuf); + } else { + common_svsmode(u, ircd->modeonreg, ""); + } + } + send_event(EVENT_NICK_IDENTIFY, 1, u->nick); + alog("%s: %s!%s@%s identified for nick %s", s_NickServ, u->nick, + u->username, u->host, u->nick); + notice_lang(s_NickServ, u, NICK_IDENTIFY_SUCCEEDED); + if (ircd->vhost) { + do_on_id(u); + } + if (NSModeOnID) { + do_setmodes(u); + } + + if (NSForceEmail && u->na && !u->na->nc->email) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_EMAIL_REQUIRED); + notice_help(s_NickServ, u, NICK_IDENTIFY_EMAIL_HOWTO); + } + + if (!(na->status & NS_RECOGNIZED)) + check_memos(u); + + /* Enable nick tracking if enabled */ + if (NSNickTracking) + nsStartNickTracking(u); + + /* Clear any timers */ + if (na->nc->flags & NI_KILLPROTECT) { + del_ns_timeout(na, TO_COLLIDE); + } + + } + return MOD_CONT; +} diff --git a/src/core/ns_info.c b/src/core/ns_info.c new file mode 100644 index 000000000..1f150b7c3 --- /dev/null +++ b/src/core/ns_info.c @@ -0,0 +1,272 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +static int do_info(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("INFO", do_info, NULL, NICK_HELP_INFO, -1, + NICK_HELP_INFO, NICK_SERVADMIN_HELP_INFO, + NICK_SERVADMIN_HELP_INFO); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_INFO); +} + +/** + * The /ns info command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_info(User * u) +{ + +/* Show hidden info to nick owners and sadmins when the "ALL" parameter is + * supplied. If a nick is online, the "Last seen address" changes to "Is + * online from". + * Syntax: INFO <nick> {ALL} + * -TheShadow (13 Mar 1999) + */ + + char *nick = strtok(NULL, " "); + char *param = strtok(NULL, " "); + + NickAlias *na; + NickRequest *nr = NULL; + int is_servadmin = is_services_admin(u); + + if (!nick) { + syntax_error(s_NickServ, u, "INFO", NICK_INFO_SYNTAX); + } else if (!(na = findnick(nick))) { + if ((nr = findrequestnick(nick))) { + notice_lang(s_NickServ, u, NICK_IS_PREREG); + if (param && stricmp(param, "ALL") == 0 && is_servadmin) { + notice_lang(s_NickServ, u, NICK_INFO_EMAIL, nr->email); + } else { + if (is_servadmin) { + notice_lang(s_NickServ, u, NICK_INFO_FOR_MORE, + s_NickServ, nr->nick); + } + } + } else if (nickIsServices(nick, 1)) { + notice_lang(s_NickServ, u, NICK_X_IS_SERVICES, nick); + } else { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } + } else if (na->status & NS_VERBOTEN) { + if (is_oper(u) && na->last_usermask) + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN_OPER, nick, + na->last_usermask, + (na->last_realname ? na-> + last_realname : getstring(u->na, NO_REASON))); + else + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, nick); + } else { + struct tm *tm; + char buf[BUFSIZE], *end; + const char *commastr = getstring(u->na, COMMA_SPACE); + int need_comma = 0; + int nick_online = 0; + int show_hidden = 0; + time_t expt; + + /* Is the real owner of the nick we're looking up online? -TheShadow */ + if (na->status & (NS_RECOGNIZED | NS_IDENTIFIED)) + nick_online = 1; + + /* Only show hidden fields to owner and sadmins and only when the ALL + * parameter is used. -TheShadow */ + if (param && stricmp(param, "ALL") == 0 && u->na + && ((nick_identified(u) && (na->nc == u->na->nc)) + || is_servadmin)) + show_hidden = 1; + + notice_lang(s_NickServ, u, NICK_INFO_REALNAME, na->nick, + na->last_realname); + + if ((nick_identified(u) && (na->nc == u->na->nc)) || is_servadmin) { + + if (nick_is_services_root(na->nc)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_ROOT, + na->nick); + else if (nick_is_services_admin(na->nc)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_ADMIN, + na->nick); + else if (nick_is_services_oper(na->nc)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_OPER, + na->nick); + + } else { + + if (nick_is_services_root(na->nc) + && !(na->nc->flags & NI_HIDE_STATUS)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_ROOT, + na->nick); + else if (nick_is_services_admin(na->nc) + && !(na->nc->flags & NI_HIDE_STATUS)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_ADMIN, + na->nick); + else if (nick_is_services_oper(na->nc) + && !(na->nc->flags & NI_HIDE_STATUS)) + notice_lang(s_NickServ, u, NICK_INFO_SERVICES_OPER, + na->nick); + + } + + + if (nick_online) { + if (show_hidden || !(na->nc->flags & NI_HIDE_MASK)) + notice_lang(s_NickServ, u, NICK_INFO_ADDRESS_ONLINE, + na->last_usermask); + else + notice_lang(s_NickServ, u, NICK_INFO_ADDRESS_ONLINE_NOHOST, + na->nick); + } else { + if (show_hidden || !(na->nc->flags & NI_HIDE_MASK)) + notice_lang(s_NickServ, u, NICK_INFO_ADDRESS, + na->last_usermask); + } + + tm = localtime(&na->time_registered); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_NickServ, u, NICK_INFO_TIME_REGGED, buf); + + if (!nick_online) { + tm = localtime(&na->last_seen); + strftime_lang(buf, sizeof(buf), u, STRFTIME_DATE_TIME_FORMAT, + tm); + notice_lang(s_NickServ, u, NICK_INFO_LAST_SEEN, buf); + } + + if (na->last_quit + && (show_hidden || !(na->nc->flags & NI_HIDE_QUIT))) + notice_lang(s_NickServ, u, NICK_INFO_LAST_QUIT, na->last_quit); + + if (na->nc->url) + notice_lang(s_NickServ, u, NICK_INFO_URL, na->nc->url); + if (na->nc->email + && (show_hidden || !(na->nc->flags & NI_HIDE_EMAIL))) + notice_lang(s_NickServ, u, NICK_INFO_EMAIL, na->nc->email); + if (na->nc->icq) + notice_lang(s_NickServ, u, NICK_INFO_ICQ, na->nc->icq); + + if (show_hidden) { + if (s_HostServ && ircd->vhost) { + if (getvHost(na->nick) != NULL) { + if (ircd->vident && getvIdent(na->nick) != NULL) { + notice_lang(s_NickServ, u, NICK_INFO_VHOST2, + getvIdent(na->nick), + getvHost(na->nick)); + } else { + notice_lang(s_NickServ, u, NICK_INFO_VHOST, + getvHost(na->nick)); + } + } + } + if (na->nc->greet) + notice_lang(s_NickServ, u, NICK_INFO_GREET, na->nc->greet); + + *buf = 0; + end = buf; + + if (na->nc->flags & NI_KILLPROTECT) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s", + getstring(u->na, NICK_INFO_OPT_KILL)); + need_comma = 1; + } + if (na->nc->flags & NI_SECURE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, NICK_INFO_OPT_SECURE)); + need_comma = 1; + } + if (na->nc->flags & NI_PRIVATE) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, NICK_INFO_OPT_PRIVATE)); + need_comma = 1; + } + if (na->nc->flags & NI_MSG) { + end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", + need_comma ? commastr : "", + getstring(u->na, NICK_INFO_OPT_MSG)); + need_comma = 1; + } + + notice_lang(s_NickServ, u, NICK_INFO_OPTIONS, + *buf ? buf : getstring(u->na, NICK_INFO_OPT_NONE)); + + if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_INFO_SUSPENDED, + na->last_quit); + } + + if (na->status & NS_NO_EXPIRE) { + notice_lang(s_NickServ, u, NICK_INFO_NO_EXPIRE); + } else { + if (is_services_admin(u)) { + expt = na->last_seen + NSExpire; + tm = localtime(&expt); + strftime_lang(buf, sizeof(buf), na->u, + STRFTIME_DATE_TIME_FORMAT, tm); + notice_lang(s_NickServ, u, NICK_INFO_EXPIRE, buf); + } + } + } + + if (!show_hidden + && ((u->na && (na->nc == u->na->nc) && nick_identified(u)) + || is_servadmin)) + notice_lang(s_NickServ, u, NICK_INFO_FOR_MORE, s_NickServ, + na->nick); + } + return MOD_CONT; +} diff --git a/src/core/ns_list.c b/src/core/ns_list.c new file mode 100644 index 000000000..d04d7f2ec --- /dev/null +++ b/src/core/ns_list.c @@ -0,0 +1,230 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_list(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + if (NSListOpersOnly) { + c = createCommand("LIST", do_list, is_oper, -1, NICK_HELP_LIST, -1, + NICK_SERVADMIN_HELP_LIST, + NICK_SERVADMIN_HELP_LIST); + } else { + c = createCommand("LIST", do_list, NULL, -1, NICK_HELP_LIST, -1, + NICK_SERVADMIN_HELP_LIST, + NICK_SERVADMIN_HELP_LIST); + } + + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + if (NSListOpersOnly && !(is_oper(u))) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_LIST); + } +} + +/** + * The /ns list command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_list(User * u) +{ + +/* SADMINS can search for nicks based on their NS_VERBOTEN and NS_NO_EXPIRE + * status. The keywords FORBIDDEN and NOEXPIRE represent these two states + * respectively. These keywords should be included after the search pattern. + * Multiple keywords are accepted and should be separated by spaces. Only one + * of the keywords needs to match a nick's state for the nick to be displayed. + * Forbidden nicks can be identified by "[Forbidden]" appearing in the last + * seen address field. Nicks with NOEXPIRE set are preceeded by a "!". Only + * SADMINS will be shown forbidden nicks and the "!" indicator. + * Syntax for sadmins: LIST pattern [FORBIDDEN] [NOEXPIRE] + * -TheShadow + */ + + + char *pattern = strtok(NULL, " "); + char *keyword; + NickAlias *na; + NickCore *mync; + int nnicks, i; + char buf[BUFSIZE]; + int is_servadmin = is_services_admin(u); + int16 matchflags = 0; + NickRequest *nr = NULL; + int nronly = 0; + char noexpire_char = ' '; + int count = 0, from = 0, to = 0; + char *tmp = NULL; + char *s = NULL; + + + + if (!pattern) { + syntax_error(s_NickServ, u, "LIST", + is_servadmin ? NICK_LIST_SERVADMIN_SYNTAX : + NICK_LIST_SYNTAX); + } else { + + if (pattern) { + if (pattern[0] == '#') { + tmp = myStrGetOnlyToken((pattern + 1), '-', 0); /* Read FROM out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + from = atoi(tmp); + tmp = myStrGetTokenRemainder(pattern, '-', 1); /* Read TO out */ + if (!tmp) { + return MOD_CONT; + } + for (s = tmp; *s; s++) { + if (!isdigit(*s)) { + return MOD_CONT; + } + } + to = atoi(tmp); + pattern = sstrdup("*"); + } + } + + nnicks = 0; + + while (is_servadmin && (keyword = strtok(NULL, " "))) { + if (stricmp(keyword, "FORBIDDEN") == 0) + matchflags |= NS_VERBOTEN; + if (stricmp(keyword, "NOEXPIRE") == 0) + matchflags |= NS_NO_EXPIRE; + if (stricmp(keyword, "UNCONFIRMED") == 0) + nronly = 1; + } + + mync = (nick_identified(u) ? u->na->nc : NULL); + + notice_lang(s_NickServ, u, NICK_LIST_HEADER, pattern); + if (nronly != 1) { + for (i = 0; i < 1024; i++) { + for (na = nalists[i]; na; na = na->next) { + /* Don't show private and forbidden nicks to non-services admins. */ + if ((na->status & NS_VERBOTEN) && !is_servadmin) + continue; + if ((na->nc->flags & NI_PRIVATE) && !is_servadmin + && na->nc != mync) + continue; + if ((matchflags != 0) && !(na->status & matchflags)) + continue; + + /* We no longer compare the pattern against the output buffer. + * Instead we build a nice nick!user@host buffer to compare. + * The output is then generated separately. -TheShadow */ + snprintf(buf, sizeof(buf), "%s!%s", na->nick, + (na->last_usermask + && !(na->status & NS_VERBOTEN)) ? na-> + last_usermask : "*@*"); + if (stricmp(pattern, na->nick) == 0 + || match_wild_nocase(pattern, buf)) { + + if ((((count + 1 >= from) && (count + 1 <= to)) + || ((from == 0) && (to == 0))) + && (++nnicks <= NSListMax)) { + if (is_servadmin + && (na->status & NS_NO_EXPIRE)) + noexpire_char = '!'; + else { + noexpire_char = ' '; + } + if ((na->nc->flags & NI_HIDE_MASK) + && !is_servadmin && na->nc != mync) { + snprintf(buf, sizeof(buf), + "%-20s [Hostname Hidden]", + na->nick); + } else if (na->status & NS_VERBOTEN) { + snprintf(buf, sizeof(buf), + "%-20s [Forbidden]", na->nick); + } else { + snprintf(buf, sizeof(buf), "%-20s %s", + na->nick, na->last_usermask); + } + notice_user(s_NickServ, u, " %c%s", + noexpire_char, buf); + } + count++; + } + } + } + } + + if (nronly == 1 || (is_servadmin && matchflags == 0)) { + noexpire_char = ' '; + for (i = 0; i < 1024; i++) { + for (nr = nrlists[i]; nr; nr = nr->next) { + snprintf(buf, sizeof(buf), "%s!*@*", nr->nick); + if (stricmp(pattern, nr->nick) == 0 + || match_wild_nocase(pattern, buf)) { + if (++nnicks <= NSListMax) { + snprintf(buf, sizeof(buf), + "%-20s [UNCONFIRMED]", nr->nick); + notice_user(s_NickServ, u, " %c%s", + noexpire_char, buf); + } + } + } + } + } + notice_lang(s_NickServ, u, NICK_LIST_RESULTS, + nnicks > NSListMax ? NSListMax : nnicks, nnicks); + } + return MOD_CONT; +} diff --git a/src/core/ns_logout.c b/src/core/ns_logout.c new file mode 100644 index 000000000..ef91b75a9 --- /dev/null +++ b/src/core/ns_logout.c @@ -0,0 +1,125 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +#define TO_COLLIDE 0 /* Collide the user with this nick */ +#define TO_RELEASE 1 /* Release a collided nick */ + +int do_logout(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("LOGOUT", do_logout, NULL, -1, NICK_HELP_LOGOUT, -1, + NICK_SERVADMIN_HELP_LOGOUT, + NICK_SERVADMIN_HELP_LOGOUT); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_LOGOUT); +} + +/** + * The /ns logout command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_logout(User * u) +{ + char *nick = strtok(NULL, " "); + char *param = strtok(NULL, " "); + User *u2; + + if (!is_services_admin(u) && nick) { + syntax_error(s_NickServ, u, "LOGOUT", NICK_LOGOUT_SYNTAX); + } else if (!(u2 = (nick ? finduser(nick) : u))) { + notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick); + } else if (!u2->na) { + if (nick) + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + else + notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); + } else if (u2->na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, u2->na->nick); + } else if (!nick && !nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (nick && is_services_admin(u2)) { + notice_lang(s_NickServ, u, NICK_LOGOUT_SERVICESADMIN, nick); + } else { + if (nick && param && !stricmp(param, "REVALIDATE")) { + cancel_user(u2); + validate_user(u2); + } else { + u2->na->status &= ~(NS_IDENTIFIED | NS_RECOGNIZED); + } + + if (ircd->modeonreg) { + common_svsmode(u2, ircd->modeonunreg, "1"); + } + + u->isSuperAdmin = 0; /* Dont let people logout and remain a SuperAdmin */ + alog("%s: %s!%s@%s logged out nickname %s", s_NickServ, u->nick, + u->username, u->host, u2->nick); + + if (nick) + notice_lang(s_NickServ, u, NICK_LOGOUT_X_SUCCEEDED, nick); + else + notice_lang(s_NickServ, u, NICK_LOGOUT_SUCCEEDED); + + /* Stop nick tracking if enabled */ + if (NSNickTracking) + nsStopNickTracking(u); + + /* Clear any timers again */ + if (u->na->nc->flags & NI_KILLPROTECT) { + del_ns_timeout(u->na, TO_COLLIDE); + } + + } + return MOD_CONT; +} diff --git a/src/core/ns_recover.c b/src/core/ns_recover.c new file mode 100644 index 000000000..2b72d94fb --- /dev/null +++ b/src/core/ns_recover.c @@ -0,0 +1,111 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_recover(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("RECOVER", do_recover, NULL, NICK_HELP_RECOVER, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_RECOVER); +} + +/** + * The /ns recover command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_recover(User * u) +{ + char *nick = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + NickAlias *na; + User *u2; + + if (!nick) { + syntax_error(s_NickServ, u, "RECOVER", NICK_RECOVER_SYNTAX); + } else if (!(u2 = finduser(nick))) { + notice_lang(s_NickServ, u, NICK_X_NOT_IN_USE, nick); + } else if (!(na = u2->na)) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + } else if (stricmp(nick, u->nick) == 0) { + notice_lang(s_NickServ, u, NICK_NO_RECOVER_SELF); + } else if (pass) { + int res = check_password(pass, na->nc->pass); + + if (res == 1) { + notice_lang(s_NickServ, u2, FORCENICKCHANGE_NOW); + collide(na, 0); + notice_lang(s_NickServ, u, NICK_RECOVERED, s_NickServ, nick); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + if (res == 0) { + alog("%s: RECOVER: invalid password for %s by %s!%s@%s", + s_NickServ, nick, u->nick, u->username, u->host); + bad_password(u); + } + } + } else { + if (group_identified(u, na->nc) + || (!(na->nc->flags & NI_SECURE) && is_on_access(u, na->nc))) { + notice_lang(s_NickServ, u2, FORCENICKCHANGE_NOW); + collide(na, 0); + notice_lang(s_NickServ, u, NICK_RECOVERED, s_NickServ, nick); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + } + } + return MOD_CONT; +} diff --git a/src/core/ns_register.c b/src/core/ns_register.c new file mode 100644 index 000000000..92f4f0589 --- /dev/null +++ b/src/core/ns_register.c @@ -0,0 +1,486 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_confirm(User * u); +int do_register(User * u); +int do_resend(User * u); +void myNickServHelp(User * u); +NickRequest *makerequest(const char *nick); +NickAlias *makenick(const char *nick); +int do_sendregmail(User * u, NickRequest * nr); +int ns_do_register(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("REGISTER", do_register, NULL, NICK_HELP_REGISTER, + -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + c = createCommand("CONFIRM", do_confirm, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + c = createCommand("RESEND", do_resend, NULL, -1, -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_REGISTER); + if (NSEmailReg) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_CONFIRM); + notice_lang(s_NickServ, u, NICK_HELP_CMD_RESEND); + } +} + +/** + * The /ns register command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_register(User * u) +{ + NickRequest *nr = NULL, *anr = NULL; + NickCore *nc = NULL; + int prefixlen = strlen(NSGuestNickPrefix); + int nicklen = strlen(u->nick); + char *pass = strtok(NULL, " "); + char *email = strtok(NULL, " "); + char passcode[11]; + int idx, min = 1, max = 62, i = 0; + int chars[] = + { ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', + 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', + 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' + }; + + if (readonly) { + notice_lang(s_NickServ, u, NICK_REGISTRATION_DISABLED); + return MOD_CONT; + } + + if (checkDefCon(DEFCON_NO_NEW_NICKS)) { + notice_lang(s_NickServ, u, OPER_DEFCON_DENIED); + return MOD_CONT; + } + + if (!is_oper(u) && NickRegDelay + && ((time(NULL) - u->my_signon) < NickRegDelay)) { + notice_lang(s_NickServ, u, NICK_REG_DELAY, NickRegDelay); + return MOD_CONT; + } + + if ((anr = findrequestnick(u->nick))) { + notice_lang(s_NickServ, u, NICK_REQUESTED); + return MOD_CONT; + } + /* Prevent "Guest" nicks from being registered. -TheShadow */ + + /* Guest nick can now have a series of between 1 and 7 digits. + * --lara + */ + if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && + stristr(u->nick, NSGuestNickPrefix) == u->nick && + strspn(u->nick + prefixlen, "1234567890") == nicklen - prefixlen) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); + return MOD_CONT; + } + + if (RestrictOperNicks) { + for (i = 0; i < RootNumber; i++) { + if (stristr(u->nick, ServicesRoots[i]) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + for (i = 0; i < servadmins.count && (nc = servadmins.list[i]); i++) { + if (stristr(u->nick, nc->display) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + for (i = 0; i < servopers.count && (nc = servopers.list[i]); i++) { + if (stristr(u->nick, nc->display) && !is_oper(u)) { + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, + u->nick); + return MOD_CONT; + } + } + } + + if (!pass) { + if (NSForceEmail) { + syntax_error(s_NickServ, u, "REGISTER", + NICK_REGISTER_SYNTAX_EMAIL); + } else { + syntax_error(s_NickServ, u, "REGISTER", NICK_REGISTER_SYNTAX); + } + } else if (NSForceEmail && !email) { + syntax_error(s_NickServ, u, "REGISTER", + NICK_REGISTER_SYNTAX_EMAIL); + } else if (time(NULL) < u->lastnickreg + NSRegDelay) { + notice_lang(s_NickServ, u, NICK_REG_PLEASE_WAIT, NSRegDelay); + } else if (u->na) { /* i.e. there's already such a nick regged */ + if (u->na->status & NS_VERBOTEN) { + alog("%s: %s@%s tried to register FORBIDden nick %s", + s_NickServ, u->username, u->host, u->nick); + notice_lang(s_NickServ, u, NICK_CANNOT_BE_REGISTERED, u->nick); + } else { + notice_lang(s_NickServ, u, NICK_ALREADY_REGISTERED, u->nick); + } + } else if (stricmp(u->nick, pass) == 0 + || (StrictPasswords && strlen(pass) < 5)) { + notice_lang(s_NickServ, u, MORE_OBSCURE_PASSWORD); + } else if (email && !MailValidate(email)) { + notice_lang(s_NickServ, u, MAIL_X_INVALID, email); + } else { +#ifdef USE_ENCRYPTION + if (strlen(pass) > PASSMAX) { + pass[PASSMAX] = 0; + notice_lang(s_NickServ, u, PASSWORD_TRUNCATED, PASSMAX); + } +#else + if (strlen(pass) > PASSMAX - 1) { /* -1 for null byte */ + pass[PASSMAX] = 0; + notice_lang(s_NickServ, u, PASSWORD_TRUNCATED, PASSMAX - 1); + } +#endif + for (idx = 0; idx < 9; idx++) { + passcode[idx] = + chars[(1 + + (int) (((float) (max - min)) * getrandom16() / + (65535 + 1.0)) + min)]; + } passcode[idx] = '\0'; + nr = makerequest(u->nick); + nr->passcode = sstrdup(passcode); + nr->password = sstrdup(pass); + if (email) { + nr->email = sstrdup(email); + } + nr->requested = time(NULL); + if (NSEmailReg) { + if (do_sendregmail(u, nr) == 0) { + notice_lang(s_NickServ, u, NICK_ENTER_REG_CODE, email, + s_NickServ); + alog("%s: sent registration verification code to %s", + s_NickServ, nr->email); + } else { + alog("%s: Unable to send registration verification mail", + s_NickServ); + notice_lang(s_NickServ, u, NICK_REG_UNABLE); + delnickrequest(nr); /* Delete the NickRequest if we couldnt send the mail */ + return MOD_CONT; + } + } else { + do_confirm(u); + } + + } + return MOD_CONT; +} + +/*************************************************************************/ + +int ns_do_register(User * u) +{ + return do_register(u); +} + + +int do_confirm(User * u) +{ + + NickRequest *nr = NULL; + NickAlias *na = NULL; + char *passcode = strtok(NULL, " "); + char *pass = NULL; + char *email = NULL; + int forced = 0; + User *utmp = NULL; +#ifdef USE_ENCRYPTION + int len; +#endif + nr = findrequestnick(u->nick); + + if (NSEmailReg) { + if (!passcode) { + notice_lang(s_NickServ, u, NICK_CONFIRM_INVALID); + return MOD_CONT; + } + + if (!nr) { + if (is_services_admin(u)) { +/* If an admin, thier nick is obviously already regged, so look at the passcode to get the nick + of the user they are trying to validate, and push that user through regardless of passcode */ + nr = findrequestnick(passcode); + if (nr) { + utmp = finduser(passcode); + if (utmp) { + sprintf(passcode, + "FORCE_ACTIVATION_DUE_TO_OPER_CONFIRM %s", + nr->passcode); + passcode = strtok(passcode, " "); + notice_lang(s_NickServ, u, NICK_FORCE_REG, + nr->nick); + do_confirm(utmp); + return MOD_CONT; + } else { + passcode = sstrdup(nr->passcode); + forced = 1; + } + } else { + notice_lang(s_NickServ, u, NICK_CONFIRM_NOT_FOUND, + s_NickServ); + return MOD_CONT; + } + } else { + notice_lang(s_NickServ, u, NICK_CONFIRM_NOT_FOUND, + s_NickServ); + return MOD_CONT; + } + } + + if (stricmp(nr->passcode, passcode) != 0) { + notice_lang(s_NickServ, u, NICK_CONFIRM_INVALID); + return MOD_CONT; + } + } + + if (!nr) { + notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED); + return MOD_CONT; + } + pass = sstrdup(nr->password); + + if (nr->email) { + email = sstrdup(nr->email); + } + na = makenick(nr->nick); + + if (na) { + int i; + char tsbuf[16]; + +#ifdef USE_ENCRYPTION + len = strlen(pass); + na->nc->pass = smalloc(PASSMAX); + if (encrypt(pass, len, na->nc->pass, PASSMAX) < 0) { + memset(pass, 0, strlen(pass)); + alog("%s: Failed to encrypt password for %s (register)", + s_NickServ, nr->nick); + notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED); + return MOD_CONT; + } + memset(pass, 0, strlen(pass)); + na->status = (int16) (NS_IDENTIFIED | NS_RECOGNIZED); + na->nc->flags |= NI_ENCRYPTEDPW; +#else + na->nc->pass = sstrdup(pass); + na->status = (int16) (NS_IDENTIFIED | NS_RECOGNIZED); +#endif + na->nc->flags |= NSDefFlags; + for (i = 0; i < RootNumber; i++) { + if (!stricmp(ServicesRoots[i], nr->nick)) { + na->nc->flags |= NI_SERVICES_ROOT; + break; + } + } + na->nc->memos.memomax = MSMaxMemos; + na->nc->channelmax = CSMaxReg; + if (forced == 1) { + na->last_usermask = sstrdup("*@*"); + na->last_realname = sstrdup("unknown"); + } else { + na->last_usermask = + scalloc(strlen(common_get_vident(u)) + + strlen(common_get_vhost(u)) + 2, 1); + sprintf(na->last_usermask, "%s@%s", common_get_vident(u), + common_get_vhost(u)); + na->last_realname = sstrdup(u->realname); + } + na->time_registered = na->last_seen = time(NULL); + if (NSAddAccessOnReg) { + na->nc->accesscount = 1; + na->nc->access = scalloc(sizeof(char *), 1); + na->nc->access[0] = create_mask(u); + } else { + na->nc->accesscount = 0; + na->nc->access = NULL; + } + na->nc->language = NSDefLanguage; + if (email) + na->nc->email = sstrdup(email); + if (forced != 1) { + u->na = na; + na->u = u; + alog("%s: '%s' registered by %s@%s (e-mail: %s)", s_NickServ, + u->nick, u->username, u->host, (email ? email : "none")); + if (NSAddAccessOnReg) + notice_lang(s_NickServ, u, NICK_REGISTERED, u->nick, + na->nc->access[0]); + else + notice_lang(s_NickServ, u, NICK_REGISTERED_NO_MASK, + u->nick); + send_event(EVENT_NICK_REGISTERED, 1, u->nick); +#ifndef USE_ENCRYPTION + notice_lang(s_NickServ, u, NICK_PASSWORD_IS, na->nc->pass); +#endif + u->lastnickreg = time(NULL); + if (ircd->modeonreg) { + if (ircd->tsonmode) { + snprintf(tsbuf, sizeof(tsbuf), "%lu", + (unsigned long int) u->timestamp); + common_svsmode(u, ircd->modeonreg, tsbuf); + } else { + common_svsmode(u, ircd->modeonreg, NULL); + } + } + + } else { + notice_lang(s_NickServ, u, NICK_FORCE_REG, nr->nick); + } + delnickrequest(nr); /* remove the nick request */ + } else { + alog("%s: makenick(%s) failed", s_NickServ, u->nick); + notice_lang(s_NickServ, u, NICK_REGISTRATION_FAILED); + } + + /* Enable nick tracking if enabled */ + if (NSNickTracking) + nsStartNickTracking(u); + + return MOD_CONT; +} + +NickRequest *makerequest(const char *nick) +{ + NickRequest *nr; + + nr = scalloc(1, sizeof(NickRequest)); + nr->nick = sstrdup(nick); + insert_requestnick(nr); + alog("%s: Nick %s has been requested", s_NickServ, nr->nick); + return nr; +} + +/* Creates a full new nick (alias + core) in NickServ database. */ + +NickAlias *makenick(const char *nick) +{ + NickAlias *na; + NickCore *nc; + + /* First make the core */ + nc = scalloc(1, sizeof(NickCore)); + nc->display = sstrdup(nick); + slist_init(&nc->aliases); + insert_core(nc); + alog("%s: group %s has been created", s_NickServ, nc->display); + + /* Then make the alias */ + na = scalloc(1, sizeof(NickAlias)); + na->nick = sstrdup(nick); + na->nc = nc; + slist_add(&nc->aliases, na); + alpha_insert_alias(na); + return na; +} + +/* Register a nick. */ + +int do_resend(User * u) +{ + NickRequest *nr = NULL; + if (NSEmailReg) { + if ((nr = findrequestnick(u->nick))) { + if (do_sendregmail(u, nr) == 0) { + notice_lang(s_NickServ, u, NICK_REG_RESENT, nr->email); + alog("%s: re-sent registration verification code for %s to %s", s_NickServ, nr->nick, nr->email); + } else { + alog("%s: Unable to re-send registration verification mail for %s", s_NickServ, nr->nick); + return MOD_CONT; + } + } + } + return MOD_CONT; +} + +int do_sendregmail(User * u, NickRequest * nr) +{ + MailInfo *mail = NULL; + char buf[BUFSIZE]; + + if (!(nr || u)) { + return -1; + } + snprintf(buf, sizeof(buf), getstring2(NULL, NICK_REG_MAIL_SUBJECT), + nr->nick); + mail = MailRegBegin(u, nr, buf, s_NickServ); + if (!mail) { + return -1; + } + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_HEAD)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_LINE_1), nr->nick); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_LINE_2), s_NickServ, + nr->passcode); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_LINE_3)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_LINE_4)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring2(NULL, NICK_REG_MAIL_LINE_5), + NetworkName); + fprintf(mail->pipe, "\n.\n"); + MailEnd(mail); + return 0; +} diff --git a/src/core/ns_release.c b/src/core/ns_release.c new file mode 100644 index 000000000..4112c4606 --- /dev/null +++ b/src/core/ns_release.c @@ -0,0 +1,107 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_release(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("RELEASE", do_release, NULL, NICK_HELP_RELEASE, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_RELEASE); +} + +/** + * The /ns release command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_release(User * u) +{ + char *nick = strtok(NULL, " "); + char *pass = strtok(NULL, " "); + NickAlias *na; + + if (!nick) { + syntax_error(s_NickServ, u, "RELEASE", NICK_RELEASE_SYNTAX); + } else if (!(na = findnick(nick))) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + } else if (!(na->status & NS_KILL_HELD)) { + notice_lang(s_NickServ, u, NICK_RELEASE_NOT_HELD, nick); + } else if (pass) { + int res = check_password(pass, na->nc->pass); + if (res == 1) { + release(na, 0); + notice_lang(s_NickServ, u, NICK_RELEASED); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + if (res == 0) { + alog("%s: RELEASE: invalid password for %s by %s!%s@%s", + s_NickServ, nick, u->nick, u->username, u->host); + bad_password(u); + } + } + } else { + if (group_identified(u, na->nc) + || (!(na->nc->flags & NI_SECURE) && is_on_access(u, na->nc))) { + release(na, 0); + notice_lang(s_NickServ, u, NICK_RELEASED); + } else { + notice_lang(s_NickServ, u, ACCESS_DENIED); + } + } + return MOD_CONT; +} diff --git a/src/core/ns_sendpass.c b/src/core/ns_sendpass.c new file mode 100644 index 000000000..14f766252 --- /dev/null +++ b/src/core/ns_sendpass.c @@ -0,0 +1,120 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_sendpass(User * u); + +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SENDPASS", do_sendpass, NULL, NICK_HELP_SENDPASS, + -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + if (!UseMail) { + return MOD_STOP; + } +#ifdef USE_ENCRYPTION + return MOD_STOP; +#else + return MOD_CONT; +#endif +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_SENDPASS); +} + +/** + * The /ns sendpass command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_sendpass(User * u) +{ + + char *nick = strtok(NULL, " "); + NickAlias *na; + + if (!nick) { + syntax_error(s_NickServ, u, "SENDPASS", NICK_SENDPASS_SYNTAX); + } else if (RestrictMail && !is_oper(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + } else if (!(na = findnick(nick))) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else { + char buf[BUFSIZE]; + MailInfo *mail; + + snprintf(buf, sizeof(buf), getstring(na, NICK_SENDPASS_SUBJECT), + na->nick); + mail = MailBegin(u, na->nc, buf, s_NickServ); + if (!mail) + return MOD_CONT; + + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_HEAD)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_1), na->nick); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_2), + na->nc->pass); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_3)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_4)); + fprintf(mail->pipe, "\n\n"); + fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_5), + NetworkName); + fprintf(mail->pipe, "\n.\n"); + + MailEnd(mail); + + alog("%s: %s!%s@%s used SENDPASS on %s", s_NickServ, u->nick, + u->username, u->host, nick); + notice_lang(s_NickServ, u, NICK_SENDPASS_OK, nick); + } + + return MOD_CONT; +} diff --git a/src/core/ns_set.c b/src/core/ns_set.c new file mode 100644 index 000000000..091a7fe42 --- /dev/null +++ b/src/core/ns_set.c @@ -0,0 +1,519 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_set(User * u); +int do_set_display(User * u, NickCore * nc, char *param); +int do_set_password(User * u, NickCore * nc, char *param); +int do_set_language(User * u, NickCore * nc, char *param); +int do_set_url(User * u, NickCore * nc, char *param); +int do_set_email(User * u, NickCore * nc, char *param); +int do_set_greet(User * u, NickCore * nc, char *param); +int do_set_icq(User * u, NickCore * nc, char *param); +int do_set_kill(User * u, NickCore * nc, char *param); +int do_set_secure(User * u, NickCore * nc, char *param); +int do_set_private(User * u, NickCore * nc, char *param); +int do_set_msg(User * u, NickCore * nc, char *param); +int do_set_hide(User * u, NickCore * nc, char *param); +int do_set_noexpire(User * u, NickAlias * nc, char *param); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", do_set, NULL, NICK_HELP_SET, -1, -1, + NICK_SERVADMIN_HELP_SET, NICK_SERVADMIN_HELP_SET); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET DISPLAY", NULL, NULL, NICK_HELP_SET_DISPLAY, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET PASSWORD", NULL, NULL, NICK_HELP_SET_PASSWORD, + -1, -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET URL", NULL, NULL, NICK_HELP_SET_URL, -1, -1, -1, + -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET EMAIL", NULL, NULL, NICK_HELP_SET_EMAIL, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET ICQ", NULL, NULL, NICK_HELP_SET_ICQ, -1, -1, -1, + -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET GREET", NULL, NULL, NICK_HELP_SET_GREET, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET KILL", NULL, NULL, NICK_HELP_SET_KILL, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET SECURE", NULL, NULL, NICK_HELP_SET_SECURE, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET PRIVATE", NULL, NULL, NICK_HELP_SET_PRIVATE, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET MSG", NULL, NULL, NICK_HELP_SET_MSG, -1, -1, -1, + -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET HIDE", NULL, NULL, NICK_HELP_SET_HIDE, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("SET NOEXPIRE", NULL, NULL, -1, -1, -1, + NICK_SERVADMIN_HELP_SET_NOEXPIRE, + NICK_SERVADMIN_HELP_SET_NOEXPIRE); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_SET); +} + +/** + * The /ns set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set(User * u) +{ + char *cmd = strtok(NULL, " "); + char *param = strtok(NULL, " "); + + NickAlias *na; + int is_servadmin = is_services_admin(u); + int set_nick = 0; + + if (readonly) { + notice_lang(s_NickServ, u, NICK_SET_DISABLED); + return MOD_CONT; + } + + if (is_servadmin && cmd && (na = findnick(cmd))) { + cmd = param; + param = strtok(NULL, " "); + set_nick = 1; + } else { + na = u->na; + } + + if (!param + && (!cmd + || (stricmp(cmd, "URL") != 0 && stricmp(cmd, "EMAIL") != 0 + && stricmp(cmd, "GREET") != 0 + && stricmp(cmd, "ICQ") != 0))) { + if (is_servadmin) { + syntax_error(s_NickServ, u, "SET", NICK_SET_SERVADMIN_SYNTAX); + } else { + syntax_error(s_NickServ, u, "SET", NICK_SET_SYNTAX); + } + } else if (!na) { + notice_lang(s_NickServ, u, NICK_NOT_REGISTERED); + } else if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + } else if (na->nc->flags & NI_SUSPENDED) { + notice_lang(s_NickServ, u, NICK_X_SUSPENDED, na->nick); + } else if (!is_servadmin && !nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else if (stricmp(cmd, "DISPLAY") == 0) { + do_set_display(u, na->nc, param); + } else if (stricmp(cmd, "PASSWORD") == 0) { + do_set_password(u, na->nc, param); + } else if (stricmp(cmd, "LANGUAGE") == 0) { + do_set_language(u, na->nc, param); + } else if (stricmp(cmd, "URL") == 0) { + do_set_url(u, na->nc, param); + } else if (stricmp(cmd, "EMAIL") == 0) { + do_set_email(u, na->nc, param); + } else if (stricmp(cmd, "ICQ") == 0) { + do_set_icq(u, na->nc, param); + } else if (stricmp(cmd, "GREET") == 0) { + do_set_greet(u, na->nc, param); + } else if (stricmp(cmd, "KILL") == 0) { + do_set_kill(u, na->nc, param); + } else if (stricmp(cmd, "SECURE") == 0) { + do_set_secure(u, na->nc, param); + } else if (stricmp(cmd, "PRIVATE") == 0) { + do_set_private(u, na->nc, param); + } else if (stricmp(cmd, "MSG") == 0) { + do_set_msg(u, na->nc, param); + } else if (stricmp(cmd, "HIDE") == 0) { + do_set_hide(u, na->nc, param); + } else if (stricmp(cmd, "NOEXPIRE") == 0) { + do_set_noexpire(u, na, param); + } else { + if (is_servadmin) + notice_lang(s_NickServ, u, NICK_SET_UNKNOWN_OPTION_OR_BAD_NICK, + cmd); + else + notice_lang(s_NickServ, u, NICK_SET_UNKNOWN_OPTION, cmd); + } + return MOD_CONT; +} + +int do_set_display(User * u, NickCore * nc, char *param) +{ + int i; + NickAlias *na; + + /* First check whether param is a valid nick of the group */ + for (i = 0; i < nc->aliases.count; i++) { + na = nc->aliases.list[i]; + if (!stricmp(na->nick, param)) { + param = na->nick; /* Because case may differ */ + break; + } + } + + if (i == nc->aliases.count) { + notice_lang(s_NickServ, u, NICK_SET_DISPLAY_INVALID); + return MOD_CONT; + } + + change_core_display(nc, param); + notice_lang(s_NickServ, u, NICK_SET_DISPLAY_CHANGED, nc->display); + + /* Enable nick tracking if enabled */ + if (NSNickTracking) + nsStartNickTracking(u); + + return MOD_CONT; +} + +int do_set_password(User * u, NickCore * nc, char *param) +{ + int len = strlen(param); + + if (NSSecureAdmins && u->na->nc != nc && nick_is_services_admin(nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } else if (stricmp(nc->display, param) == 0 + || (StrictPasswords && len < 5)) { + notice_lang(s_NickServ, u, MORE_OBSCURE_PASSWORD); + return MOD_CONT; + } + + if (nc->pass) + free(nc->pass); + +#ifdef USE_ENCRYPTION + nc->pass = smalloc(PASSMAX); + + if (encrypt(param, len, nc->pass, PASSMAX) < 0) { + memset(param, 0, len); + alog("%s: Failed to encrypt password for %s (set)", s_NickServ, + nc->display); + notice_lang(s_NickServ, u, NICK_SET_PASSWORD_FAILED); + return MOD_CONT; + } + + memset(param, 0, len); + notice_lang(s_NickServ, u, NICK_SET_PASSWORD_CHANGED); +#else + nc->pass = sstrdup(param); + notice_lang(s_NickServ, u, NICK_SET_PASSWORD_CHANGED_TO, nc->pass); +#endif + + if (u->na && u->na->nc != nc && is_services_admin(u)) { + alog("%s: %s!%s@%s used SET PASSWORD as Services admin on %s (e-mail: %s)", s_NickServ, u->nick, u->username, u->host, nc->display, (nc->email ? nc->email : "none")); + if (WallSetpass) + anope_cmd_global(s_NickServ, + "\2%s\2 used SET PASSWORD as Services admin on \2%s\2", + u->nick, nc->display); + } else { + alog("%s: %s!%s@%s (e-mail: %s) changed its password.", s_NickServ, + u->nick, u->username, u->host, + (nc->email ? nc->email : "none")); + } + return MOD_CONT; +} + +int do_set_language(User * u, NickCore * nc, char *param) +{ + int langnum; + + if (param[strspn(param, "0123456789")] != 0) { /* i.e. not a number */ + syntax_error(s_NickServ, u, "SET LANGUAGE", + NICK_SET_LANGUAGE_SYNTAX); + return MOD_CONT; + } + langnum = atoi(param) - 1; + if (langnum < 0 || langnum >= NUM_LANGS || langlist[langnum] < 0) { + notice_lang(s_NickServ, u, NICK_SET_LANGUAGE_UNKNOWN, langnum + 1, + s_NickServ); + return MOD_CONT; + } + nc->language = langlist[langnum]; + notice_lang(s_NickServ, u, NICK_SET_LANGUAGE_CHANGED); + return MOD_CONT; +} + +int do_set_url(User * u, NickCore * nc, char *param) +{ + if (nc->url) + free(nc->url); + + if (param) { + nc->url = sstrdup(param); + notice_lang(s_NickServ, u, NICK_SET_URL_CHANGED, param); + } else { + nc->url = NULL; + notice_lang(s_NickServ, u, NICK_SET_URL_UNSET); + } + return MOD_CONT; +} + +int do_set_email(User * u, NickCore * nc, char *param) +{ + if (!param && NSForceEmail) { + notice_lang(s_NickServ, u, NICK_SET_EMAIL_UNSET_IMPOSSIBLE); + return MOD_CONT; + } else if (NSSecureAdmins && u->na->nc != nc + && nick_is_services_admin(nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } else if (param && !MailValidate(param)) { + notice_lang(s_NickServ, u, MAIL_X_INVALID, param); + return MOD_CONT; + } + + if (u->na && u->na->nc != nc && is_services_admin(u)) { + alog("%s: %s!%s@%s used SET EMAIL as Services admin on %s (e-mail: %s)", s_NickServ, u->nick, u->username, u->host, nc->display, (nc->email ? nc->email : "none")); + } else { + alog("%s: %s!%s@%s (e-mail: %s) changed its e-mail to %s.", + s_NickServ, u->nick, u->username, u->host, + (nc->email ? nc->email : "none"), (param ? param : "none")); + } + if (nc->email) + free(nc->email); + + if (param) { + nc->email = sstrdup(param); + notice_lang(s_NickServ, u, NICK_SET_EMAIL_CHANGED, param); + } else { + nc->email = NULL; + notice_lang(s_NickServ, u, NICK_SET_EMAIL_UNSET); + } + return MOD_CONT; +} + +int do_set_icq(User * u, NickCore * nc, char *param) +{ + if (param) { + int32 tmp = atol(param); + if (!tmp) { + notice_lang(s_NickServ, u, NICK_SET_ICQ_INVALID, param); + } else { + nc->icq = tmp; + notice_lang(s_NickServ, u, NICK_SET_ICQ_CHANGED, param); + } + } else { + nc->icq = 0; + notice_lang(s_NickServ, u, NICK_SET_ICQ_UNSET); + } + return MOD_CONT; +} + +int do_set_greet(User * u, NickCore * nc, char *param) +{ + if (nc->greet) + free(nc->greet); + + if (param) { + char buf[BUFSIZE]; + char *end = strtok(NULL, ""); + + snprintf(buf, sizeof(buf), "%s%s%s", param, (end ? " " : ""), + (end ? end : "")); + + nc->greet = sstrdup(buf); + notice_lang(s_NickServ, u, NICK_SET_GREET_CHANGED, buf); + } else { + nc->greet = NULL; + notice_lang(s_NickServ, u, NICK_SET_GREET_UNSET); + } + return MOD_CONT; +} + +int do_set_kill(User * u, NickCore * nc, char *param) +{ + if (stricmp(param, "ON") == 0) { + nc->flags |= NI_KILLPROTECT; + nc->flags &= ~(NI_KILL_QUICK | NI_KILL_IMMED); + notice_lang(s_NickServ, u, NICK_SET_KILL_ON); + } else if (stricmp(param, "QUICK") == 0) { + nc->flags |= NI_KILLPROTECT | NI_KILL_QUICK; + nc->flags &= ~NI_KILL_IMMED; + notice_lang(s_NickServ, u, NICK_SET_KILL_QUICK); + } else if (stricmp(param, "IMMED") == 0) { + if (NSAllowKillImmed) { + nc->flags |= NI_KILLPROTECT | NI_KILL_IMMED; + nc->flags &= ~NI_KILL_QUICK; + notice_lang(s_NickServ, u, NICK_SET_KILL_IMMED); + } else { + notice_lang(s_NickServ, u, NICK_SET_KILL_IMMED_DISABLED); + } + } else if (stricmp(param, "OFF") == 0) { + nc->flags &= ~(NI_KILLPROTECT | NI_KILL_QUICK | NI_KILL_IMMED); + notice_lang(s_NickServ, u, NICK_SET_KILL_OFF); + } else { + syntax_error(s_NickServ, u, "SET KILL", + NSAllowKillImmed ? NICK_SET_KILL_IMMED_SYNTAX : + NICK_SET_KILL_SYNTAX); + } + return MOD_CONT; +} + +int do_set_secure(User * u, NickCore * nc, char *param) +{ + if (stricmp(param, "ON") == 0) { + nc->flags |= NI_SECURE; + notice_lang(s_NickServ, u, NICK_SET_SECURE_ON); + } else if (stricmp(param, "OFF") == 0) { + nc->flags &= ~NI_SECURE; + notice_lang(s_NickServ, u, NICK_SET_SECURE_OFF); + } else { + syntax_error(s_NickServ, u, "SET SECURE", NICK_SET_SECURE_SYNTAX); + } + return MOD_CONT; +} + +int do_set_private(User * u, NickCore * nc, char *param) +{ + if (stricmp(param, "ON") == 0) { + nc->flags |= NI_PRIVATE; + notice_lang(s_NickServ, u, NICK_SET_PRIVATE_ON); + } else if (stricmp(param, "OFF") == 0) { + nc->flags &= ~NI_PRIVATE; + notice_lang(s_NickServ, u, NICK_SET_PRIVATE_OFF); + } else { + syntax_error(s_NickServ, u, "SET PRIVATE", + NICK_SET_PRIVATE_SYNTAX); + } + return MOD_CONT; +} + +int do_set_msg(User * u, NickCore * nc, char *param) +{ + if (!UsePrivmsg) { + notice_lang(s_NickServ, u, NICK_SET_OPTION_DISABLED, "MSG"); + return MOD_CONT; + } + + if (stricmp(param, "ON") == 0) { + nc->flags |= NI_MSG; + notice_lang(s_NickServ, u, NICK_SET_MSG_ON); + } else if (stricmp(param, "OFF") == 0) { + nc->flags &= ~NI_MSG; + notice_lang(s_NickServ, u, NICK_SET_MSG_OFF); + } else { + syntax_error(s_NickServ, u, "SET MSG", NICK_SET_MSG_SYNTAX); + } + return MOD_CONT; +} + +int do_set_hide(User * u, NickCore * nc, char *param) +{ + int flag, onmsg, offmsg; + + if (stricmp(param, "EMAIL") == 0) { + flag = NI_HIDE_EMAIL; + onmsg = NICK_SET_HIDE_EMAIL_ON; + offmsg = NICK_SET_HIDE_EMAIL_OFF; + } else if (stricmp(param, "USERMASK") == 0) { + flag = NI_HIDE_MASK; + onmsg = NICK_SET_HIDE_MASK_ON; + offmsg = NICK_SET_HIDE_MASK_OFF; + } else if (stricmp(param, "STATUS") == 0) { + flag = NI_HIDE_STATUS; + onmsg = NICK_SET_HIDE_STATUS_ON; + offmsg = NICK_SET_HIDE_STATUS_OFF; + } else if (stricmp(param, "QUIT") == 0) { + flag = NI_HIDE_QUIT; + onmsg = NICK_SET_HIDE_QUIT_ON; + offmsg = NICK_SET_HIDE_QUIT_OFF; + } else { + syntax_error(s_NickServ, u, "SET HIDE", NICK_SET_HIDE_SYNTAX); + return MOD_CONT; + } + + param = strtok(NULL, " "); + if (!param) { + syntax_error(s_NickServ, u, "SET HIDE", NICK_SET_HIDE_SYNTAX); + } else if (stricmp(param, "ON") == 0) { + nc->flags |= flag; + notice_lang(s_NickServ, u, onmsg, s_NickServ); + } else if (stricmp(param, "OFF") == 0) { + nc->flags &= ~flag; + notice_lang(s_NickServ, u, offmsg, s_NickServ); + } else { + syntax_error(s_NickServ, u, "SET HIDE", NICK_SET_HIDE_SYNTAX); + } + return MOD_CONT; +} + +int do_set_noexpire(User * u, NickAlias * na, char *param) +{ + if (!is_services_admin(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + if (!param) { + syntax_error(s_NickServ, u, "SET NOEXPIRE", + NICK_SET_NOEXPIRE_SYNTAX); + return MOD_CONT; + } + if (stricmp(param, "ON") == 0) { + na->status |= NS_NO_EXPIRE; + notice_lang(s_NickServ, u, NICK_SET_NOEXPIRE_ON, na->nick); + } else if (stricmp(param, "OFF") == 0) { + na->status &= ~NS_NO_EXPIRE; + notice_lang(s_NickServ, u, NICK_SET_NOEXPIRE_OFF, na->nick); + } else { + syntax_error(s_NickServ, u, "SET NOEXPIRE", + NICK_SET_NOEXPIRE_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/ns_status.c b/src/core/ns_status.c new file mode 100644 index 000000000..865329204 --- /dev/null +++ b/src/core/ns_status.c @@ -0,0 +1,94 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_status(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("STATUS", do_status, NULL, NICK_HELP_STATUS, -1, -1, + -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_STATUS); +} + +/** + * The /ns status command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_status(User * u) +{ + User *u2; + NickAlias *na = NULL; + int i = 0; + char *nick = strtok(NULL, " "); + + /* If no nickname is given, we assume that the user + * is asking for himself */ + if (!nick) + nick = u->nick; + + while (nick && (i++ < 16)) { + if (!(u2 = finduser(nick))) /* Nick is not online */ + notice_lang(s_NickServ, u, NICK_STATUS_0, nick); + else if (nick_identified(u2)) /* Nick is identified */ + notice_lang(s_NickServ, u, NICK_STATUS_3, nick); + else if (nick_recognized(u2)) /* Nick is recognised, but NOT identified */ + notice_lang(s_NickServ, u, NICK_STATUS_2, nick); + else if ((na = findnick(nick)) == NULL) /* Nick is online, but NOT a registered */ + notice_lang(s_NickServ, u, NICK_STATUS_0, nick); + else + notice_lang(s_NickServ, u, NICK_STATUS_1, nick); + + /* Get the next nickname */ + nick = strtok(NULL, " "); + } + return MOD_CONT; +} diff --git a/src/core/ns_suspend.c b/src/core/ns_suspend.c new file mode 100644 index 000000000..ba48c2175 --- /dev/null +++ b/src/core/ns_suspend.c @@ -0,0 +1,193 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_suspend(User * u); +int do_unsuspend(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SUSPEND", do_suspend, is_services_admin, -1, -1, -1, + NICK_SERVADMIN_HELP_SUSPEND, + NICK_SERVADMIN_HELP_SUSPEND); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + c = createCommand("UNSUSPEND", do_unsuspend, is_services_admin, -1, -1, + -1, NICK_SERVADMIN_HELP_UNSUSPEND, + NICK_SERVADMIN_HELP_UNSUSPEND); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_NickServ, u, NICK_HELP_CMD_SUSPEND); + notice_lang(s_NickServ, u, NICK_HELP_CMD_UNSUSPEND); + } +} + +/** + * The /ns suspend command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_suspend(User * u) +{ + NickAlias *na, *na2; + char *nick = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + int i; + + if (!nick || !reason) { + syntax_error(s_NickServ, u, "SUSPEND", NICK_SUSPEND_SYNTAX); + return MOD_CONT; + } + + if (readonly) { + notice_lang(s_NickServ, u, READ_ONLY_MODE); + return MOD_CONT; + } + + if ((na = findnick(nick)) == NULL) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + return MOD_CONT; + } + + if (NSSecureAdmins && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (na) { + na->nc->flags |= NI_SUSPENDED; + na->nc->flags |= NI_SECURE; + na->nc->flags &= ~(NI_KILLPROTECT | NI_KILL_QUICK | NI_KILL_IMMED); + + for (i = 0; i < na->nc->aliases.count; i++) { + na2 = na->nc->aliases.list[i]; + if (na2->nc == na->nc) { + na2->status &= ~(NS_IDENTIFIED | NS_RECOGNIZED); + na2->last_quit = sstrdup(reason); + } + } + + if (WallForbid) + anope_cmd_global(s_NickServ, "\2%s\2 used SUSPEND on \2%s\2", + u->nick, nick); + + alog("%s: %s set SUSPEND for nick %s", s_NickServ, u->nick, nick); + notice_lang(s_NickServ, u, NICK_SUSPEND_SUCCEEDED, nick); + send_event(EVENT_NICK_SUSPENDED, 1, nick); + + } else { + + alog("%s: Valid SUSPEND for %s by %s failed", s_NickServ, nick, + u->nick); + notice_lang(s_NickServ, u, NICK_SUSPEND_FAILED, nick); + + } + return MOD_CONT; +} + +/*************************************************************************/ + +int do_unsuspend(User * u) +{ + NickAlias *na; + char *nick = strtok(NULL, " "); + + if (!nick) { + syntax_error(s_NickServ, u, "UNSUSPEND", NICK_UNSUSPEND_SYNTAX); + return MOD_CONT; + } + + if (readonly) { + notice_lang(s_NickServ, u, READ_ONLY_MODE); + return MOD_CONT; + } + + if ((na = findnick(nick)) == NULL) { + notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, na->nick); + return MOD_CONT; + } + if (NSSecureAdmins && nick_is_services_admin(na->nc) + && !is_services_root(u)) { + notice_lang(s_NickServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (na) { + na->nc->flags &= ~NI_SUSPENDED; + + if (WallForbid) + anope_cmd_global(s_NickServ, "\2%s\2 used UNSUSPEND on \2%s\2", + u->nick, nick); + + alog("%s: %s set UNSUSPEND for nick %s", s_NickServ, u->nick, + nick); + notice_lang(s_NickServ, u, NICK_UNSUSPEND_SUCCEEDED, nick); + send_event(EVENT_NICK_UNSUSPEND, 1, nick); + + } else { + + alog("%s: Valid UNSUSPEND for %s by %s failed", s_NickServ, nick, + u->nick); + notice_lang(s_NickServ, u, NICK_UNSUSPEND_FAILED, nick); + + } + + return MOD_CONT; + +} diff --git a/src/core/ns_update.c b/src/core/ns_update.c new file mode 100644 index 000000000..0ec8b176a --- /dev/null +++ b/src/core/ns_update.c @@ -0,0 +1,90 @@ +/* NickServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_nickupdate(User * u); +void myNickServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("UPDATE", do_nickupdate, NULL, NICK_HELP_UPDATE, -1, + -1, -1, -1); + moduleAddCommand(NICKSERV, c, MOD_UNIQUE); + + moduleSetNickHelp(myNickServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /ns help output. + * @param u The user who is requesting help + **/ +void myNickServHelp(User * u) +{ + notice_lang(s_NickServ, u, NICK_HELP_CMD_UPDATE); +} + +/** + * The /ns update command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_nickupdate(User * u) +{ + NickAlias *na; + + if (!nick_identified(u)) { + notice_lang(s_NickServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ); + } else { + na = u->na; + if (NSModeOnID) + do_setmodes(u); + check_memos(u); + if (na->last_realname) + free(na->last_realname); + na->last_realname = sstrdup(u->realname); + na->status |= NS_IDENTIFIED; + na->last_seen = time(NULL); + if (ircd->vhost) { + do_on_id(u); + } + notice_lang(s_NickServ, u, NICK_UPDATE_SUCCESS, s_NickServ); + } + return MOD_CONT; +} diff --git a/src/core/os_admin.c b/src/core/os_admin.c new file mode 100644 index 000000000..56df4b195 --- /dev/null +++ b/src/core/os_admin.c @@ -0,0 +1,250 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_admin(User * u); +int admin_list_callback(SList * slist, int number, void *item, + va_list args); +int admin_list(int number, NickCore * nc, User * u, int *sent_header); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("ADMIN", do_admin, is_oper, OPER_HELP_ADMIN, -1, -1, + -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_ADMIN); + } +} + +/** + * The /os admin command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_admin(User * u) +{ + char *cmd = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + NickAlias *na; + int res = 0; + + if (skeleton) { + notice_lang(s_OperServ, u, OPER_ADMIN_SKELETON); + return MOD_CONT; + } + + if (!cmd || (!nick && stricmp(cmd, "LIST") && stricmp(cmd, "CLEAR"))) { + syntax_error(s_OperServ, u, "ADMIN", OPER_ADMIN_SYNTAX); + } else if (!stricmp(cmd, "ADD")) { + if (!is_services_root(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (!(na = findnick(nick))) { + notice_lang(s_OperServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_OperServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + if (na->nc->flags & NI_SERVICES_ADMIN + || slist_indexof(&servadmins, na->nc) != -1) { + notice_lang(s_OperServ, u, OPER_ADMIN_EXISTS, nick); + return MOD_CONT; + } + + res = slist_add(&servadmins, na->nc); + if (res == -2) { + notice_lang(s_OperServ, u, OPER_ADMIN_REACHED_LIMIT, nick); + return MOD_CONT; + } else { + if (na->nc->flags & NI_SERVICES_OPER + && (res = slist_indexof(&servopers, na->nc)) != -1) { + slist_delete(&servopers, res); + na->nc->flags |= NI_SERVICES_ADMIN; + notice_lang(s_OperServ, u, OPER_ADMIN_MOVED, nick); + } else { + na->nc->flags |= NI_SERVICES_ADMIN; + notice_lang(s_OperServ, u, OPER_ADMIN_ADDED, nick); + } + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + } else if (!stricmp(cmd, "DEL")) { + if (!is_services_root(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (servadmins.count == 0) { + notice_lang(s_OperServ, u, OPER_ADMIN_LIST_EMPTY); + return MOD_CONT; + } + + if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { + /* Deleting a range */ + res = slist_delete_range(&servadmins, nick, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_ADMIN_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_ADMIN_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_ADMIN_DELETED_SEVERAL, + res); + } + } else { + if (!(na = findnick(nick))) { + notice_lang(s_OperServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_OperServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + if (!(na->nc->flags & NI_SERVICES_ADMIN) + || (res = slist_indexof(&servadmins, na->nc)) == -1) { + notice_lang(s_OperServ, u, OPER_ADMIN_NOT_FOUND, nick); + return MOD_CONT; + } + + slist_delete(&servadmins, res); + notice_lang(s_OperServ, u, OPER_ADMIN_DELETED, nick); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + } else if (!stricmp(cmd, "LIST")) { + int sent_header = 0; + + if (servadmins.count == 0) { + notice_lang(s_OperServ, u, OPER_ADMIN_LIST_EMPTY); + return MOD_CONT; + } + + if (!nick || (isdigit(*nick) + && strspn(nick, "1234567890,-") == strlen(nick))) { + res = + slist_enum(&servadmins, nick, &admin_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_ADMIN_NO_MATCH); + return MOD_CONT; + } else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Admin"); + } + } else { + int i; + + for (i = 0; i < servadmins.count; i++) + if (!stricmp + (nick, ((NickCore *) servadmins.list[i])->display) + || match_wild_nocase(nick, + ((NickCore *) servadmins. + list[i])->display)) + admin_list(i + 1, servadmins.list[i], u, &sent_header); + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_ADMIN_NO_MATCH); + else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Admin"); + } + } + } else if (!stricmp(cmd, "CLEAR")) { + if (!is_services_root(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (servadmins.count == 0) { + notice_lang(s_OperServ, u, OPER_ADMIN_LIST_EMPTY); + return MOD_CONT; + } + + slist_clear(&servadmins, 1); + notice_lang(s_OperServ, u, OPER_ADMIN_CLEAR); + } else { + syntax_error(s_OperServ, u, "ADMIN", OPER_ADMIN_SYNTAX); + } + return MOD_CONT; +} + +int admin_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return admin_list(number, item, u, sent_header); +} + +int admin_list(int number, NickCore * nc, User * u, int *sent_header) +{ + if (!nc) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_ADMIN_LIST_HEADER); + *sent_header = 1; + } + + notice_lang(s_OperServ, u, OPER_ADMIN_LIST_FORMAT, number, + nc->display); + return 1; +} diff --git a/src/core/os_akill.c b/src/core/os_akill.c new file mode 100644 index 000000000..97a974e7f --- /dev/null +++ b/src/core/os_akill.c @@ -0,0 +1,378 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_akill(User * u); +int akill_view_callback(SList * slist, int number, void *item, + va_list args); +int akill_view(int number, Akill * ak, User * u, int *sent_header); +int akill_list_callback(SList * slist, int number, void *item, + va_list args); +int akill_list(int number, Akill * ak, User * u, int *sent_header); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("AKILL", do_akill, is_services_oper, OPER_HELP_AKILL, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_AKILL); + } +} + +/** + * The /os command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +/* Manage the AKILL list. */ + +int do_akill(User * u) +{ + char *cmd = strtok(NULL, " "); + char breason[BUFSIZE]; + + if (!cmd) + cmd = ""; + + if (!stricmp(cmd, "ADD")) { + int deleted = 0; + char *expiry, *mask, *reason; + time_t expires; + + mask = strtok(NULL, " "); + if (mask && *mask == '+') { + expiry = mask; + mask = strtok(NULL, " "); + } else { + expiry = NULL; + } + + expires = expiry ? dotime(expiry) : AutokillExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (expiry && isdigit(expiry[strlen(expiry) - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires != 0 && expires < 60) { + notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); + return MOD_CONT; + } else if (expires > 0) { + expires += time(NULL); + } + + if (mask && (reason = strtok(NULL, ""))) { + /* We first do some sanity check on the proposed mask. */ + if (strchr(mask, '!')) { + notice_lang(s_OperServ, u, OPER_AKILL_NO_NICK); + return MOD_CONT; + } + + if (!strchr(mask, '@')) { + notice_lang(s_OperServ, u, BAD_USERHOST_MASK); + return MOD_CONT; + } + + if (mask && strspn(mask, "~@.*?") == strlen(mask)) { + notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); + return MOD_CONT; + } + + /** + * Changed sprintf() to snprintf()and increased the size of + * breason to match bufsize + * -Rob + **/ + if (AddAkiller) { + snprintf(breason, sizeof(breason), "[%s] %s", u->nick, + reason); + reason = sstrdup(breason); + } + + deleted = add_akill(u, mask, u->nick, expires, reason); + if (deleted < 0) + return MOD_CONT; + else if (deleted) + notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL, + deleted); + notice_lang(s_OperServ, u, OPER_AKILL_ADDED, mask); + + if (WallOSAkill) { + char buf[128]; + + if (!expires) { + strcpy(buf, "does not expire"); + } else { + int wall_expiry = expires - time(NULL); + char *s = NULL; + + if (wall_expiry >= 86400) { + wall_expiry /= 86400; + s = "day"; + } else if (wall_expiry >= 3600) { + wall_expiry /= 3600; + s = "hour"; + } else if (wall_expiry >= 60) { + wall_expiry /= 60; + s = "minute"; + } + + snprintf(buf, sizeof(buf), "expires in %d %s%s", + wall_expiry, s, + (wall_expiry == 1) ? "" : "s"); + } + + anope_cmd_global(s_OperServ, + "%s added an AKILL for %s (%s) (%s)", + u->nick, mask, reason, buf); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else { + syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); + } + + } else if (!stricmp(cmd, "DEL")) { + + char *mask; + int res = 0; + + mask = strtok(NULL, " "); + + if (!mask) { + syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); + return MOD_CONT; + } + + if (akills.count == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); + return MOD_CONT; + } + + if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { + /* Deleting a range */ + res = slist_delete_range(&akills, mask, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_AKILL_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL, + res); + } + } else { + if ((res = slist_indexof(&akills, mask)) == -1) { + notice_lang(s_OperServ, u, OPER_AKILL_NOT_FOUND, mask); + return MOD_CONT; + } + + slist_delete(&akills, res); + notice_lang(s_OperServ, u, OPER_AKILL_DELETED, mask); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else if (!stricmp(cmd, "LIST")) { + char *mask; + int res, sent_header = 0; + + if (akills.count == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, " "); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&akills, mask, &akill_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); + return MOD_CONT; + } else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill"); + } + } else { + int i; + char amask[BUFSIZE]; + + for (i = 0; i < akills.count; i++) { + snprintf(amask, sizeof(amask), "%s@%s", + ((Akill *) akills.list[i])->user, + ((Akill *) akills.list[i])->host); + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + akill_list(i + 1, akills.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); + else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill"); + } + } + } else if (!stricmp(cmd, "VIEW")) { + char *mask; + int res, sent_header = 0; + + if (akills.count == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, " "); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&akills, mask, &akill_view_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char amask[BUFSIZE]; + + for (i = 0; i < akills.count; i++) { + snprintf(amask, sizeof(amask), "%s@%s", + ((Akill *) akills.list[i])->user, + ((Akill *) akills.list[i])->host); + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + akill_view(i + 1, akills.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH); + } + } else if (!stricmp(cmd, "CLEAR")) { + slist_clear(&akills, 1); + notice_lang(s_OperServ, u, OPER_AKILL_CLEAR); + } else { + syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX); + } + return MOD_CONT; +} + +int akill_view(int number, Akill * ak, User * u, int *sent_header) +{ + char mask[BUFSIZE]; + char timebuf[32], expirebuf[256]; + struct tm tm; + + if (!ak) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_AKILL_VIEW_HEADER); + *sent_header = 1; + } + + snprintf(mask, sizeof(mask), "%s@%s", ak->user, ak->host); + tm = *localtime(&ak->seton); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, + &tm); + expire_left(u->na, expirebuf, sizeof(expirebuf), ak->expires); + notice_lang(s_OperServ, u, OPER_AKILL_VIEW_FORMAT, number, mask, + ak->by, timebuf, expirebuf, ak->reason); + + return 1; +} + +/* Lists an AKILL entry, prefixing it with the header if needed */ + +int akill_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return akill_list(number, item, u, sent_header); +} + +/* Callback for enumeration purposes */ + +int akill_view_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return akill_view(number, item, u, sent_header); +} + +/* Lists an AKILL entry, prefixing it with the header if needed */ +int akill_list(int number, Akill * ak, User * u, int *sent_header) +{ + char mask[BUFSIZE]; + + if (!ak) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_AKILL_LIST_HEADER); + *sent_header = 1; + } + + snprintf(mask, sizeof(mask), "%s@%s", ak->user, ak->host); + notice_lang(s_OperServ, u, OPER_AKILL_LIST_FORMAT, number, mask, + ak->reason); + + return 1; +} diff --git a/src/core/os_chankill.c b/src/core/os_chankill.c new file mode 100644 index 000000000..c391390e0 --- /dev/null +++ b/src/core/os_chankill.c @@ -0,0 +1,130 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_chankill(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("CHANKILL", do_chankill, is_services_admin, + OPER_HELP_CHANKILL, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_CHANKILL); + } +} + +/** + * ChanKill - Akill an entire channel (got botnet?) + * + * /msg OperServ ChanKill +expire #channel reason + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + * + **/ +int do_chankill(User * u) +{ + char *expiry, *channel, *reason; + time_t expires; + char breason[BUFSIZE]; + char mask[USERMAX + HOSTMAX + 2]; + struct c_userlist *cu, *next; + Channel *c; + + channel = strtok(NULL, " "); + if (channel && *channel == '+') { + expiry = channel; + channel = strtok(NULL, " "); + } else { + expiry = NULL; + } + + expires = expiry ? dotime(expiry) : ChankillExpiry; + if (expiry && isdigit(expiry[strlen(expiry) - 1])) + expires *= 86400; + if (expires != 0 && expires < 60) { + notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); + return MOD_CONT; + } else if (expires > 0) { + expires += time(NULL); + } + + if (channel && (reason = strtok(NULL, ""))) { + + if (AddAkiller) { + snprintf(breason, sizeof(breason), "[%s] %s", u->nick, reason); + reason = sstrdup(breason); + } + + if ((c = findchan(channel))) { + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (is_oper(cu->user)) { + continue; + } + strncpy(mask, "*@", 3); /* Use *@" for the akill's, */ + strncat(mask, cu->user->host, HOSTMAX); + add_akill(NULL, mask, s_OperServ, expires, reason); + check_akill(cu->user->nick, cu->user->username, + cu->user->host, NULL, NULL); + } + if (WallOSAkill) { + anope_cmd_global(s_OperServ, "%s used CHANKILL on %s (%s)", + u->nick, channel, reason); + } + } else { + notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, channel); + } + } else { + syntax_error(s_OperServ, u, "CHANKILL", OPER_CHANKILL_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/os_chanlist.c b/src/core/os_chanlist.c new file mode 100644 index 000000000..6a25c3bc9 --- /dev/null +++ b/src/core/os_chanlist.c @@ -0,0 +1,116 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_chanlist(User * u); +void myOperServHelp(User * u); +extern MDE int anope_get_private_mode(); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("CHANLIST", do_chanlist, is_services_admin, + OPER_HELP_CHANLIST, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_CHANLIST); + } +} + +/** + * The /os chanlist command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_chanlist(User * u) +{ + char *pattern = strtok(NULL, " "); + char *opt = strtok(NULL, " "); + + int modes = 0; + User *u2; + + if (opt && !stricmp(opt, "SECRET")) + modes |= (anope_get_secret_mode() | anope_get_private_mode()); + + if (pattern && (u2 = finduser(pattern))) { + struct u_chanlist *uc; + + notice_lang(s_OperServ, u, OPER_CHANLIST_HEADER_USER, u2->nick); + + for (uc = u2->chans; uc; uc = uc->next) { + if (modes && !(uc->chan->mode & modes)) + continue; + notice_lang(s_OperServ, u, OPER_CHANLIST_RECORD, + uc->chan->name, uc->chan->usercount, + chan_get_modes(uc->chan, 1, 1), + (uc->chan->topic ? uc->chan->topic : "")); + } + } else { + int i; + Channel *c; + + notice_lang(s_OperServ, u, OPER_CHANLIST_HEADER); + + for (i = 0; i < 1024; i++) { + for (c = chanlist[i]; c; c = c->next) { + if (pattern && !match_wild_nocase(pattern, c->name)) + continue; + if (modes && !(c->mode & modes)) + continue; + notice_lang(s_OperServ, u, OPER_CHANLIST_RECORD, c->name, + c->usercount, chan_get_modes(c, 1, 1), + (c->topic ? c->topic : "")); + } + } + } + + notice_lang(s_OperServ, u, OPER_CHANLIST_END); + return MOD_CONT; +} diff --git a/src/core/os_clearmodes.c b/src/core/os_clearmodes.c new file mode 100644 index 000000000..9ec37a421 --- /dev/null +++ b/src/core/os_clearmodes.c @@ -0,0 +1,356 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_clearmodes(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("CLEARMODES", do_clearmodes, is_services_oper, + OPER_HELP_CLEARMODES, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_CLEARMODES); + } +} + +/** + * The /os clearmodes command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_clearmodes(User * u) +{ + char *s; + int i; + char *argv[2]; + char *chan = strtok(NULL, " "); + Channel *c; + int all = 0; + int count; /* For saving ban info */ + char **bans; /* For saving ban info */ + int exceptcount; /* For saving except info */ + char **excepts; /* For saving except info */ + int invitecount; /* For saving invite info */ + char **invites; /* For saving invite info */ + struct c_userlist *cu, *next; + + if (!chan) { + syntax_error(s_OperServ, u, "CLEARMODES", OPER_CLEARMODES_SYNTAX); + return MOD_CONT; + } else if (!(c = findchan(chan))) { + notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, chan); + return MOD_CONT; + } else if (c->bouncy_modes) { + notice_lang(s_OperServ, u, OPER_BOUNCY_MODES_U_LINE); + return MOD_CONT; + } else { + s = strtok(NULL, " "); + if (s) { + if (stricmp(s, "ALL") == 0) { + all = 1; + } else { + syntax_error(s_OperServ, u, "CLEARMODES", + OPER_CLEARMODES_SYNTAX); + return MOD_CONT; + } + } + + if (WallOSClearmodes) { + anope_cmd_global(s_OperServ, "%s used CLEARMODES%s on %s", + u->nick, all ? " ALL" : "", chan); + } + if (all) { + /* Clear mode +o */ + if (ircd->svsmode_ucmode) { + anope_cmd_svsmode_chan(c->name, "-o", NULL); + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_OP)) { + continue; + } + argv[0] = sstrdup("-o"); + argv[1] = cu->user->nick; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } else { + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_OP)) + continue; + argv[0] = sstrdup("-o"); + argv[1] = cu->user->nick; + anope_cmd_mode(s_OperServ, c->name, "-o %s", + cu->user->nick); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } + + if (ircd->svsmode_ucmode) { + anope_cmd_svsmode_chan(c->name, "-v", NULL); + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_VOICE)) { + continue; + } + argv[0] = sstrdup("-v"); + argv[1] = cu->user->nick; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } else { + /* Clear mode +v */ + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_VOICE)) + continue; + argv[0] = sstrdup("-v"); + argv[1] = sstrdup(cu->user->nick); + anope_cmd_mode(s_OperServ, c->name, "-v %s", + cu->user->nick); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } + + /* Clear mode +h */ + if (ircd->svsmode_ucmode && ircd->halfop) { + anope_cmd_svsmode_chan(c->name, "-h", NULL); + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_HALFOP)) { + continue; + } + argv[0] = sstrdup("-h"); + argv[1] = cu->user->nick; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } else { + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_HALFOP)) + continue; + argv[0] = sstrdup("-h"); + argv[1] = sstrdup(cu->user->nick); + anope_cmd_mode(s_OperServ, c->name, "-h %s", + cu->user->nick); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } + /* Clear mode Owners */ + if (ircd->svsmode_ucmode && ircd->owner) { + anope_cmd_svsmode_chan(c->name, ircd->ownerunset, NULL); + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_HALFOP)) { + continue; + } + argv[0] = sstrdup(ircd->ownerunset); + argv[1] = cu->user->nick; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } else { + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_OWNER)) + continue; + argv[0] = sstrdup(ircd->ownerunset); + argv[1] = sstrdup(cu->user->nick); + anope_cmd_mode(s_OperServ, c->name, "%s %s", + ircd->ownerunset, cu->user->nick); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } + /* Clear mode protected or admins */ + if (ircd->svsmode_ucmode && (ircd->protect || ircd->admin)) { + + anope_cmd_svsmode_chan(c->name, ircd->adminunset, NULL); + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_HALFOP)) { + continue; + } + argv[0] = sstrdup(ircd->adminunset); + argv[1] = cu->user->nick; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } else { + for (cu = c->users; cu; cu = next) { + next = cu->next; + if (!chan_has_user_status(c, cu->user, CUS_PROTECT)) + continue; + argv[0] = sstrdup(ircd->adminunset); + argv[1] = sstrdup(cu->user->nick); + anope_cmd_mode(s_OperServ, c->name, "%s %s", + ircd->adminunset, cu->user->nick); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + } + + + } + + if (c->mode) { + /* Clear modes the bulk of the modes */ + anope_cmd_mode(s_OperServ, c->name, "%s", ircd->modestoremove); + argv[0] = sstrdup(ircd->modestoremove); + chan_set_modes(s_OperServ, c, 1, argv, 0); + free(argv[0]); + + /* to prevent the internals from complaining send -k, -L, -f by themselves if we need + to send them - TSL */ + if (c->key) { + anope_cmd_mode(s_OperServ, c->name, "-k %s", c->key); + argv[0] = sstrdup("-k"); + argv[1] = c->key; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + if (ircd->Lmode && c->redirect) { + anope_cmd_mode(s_OperServ, c->name, "-L %s", c->redirect); + argv[0] = sstrdup("-L"); + argv[1] = c->redirect; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } + if (ircd->fmode && c->flood) { + if (flood_mode_char_remove) { + anope_cmd_mode(s_OperServ, c->name, "%s %s", + flood_mode_char_remove, c->flood); + argv[0] = sstrdup(flood_mode_char_remove); + argv[1] = c->flood; + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[0]); + } else { + if (debug) { + alog("debug: flood_mode_char_remove was not set unable to remove flood/throttle modes"); + } + } + } + } + + /* Clear bans */ + count = c->bancount; + bans = scalloc(sizeof(char *) * count, 1); + + for (i = 0; i < count; i++) + bans[i] = sstrdup(c->bans[i]); + + for (i = 0; i < count; i++) { + argv[0] = sstrdup("-b"); + argv[1] = bans[i]; + anope_cmd_mode(s_OperServ, c->name, "-b %s", argv[1]); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[1]); + free(argv[0]); + } + + free(bans); + + excepts = NULL; + + if (ircd->except) { + /* Clear excepts */ + exceptcount = c->exceptcount; + excepts = scalloc(sizeof(char *) * exceptcount, 1); + + for (i = 0; i < exceptcount; i++) + excepts[i] = sstrdup(c->excepts[i]); + + for (i = 0; i < exceptcount; i++) { + argv[0] = sstrdup("-e"); + argv[1] = excepts[i]; + anope_cmd_mode(s_OperServ, c->name, "-e %s", argv[1]); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[1]); + free(argv[0]); + } + if (excepts) { + free(excepts); + } + } + + if (ircd->invitemode) { + /* Clear invites */ + invitecount = c->invitecount; + invites = scalloc(sizeof(char *) * invitecount, 1); + + for (i = 0; i < invitecount; i++) + invites[i] = sstrdup(c->invite[i]); + + for (i = 0; i < invitecount; i++) { + argv[0] = sstrdup("-I"); + argv[1] = excepts[i]; + anope_cmd_mode(s_OperServ, c->name, "-I %s", argv[1]); + chan_set_modes(s_OperServ, c, 2, argv, 0); + free(argv[1]); + free(argv[0]); + } + + free(invites); + } + + } + + if (all) { + notice_lang(s_OperServ, u, OPER_CLEARMODES_ALL_DONE, chan); + } else { + notice_lang(s_OperServ, u, OPER_CLEARMODES_DONE, chan); + } + return MOD_CONT; +} diff --git a/src/core/os_defcon.c b/src/core/os_defcon.c new file mode 100644 index 000000000..3517f32d3 --- /dev/null +++ b/src/core/os_defcon.c @@ -0,0 +1,167 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +extern MDE time_t DefContimer; +extern MDE void runDefCon(void); +int do_defcon(User * u); +void defcon_sendlvls(User * u); + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("DEFCON", do_defcon, is_services_admin, + OPER_HELP_DEFCON, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_DEFCON); + } +} + +/** + * Defcon - A method of impelemting various stages of securty, the hope is this will help serives + * protect a network during an attack, allowing admins to choose the precautions taken at each + * level. + * + * /msg OperServ DefCon [level] + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + * + **/ +int do_defcon(User * u) +{ + char *lvl = strtok(NULL, " "); + int newLevel = 0; + char *langglobal; + langglobal = getstring(NULL, DEFCON_GLOBAL); + + if (!DefConLevel) { /* If we dont have a .conf setting! */ + notice_lang(s_OperServ, u, OPER_DEFCON_NO_CONF); + return MOD_CONT; + } + + if (!lvl) { + notice_lang(s_OperServ, u, OPER_DEFCON_CHANGED, DefConLevel); + defcon_sendlvls(u); + return MOD_CONT; + } + newLevel = atoi(lvl); + if (newLevel < 1 || newLevel > 5) { + notice_lang(s_OperServ, u, OPER_DEFCON_SYNTAX); + return MOD_CONT; + } + DefConLevel = newLevel; + send_event(EVENT_DEFCON_LEVEL, 1, lvl); + DefContimer = time(NULL); + notice_lang(s_OperServ, u, OPER_DEFCON_CHANGED, DefConLevel); + defcon_sendlvls(u); + alog("Defcon level changed to %d by Oper %s", newLevel, u->nick); + anope_cmd_global(s_OperServ, getstring2(NULL, OPER_DEFCON_WALL), + u->nick, newLevel); + /* Global notice the user what is happening. Also any Message that + the Admin would like to add. Set in config file. */ + if (GlobalOnDefcon) { + if ((DefConLevel == 5) && (DefConOffMessage)) { + oper_global(NULL, "%s", DefConOffMessage); + } else { + oper_global(NULL, langglobal, DefConLevel); + } + } + if (GlobalOnDefconMore) { + if ((DefConOffMessage) && DefConLevel == 5) { + } else { + oper_global(NULL, "%s", DefconMessage); + } + } + /* Run any defcon functions, e.g. FORCE CHAN MODE */ + runDefCon(); + return MOD_CONT; +} + + + +/** + * Send a message to the oper about which precautions are "active" for this level + **/ +void defcon_sendlvls(User * u) +{ + if (checkDefCon(DEFCON_NO_NEW_CHANNELS)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_CHANNELS); + } + if (checkDefCon(DEFCON_NO_NEW_NICKS)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_NICKS); + } + if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_MLOCK_CHANGE); + } + if (checkDefCon(DEFCON_FORCE_CHAN_MODES) && (DefConChanModes)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_FORCE_CHAN_MODES, + DefConChanModes); + } + if (checkDefCon(DEFCON_REDUCE_SESSION)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_REDUCE_SESSION, + DefConSessionLimit); + } + if (checkDefCon(DEFCON_NO_NEW_CLIENTS)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_CLIENTS); + } + if (checkDefCon(DEFCON_OPER_ONLY)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_OPER_ONLY); + } + if (checkDefCon(DEFCON_SILENT_OPER_ONLY)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_SILENT_OPER_ONLY); + } + if (checkDefCon(DEFCON_AKILL_NEW_CLIENTS)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_AKILL_NEW_CLIENTS); + } + if (checkDefCon(DEFCON_NO_NEW_MEMOS)) { + notice_lang(s_OperServ, u, OPER_HELP_DEFCON_NO_NEW_MEMOS); + } +} diff --git a/src/core/os_global.c b/src/core/os_global.c new file mode 100644 index 000000000..37ddcca78 --- /dev/null +++ b/src/core/os_global.c @@ -0,0 +1,81 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_global(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("GLOBAL", do_global, is_services_oper, + OPER_HELP_GLOBAL, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_GLOBAL); + } +} + +/** + * The /os global command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_global(User * u) +{ + char *msg = strtok(NULL, ""); + + if (!msg) { + syntax_error(s_OperServ, u, "GLOBAL", OPER_GLOBAL_SYNTAX); + return MOD_CONT; + } + if (WallOSGlobal) + anope_cmd_global(s_OperServ, "\2%s\2 just used GLOBAL command.", + u->nick); + oper_global(u->nick, "%s", msg); + return MOD_CONT; +} diff --git a/src/core/os_help.c b/src/core/os_help.c new file mode 100644 index 000000000..481e3e424 --- /dev/null +++ b/src/core/os_help.c @@ -0,0 +1,66 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_help(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("HELP", do_help, is_oper, -1, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + + +/** + * The /os help command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_help(User * u) +{ + const char *cmd = strtok(NULL, ""); + + if (!cmd) { + notice_help(s_OperServ, u, OPER_HELP); + moduleDisplayHelp(5, u); + notice_help(s_OperServ, u, OPER_HELP_LOGGED); + } else { + mod_help_cmd(s_OperServ, u, OPERSERV, cmd); + } + return MOD_CONT; +} diff --git a/src/core/os_ignore.c b/src/core/os_ignore.c new file mode 100644 index 000000000..a4d73d649 --- /dev/null +++ b/src/core/os_ignore.c @@ -0,0 +1,200 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_ignorelist(User * u); +void myOperServHelp(User * u); +int do_ignoreuser(User * u); +int do_clearignore(User * u); +void delete_ignore(const char *nick); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("IGNORE", do_ignoreuser, is_services_admin, + OPER_HELP_IGNORE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_IGNORE); + } +} + +/** + * The /os ignore command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_ignoreuser(User * u) +{ + char *cmd = strtok(NULL, " "); + int t; + + if (!cmd) { + notice_lang(s_OperServ, u, OPER_IGNORE_SYNTAX); + return MOD_CONT; + } + + if (!stricmp(cmd, "ADD")) { + + char *time = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + char *rest = strtok(NULL, ""); + + if (!nick) { + notice_lang(s_OperServ, u, OPER_IGNORE_SYNTAX); + return MOD_CONT; + } else if (!time) { + notice_lang(s_OperServ, u, OPER_IGNORE_SYNTAX); + return MOD_CONT; + } else { + t = dotime(time); + rest = NULL; + + if (t <= -1) { + notice_lang(s_OperServ, u, OPER_IGNORE_VALID_TIME); + return MOD_CONT; + } else if (t == 0) { + t = 157248000; /* if 0 is given, we set time to 157248000 seconds == 5 years (let's hope the next restart will be before that time ;-)) */ + add_ignore(nick, t); + notice_lang(s_OperServ, u, OPER_IGNORE_PERM_DONE, nick); + } else { + add_ignore(nick, t); + notice_lang(s_OperServ, u, OPER_IGNORE_TIME_DONE, nick, + time); + } + } + } else if (!stricmp(cmd, "LIST")) { + do_ignorelist(u); + } + + else if (!stricmp(cmd, "DEL")) { + char *nick = strtok(NULL, " "); + if (!nick) { + notice_lang(s_OperServ, u, OPER_IGNORE_SYNTAX); + } else { + if (get_ignore(nick) == 0) { + notice_lang(s_OperServ, u, OPER_IGNORE_LIST_NOMATCH, nick); + return MOD_CONT; + } else { + delete_ignore(nick); + notice_lang(s_OperServ, u, OPER_IGNORE_DEL_DONE, nick); + } + } + } else if (!stricmp(cmd, "CLEAR")) { + do_clearignore(u); + + } else + notice_lang(s_OperServ, u, OPER_IGNORE_SYNTAX); + return MOD_CONT; +} + +/* shows the Services ignore list */ + +int do_ignorelist(User * u) +{ + int sent_header = 0; + IgnoreData *id; + int i; + + for (i = 0; i < 256; i++) { + for (id = ignore[i]; id; id = id->next) { + if (!sent_header) { + notice_lang(s_OperServ, u, OPER_IGNORE_LIST); + sent_header = 1; + } + notice_user(s_OperServ, u, "%s", id->who); + } + } + if (!sent_header) + notice_lang(s_OperServ, u, OPER_IGNORE_LIST_EMPTY); + return MOD_CONT; +} + +/* deletes a nick from the ignore list */ + +void delete_ignore(const char *nick) +{ + IgnoreData *ign, *prev; + IgnoreData **whichlist; + + if (!nick || !*nick) { + return; + } + + whichlist = &ignore[tolower(nick[0])]; + + for (ign = *whichlist, prev = NULL; ign; prev = ign, ign = ign->next) { + if (stricmp(ign->who, nick) == 0) + break; + } + if (prev) + prev->next = ign->next; + else + *whichlist = ign->next; + free(ign); + ign = NULL; +} + +/**************************************************************************/ +/* Cleares the Services ignore list */ + +int do_clearignore(User * u) +{ + IgnoreData *id = NULL, *next = NULL; + int i; + for (i = 0; i < 256; i++) { + for (id = ignore[i]; id; id = next) { + next = id->next; + free(id); + if (!next) { + ignore[i] = NULL; + } + } + } + notice_lang(s_OperServ, u, OPER_IGNORE_LIST_CLEARED); + return MOD_CONT; +} diff --git a/src/core/os_jupe.c b/src/core/os_jupe.c new file mode 100644 index 000000000..faaa55122 --- /dev/null +++ b/src/core/os_jupe.c @@ -0,0 +1,88 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_jupe(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("JUPE", do_jupe, is_services_admin, OPER_HELP_JUPE, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_JUPE); + } +} + +/** + * The /os jupe command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_jupe(User * u) +{ + char *jserver = strtok(NULL, " "); + char *reason = strtok(NULL, ""); + + if (!jserver) { + syntax_error(s_OperServ, u, "JUPE", OPER_JUPE_SYNTAX); + } else { + if (!isValidHost(jserver, 3)) { + notice_lang(s_OperServ, u, OPER_JUPE_HOST_ERROR); + } else { + anope_cmd_jupe(jserver, u->nick, reason); + + if (WallOSJupe) + anope_cmd_global(s_OperServ, "\2%s\2 used JUPE on \2%s\2", + u->nick, jserver); + } + } + return MOD_CONT; +} diff --git a/src/core/os_kick.c b/src/core/os_kick.c new file mode 100644 index 000000000..fa0edc440 --- /dev/null +++ b/src/core/os_kick.c @@ -0,0 +1,100 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_os_kick(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("KICK", do_os_kick, is_services_oper, OPER_HELP_KICK, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_KICK); + } +} + +/** + * The /os kick command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_os_kick(User * u) +{ + char *argv[3]; + char *chan, *nick, *s; + Channel *c; + + chan = strtok(NULL, " "); + nick = strtok(NULL, " "); + s = strtok(NULL, ""); + if (!chan || !nick || !s) { + syntax_error(s_OperServ, u, "KICK", OPER_KICK_SYNTAX); + return MOD_CONT; + } + if (!(c = findchan(chan))) { + notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (c->bouncy_modes) { + notice_lang(s_OperServ, u, OPER_BOUNCY_MODES_U_LINE); + return MOD_CONT; + } + anope_cmd_kick(s_OperServ, chan, nick, "%s (%s)", u->nick, s); + if (WallOSKick) + anope_cmd_global(s_OperServ, "%s used KICK on %s/%s", u->nick, + nick, chan); + argv[0] = sstrdup(chan); + argv[1] = sstrdup(nick); + argv[2] = sstrdup(s); + do_kick(s_OperServ, 3, argv); + free(argv[2]); + free(argv[1]); + free(argv[0]); + return MOD_CONT; +} diff --git a/src/core/os_killclones.c b/src/core/os_killclones.c new file mode 100644 index 000000000..8f1ac3cbc --- /dev/null +++ b/src/core/os_killclones.c @@ -0,0 +1,129 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_killclones(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("KILLCLONES", do_killclones, is_services_oper, + OPER_HELP_KILLCLONES, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_KILLCLONES); + } +} + +/** Kill all users matching a certain host. The host is obtained from the + * supplied nick. The raw hostmsk is not supplied with the command in an effort + * to prevent abuse and mistakes from being made - which might cause *.com to + * be killed. It also makes it very quick and simple to use - which is usually + * what you want when someone starts loading numerous clones. In addition to + * killing the clones, we add a temporary AKILL to prevent them from + * immediately reconnecting. + * Syntax: KILLCLONES nick + * -TheShadow (29 Mar 1999) + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_killclones(User * u) +{ + char *clonenick = strtok(NULL, " "); + int count = 0; + User *cloneuser, *user, *tempuser; + char *clonemask, *akillmask; + char killreason[NICKMAX + 32]; + char akillreason[] = "Temporary KILLCLONES akill."; + + if (!clonenick) { + notice_lang(s_OperServ, u, OPER_KILLCLONES_SYNTAX); + + } else if (!(cloneuser = finduser(clonenick))) { + notice_lang(s_OperServ, u, OPER_KILLCLONES_UNKNOWN_NICK, + clonenick); + + } else { + clonemask = smalloc(strlen(cloneuser->host) + 5); + sprintf(clonemask, "*!*@%s", cloneuser->host); + + akillmask = smalloc(strlen(cloneuser->host) + 3); + sprintf(akillmask, "*@%s", cloneuser->host); + + user = firstuser(); + while (user) { + if (match_usermask(clonemask, user) != 0) { + tempuser = nextuser(); + count++; + snprintf(killreason, sizeof(killreason), + "Cloning [%d]", count); + kill_user(NULL, user->nick, killreason); + user = tempuser; + } else { + user = nextuser(); + } + } + + add_akill(u, akillmask, u->nick, + time(NULL) + KillClonesAkillExpire, akillreason); + + anope_cmd_global(s_OperServ, + "\2%s\2 used KILLCLONES for \2%s\2 killing " + "\2%d\2 clones. A temporary AKILL has been added " + "for \2%s\2.", u->nick, clonemask, count, + akillmask); + + alog("%s: KILLCLONES: %d clone(s) matching %s killed.", + s_OperServ, count, clonemask); + + free(akillmask); + free(clonemask); + } + return MOD_CONT; +} diff --git a/src/core/os_logonnews.c b/src/core/os_logonnews.c new file mode 100644 index 000000000..31d482574 --- /dev/null +++ b/src/core/os_logonnews.c @@ -0,0 +1,65 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + /** + * For some unknown reason, do_logonnews is actaully defined in news.c + * we can look at moving it here later + **/ + c = createCommand("LOGONNEWS", do_logonnews, is_services_oper, + NEWS_HELP_LOGON, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_LOGONNEWS); + } +} diff --git a/src/core/os_mode.c b/src/core/os_mode.c new file mode 100644 index 000000000..b926d16a4 --- /dev/null +++ b/src/core/os_mode.c @@ -0,0 +1,101 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_os_mode(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("MODE", do_os_mode, is_services_oper, OPER_HELP_MODE, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_MODE); + } +} + +/** + * The /os mode command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_os_mode(User * u) +{ + int ac; + char **av; + char *chan = strtok(NULL, " "), *modes = strtok(NULL, ""); + Channel *c; + + if (!chan || !modes) { + syntax_error(s_OperServ, u, "MODE", OPER_MODE_SYNTAX); + return MOD_CONT; + } + + if (!(c = findchan(chan))) { + notice_lang(s_OperServ, u, CHAN_X_NOT_IN_USE, chan); + } else if (c->bouncy_modes) { + notice_lang(s_OperServ, u, OPER_BOUNCY_MODES_U_LINE); + return MOD_CONT; + } else if ((ircd->adminmode) && (!is_services_admin(u)) + && (c->mode & ircd->adminmode)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } else { + anope_cmd_mode(s_OperServ, chan, "%s", modes); + + ac = split_buf(modes, &av, 1); + chan_set_modes(s_OperServ, c, ac, av, -1); + + if (WallOSMode) + anope_cmd_global(s_OperServ, "%s used MODE %s on %s", u->nick, + modes, chan); + } + return MOD_CONT; +} diff --git a/src/core/os_modinfo.c b/src/core/os_modinfo.c new file mode 100644 index 000000000..c8bba7f92 --- /dev/null +++ b/src/core/os_modinfo.c @@ -0,0 +1,149 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_modinfo(User * u); +void myOperServHelp(User * u); +int showModuleMsgLoaded(MessageHash * msgList, char *mod_name, User * u); +int showModuleCmdLoaded(CommandHash * cmdList, char *mod_name, User * u); +extern MDE Module *findModule(char *name); + +extern MDE Module *mod_current_module; +extern MDE int mod_current_op; +extern MDE User *mod_current_user; +extern MDE ModuleHash *MODULE_HASH[MAX_CMD_HASH]; + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("MODINFO", do_modinfo, is_oper, -1, -1, -1, -1, + OPER_HELP_MODINFO); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_MODINFO); + } +} + +/** + * The /os command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_modinfo(User * u) +{ + char *file; + struct tm tm; + char timebuf[64]; + Module *m; + int idx = 0; + int display = 0; + + file = strtok(NULL, ""); + if (!file) { + syntax_error(s_OperServ, u, "MODINFO", OPER_MODULE_INFO_SYNTAX); + return MOD_CONT; + } + m = findModule(file); + if (m) { + tm = *localtime(&m->time); + strftime_lang(timebuf, sizeof(timebuf), u, + STRFTIME_DATE_TIME_FORMAT, &tm); + notice_lang(s_OperServ, u, OPER_MODULE_INFO_LIST, m->name, + m->version ? m->version : "?", + m->author ? m->author : "?", timebuf); + for (idx = 0; idx < MAX_CMD_HASH; idx++) { + display += showModuleCmdLoaded(HOSTSERV[idx], m->name, u); + display += showModuleCmdLoaded(OPERSERV[idx], m->name, u); + display += showModuleCmdLoaded(NICKSERV[idx], m->name, u); + display += showModuleCmdLoaded(CHANSERV[idx], m->name, u); + display += showModuleCmdLoaded(BOTSERV[idx], m->name, u); + display += showModuleCmdLoaded(MEMOSERV[idx], m->name, u); + display += showModuleCmdLoaded(HELPSERV[idx], m->name, u); + display += showModuleMsgLoaded(IRCD[idx], m->name, u); + + } + } + if (display == 0) { + notice_lang(s_OperServ, u, OPER_MODULE_NO_INFO, file); + } + return MOD_CONT; +} + +int showModuleCmdLoaded(CommandHash * cmdList, char *mod_name, User * u) +{ + Command *c; + CommandHash *current; + int display = 0; + + for (current = cmdList; current; current = current->next) { + for (c = current->c; c; c = c->next) { + if ((c->mod_name) && (stricmp(c->mod_name, mod_name) == 0)) { + notice_lang(s_OperServ, u, OPER_MODULE_CMD_LIST, + c->service, c->name); + display++; + } + } + } + return display; +} + +int showModuleMsgLoaded(MessageHash * msgList, char *mod_name, User * u) +{ + Message *msg; + MessageHash *mcurrent; + int display = 0; + for (mcurrent = msgList; mcurrent; mcurrent = mcurrent->next) { + for (msg = mcurrent->m; msg; msg = msg->next) { + if ((msg->mod_name) && (stricmp(msg->mod_name, mod_name) == 0)) { + notice_lang(s_OperServ, u, OPER_MODULE_MSG_LIST, + msg->name); + display++; + } + } + } + return display; +} diff --git a/src/core/os_modlist.c b/src/core/os_modlist.c new file mode 100644 index 000000000..2a56983ea --- /dev/null +++ b/src/core/os_modlist.c @@ -0,0 +1,182 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +extern MDE Module *mod_current_module; +extern MDE int mod_current_op; +extern MDE User *mod_current_user; +extern MDE ModuleHash *MODULE_HASH[MAX_CMD_HASH]; + +extern MDE Module *createModule(char *filename); + +int do_modlist(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("MODLIST", do_modlist, is_oper, -1, -1, -1, -1, + OPER_HELP_MODLIST); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_MODLIST); + } +} + +/** + * The /os modlist command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_modlist(User * u) +{ + int idx; + int count = 0; + int showCore = 0; + int showThird = 1; + int showProto = 1; + int showSupported = 1; + int showQA = 1; + + char *param; + ModuleHash *current = NULL; + + char core[] = "Core"; + char third[] = "3rd"; + char proto[] = "Protocol"; + char supported[] = "Supported"; + char qa[] = "QATested"; + + param = strtok(NULL, ""); + if (param) { + if (stricmp(param, core) == 0) { + showCore = 1; + showThird = 0; + showProto = 0; + showSupported = 0; + showQA = 0; + } else if (stricmp(param, third) == 0) { + showCore = 0; + showThird = 1; + showSupported = 0; + showQA = 0; + showProto = 0; + } else if (stricmp(param, proto) == 0) { + showCore = 0; + showThird = 0; + showProto = 1; + showSupported = 0; + showQA = 0; + } else if (stricmp(param, supported) == 0) { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 1; + showQA = 0; + } else if (stricmp(param, qa) == 0) { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 0; + showQA = 1; + } + } + + notice_lang(s_OperServ, u, OPER_MODULE_LIST_HEADER); + + for (idx = 0; idx != MAX_CMD_HASH; idx++) { + for (current = MODULE_HASH[idx]; current; current = current->next) { + switch (current->m->type) { + case CORE: + if (showCore) { + notice_lang(s_OperServ, u, OPER_MODULE_LIST, + current->name, current->m->version, core); + count++; + } + break; + case THIRD: + if (showThird) { + notice_lang(s_OperServ, u, OPER_MODULE_LIST, + current->name, current->m->version, third); + count++; + } + break; + case PROTOCOL: + if (showProto) { + notice_lang(s_OperServ, u, OPER_MODULE_LIST, + current->name, current->m->version, proto); + count++; + } + break; + case SUPPORTED: + if (showSupported) { + notice_lang(s_OperServ, u, OPER_MODULE_LIST, + current->name, current->m->version, + supported); + count++; + } + break; + case QATESTED: + if (showQA) { + notice_lang(s_OperServ, u, OPER_MODULE_LIST, + current->name, current->m->version, qa); + count++; + } + break; + } + + } + } + if (count == 0) { + notice_lang(s_OperServ, u, OPER_MODULE_NO_LIST); + } else { + notice_lang(s_OperServ, u, OPER_MODULE_LIST_FOOTER, count); + } + + return MOD_CONT; +} diff --git a/src/core/os_modload.c b/src/core/os_modload.c new file mode 100644 index 000000000..732d629f4 --- /dev/null +++ b/src/core/os_modload.c @@ -0,0 +1,96 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +extern MDE Module *mod_current_module; +extern MDE int mod_current_op; +extern MDE User *mod_current_user; +extern MDE ModuleHash *MODULE_HASH[MAX_CMD_HASH]; + +extern MDE Module *createModule(char *filename); + +int do_modload(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("MODLOAD", do_modload, is_services_root, -1, -1, -1, + -1, OPER_HELP_MODLOAD); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_root(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_MODLOAD); + } +} + +/** + * The /os modload command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_modload(User * u) +{ + char *name; + Module *m; + + name = strtok(NULL, ""); + if (!name) { + syntax_error(s_OperServ, u, "MODLOAD", OPER_MODULE_LOAD_SYNTAX); + return MOD_CONT; + } + m = findModule(name); + if (!m) { + m = createModule(name); + mod_current_module = m; + mod_current_user = u; + mod_current_op = 1; + } else { + notice_lang(s_OperServ, u, OPER_MODULE_LOAD_FAIL, name); + } + return MOD_CONT; +} diff --git a/src/core/os_modunload.c b/src/core/os_modunload.c new file mode 100644 index 000000000..315c7a7c4 --- /dev/null +++ b/src/core/os_modunload.c @@ -0,0 +1,95 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +extern MDE Module *mod_current_module; +extern MDE int mod_current_op; +extern MDE User *mod_current_user; +extern MDE ModuleHash *MODULE_HASH[MAX_CMD_HASH]; + +int do_modunload(User * u); + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("MODUNLOAD", do_modunload, is_services_root, -1, -1, + -1, -1, OPER_HELP_MODUNLOAD); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_root(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_MODUNLOAD); + } +} + +/** + * The /os modunload command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_modunload(User * u) +{ + char *name; + Module *m; + + name = strtok(NULL, ""); + if (!name) { + syntax_error(s_OperServ, u, "MODUNLOAD", + OPER_MODULE_UNLOAD_SYNTAX); + return MOD_CONT; + } + m = findModule(name); + if (m) { + mod_current_user = u; + mod_current_module = m; + mod_current_op = 2; + } else { + notice_lang(s_OperServ, u, OPER_MODULE_REMOVE_FAIL, name); + } + return MOD_CONT; +} diff --git a/src/core/os_noop.c b/src/core/os_noop.c new file mode 100644 index 000000000..774433a34 --- /dev/null +++ b/src/core/os_noop.c @@ -0,0 +1,106 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_noop(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("NOOP", do_noop, is_services_admin, OPER_HELP_NOOP, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_NOOP); + } +} + +/** + * The /os noop command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_noop(User * u) +{ + char *cmd = strtok(NULL, " "); + char *server = strtok(NULL, " "); + + if (!cmd || !server) { + syntax_error(s_OperServ, u, "NOOP", OPER_NOOP_SYNTAX); + } else if (!stricmp(cmd, "SET")) { + User *u2; + User *u3 = NULL; + char reason[NICKMAX + 32]; + + /* Remove the O:lines */ + anope_cmd_svsnoop(server, 1); + + snprintf(reason, sizeof(reason), "NOOP command used by %s", + u->nick); + if (WallOSNoOp) + anope_cmd_global(s_OperServ, "\2%s\2 used NOOP on \2%s\2", + u->nick, server); + notice_lang(s_OperServ, u, OPER_NOOP_SET, server); + + /* Kill all the IRCops of the server */ + for (u2 = firstuser(); u2; u2 = u3) { + u3 = nextuser(); + if ((u2) && is_oper(u2) && (u2->server->name) + && match_wild(server, u2->server->name)) { + kill_user(s_OperServ, u2->nick, reason); + } + } + } else if (!stricmp(cmd, "REVOKE")) { + anope_cmd_svsnoop(server, 0); + notice_lang(s_OperServ, u, OPER_NOOP_REVOKE, server); + } else { + syntax_error(s_OperServ, u, "NOOP", OPER_NOOP_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/os_oline.c b/src/core/os_oline.c new file mode 100644 index 000000000..39ae5ae49 --- /dev/null +++ b/src/core/os_oline.c @@ -0,0 +1,111 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" +int do_operoline(User * u); + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("OLINE", do_operoline, is_services_admin, + OPER_HELP_OLINE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + if (!ircd->omode) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u) && u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_OLINE); + } +} + +/** + * The /os oline command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_operoline(User * u) +{ + char *nick = strtok(NULL, " "); + char *flags = strtok(NULL, ""); + User *u2 = NULL; + + /* Only allow this if SuperAdmin is enabled */ + if (!u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_ONLY); + return MOD_CONT; + } + + if (!nick || !flags) { + syntax_error(s_OperServ, u, "OLINE", OPER_OLINE_SYNTAX); + return MOD_CONT; + } else { + u2 = finduser(nick); + +/* let's check whether the user is online */ + + if (!finduser(nick)) { + notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick); + } else if (u2 && flags[0] == '+') { + anope_cmd_svso(s_OperServ, nick, flags); + anope_cmd_mode(s_OperServ, nick, "+o"); + common_svsmode(u2, "+o", NULL); + notice_lang(s_OperServ, u2, OPER_OLINE_IRCOP); + notice_lang(s_OperServ, u, OPER_OLINE_SUCCESS, flags, nick); + anope_cmd_global(s_OperServ, "\2%s\2 used OLINE for %s", + u->nick, nick); + } else if (u2 && flags[0] == '-') { + anope_cmd_svso(s_OperServ, nick, flags); + notice_lang(s_OperServ, u, OPER_OLINE_SUCCESS, flags, nick); + anope_cmd_global(s_OperServ, "\2%s\2 used OLINE for %s", + u->nick, nick); + } else + syntax_error(s_OperServ, u, "OLINE", OPER_OLINE_SYNTAX); + } + return MOD_CONT; +} diff --git a/src/core/os_oper.c b/src/core/os_oper.c new file mode 100644 index 000000000..4df712036 --- /dev/null +++ b/src/core/os_oper.c @@ -0,0 +1,244 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_oper(User * u); +int oper_list_callback(SList * slist, int number, void *item, + va_list args); +int oper_list(int number, NickCore * nc, User * u, int *sent_header); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("OPER", do_oper, is_oper, OPER_HELP_OPER, -1, -1, -1, + -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_OPER); + } +} + +/** + * The /os oper command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_oper(User * u) +{ + char *cmd = strtok(NULL, " "); + char *nick = strtok(NULL, " "); + NickAlias *na; + int res = 0; + + if (skeleton) { + notice_lang(s_OperServ, u, OPER_OPER_SKELETON); + return MOD_CONT; + } + + if (!cmd || (!nick && stricmp(cmd, "LIST") && stricmp(cmd, "CLEAR"))) { + syntax_error(s_OperServ, u, "OPER", OPER_OPER_SYNTAX); + } else if (!stricmp(cmd, "ADD")) { + if (!is_services_admin(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (!(na = findnick(nick))) { + notice_lang(s_OperServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_OperServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + if (na->nc->flags & NI_SERVICES_OPER + || slist_indexof(&servopers, na->nc) != -1) { + notice_lang(s_OperServ, u, OPER_OPER_EXISTS, nick); + return MOD_CONT; + } + + res = slist_add(&servopers, na->nc); + if (res == -2) { + notice_lang(s_OperServ, u, OPER_OPER_REACHED_LIMIT, nick); + return MOD_CONT; + } else { + if (na->nc->flags & NI_SERVICES_ADMIN + && (res = slist_indexof(&servadmins, na->nc)) != -1) { + slist_delete(&servadmins, res); + na->nc->flags |= NI_SERVICES_OPER; + notice_lang(s_OperServ, u, OPER_OPER_MOVED, nick); + } else { + na->nc->flags |= NI_SERVICES_OPER; + notice_lang(s_OperServ, u, OPER_OPER_ADDED, nick); + } + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + } else if (!stricmp(cmd, "DEL")) { + if (!is_services_admin(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { + /* Deleting a range */ + res = slist_delete_range(&servopers, nick, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_OPER_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_OPER_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_OPER_DELETED_SEVERAL, res); + } + } else { + if (!(na = findnick(nick))) { + notice_lang(s_OperServ, u, NICK_X_NOT_REGISTERED, nick); + return MOD_CONT; + } + + if (na->status & NS_VERBOTEN) { + notice_lang(s_OperServ, u, NICK_X_FORBIDDEN, nick); + return MOD_CONT; + } + + if (!(na->nc->flags & NI_SERVICES_OPER) + || (res = slist_indexof(&servopers, na->nc)) == -1) { + notice_lang(s_OperServ, u, OPER_OPER_NOT_FOUND, nick); + return MOD_CONT; + } + + slist_delete(&servopers, res); + notice_lang(s_OperServ, u, OPER_OPER_DELETED, nick); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + } else if (!stricmp(cmd, "LIST")) { + int sent_header = 0; + + if (servopers.count == 0) { + notice_lang(s_OperServ, u, OPER_OPER_LIST_EMPTY); + return MOD_CONT; + } + + if (!nick || (isdigit(*nick) + && strspn(nick, "1234567890,-") == strlen(nick))) { + res = + slist_enum(&servopers, nick, &oper_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_OPER_NO_MATCH); + return MOD_CONT; + } else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Oper"); + } + } else { + int i; + + for (i = 0; i < servopers.count; i++) + if (!stricmp + (nick, ((NickCore *) servopers.list[i])->display) + || match_wild_nocase(nick, + ((NickCore *) servopers.list[i])-> + display)) + oper_list(i + 1, servopers.list[i], u, &sent_header); + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_OPER_NO_MATCH); + else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Oper"); + } + } + } else if (!stricmp(cmd, "CLEAR")) { + if (!is_services_admin(u)) { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + return MOD_CONT; + } + + if (servopers.count == 0) { + notice_lang(s_OperServ, u, OPER_OPER_LIST_EMPTY); + return MOD_CONT; + } + + slist_clear(&servopers, 1); + notice_lang(s_OperServ, u, OPER_OPER_CLEAR); + } else { + syntax_error(s_OperServ, u, "OPER", OPER_OPER_SYNTAX); + } + return MOD_CONT; +} + +/* Lists an oper entry, prefixing it with the header if needed */ + +int oper_list(int number, NickCore * nc, User * u, int *sent_header) +{ + if (!nc) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_OPER_LIST_HEADER); + *sent_header = 1; + } + + notice_lang(s_OperServ, u, OPER_OPER_LIST_FORMAT, number, nc->display); + return 1; +} + +/* Callback for enumeration purposes */ + +int oper_list_callback(SList * slist, int number, void *item, va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return oper_list(number, item, u, sent_header); +} diff --git a/src/core/os_opernews.c b/src/core/os_opernews.c new file mode 100644 index 000000000..706357893 --- /dev/null +++ b/src/core/os_opernews.c @@ -0,0 +1,65 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + /** + * For some unknown reason, do_opernews is actaully defined in news.c + * we can look at moving it here later + **/ + c = createCommand("OPERNEWS", do_opernews, is_services_oper, + NEWS_HELP_LOGON, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_OPERNEWS); + } +} diff --git a/src/core/os_quit.c b/src/core/os_quit.c new file mode 100644 index 000000000..6b7fe8f79 --- /dev/null +++ b/src/core/os_quit.c @@ -0,0 +1,82 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_os_quit(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("QUIT", do_os_quit, is_services_admin, + OPER_HELP_QUIT, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_QUIT); + } +} + +/** + * The /os quit command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_os_quit(User * u) +{ + quitmsg = calloc(28 + strlen(u->nick), 1); + if (!quitmsg) + quitmsg = "QUIT command received, but out of memory!"; + else + sprintf(quitmsg, "QUIT command received from %s", u->nick); + + if (GlobalOnCycle) { + oper_global(NULL, "%s", GlobalOnCycleMessage); + } + quitting = 1; + return MOD_CONT; +} diff --git a/src/core/os_randomnews.c b/src/core/os_randomnews.c new file mode 100644 index 000000000..cf5ab6b3a --- /dev/null +++ b/src/core/os_randomnews.c @@ -0,0 +1,65 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + /** + * For some unknown reason, do_randomnews is actaully defined in news.c + * we can look at moving it here later + **/ + c = createCommand("RANDOMNEWS", do_randomnews, is_services_oper, + NEWS_HELP_OPER, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_RANDOMNEWS); + } +} diff --git a/src/core/os_raw.c b/src/core/os_raw.c new file mode 100644 index 000000000..64e85dadd --- /dev/null +++ b/src/core/os_raw.c @@ -0,0 +1,77 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_raw(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("RAW", do_raw, is_services_admin, OPER_HELP_RAW, -1, + -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + if (DisableRaw) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * The /os raw command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_raw(User * u) +{ + char *text = strtok(NULL, ""); + if (!text) + syntax_error(s_OperServ, u, "RAW", OPER_RAW_SYNTAX); + else { + send_cmd(NULL, "%s", text); + if (WallOSRaw) { + char *kw = strtok(text, " "); + while (kw && *kw == ':') + kw = strtok(NULL, " "); + anope_cmd_global(s_OperServ, + "\2%s\2 used RAW command for \2%s\2", + u->nick, + (kw ? kw : "\2non RFC compliant message\2")); + } + alog("%s used RAW command for %s", u->nick, text); + } + return MOD_CONT; +} diff --git a/src/core/os_reload.c b/src/core/os_reload.c new file mode 100644 index 000000000..2ea882b6c --- /dev/null +++ b/src/core/os_reload.c @@ -0,0 +1,84 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_reload(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("RELOAD", do_reload, is_services_admin, + OPER_HELP_RELOAD, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_RELOAD); + } +} + +/** + * The /os relaod command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_reload(User * u) +{ + if (!read_config(1)) { + quitmsg = calloc(28 + strlen(u->nick), 1); + if (!quitmsg) + quitmsg = + "Error during the reload of the configuration file, but out of memory!"; + else + sprintf(quitmsg, + "Error during the reload of the configuration file!"); + quitting = 1; + } + send_event(EVENT_RELOAD, 1, EVENT_START); + notice_lang(s_OperServ, u, OPER_RELOAD); + return MOD_CONT; +} diff --git a/src/core/os_restart.c b/src/core/os_restart.c new file mode 100644 index 000000000..eb4bd7e2c --- /dev/null +++ b/src/core/os_restart.c @@ -0,0 +1,89 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +/* OperServ restart needs access to this if were gonna avoid sending ourself a signal */ +extern MDE void do_restart_services(void); + +int do_restart(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + c = createCommand("RESTART", do_restart, is_services_admin, + OPER_HELP_RESTART, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_RESTART); + } +} + +/** + * The /os restart command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_restart(User * u) +{ +#ifdef SERVICES_BIN + quitmsg = calloc(31 + strlen(u->nick), 1); + if (!quitmsg) + quitmsg = "RESTART command received, but out of memory!"; + else + sprintf(quitmsg, "RESTART command received from %s", u->nick); + + if (GlobalOnCycle) { + oper_global(NULL, "%s", GlobalOnCycleMessage); + } + /* raise(SIGHUP); */ + do_restart_services(); +#else + notice_lang(s_OperServ, u, OPER_CANNOT_RESTART); +#endif + return MOD_CONT; +} diff --git a/src/core/os_session.c b/src/core/os_session.c new file mode 100644 index 000000000..6be2dfb26 --- /dev/null +++ b/src/core/os_session.c @@ -0,0 +1,68 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + /** + * do_session/do_exception are exported from sessions.c - we just want to provide an interface. + **/ + c = createCommand("SESSION", do_session, is_services_admin, + OPER_HELP_SESSION, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("EXCEPTION", do_exception, is_services_admin, + OPER_HELP_EXCEPTION, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SESSION); + notice_lang(s_OperServ, u, OPER_HELP_CMD_EXCEPTION); + } +} diff --git a/src/core/os_set.c b/src/core/os_set.c new file mode 100644 index 000000000..616d65a57 --- /dev/null +++ b/src/core/os_set.c @@ -0,0 +1,262 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_set(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SET", do_set, is_services_admin, OPER_HELP_SET, -1, + -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET LIST", NULL, NULL, OPER_HELP_SET_LIST, -1, -1, + -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET READONLY", NULL, NULL, OPER_HELP_SET_READONLY, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET LOGCHAN", NULL, NULL, OPER_HELP_SET_LOGCHAN, -1, + -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET DEBUG", NULL, NULL, OPER_HELP_SET_DEBUG, -1, -1, + -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET NOEXPIRE", NULL, NULL, OPER_HELP_SET_NOEXPIRE, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET IGNORE", NULL, NULL, OPER_HELP_SET_IGNORE, -1, + -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("SET SUPERADMIN", NULL, NULL, + OPER_HELP_SET_SUPERADMIN, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); +#ifdef USE_MYSQL + c = createCommand("SET SQL", NULL, NULL, OPER_HELP_SET_SQL, -1, -1, -1, + -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); +#endif + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SET); + } +} + +/** + * The /os set command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_set(User * u) +{ + char *option = strtok(NULL, " "); + char *setting = strtok(NULL, " "); + int index; + + if (!option) { + syntax_error(s_OperServ, u, "SET", OPER_SET_SYNTAX); + } else if (stricmp(option, "LIST") == 0) { + index = + (allow_ignore ? OPER_SET_LIST_OPTION_ON : + OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "IGNORE"); + index = + (readonly ? OPER_SET_LIST_OPTION_ON : + OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "READONLY"); + index = + (logchan ? OPER_SET_LIST_OPTION_ON : OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "LOGCHAN"); + index = + (debug ? OPER_SET_LIST_OPTION_ON : OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "DEBUG"); + index = + (noexpire ? OPER_SET_LIST_OPTION_ON : + OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "NOEXPIRE"); +#ifdef USE_MYSQL + index = + (do_mysql ? OPER_SET_LIST_OPTION_ON : + OPER_SET_LIST_OPTION_OFF); + notice_lang(s_OperServ, u, index, "SQL"); +#endif + } else if (!setting) { + syntax_error(s_OperServ, u, "SET", OPER_SET_SYNTAX); + } else if (stricmp(option, "IGNORE") == 0) { + if (stricmp(setting, "on") == 0) { + allow_ignore = 1; + notice_lang(s_OperServ, u, OPER_SET_IGNORE_ON); + } else if (stricmp(setting, "off") == 0) { + allow_ignore = 0; + notice_lang(s_OperServ, u, OPER_SET_IGNORE_OFF); + } else { + notice_lang(s_OperServ, u, OPER_SET_IGNORE_ERROR); + } +#ifdef USE_MYSQL + } else if (stricmp(option, "SQL") == 0) { + if (stricmp(setting, "on") == 0) { + if (!MysqlHost) { + notice_lang(s_OperServ, u, OPER_SET_SQL_ERROR_DISABLED); + } else { + if (rdb_init()) { + notice_lang(s_OperServ, u, OPER_SET_SQL_ON); + } else { + notice_lang(s_OperServ, u, OPER_SET_SQL_ERROR_INIT); + } + } + } else if (stricmp(setting, "off") == 0) { + if (!MysqlHost) { + notice_lang(s_OperServ, u, OPER_SET_SQL_ERROR_DISABLED); + } else { + /* could call rdb_close() but that does nothing - TSL */ + do_mysql = 0; + notice_lang(s_OperServ, u, OPER_SET_SQL_OFF); + } + } else { + notice_lang(s_OperServ, u, OPER_SET_SQL_ERROR); + } +#endif + } else if (stricmp(option, "READONLY") == 0) { + if (stricmp(setting, "on") == 0) { + readonly = 1; + alog("Read-only mode activated"); + close_log(); + notice_lang(s_OperServ, u, OPER_SET_READONLY_ON); + } else if (stricmp(setting, "off") == 0) { + readonly = 0; + open_log(); + alog("Read-only mode deactivated"); + notice_lang(s_OperServ, u, OPER_SET_READONLY_OFF); + } else { + notice_lang(s_OperServ, u, OPER_SET_READONLY_ERROR); + } + + } else if (stricmp(option, "LOGCHAN") == 0) { + /* Unlike the other SET commands where only stricmp is necessary, + * we also have to ensure that LogChannel is defined or we can't + * send to it. + * + * -jester + */ + if (LogChannel && (stricmp(setting, "on") == 0)) { + if (ircd->join2msg) { + anope_cmd_join(s_GlobalNoticer, LogChannel, time(NULL)); + } + logchan = 1; + alog("Now sending log messages to %s", LogChannel); + notice_lang(s_OperServ, u, OPER_SET_LOGCHAN_ON, LogChannel); + } else if (LogChannel && (stricmp(setting, "off") == 0)) { + alog("No longer sending log messages to a channel"); + if (ircd->join2msg) { + anope_cmd_part(s_GlobalNoticer, LogChannel, NULL); + } + logchan = 0; + notice_lang(s_OperServ, u, OPER_SET_LOGCHAN_OFF); + } else { + notice_lang(s_OperServ, u, OPER_SET_LOGCHAN_ERROR); + } + /** + * Allow the user to turn super admin on/off + * + * Rob + **/ + } else if (stricmp(option, "SUPERADMIN") == 0) { + if (!SuperAdmin) { + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_NOT_ENABLED); + } else if (stricmp(setting, "on") == 0) { + u->isSuperAdmin = 1; + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_ON); + alog("%s: %s is a SuperAdmin ", s_OperServ, u->nick); + anope_cmd_global(s_OperServ, + getstring2(NULL, OPER_SUPER_ADMIN_WALL_ON), + u->nick); + } else if (stricmp(setting, "off") == 0) { + u->isSuperAdmin = 0; + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_OFF); + alog("%s: %s is no longer a SuperAdmin", s_OperServ, u->nick); + anope_cmd_global(s_OperServ, + getstring2(NULL, OPER_SUPER_ADMIN_WALL_OFF), + u->nick); + } else { + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_SYNTAX); + } + } else if (stricmp(option, "DEBUG") == 0) { + if (stricmp(setting, "on") == 0) { + debug = 1; + alog("Debug mode activated"); + notice_lang(s_OperServ, u, OPER_SET_DEBUG_ON); + } else if (stricmp(setting, "off") == 0 || + (*setting == '0' && atoi(setting) == 0)) { + alog("Debug mode deactivated"); + debug = 0; + notice_lang(s_OperServ, u, OPER_SET_DEBUG_OFF); + } else if (isdigit(*setting) && atoi(setting) > 0) { + debug = atoi(setting); + alog("Debug mode activated (level %d)", debug); + notice_lang(s_OperServ, u, OPER_SET_DEBUG_LEVEL, debug); + } else { + notice_lang(s_OperServ, u, OPER_SET_DEBUG_ERROR); + } + + } else if (stricmp(option, "NOEXPIRE") == 0) { + if (stricmp(setting, "ON") == 0) { + noexpire = 1; + alog("No expire mode activated"); + notice_lang(s_OperServ, u, OPER_SET_NOEXPIRE_ON); + } else if (stricmp(setting, "OFF") == 0) { + noexpire = 0; + alog("No expire mode deactivated"); + notice_lang(s_OperServ, u, OPER_SET_NOEXPIRE_OFF); + } else { + notice_lang(s_OperServ, u, OPER_SET_NOEXPIRE_ERROR); + } + } else { + notice_lang(s_OperServ, u, OPER_SET_UNKNOWN_OPTION, option); + } + return MOD_CONT; +} diff --git a/src/core/os_sgline.c b/src/core/os_sgline.c new file mode 100644 index 000000000..aa1520e24 --- /dev/null +++ b/src/core/os_sgline.c @@ -0,0 +1,355 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int sgline_view_callback(SList * slist, int number, void *item, + va_list args); +int sgline_view(int number, SXLine * sx, User * u, int *sent_header); +int sgline_list_callback(SList * slist, int number, void *item, + va_list args); +int sgline_list(int number, SXLine * sx, User * u, int *sent_header); +int do_sgline(User * u); + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SGLINE", do_sgline, is_services_oper, + OPER_HELP_SGLINE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + if (!ircd->sgline) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SGLINE); + } +} + +/** + * The /os sgline command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_sgline(User * u) +{ + char *cmd = strtok(NULL, " "); + + if (!cmd) + cmd = ""; + + if (!stricmp(cmd, "ADD")) { + int deleted = 0; + char *expiry, *mask, *reason; + time_t expires; + + mask = strtok(NULL, ":"); + if (mask && *mask == '+') { + expiry = mask; + mask = strchr(expiry, ' '); + if (mask) { + *mask = 0; + mask++; + } + } else { + expiry = NULL; + } + + expires = expiry ? dotime(expiry) : SGLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (expiry && isdigit(expiry[strlen(expiry) - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires != 0 && expires < 60) { + notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); + return MOD_CONT; + } else if (expires > 0) { + expires += time(NULL); + } + + if (mask && (reason = strtok(NULL, ""))) { + /* We first do some sanity check on the proposed mask. */ + + if (mask && strspn(mask, "*?") == strlen(mask)) { + notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); + return MOD_CONT; + } + + deleted = add_sgline(u, mask, u->nick, expires, reason); + if (deleted < 0) + return MOD_CONT; + else if (deleted) + notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL, + deleted); + notice_lang(s_OperServ, u, OPER_SGLINE_ADDED, mask); + + if (WallOSSGLine) { + char buf[128]; + + if (!expires) { + strcpy(buf, "does not expire"); + } else { + int wall_expiry = expires - time(NULL); + char *s = NULL; + + if (wall_expiry >= 86400) { + wall_expiry /= 86400; + s = "day"; + } else if (wall_expiry >= 3600) { + wall_expiry /= 3600; + s = "hour"; + } else if (wall_expiry >= 60) { + wall_expiry /= 60; + s = "minute"; + } + + snprintf(buf, sizeof(buf), "expires in %d %s%s", + wall_expiry, s, + (wall_expiry == 1) ? "" : "s"); + } + + anope_cmd_global(s_OperServ, + "%s added an SGLINE for %s (%s)", u->nick, + mask, buf); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else { + syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); + } + + } else if (!stricmp(cmd, "DEL")) { + + char *mask; + int res = 0; + + mask = strtok(NULL, ""); + + if (!mask) { + syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); + return MOD_CONT; + } + + if (sglines.count == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); + return MOD_CONT; + } + + if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { + /* Deleting a range */ + res = slist_delete_range(&sglines, mask, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_SGLINE_DELETED_SEVERAL, + res); + } + } else { + if ((res = slist_indexof(&sglines, mask)) == -1) { + notice_lang(s_OperServ, u, OPER_SGLINE_NOT_FOUND, mask); + return MOD_CONT; + } + + slist_delete(&sglines, res); + notice_lang(s_OperServ, u, OPER_SGLINE_DELETED, mask); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else if (!stricmp(cmd, "LIST")) { + char *mask; + int res, sent_header = 0; + + if (sglines.count == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, ""); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&sglines, mask, &sgline_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < sglines.count; i++) { + amask = ((SXLine *) sglines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + sgline_list(i + 1, sglines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); + else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "SGLine"); + } + } + } else if (!stricmp(cmd, "VIEW")) { + char *mask; + int res, sent_header = 0; + + if (sglines.count == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, ""); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&sglines, mask, &sgline_view_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < sglines.count; i++) { + amask = ((SXLine *) sglines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + sgline_view(i + 1, sglines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SGLINE_NO_MATCH); + } + } else if (!stricmp(cmd, "CLEAR")) { + slist_clear(&sglines, 1); + notice_lang(s_OperServ, u, OPER_SGLINE_CLEAR); + } else { + syntax_error(s_OperServ, u, "SGLINE", OPER_SGLINE_SYNTAX); + } + return MOD_CONT; +} + +/* Lists an SGLINE entry, prefixing it with the header if needed */ + +int sgline_view(int number, SXLine * sx, User * u, int *sent_header) +{ + char timebuf[32], expirebuf[256]; + struct tm tm; + + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SGLINE_VIEW_HEADER); + *sent_header = 1; + } + + tm = *localtime(&sx->seton); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, + &tm); + expire_left(u->na, expirebuf, sizeof(expirebuf), sx->expires); + notice_lang(s_OperServ, u, OPER_SGLINE_VIEW_FORMAT, number, sx->mask, + sx->by, timebuf, expirebuf, sx->reason); + + return 1; +} + +/* Callback for enumeration purposes */ + +int sgline_view_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return sgline_view(number, item, u, sent_header); +} + +/* Lists an SGLINE entry, prefixing it with the header if needed */ + +int sgline_list(int number, SXLine * sx, User * u, int *sent_header) +{ + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SGLINE_LIST_HEADER); + *sent_header = 1; + } + + notice_lang(s_OperServ, u, OPER_SGLINE_LIST_FORMAT, number, sx->mask, + sx->reason); + + return 1; +} + +/* Callback for enumeration purposes */ + +int sgline_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return sgline_list(number, item, u, sent_header); +} diff --git a/src/core/os_shutdown.c b/src/core/os_shutdown.c new file mode 100644 index 000000000..74e61436c --- /dev/null +++ b/src/core/os_shutdown.c @@ -0,0 +1,83 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_shutdown(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SHUTDOWN", do_shutdown, is_services_admin, + OPER_HELP_SHUTDOWN, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SHUTDOWN); + } +} + +/** + * The /os shutdown command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_shutdown(User * u) +{ + quitmsg = calloc(32 + strlen(u->nick), 1); + if (!quitmsg) + quitmsg = "SHUTDOWN command received, but out of memory!"; + else + sprintf(quitmsg, "SHUTDOWN command received from %s", u->nick); + + if (GlobalOnCycle) { + oper_global(NULL, "%s", GlobalOnCycleMessage); + } + save_data = 1; + delayed_quit = 1; + return MOD_CONT; +} diff --git a/src/core/os_sqline.c b/src/core/os_sqline.c new file mode 100644 index 000000000..9e9bc63d7 --- /dev/null +++ b/src/core/os_sqline.c @@ -0,0 +1,355 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_sqline(User * u); +int sqline_view_callback(SList * slist, int number, void *item, + va_list args); +int sqline_view(int number, SXLine * sx, User * u, int *sent_header); +int sqline_list_callback(SList * slist, int number, void *item, + va_list args); +int sqline_list(int number, SXLine * sx, User * u, int *sent_header); + +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SQLINE", do_sqline, is_services_oper, + OPER_HELP_SQLINE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + if (!ircd->sqline) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SQLINE); + } +} + +/** + * The /os sqline command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_sqline(User * u) +{ + char *cmd = strtok(NULL, " "); + + if (!cmd) + cmd = ""; + + if (!stricmp(cmd, "ADD")) { + int deleted = 0; + char *expiry, *mask, *reason; + time_t expires; + + mask = strtok(NULL, " "); + if (mask && *mask == '+') { + expiry = mask; + mask = strtok(NULL, " "); + } else { + expiry = NULL; + } + + expires = expiry ? dotime(expiry) : SQLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (expiry && isdigit(expiry[strlen(expiry) - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires != 0 && expires < 60) { + notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); + return MOD_CONT; + } else if (expires > 0) { + expires += time(NULL); + } + + if (mask && (reason = strtok(NULL, ""))) { + + /* We first do some sanity check on the proposed mask. */ + if (strspn(mask, "*") == strlen(mask)) { + notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); + return MOD_CONT; + } + + /* Channel SQLINEs are only supported on Bahamut servers */ + if (*mask == '#' && !ircd->chansqline) { + notice_lang(s_OperServ, u, + OPER_SQLINE_CHANNELS_UNSUPPORTED); + return MOD_CONT; + } + + deleted = add_sqline(u, mask, u->nick, expires, reason); + if (deleted < 0) + return MOD_CONT; + else if (deleted) + notice_lang(s_OperServ, u, OPER_SQLINE_DELETED_SEVERAL, + deleted); + notice_lang(s_OperServ, u, OPER_SQLINE_ADDED, mask); + + if (WallOSSQLine) { + char buf[128]; + + if (!expires) { + strcpy(buf, "does not expire"); + } else { + int wall_expiry = expires - time(NULL); + char *s = NULL; + + if (wall_expiry >= 86400) { + wall_expiry /= 86400; + s = "day"; + } else if (wall_expiry >= 3600) { + wall_expiry /= 3600; + s = "hour"; + } else if (wall_expiry >= 60) { + wall_expiry /= 60; + s = "minute"; + } + + snprintf(buf, sizeof(buf), "expires in %d %s%s", + wall_expiry, s, + (wall_expiry == 1) ? "" : "s"); + } + + anope_cmd_global(s_OperServ, + "%s added an SQLINE for %s (%s)", u->nick, + mask, buf); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else { + syntax_error(s_OperServ, u, "SQLINE", OPER_SQLINE_SYNTAX); + } + + } else if (!stricmp(cmd, "DEL")) { + + char *mask; + int res = 0; + + mask = strtok(NULL, ""); + + if (!mask) { + syntax_error(s_OperServ, u, "SQLINE", OPER_SQLINE_SYNTAX); + return MOD_CONT; + } + + if (sqlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_LIST_EMPTY); + return MOD_CONT; + } + + if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { + /* Deleting a range */ + res = slist_delete_range(&sqlines, mask, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_SQLINE_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_SQLINE_DELETED_SEVERAL, + res); + } + } else { + if ((res = slist_indexof(&sqlines, mask)) == -1) { + notice_lang(s_OperServ, u, OPER_SQLINE_NOT_FOUND, mask); + return MOD_CONT; + } + + slist_delete(&sqlines, res); + notice_lang(s_OperServ, u, OPER_SQLINE_DELETED, mask); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else if (!stricmp(cmd, "LIST")) { + char *mask; + int res, sent_header = 0; + + if (sqlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, ""); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&sqlines, mask, &sqline_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < sqlines.count; i++) { + amask = ((SXLine *) sqlines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + sqline_list(i + 1, sqlines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SQLINE_NO_MATCH); + else { + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "SQLine"); + } + } + } else if (!stricmp(cmd, "VIEW")) { + char *mask; + int res, sent_header = 0; + + if (sqlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, ""); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&sqlines, mask, &sqline_view_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SQLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < sqlines.count; i++) { + amask = ((SXLine *) sqlines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + sqline_view(i + 1, sqlines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SQLINE_NO_MATCH); + } + } else if (!stricmp(cmd, "CLEAR")) { + slist_clear(&sqlines, 1); + notice_lang(s_OperServ, u, OPER_SQLINE_CLEAR); + } else { + syntax_error(s_OperServ, u, "SQLINE", OPER_SQLINE_SYNTAX); + } + return MOD_CONT; +} + +int sqline_view(int number, SXLine * sx, User * u, int *sent_header) +{ + char timebuf[32], expirebuf[256]; + struct tm tm; + + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SQLINE_VIEW_HEADER); + *sent_header = 1; + } + + tm = *localtime(&sx->seton); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, + &tm); + expire_left(u->na, expirebuf, sizeof(expirebuf), sx->expires); + notice_lang(s_OperServ, u, OPER_SQLINE_VIEW_FORMAT, number, sx->mask, + sx->by, timebuf, expirebuf, sx->reason); + + return 1; +} + +/* Callback for enumeration purposes */ + +int sqline_view_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return sqline_view(number, item, u, sent_header); +} + +/* Lists an SQLINE entry, prefixing it with the header if needed */ + +int sqline_list(int number, SXLine * sx, User * u, int *sent_header) +{ + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SQLINE_LIST_HEADER); + *sent_header = 1; + } + + notice_lang(s_OperServ, u, OPER_SQLINE_LIST_FORMAT, number, sx->mask, + sx->reason); + + return 1; +} + +/* Callback for enumeration purposes */ + +int sqline_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return sqline_list(number, item, u, sent_header); +} diff --git a/src/core/os_staff.c b/src/core/os_staff.c new file mode 100644 index 000000000..67d07a94e --- /dev/null +++ b/src/core/os_staff.c @@ -0,0 +1,158 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_staff(User * u); +void myOperServHelp(User * u); +int opers_list_callback(SList * slist, int number, void *item, + va_list args); +int opers_list(int number, NickCore * nc, User * u, char *level); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("STAFF", do_staff, is_oper, OPER_HELP_STAFF, -1, -1, + -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_STAFF); + } +} + +/** + * The /os staff command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_staff(User * u) +{ + int idx = 0; + User *au = NULL; + NickCore *nc; + NickAlias *na; + int found; + int i; + + notice_lang(s_OperServ, u, OPER_STAFF_LIST_HEADER); + slist_enum(&servopers, NULL, &opers_list_callback, u, "OPER"); + slist_enum(&servadmins, NULL, &opers_list_callback, u, "ADMN"); + + for (idx = 0; idx < RootNumber; idx++) { + found = 0; + if ((au = finduser(ServicesRoots[idx]))) { /* see if user is online */ + found = 1; + notice_lang(s_OperServ, u, OPER_STAFF_FORMAT, '*', "ROOT", + ServicesRoots[idx]); + } else if ((nc = findcore(ServicesRoots[idx]))) { + for (i = 0; i < nc->aliases.count; i++) { /* check all aliases */ + na = nc->aliases.list[i]; + if ((au = finduser(na->nick))) { /* see if user is online */ + found = 1; + notice_lang(s_OperServ, u, OPER_STAFF_AFORMAT, + '*', "ROOT", ServicesRoots[idx], na->nick); + } + } + } + + if (!found) + notice_lang(s_OperServ, u, OPER_STAFF_FORMAT, ' ', "ROOT", + ServicesRoots[idx]); + + } + notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Staff"); + return MOD_CONT; +} + +/** + * Function for the enumerator to call + **/ +int opers_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + char *level = va_arg(args, char *); + + return opers_list(number, item, u, level); +} + + +/** + * Display an Opers list Entry + **/ +int opers_list(int number, NickCore * nc, User * u, char *level) +{ + User *au = NULL; + NickAlias *na; + int found; + int i; + + if (!nc) + return 0; + + found = 0; + if ((au = finduser(nc->display))) { /* see if user is online */ + found = 1; + notice_lang(s_OperServ, u, OPER_STAFF_FORMAT, '*', level, + nc->display); + } else { + for (i = 0; i < nc->aliases.count; i++) { /* check all aliases */ + na = nc->aliases.list[i]; + if ((au = finduser(na->nick))) { /* see if user is online */ + found = 1; + notice_lang(s_OperServ, u, OPER_STAFF_AFORMAT, '*', level, + nc->display, na->nick); + } + } + } + + if (!found) + notice_lang(s_OperServ, u, OPER_STAFF_FORMAT, ' ', level, + nc->display); + + return 1; +} diff --git a/src/core/os_stats.c b/src/core/os_stats.c new file mode 100644 index 000000000..f621c56d1 --- /dev/null +++ b/src/core/os_stats.c @@ -0,0 +1,400 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + + + +int do_stats(User * u); +void get_operserv_stats(long *nrec, long *memuse); +void myOperServHelp(User * u); + +extern MDE struct clone clonelist[CLONE_DETECT_SIZE]; +extern MDE struct clone warnings[CLONE_DETECT_SIZE]; + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("STATS", do_stats, is_services_oper, OPER_HELP_STATS, + -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + c = createCommand("UPTIME", do_stats, is_services_oper, + OPER_HELP_STATS, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_STATS); + } +} + +/** + * The /os stats command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_stats(User * u) +{ + time_t uptime = time(NULL) - start_time; + char *extra = strtok(NULL, ""); + int days = uptime / 86400, hours = (uptime / 3600) % 24, + mins = (uptime / 60) % 60, secs = uptime % 60; + struct tm *tm; + char timebuf[64]; + + if (extra && stricmp(extra, "ALL") != 0) { + if (stricmp(extra, "AKILL") == 0) { + int timeout; + /* AKILLs */ + notice_lang(s_OperServ, u, OPER_STATS_AKILL_COUNT, + akills.count); + timeout = AutokillExpiry + 59; + if (timeout >= 172800) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_DAYS, + timeout / 86400); + else if (timeout >= 86400) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_DAY); + else if (timeout >= 7200) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_HOURS, + timeout / 3600); + else if (timeout >= 3600) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_HOUR); + else if (timeout >= 120) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_MINS, + timeout / 60); + else if (timeout >= 60) + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_MIN); + else + notice_lang(s_OperServ, u, OPER_STATS_AKILL_EXPIRE_NONE); + if (ircd->sgline) { + /* SGLINEs */ + notice_lang(s_OperServ, u, OPER_STATS_SGLINE_COUNT, + sglines.count); + timeout = SGLineExpiry + 59; + if (timeout >= 172800) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_DAYS, + timeout / 86400); + else if (timeout >= 86400) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_DAY); + else if (timeout >= 7200) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_HOURS, + timeout / 3600); + else if (timeout >= 3600) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_HOUR); + else if (timeout >= 120) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_MINS, + timeout / 60); + else if (timeout >= 60) + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_MIN); + else + notice_lang(s_OperServ, u, + OPER_STATS_SGLINE_EXPIRE_NONE); + } + if (ircd->sqline) { + /* SQLINEs */ + notice_lang(s_OperServ, u, OPER_STATS_SQLINE_COUNT, + sqlines.count); + timeout = SQLineExpiry + 59; + if (timeout >= 172800) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_DAYS, + timeout / 86400); + else if (timeout >= 86400) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_DAY); + else if (timeout >= 7200) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_HOURS, + timeout / 3600); + else if (timeout >= 3600) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_HOUR); + else if (timeout >= 120) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_MINS, + timeout / 60); + else if (timeout >= 60) + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_MIN); + else + notice_lang(s_OperServ, u, + OPER_STATS_SQLINE_EXPIRE_NONE); + } + if (ircd->szline) { + /* SZLINEs */ + notice_lang(s_OperServ, u, OPER_STATS_SZLINE_COUNT, + szlines.count); + timeout = SZLineExpiry + 59; + if (timeout >= 172800) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_DAYS, + timeout / 86400); + else if (timeout >= 86400) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_DAY); + else if (timeout >= 7200) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_HOURS, + timeout / 3600); + else if (timeout >= 3600) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_HOUR); + else if (timeout >= 120) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_MINS, + timeout / 60); + else if (timeout >= 60) + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_MIN); + else + notice_lang(s_OperServ, u, + OPER_STATS_SZLINE_EXPIRE_NONE); + } + return MOD_CONT; + } else if (!stricmp(extra, "RESET")) { + if (is_services_admin(u)) { + maxusercnt = usercnt; + notice_lang(s_OperServ, u, OPER_STATS_RESET); + } else { + notice_lang(s_OperServ, u, PERMISSION_DENIED); + } + return MOD_CONT; + } else { + notice_lang(s_OperServ, u, OPER_STATS_UNKNOWN_OPTION, extra); + } + } + + notice_lang(s_OperServ, u, OPER_STATS_CURRENT_USERS, usercnt, opcnt); + tm = localtime(&maxusertime); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_DATE_TIME_FORMAT, + tm); + notice_lang(s_OperServ, u, OPER_STATS_MAX_USERS, maxusercnt, timebuf); + if (days > 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_DHMS, + days, hours, mins, secs); + } else if (days == 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1DHMS, + days, hours, mins, secs); + } else { + if (hours > 1) { + if (mins != 1) { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_HMS, + hours, mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_HM1S, + hours, mins, secs); + } + } else { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_H1MS, + hours, mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_H1M1S, + hours, mins, secs); + } + } + } else if (hours == 1) { + if (mins != 1) { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1HMS, + hours, mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1HM1S, + hours, mins, secs); + } + } else { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1H1MS, + hours, mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1H1M1S, + hours, mins, secs); + } + } + } else { + if (mins != 1) { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_MS, + mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_M1S, + mins, secs); + } + } else { + if (secs != 1) { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1MS, + mins, secs); + } else { + notice_lang(s_OperServ, u, OPER_STATS_UPTIME_1M1S, + mins, secs); + } + } + } + } + + if (extra && stricmp(extra, "ALL") == 0 && is_services_admin(u)) { + long count, mem; + + notice_lang(s_OperServ, u, OPER_STATS_BYTES_READ, + total_read / 1024); + notice_lang(s_OperServ, u, OPER_STATS_BYTES_WRITTEN, + total_written / 1024); + + get_user_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_USER_MEM, count, + (mem + 512) / 1024); + get_channel_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_CHANNEL_MEM, count, + (mem + 512) / 1024); + get_core_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_GROUPS_MEM, count, + (mem + 512) / 1024); + get_aliases_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_ALIASES_MEM, count, + (mem + 512) / 1024); + get_chanserv_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_CHANSERV_MEM, count, + (mem + 512) / 1024); + get_botserv_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_BOTSERV_MEM, count, + (mem + 512) / 1024); + get_operserv_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_OPERSERV_MEM, count, + (mem + 512) / 1024); + get_session_stats(&count, &mem); + notice_lang(s_OperServ, u, OPER_STATS_SESSIONS_MEM, count, + (mem + 512) / 1024); + } + return MOD_CONT; +} + +void get_operserv_stats(long *nrec, long *memuse) +{ + int i; + long mem = 0, count = 0, mem2 = 0, count2 = 0; + Akill *ak; + SXLine *sx; + + if (CheckClones) { + mem = sizeof(struct clone) * CLONE_DETECT_SIZE * 2; + for (i = 0; i < CLONE_DETECT_SIZE; i++) { + if (clonelist[i].host) { + count++; + mem += strlen(clonelist[i].host) + 1; + } + if (warnings[i].host) { + count++; + mem += strlen(warnings[i].host) + 1; + } + } + } + + count += akills.count; + mem += akills.capacity; + mem += akills.count * sizeof(Akill); + + for (i = 0; i < akills.count; i++) { + ak = akills.list[i]; + mem += strlen(ak->user) + 1; + mem += strlen(ak->host) + 1; + mem += strlen(ak->by) + 1; + mem += strlen(ak->reason) + 1; + } + + if (ircd->sgline) { + count += sglines.count; + mem += sglines.capacity; + mem += sglines.count * sizeof(SXLine); + + for (i = 0; i < sglines.count; i++) { + sx = sglines.list[i]; + mem += strlen(sx->mask) + 1; + mem += strlen(sx->by) + 1; + mem += strlen(sx->reason) + 1; + } + } + if (ircd->sqline) { + count += sqlines.count; + mem += sqlines.capacity; + mem += sqlines.count * sizeof(SXLine); + + for (i = 0; i < sqlines.count; i++) { + sx = sqlines.list[i]; + mem += strlen(sx->mask) + 1; + mem += strlen(sx->by) + 1; + mem += strlen(sx->reason) + 1; + } + } + if (ircd->szline) { + count += szlines.count; + mem += szlines.capacity; + mem += szlines.count * sizeof(SXLine); + + for (i = 0; i < szlines.count; i++) { + sx = szlines.list[i]; + mem += strlen(sx->mask) + 1; + mem += strlen(sx->by) + 1; + mem += strlen(sx->reason) + 1; + } + } + + + get_news_stats(&count2, &mem2); + count += count2; + mem += mem2; + get_exception_stats(&count2, &mem2); + count += count2; + mem += mem2; + + *nrec = count; + *memuse = mem; +} diff --git a/src/core/os_svsnick.c b/src/core/os_svsnick.c new file mode 100644 index 000000000..9c0af28ca --- /dev/null +++ b/src/core/os_svsnick.c @@ -0,0 +1,126 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_svsnick(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SVSNICK", do_svsnick, is_services_admin, + OPER_HELP_SVSNICK, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + if (!ircd->svsnick) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u) && u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SVSNICK); + } +} + +/** + * The /os svsnick command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +/* Forcefully change a user's nickname */ + +int do_svsnick(User * u) +{ + char *nick = strtok(NULL, " "); + char *newnick = strtok(NULL, " "); + + NickAlias *na; + char *c; + + /* Only allow this if SuperAdmin is enabled */ + if (!u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_ONLY); + return MOD_CONT; + } + + if (!nick || !newnick) { + syntax_error(s_OperServ, u, "SVSNICK", OPER_SVSNICK_SYNTAX); + return MOD_CONT; + } + + /* Truncate long nicknames to NICKMAX-2 characters */ + if (strlen(newnick) > (NICKMAX - 2)) { + notice_lang(s_NickServ, u, NICK_X_TRUNCATED, + newnick, NICKMAX - 2, newnick); + newnick[NICKMAX - 2] = '\0'; + } + + /* Check for valid characters */ + if (*newnick == '-' || isdigit(*newnick)) { + notice_lang(s_OperServ, u, NICK_X_ILLEGAL, newnick); + return MOD_CONT; + } +#define isvalid(c) (((c) >= 'A' && (c) <= '~') || isdigit(c) || (c) == '-') + for (c = newnick; *c && (c - newnick) < NICKMAX; c++) { + if (!isvalid(*c) || isspace(*c)) { + notice_lang(s_OperServ, u, NICK_X_ILLEGAL, nick); + return MOD_CONT; + } + } + + /* Check for a nick in use or a forbidden/suspended nick */ + if (!finduser(nick)) { + notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick); + } else if (finduser(newnick)) { + notice_lang(s_NickServ, u, NICK_X_IN_USE, newnick); + } else if ((na = findnick(newnick)) && (na->status & NS_VERBOTEN)) { + notice_lang(s_NickServ, u, NICK_X_FORBIDDEN, newnick); + } else { + notice_lang(s_OperServ, u, OPER_SVSNICK_NEWNICK, nick, newnick); + anope_cmd_global(s_OperServ, "%s used SVSNICK to change %s to %s", + u->nick, nick, newnick); + anope_cmd_svsnick(nick, newnick, time(NULL)); + } + return MOD_CONT; +} diff --git a/src/core/os_szline.c b/src/core/os_szline.c new file mode 100644 index 000000000..379bbbfdc --- /dev/null +++ b/src/core/os_szline.c @@ -0,0 +1,350 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_szline(User * u); +void myOperServHelp(User * u); +int szline_view_callback(SList * slist, int number, void *item, + va_list args); +int szline_list_callback(SList * slist, int number, void *item, + va_list args); +int szline_view(int number, SXLine * sx, User * u, int *sent_header); +int szline_list(int number, SXLine * sx, User * u, int *sent_header); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("SZLINE", do_szline, is_services_oper, + OPER_HELP_SZLINE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + if (!ircd->szline) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_oper(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_SZLINE); + } +} + +/** + * The /os szline command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_szline(User * u) +{ + char *cmd = strtok(NULL, " "); + + if (!cmd) + cmd = ""; + + if (!stricmp(cmd, "ADD")) { + int deleted = 0; + char *expiry, *mask, *reason; + time_t expires; + + mask = strtok(NULL, " "); + if (mask && *mask == '+') { + expiry = mask; + mask = strtok(NULL, " "); + } else { + expiry = NULL; + } + + expires = expiry ? dotime(expiry) : SZLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (expiry && isdigit(expiry[strlen(expiry) - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires != 0 && expires < 60) { + notice_lang(s_OperServ, u, BAD_EXPIRY_TIME); + return MOD_CONT; + } else if (expires > 0) { + expires += time(NULL); + } + + if (mask && (reason = strtok(NULL, ""))) { + /* We first do some sanity check on the proposed mask. */ + + if (strchr(mask, '!') || strchr(mask, '@')) { + notice_lang(s_OperServ, u, OPER_SZLINE_ONLY_IPS); + return MOD_CONT; + } + + if (strspn(mask, "*?") == strlen(mask)) { + notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask); + return MOD_CONT; + } + + deleted = add_szline(u, mask, u->nick, expires, reason); + if (deleted < 0) + return MOD_CONT; + else if (deleted) + notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_SEVERAL, + deleted); + notice_lang(s_OperServ, u, OPER_SZLINE_ADDED, mask); + + if (WallOSSZLine) { + char buf[128]; + + if (!expires) { + strcpy(buf, "does not expire"); + } else { + int wall_expiry = expires - time(NULL); + char *s = NULL; + + if (wall_expiry >= 86400) { + wall_expiry /= 86400; + s = "day"; + } else if (wall_expiry >= 3600) { + wall_expiry /= 3600; + s = "hour"; + } else if (wall_expiry >= 60) { + wall_expiry /= 60; + s = "minute"; + } + + snprintf(buf, sizeof(buf), "expires in %d %s%s", + wall_expiry, s, + (wall_expiry == 1) ? "" : "s"); + } + + anope_cmd_global(s_OperServ, + "%s added an SZLINE for %s (%s)", u->nick, + mask, buf); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else { + syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX); + } + + } else if (!stricmp(cmd, "DEL")) { + + char *mask; + int res = 0; + + mask = strtok(NULL, " "); + + if (!mask) { + syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX); + return MOD_CONT; + } + + if (szlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY); + return MOD_CONT; + } + + if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { + /* Deleting a range */ + res = slist_delete_range(&szlines, mask, NULL); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH); + return MOD_CONT; + } else if (res == 1) { + notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_ONE); + } else { + notice_lang(s_OperServ, u, OPER_SZLINE_DELETED_SEVERAL, + res); + } + } else { + if ((res = slist_indexof(&szlines, mask)) == -1) { + notice_lang(s_OperServ, u, OPER_SZLINE_NOT_FOUND, mask); + return MOD_CONT; + } + + slist_delete(&szlines, res); + notice_lang(s_OperServ, u, OPER_SZLINE_DELETED, mask); + } + + if (readonly) + notice_lang(s_OperServ, u, READ_ONLY_MODE); + + } else if (!stricmp(cmd, "LIST")) { + char *mask; + int res, sent_header = 0; + + if (szlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, " "); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&szlines, mask, &szline_list_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < szlines.count; i++) { + amask = ((SXLine *) szlines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + szline_list(i + 1, szlines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH); + } + } else if (!stricmp(cmd, "VIEW")) { + char *mask; + int res, sent_header = 0; + + if (szlines.count == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_LIST_EMPTY); + return MOD_CONT; + } + + mask = strtok(NULL, " "); + + if (!mask || (isdigit(*mask) + && strspn(mask, "1234567890,-") == strlen(mask))) { + res = + slist_enum(&szlines, mask, &szline_view_callback, u, + &sent_header); + if (res == 0) { + notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH); + return MOD_CONT; + } + } else { + int i; + char *amask; + + for (i = 0; i < szlines.count; i++) { + amask = ((SXLine *) szlines.list[i])->mask; + if (!stricmp(mask, amask) + || match_wild_nocase(mask, amask)) + szline_view(i + 1, szlines.list[i], u, &sent_header); + } + + if (!sent_header) + notice_lang(s_OperServ, u, OPER_SZLINE_NO_MATCH); + } + } else if (!stricmp(cmd, "CLEAR")) { + slist_clear(&szlines, 1); + notice_lang(s_OperServ, u, OPER_SZLINE_CLEAR); + } else { + syntax_error(s_OperServ, u, "SZLINE", OPER_SZLINE_SYNTAX); + } + return MOD_CONT; +} + + +int szline_view(int number, SXLine * sx, User * u, int *sent_header) +{ + char timebuf[32], expirebuf[256]; + struct tm tm; + + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SZLINE_VIEW_HEADER); + *sent_header = 1; + } + + tm = *localtime(&sx->seton); + strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT, + &tm); + expire_left(u->na, expirebuf, sizeof(expirebuf), sx->expires); + notice_lang(s_OperServ, u, OPER_SZLINE_VIEW_FORMAT, number, sx->mask, + sx->by, timebuf, expirebuf, sx->reason); + + return 1; +} + +/* Callback for enumeration purposes */ + +int szline_view_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return szline_view(number, item, u, sent_header); +} + +/* Callback for enumeration purposes */ + +int szline_list_callback(SList * slist, int number, void *item, + va_list args) +{ + User *u = va_arg(args, User *); + int *sent_header = va_arg(args, int *); + + return szline_list(number, item, u, sent_header); +} + +/* Lists an SZLINE entry, prefixing it with the header if needed */ + +int szline_list(int number, SXLine * sx, User * u, int *sent_header) +{ + if (!sx) + return 0; + + if (!*sent_header) { + notice_lang(s_OperServ, u, OPER_SZLINE_LIST_HEADER); + *sent_header = 1; + } + + notice_lang(s_OperServ, u, OPER_SZLINE_LIST_FORMAT, number, sx->mask, + sx->reason); + + return 1; +} diff --git a/src/core/os_umode.c b/src/core/os_umode.c new file mode 100644 index 000000000..ecd8006d9 --- /dev/null +++ b/src/core/os_umode.c @@ -0,0 +1,116 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_operumodes(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("UMODE", do_operumodes, is_services_admin, + OPER_HELP_UMODE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + if (!ircd->umode) { + return MOD_STOP; + } + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u) && u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_UMODE); + } +} + +/** + * Change any user's UMODES + * + * modified to be part of the SuperAdmin directive -jester + * check user flag for SuperAdmin -rob + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + */ +int do_operumodes(User * u) +{ + char *nick = strtok(NULL, " "); + char *modes = strtok(NULL, ""); + + User *u2; + + /* Only allow this if SuperAdmin is enabled */ + if (!u->isSuperAdmin) { + notice_lang(s_OperServ, u, OPER_SUPER_ADMIN_ONLY); + return MOD_CONT; + } + + if (!nick || !modes) { + syntax_error(s_OperServ, u, "UMODE", OPER_UMODE_SYNTAX); + return MOD_CONT; + } + + /** + * Only accept a +/- mode string + *-rob + **/ + if ((modes[0] != '+') && (modes[0] != '-')) { + syntax_error(s_OperServ, u, "UMODE", OPER_UMODE_SYNTAX); + return MOD_CONT; + } + if (!(u2 = finduser(nick))) { + notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, nick); + } else { + anope_cmd_mode(s_OperServ, nick, "%s", modes); + + common_svsmode(u2, modes, NULL); + + notice_lang(s_OperServ, u, OPER_UMODE_SUCCESS, nick); + notice_lang(s_OperServ, u2, OPER_UMODE_CHANGED, u->nick); + + if (WallOSMode) + anope_cmd_global(s_OperServ, "\2%s\2 used UMODE on %s", + u->nick, nick); + } + return MOD_CONT; +} diff --git a/src/core/os_update.c b/src/core/os_update.c new file mode 100644 index 000000000..2ec18ebde --- /dev/null +++ b/src/core/os_update.c @@ -0,0 +1,74 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +int do_update(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("UPDATE", do_update, is_services_admin, + OPER_HELP_UPDATE, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_UPDATE); + } +} + +/** + * The /os update command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ +int do_update(User * u) +{ + notice_lang(s_OperServ, u, OPER_UPDATING); + save_data = 1; + return MOD_CONT; +} diff --git a/src/core/os_userlist.c b/src/core/os_userlist.c new file mode 100644 index 000000000..7d7b75bc1 --- /dev/null +++ b/src/core/os_userlist.c @@ -0,0 +1,121 @@ +/* OperServ core functions + * + * (C) 2003-2005 Anope Team + * Contact us at info@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + * + * $Id$ + * + */ +/*************************************************************************/ + +#include "module.h" + +extern MDE int anope_get_invite_mode(); +extern MDE int anope_get_invis_mode(); + +int do_userlist(User * u); +void myOperServHelp(User * u); + +/** + * Create the command, and tell anope about it. + * @param argc Argument count + * @param argv Argument list + * @return MOD_CONT to allow the module, MOD_STOP to stop it + **/ +int AnopeInit(int argc, char **argv) +{ + Command *c; + + moduleAddAuthor("Anope"); + moduleAddVersion("$Id$"); + moduleSetType(CORE); + + c = createCommand("USERLIST", do_userlist, is_services_admin, + OPER_HELP_USERLIST, -1, -1, -1, -1); + moduleAddCommand(OPERSERV, c, MOD_UNIQUE); + + moduleSetOperHelp(myOperServHelp); + + return MOD_CONT; +} + +/** + * Unload the module + **/ +void AnopeFini(void) +{ + +} + + +/** + * Add the help response to anopes /os help output. + * @param u The user who is requesting help + **/ +void myOperServHelp(User * u) +{ + if (is_services_admin(u)) { + notice_lang(s_OperServ, u, OPER_HELP_CMD_USERLIST); + } +} + +/** + * The /os userlist command. + * @param u The user who issued the command + * @param MOD_CONT to continue processing other modules, MOD_STOP to stop processing. + **/ + +int do_userlist(User * u) +{ + char *pattern = strtok(NULL, " "); + char *opt = strtok(NULL, " "); + + Channel *c; + int modes = 0; + + if (opt && !stricmp(opt, "INVISIBLE")) + modes |= anope_get_invis_mode(); + + if (pattern && (c = findchan(pattern))) { + struct c_userlist *cu; + + notice_lang(s_OperServ, u, OPER_USERLIST_HEADER_CHAN, pattern); + + for (cu = c->users; cu; cu = cu->next) { + if (modes && !(cu->user->mode & modes)) + continue; + notice_lang(s_OperServ, u, OPER_USERLIST_RECORD, + cu->user->nick, common_get_vident(cu->user), + common_get_vhost(cu->user)); + } + } else { + char mask[BUFSIZE]; + int i; + User *u2; + + notice_lang(s_OperServ, u, OPER_USERLIST_HEADER); + + for (i = 0; i < 1024; i++) { + for (u2 = userlist[i]; u2; u2 = u2->next) { + if (pattern) { + snprintf(mask, sizeof(mask), "%s!%s@%s", u2->nick, + common_get_vident(u2), common_get_vhost(u2)); + if (!match_wild_nocase(pattern, mask)) + continue; + if (modes && !(u2->mode & modes)) + continue; + } + notice_lang(s_OperServ, u, OPER_USERLIST_RECORD, u2->nick, + common_get_vident(u2), common_get_vhost(u2)); + } + } + } + + notice_lang(s_OperServ, u, OPER_USERLIST_END); + return MOD_CONT; +} |
