summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/Makefile48
-rw-r--r--src/modules/Makefile.sub28
-rw-r--r--src/modules/README1
-rw-r--r--src/modules/bs_fantasy_unban.c82
-rwxr-xr-xsrc/modules/configure58
-rw-r--r--src/modules/cs_appendtopic.c247
-rw-r--r--src/modules/cs_enforce.c479
-rw-r--r--src/modules/cs_tban.c253
-rw-r--r--src/modules/demos/catserv/Makefile9
-rw-r--r--src/modules/demos/catserv/README4
-rw-r--r--src/modules/demos/catserv/catserv_extern.h11
-rw-r--r--src/modules/demos/catserv/catserv_messages.c14
-rw-r--r--src/modules/demos/catserv/catserv_messages.h10
-rw-r--r--src/modules/demos/catserv/ircd_catserv.c112
-rw-r--r--src/modules/demos/catserv/makefile.win324
-rw-r--r--src/modules/demos/catserv/meow.c9
-rw-r--r--src/modules/demos/catserv/meow.h9
-rw-r--r--src/modules/demos/catserv/purr.c8
-rw-r--r--src/modules/demos/catserv/purr.h9
-rw-r--r--src/modules/demos/events.c82
-rw-r--r--src/modules/demos/hs_conf.c74
-rw-r--r--src/modules/demos/hs_moo.c119
-rw-r--r--src/modules/dummy/Makefile6
-rw-r--r--src/modules/hs_request.c986
-rw-r--r--src/modules/makefile.inc.win322
-rw-r--r--src/modules/makefile.sub.win3219
-rw-r--r--src/modules/makefile.win3241
-rw-r--r--src/modules/ns_maxemail.c228
-rw-r--r--src/modules/ns_noop_convert.c173
-rw-r--r--src/modules/os_ignore_db.c545
-rw-r--r--src/modules/os_info.c780
31 files changed, 4450 insertions, 0 deletions
diff --git a/src/modules/Makefile b/src/modules/Makefile
new file mode 100644
index 000000000..cafbe451c
--- /dev/null
+++ b/src/modules/Makefile
@@ -0,0 +1,48 @@
+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}' 'MODULEFLAGS=${MODULEFLAGS}'
+
+OBJECTS= $(SRCS:.c=.o)
+SO_FILES=$(OBJECTS:.o=.s)
+CDEFS= -rdynamic -Wall
+
+all: modules subs
+
+modules: $(OBJECTS) $(SO_FILES)
+
+install:
+ $(CP) ./*.so $(MODULE_PATH)
+ @for i in $(SUBS); do \
+ echo "make install in $$i..."; \
+ (cd $$i; $(MAKE) $(MAKEARGS) install);done
+
+distclean: spotless
+
+.c.o:
+ $(CC) ${CFLAGS} ${CDEFS} ${MODULEFLAGS} -I../${INCLUDEDIR} -c $<
+
+.o.s:
+ $(CC) ${SHARED} ../mod_version.o $< -o $*.so ${PROFILE}
+ @$(TOUCH) $*.s
+
+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 *.s *.so *.c~ core
+
+spotless:
+ rm -f *.o *.s *.so *.c~ core *.so Makefile.inc
+
diff --git a/src/modules/Makefile.sub b/src/modules/Makefile.sub
new file mode 100644
index 000000000..7697249bf
--- /dev/null
+++ b/src/modules/Makefile.sub
@@ -0,0 +1,28 @@
+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}' 'MODULEFLAGS=${MODULEFLAGS}'
+
+OBJECTS= $(SRCS:.c=.o)
+SO_FILES=$(OBJECTS:.o=.s)
+CDEFS= -rdynamic -Wall
+
+all: module
+
+module: $(OBJECTS) so
+
+distclean: spotless
+
+.c.o:
+ $(CC) ${CFLAGS} ${CDEFS} ${MODULEFLAGS} -I../ -I../../${INCLUDEDIR} -c $<
+
+so:
+ $(CC) ${SHARED} ../../mod_version.o $(OBJECTS) -o ../$(TARGET).so ${PROFILE}
+
+clean:
+ rm -f *.o *.so *.c~ core
+
+spotless:
+ rm -f *~ *.o *.so *.c~ core
diff --git a/src/modules/README b/src/modules/README
new file mode 100644
index 000000000..6aee0ac47
--- /dev/null
+++ b/src/modules/README
@@ -0,0 +1 @@
+Please read the "MODULES" file located on the "docs" directory.
diff --git a/src/modules/bs_fantasy_unban.c b/src/modules/bs_fantasy_unban.c
new file mode 100644
index 000000000..a17e06551
--- /dev/null
+++ b/src/modules/bs_fantasy_unban.c
@@ -0,0 +1,82 @@
+/* BotServ core fantasy functions
+ *
+ * (C) 2003-2008 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);
+
+ /* free target if needed (#852) */
+ Anope_Free(target);
+ }
+
+ return MOD_CONT;
+}
diff --git a/src/modules/configure b/src/modules/configure
new file mode 100755
index 000000000..cf2158d66
--- /dev/null
+++ b/src/modules/configure
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+echo2 () {
+ $ECHO2 "$*$ECHO2SUF" # these are defined later
+}
+
+ECHO2SUF=''
+if [ "`echo -n a ; echo -n b`" = "ab" ] ; then
+ ECHO2='echo -n'
+elif [ "`echo 'a\c' ; echo 'b\c'`" = "ab" ] ; then
+ ECHO2='echo' ; ECHO2SUF='\c'
+elif [ "`printf 'a' 2>&1 ; printf 'b' 2>&1`" = "ab" ] ; then
+ ECHO2='printf "%s"'
+else
+ # oh well...
+ ECHO2='echo'
+fi
+export ECHO2 ECHO2SUF
+
+
+echo2 "SRCS=" > ./Makefile.inc
+FIRST=1
+for oldfile in *.c
+do
+ if [ "$FIRST" = 1 ] ; then
+ echo2 " "$oldfile >> ./Makefile.inc
+ else
+ echo "\\" >> ./Makefile.inc
+ echo2 " " $oldfile >> ./Makefile.inc
+ fi
+ FIRST=0
+done
+echo "" >> ./Makefile.inc
+
+echo2 "SUBS=" >> ./Makefile.inc
+FIRST=1
+for dir in *
+do
+ if [ -d $dir ] ; then
+ if [ -f $dir/configure ] ; then
+ cd $dir
+ ./configure
+ cd ..
+ fi
+ if [ -f $dir/Makefile ] ; then
+ if [ "$FIRST" = 1 ] ; then
+ echo2 " "$dir >> ./Makefile.inc
+ else
+ echo "\\" >> ./Makefile.inc
+ echo2 " " $dir >> ./Makefile.inc
+ fi
+ FIRST=0
+ fi
+ fi
+done
+
+exit 0
+
diff --git a/src/modules/cs_appendtopic.c b/src/modules/cs_appendtopic.c
new file mode 100644
index 000000000..7e0d27bb4
--- /dev/null
+++ b/src/modules/cs_appendtopic.c
@@ -0,0 +1,247 @@
+/* cs_appendtopic.c - Add text to a channels topic
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Based on the original module by SGR <Alex_SGR@ntlworld.com>
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: GeniusDex <geniusdex@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send bug reports to the Anope Coder instead of the module
+ * author, because any changes since the inclusion into anope
+ * are not supported by the original author.
+ *
+ */
+/*************************************************************************/
+
+#include "module.h"
+
+#define AUTHOR "SGR"
+#define VERSION "$Id$"
+
+ /* ------------------------------------------------------------
+ * Name: cs_appendtopic
+ * Author: SGR <Alex_SGR@ntlworld.com>
+ * Date: 31/08/2003
+ * ------------------------------------------------------------
+ *
+ * This module has no configurable options. For information on
+ * this module, load it and refer to /ChanServ APPENDTOPIC HELP
+ *
+ * Thanks to dengel, Rob and Certus for all there support.
+ * Especially Rob, who always manages to show me where I have
+ * not allocated any memory. Even if it takes a few weeks of
+ * pestering to get him to look at it.
+ *
+ * ------------------------------------------------------------
+ */
+
+/* ---------------------------------------------------------------------- */
+/* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING */
+/* ---------------------------------------------------------------------- */
+
+#define LNG_NUM_STRINGS 3
+
+#define LNG_CHAN_HELP 0
+#define LNG_CHAN_HELP_APPENDTOPIC 1
+#define LNG_APPENDTOPIC_SYNTAX 2
+
+int my_cs_appendtopic(User * u);
+void my_cs_help(User * u);
+int my_cs_help_appendtopic(User * u);
+void my_add_languages(void);
+
+int AnopeInit(int argc, char **argv)
+{
+ Command *c;
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ c = createCommand("APPENDTOPIC", my_cs_appendtopic, NULL, -1, -1, -1,
+ -1, -1);
+ if ((status = moduleAddCommand(CHANSERV, c, MOD_HEAD))) {
+ alog("[cs_appendtopic] Unable to create APPENDTOPIC command: %d",
+ status);
+ return MOD_STOP;
+ }
+ moduleAddHelp(c, my_cs_help_appendtopic);
+ moduleSetChanHelp(my_cs_help);
+
+ my_add_languages();
+
+ alog("[cs_appendtopic] Loaded successfully");
+
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ alog("[cs_appendtopic] Unloaded successfully");
+}
+
+void my_cs_help(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP);
+}
+
+int my_cs_help_appendtopic(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, LNG_APPENDTOPIC_SYNTAX);
+ notice(s_ChanServ, u->nick, " ");
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP_APPENDTOPIC);
+ return MOD_STOP;
+}
+
+int my_cs_appendtopic(User * u)
+{
+ char *cur_buffer;
+ char *chan;
+ char *newtopic;
+ char topic[1024];
+ Channel *c;
+ ChannelInfo *ci;
+
+ cur_buffer = moduleGetLastBuffer();
+ chan = myStrGetToken(cur_buffer, ' ', 0);
+ newtopic = myStrGetTokenRemainder(cur_buffer, ' ', 1);
+
+ if (!chan || !newtopic) {
+ moduleNoticeLang(s_ChanServ, u, LNG_APPENDTOPIC_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) {
+ snprintf(topic, sizeof(topic), "%s %s", ci->last_topic,
+ newtopic);
+ free(ci->last_topic);
+ } else {
+ strscpy(topic, newtopic, sizeof(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, c->creation_time);
+ anope_cmd_mode(NULL, c->name, "+o %s", s_ChanServ);
+ }
+ }
+ anope_cmd_topic(whosends(ci), c->name, u->nick, topic, c->topic_time);
+ if (ircd->join2set) {
+ if (whosends(ci) == s_ChanServ) {
+ anope_cmd_part(s_ChanServ, c->name, NULL);
+ }
+ }
+ }
+ return MOD_CONT;
+}
+
+void my_add_languages(void)
+{
+ /* English (US) */
+ char *langtable_en_us[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Add text to a channels topic",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "This command allows users to append text to a currently set\n"
+ "channel topic. When TOPICLOCK is on, the topic is updated and\n"
+ "the new, updated topic is locked.",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Syntax: APPENDTOPIC channel text\n"
+ };
+
+ /* Dutch (NL) */
+ char *langtable_nl[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Voeg tekst aan een kanaal onderwerp toe",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "Dit command stelt gebruikers in staat om text toe te voegen\n"
+ "achter het huidige onderwerp van een kanaal. Als TOPICLOCK aan\n"
+ "staat, zal het onderwerp worden bijgewerkt en zal het nieuwe,\n"
+ "bijgewerkte topic worden geforceerd.",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Gebruik: APPENDTOPIC kanaal tekst\n"
+ };
+
+ /* German (DE) */
+ char *langtable_de[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Fьgt einen Text zu einem Channel-Topic hinzu.",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "Dieser Befehl erlaubt Benutzern, einen Text zu dem vorhandenen Channel-Topic\n"
+ "hinzuzufьgen. Wenn TOPICLOCK gesetzt ist, wird das Topic aktualisiert\n"
+ "und das neue, aktualisierte Topic wird gesperrt.",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Syntax: APPENDTOPIC Channel Text\n"
+ };
+
+ /* Portuguese (PT) */
+ char *langtable_pt[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Adiciona texto ao tуpico de um canal",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "Este comando permite aos usuбrios anexar texto a um tуpico de canal\n"
+ "jб definido. Quando TOPICLOCK estб ativado, o tуpico й atualizado e\n"
+ "o novo tуpico й travado.",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Sintaxe: APPENDTOPIC canal texto\n"
+ };
+
+ /* Russian (RU) */
+ char *langtable_ru[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Добавляет текст к топику канала",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "Данная команда позволяет добавить текст к топику, который установлен на указанном\n"
+ "канале. Если активирован режим TOPICLOCK, топик будет обновлен и заблокирован.\n"
+ "Примечание: текст будет ДОБАВЛЕН к топику, то есть старый топик удален НЕ БУДЕТ.\n",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Синтаксис: APPENDTOPIC #канал текст\n"
+ };
+
+ /* Italian (IT) */
+ char *langtable_it[] = {
+ /* LNG_CHAN_HELP */
+ " APPENDTOPIC Aggiunge del testo al topic di un canale",
+ /* LNG_CHAN_HELP_APPENDTOPIC */
+ "Questo comando permette agli utenti di aggiungere del testo ad un topic di un canale\n"
+ "giа impostato. Se TOPICLOCK и attivato, il topic viene aggiornato e il nuovo topic\n"
+ "viene bloccato.",
+ /* LNG_APPENDTOPIC_SYNTAX */
+ "Sintassi: APPENDTOPIC canale testo\n"
+ };
+
+ moduleInsertLanguage(LANG_EN_US, LNG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_NL, LNG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_DE, LNG_NUM_STRINGS, langtable_de);
+ moduleInsertLanguage(LANG_PT, LNG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LNG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LNG_NUM_STRINGS, langtable_it);
+}
+
+/* EOF */
diff --git a/src/modules/cs_enforce.c b/src/modules/cs_enforce.c
new file mode 100644
index 000000000..a9beec419
--- /dev/null
+++ b/src/modules/cs_enforce.c
@@ -0,0 +1,479 @@
+/* cs_enforce - Add a /cs ENFORCE command to enforce various set
+ * options and channelmodes on a channel.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: GeniusDex <geniusdex@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send any bug reports to the Anope Coder, as he will be able
+ * to deal with it best.
+ */
+
+#include "module.h"
+
+#define AUTHOR "Anope"
+#define VERSION "$Id$"
+
+int my_cs_enforce(User * u);
+void my_cs_help(User * u);
+int my_cs_help_enforce(User * u);
+void my_add_languages(void);
+
+#define LNG_NUM_STRINGS 6
+
+#define LNG_CHAN_HELP 0
+#define LNG_ENFORCE_SYNTAX 1
+#define LNG_CHAN_HELP_ENFORCE 2
+#define LNG_CHAN_HELP_ENFORCE_R_ENABLED 3
+#define LNG_CHAN_HELP_ENFORCE_R_DISABLED 4
+#define LNG_CHAN_RESPONSE 5
+
+int AnopeInit(int argc, char **argv)
+{
+ Command *c;
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ c = createCommand("ENFORCE", my_cs_enforce, NULL, -1, -1, -1, -1, -1);
+ if ((status = moduleAddCommand(CHANSERV, c, MOD_HEAD))) {
+ alog("[cs_enforce] Unable to create ENFORCE command: %d", status);
+ return MOD_STOP;
+ }
+
+ moduleAddHelp(c, my_cs_help_enforce);
+ moduleSetChanHelp(my_cs_help);
+
+ my_add_languages();
+
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ /* Nothing to clean up */
+}
+
+/* Enforcing functions */
+void do_enforce_secureops(Channel * c)
+{
+ struct c_userlist *user;
+ struct c_userlist *next;
+ ChannelInfo *ci;
+ uint32 flags;
+
+ if (!(ci = c->ci))
+ return;
+
+ if (debug)
+ alog("debug: cs_enforce: Enforcing SECUREOPS on %s", c->name);
+
+ /* Dirty hack to allow chan_set_correct_modes to work ok.
+ * We pretend like SECUREOPS is on so it doesn't ignore that
+ * part of the code. This way we can enforce SECUREOPS even
+ * if it's off.
+ */
+ flags = ci->flags;
+ ci->flags |= CI_SECUREOPS;
+
+ user = c->users;
+ do {
+ next = user->next;
+ chan_set_correct_modes(user->user, c, 0);
+ user = next;
+ } while (user);
+
+ ci->flags = flags;
+}
+
+void do_enforce_restricted(Channel * c)
+{
+ struct c_userlist *user;
+ struct c_userlist *next;
+ ChannelInfo *ci;
+ int16 old_nojoin_level;
+ char mask[BUFSIZE];
+ char *reason;
+ char *av[3];
+ User *u;
+
+ if (!(ci = c->ci))
+ return;
+
+ if (debug)
+ alog("debug: cs_enforce: Enforcing RESTRICTED on %s", c->name);
+
+ old_nojoin_level = ci->levels[CA_NOJOIN];
+ if (ci->levels[CA_NOJOIN] < 0)
+ ci->levels[CA_NOJOIN] = 0;
+
+ user = c->users;
+ do {
+ next = user->next;
+ u = user->user;
+ if (check_access(u, c->ci, CA_NOJOIN)) {
+ get_idealban(ci, u, mask, sizeof(mask));
+ reason = getstring(u->na, CHAN_NOT_ALLOWED_TO_JOIN);
+ anope_cmd_mode(whosends(ci), ci->name, "+b %s %lu", mask,
+ time(NULL));
+ 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);
+ }
+ user = next;
+ } while (user);
+
+ ci->levels[CA_NOJOIN] = old_nojoin_level;
+}
+
+void do_enforce_cmode_R(Channel * c)
+{
+ struct c_userlist *user;
+ struct c_userlist *next;
+ ChannelInfo *ci;
+ char mask[BUFSIZE];
+ char *reason;
+ char *av[3];
+ User *u;
+ CBMode *cbm;
+
+ if (!(ci = c->ci))
+ return;
+
+ if (debug)
+ alog("debug: cs_enforce: Enforcing mode +R on %s", c->name);
+
+ user = c->users;
+ do {
+ next = user->next;
+ u = user->user;
+ if (!nick_identified(u)) {
+ get_idealban(ci, u, mask, sizeof(mask));
+ reason = getstring(u->na, CHAN_NOT_ALLOWED_TO_JOIN);
+ if (((cbm = &cbmodes['R'])->flag == 0)
+ || !(c->mode & cbm->flag))
+ anope_cmd_mode(whosends(ci), ci->name, "+b %s %lu", mask,
+ time(NULL));
+ 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);
+ }
+ user = next;
+ } while (user);
+}
+
+/* Enforcing Group Functions */
+void do_enforce_set(Channel * c)
+{
+ ChannelInfo *ci;
+
+ if (!(ci = c->ci))
+ return;
+
+ if (ci->flags & CI_SECUREOPS)
+ do_enforce_secureops(c);
+ if (ci->flags & CI_RESTRICTED)
+ do_enforce_restricted(c);
+}
+
+void do_enforce_modes(Channel * c)
+{
+ CBMode *cbm;
+
+ if (((cbm = &cbmodes['R'])->flag != 0) && (c->mode & cbm->flag))
+ do_enforce_cmode_R(c);
+}
+
+/* End of enforcing functions */
+
+int my_cs_enforce(User * u)
+{
+ char *cur_buffer;
+ char *chan=NULL;
+ char *what=NULL;
+ Channel *c;
+ ChannelInfo *ci;
+
+ cur_buffer = moduleGetLastBuffer();
+ chan = myStrGetToken(cur_buffer, ' ', 0);
+
+ if (!chan) {
+ moduleNoticeLang(s_ChanServ, u, LNG_ENFORCE_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, ci->name);
+ } else if (!is_services_admin(u) && !check_access(u, ci, CA_AKICK)) {
+ notice_lang(s_ChanServ, u, PERMISSION_DENIED);
+ } else {
+ what = myStrGetToken(cur_buffer, ' ', 1);
+ if (!what || (stricmp(what, "SET") == 0)) {
+ do_enforce_set(c);
+ moduleNoticeLang(s_ChanServ,u,LNG_CHAN_RESPONSE,what);
+ } else if (stricmp(what, "MODES") == 0) {
+ do_enforce_modes(c);
+ moduleNoticeLang(s_ChanServ,u,LNG_CHAN_RESPONSE,what);
+ } else if (stricmp(what, "SECUREOPS") == 0) {
+ do_enforce_secureops(c);
+ moduleNoticeLang(s_ChanServ,u,LNG_CHAN_RESPONSE,what);
+ } else if (stricmp(what, "RESTRICTED") == 0) {
+ do_enforce_restricted(c);
+ moduleNoticeLang(s_ChanServ,u,LNG_CHAN_RESPONSE,what);
+ } else if (stricmp(what, "+R") == 0) {
+ do_enforce_cmode_R(c);
+ moduleNoticeLang(s_ChanServ,u,LNG_CHAN_RESPONSE,what);
+ } else {
+ moduleNoticeLang(s_ChanServ, u, LNG_ENFORCE_SYNTAX);
+ }
+ }
+
+ if(chan) free(chan);
+ if(what) free(what);
+
+ return MOD_CONT;
+}
+
+/* Language and response stuff */
+void my_cs_help(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP);
+}
+
+int my_cs_help_enforce(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, LNG_ENFORCE_SYNTAX);
+ notice(s_ChanServ, u->nick, " ");
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP_ENFORCE);
+ notice(s_ChanServ, u->nick, " ");
+ if (cbmodes['R'].flag != 0)
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP_ENFORCE_R_ENABLED);
+ else
+ moduleNoticeLang(s_ChanServ, u, LNG_CHAN_HELP_ENFORCE_R_DISABLED);
+
+ return MOD_STOP;
+}
+
+void my_add_languages(void)
+{
+ /* English (US) */
+ char *langtable_en_us[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Enforce various channel modes and set options",
+ /* LNG_ENFORCE_SYNTAX */
+ "Syntax: \002ENFORCE \037channel\037 [\037what\037]\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Enforce various channel modes and set options. The \037channel\037\n"
+ "option indicates what channel to enforce the modes and options\n"
+ "on. The \037what\037 option indicates what modes and options to\n"
+ "enforce, and can be any of SET, SECUREOPS, RESTRICTED, MODES,\n"
+ "or +R. When left out, it defaults to SET.\n"
+ " \n"
+ "If \037what\037 is SET, it will enforce SECUREOPS and RESTRICTED\n"
+ "on the users currently in the channel, if they are set. Give\n"
+ "SECUREOPS to enforce the SECUREOPS option, even if it is not\n"
+ "enabled. Use RESTRICTED to enfore the RESTRICTED option, also\n"
+ "if it's not enabled.",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "If \037what\037 is MODES, it will enforce channelmode +R if it is\n"
+ "set. If +R is specified for \037what\037, the +R channelmode will\n"
+ "also be enforced, but even if it is not set. If it is not set,\n"
+ "users will be banned to ensure they don't just rejoin.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "If \037what\037 is MODES, nothing will be enforced, since it would\n"
+ "enforce modes that the current ircd does not support. If +R is\n"
+ "specified for \037what\037, an equalivant of channelmode +R on\n"
+ "other ircds will be enforced. All users that are in the channel\n"
+ "but have not identified for their nickname will be kicked and\n"
+ "banned from the channel.",
+ /* LNG_CHAN_RESPONSE */
+ "Enforced %s"
+ };
+
+ /* Dutch (NL) */
+ char *langtable_nl[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Forceer enkele kanaalmodes en set-opties",
+ /* LNG_ENFORCE_SYNTAX */
+ "Syntax: \002ENFORCE \037kanaal\037 [\037wat\037]\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Forceer enkele kannalmodes en set-opties. De \037kanaal\037 optie\n"
+ "geeft aan op welk kanaal de modes en opties geforceerd moeten\n"
+ "worden. De \037wat\037 optie geeft aan welke modes en opties\n"
+ "geforceerd moeten worden; dit kan SET, SECUREOPS, RESTRICTED,\n"
+ "MODES, of +R zijn. Indien weggelaten is dit standaard SET.\n"
+ " \n"
+ "Als er voor \037wat\037 SET wordt ingevuld, zullen SECUREOPS en\n"
+ "RESTRICTED geforceerd worden op de gebruikers in het kanaal,\n"
+ "maar alleen als die opties aangezet zijn voor het kanaal. Als\n"
+ "SECUREOPS of RESTRICTED wordt gegeven voor \037wat\037 zal die optie\n"
+ "altijd geforceerd worden, ook als die niet is aangezet.",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "Als er voor \037wat\037 MODES wordt ingevuld, zal kanaalmode +R worden\n"
+ "geforceerd, als die op het kanaal aan staat. Als +R wordt ingevuld,\n"
+ "zal kanaalmode +R worden geforceerd, maar ook als die niet aan"
+ "staat voor het kanaal. Als +R niet aan staat, zullen alle ook\n"
+ "gebanned worden om te zorgen dat ze niet opnieuw het kanaal binnen\n"
+ "kunnen komen.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "Als er voor \037wat\037 MODES wordt ingevuld, zal er niks gebeuren.\n"
+ "Normaal gesproken wordt er een kanaalmode geforceerd die op deze\n"
+ "server niet ondersteund wordt. Als +R wordt ingevuld voor \037wat\037\n"
+ "zullen alle gebruikers die in het kanaal zitten maar zich niet\n"
+ "hebben geidentificeerd voor hun nick uit het kanaal gekicked en\n"
+ "verbannen worden.",
+ /* LNG_CHAN_RESPONSE */
+ "Enforced %s"
+ };
+
+ /* German (DE) */
+ char *langtable_de[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Erzwingt verschieden Modes und SET Optionen",
+ /* LNG_ENFORCE_SYNTAX */
+ "Syntax: \002ENFORCE \037Channel\037 [\037was\037]\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Erzwingt verschieden Modes und SET Optionen. Die \037Channel\037\n"
+ "Option zeigt dir den Channel an, indem Modes und Optionen\n"
+ "zu erzwingen sind. Die \037was\037 Option zeigt dir welche Modes\n"
+ "und Optionen zu erzwingen sind. Die kцnnen nur SET, SECUREOPS,\n"
+ "RESTRICTED, MODES oder +R sein.Default ist SET.\n"
+ " \n"
+ "Wenn \037was\037 SET ist, wird SECUREOPS und RESTRICTED\n"
+ "auf die User die z.Z.in Channel sind erzwungen, wenn sie AN sind.\n"
+ "Benutze SECUREOPS oder RESTRICTED , um die Optionen einzeln\n"
+ "zu erzwingen, also wenn sie nicht eingeschaltet sind.",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "Wenn \037was\037 MODES ist, wird das ChannelMode +R erzwungen\n"
+ "falls an. Wenn \037was\037 +R ist, wird +R erzwungen aber eben\n"
+ "wenn noch nicht als Channel-Mode ist. Wenn +R noch nicht als\n"
+ "Channel-Mode war werden alle User aus den Channel gebannt um\n"
+ "sicher zu sein das sie nicht rejoinen.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "Wenn \037was\037 MODES ist, wird nichts erzwungen weil es MODES seine\n"
+ "kцnnen die dein IRCD nicht unterstьtzt. Wenn \037was\037 +R ist\n"
+ "oder ein Modes was auf ein anderen IRCD gleich +R ist, wird es\n"
+ "erzwungen. Alle User die nicht fьr deren Nicknamen identifiziert\n"
+ "sind werden aus den Channel gekickt und gebannt.",
+ /* LNG_CHAN_RESPONSE */
+ "Erzwungen %s"
+ };
+
+ /* Portuguese (PT) */
+ char *langtable_pt[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Verifica o cumprimento de vбrios modos de canal e opзхes ajustadas",
+ /* LNG_ENFORCE_SYNTAX */
+ "Sintaxe: \002ENFORCE \037canal\037 [\037opзгo\037]\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Verifica o cumprimento de vбrios modos de canal e opзхes ajustadas.\n"
+ "O campo \037canal\037 indica qual canal deve ter os modos e opзхes verificadas\n"
+ "O campo \037opзгo\037 indica quais modos e opзхes devem ser verificadas,\n"
+ "e pode ser: SET, SECUREOPS, RESTRICTED, MODES ou +R\n"
+ "Quando deixado em branco, o padrгo й SET.\n"
+ " \n"
+ "Se \037opзгo\037 for SET, serгo verificadas as opзхes SECUREOPS e RESTRICTED\n"
+ "para usuбrios que estiverem no canal, caso elas estejam ativadas. Use\n"
+ "SECUREOPS para verificar a opзгo SECUREOPS, mesmo que ela nгo esteja ativada\n"
+ "Use RESTRICTED para verificar a opзгo RESTRICTED, mesmo que ela nгo esteja\n"
+ "ativada.",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "Se \037opзгo\037 for MODES, serб verificado o modo de canal +R caso ele\n"
+ "esteja ativado. Se +R for especificado para \037opзгo\037, o modo de canal\n"
+ "+R tambйm serб verificado, mesmo que ele nгo esteja ativado. Se ele nгo\n"
+ "estiver ativado, os usuбrios serгo banidos para evitar que reentrem no canal.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "Se \037opзгo\037 for MODES, nada serб verificado, visto que isto poderia\n"
+ "verificar modos que o IRCd atual nгo suporta. Se +R for especificado\n"
+ "para \037opзгo\037, um equivalente ao modo de canal +R em outros IRCds\n"
+ "serб verificado. Todos os usuбrios que estгo no canal, mas nгo estejam\n"
+ "identificados para seus nicks serгo kickados e banidos do canal.",
+ /* LNG_CHAN_RESPONSE */
+ "Verificado %s"
+ };
+
+ /* Russian (RU) */
+ char *langtable_ru[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Перепроверка и установка различных режимов и опций канала",
+ /* LNG_ENFORCE_SYNTAX */
+ "Синтаксис: \002ENFORCE \037#канал\037 \037параметр\037\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Перепроверка и установка различных режимов и опций канала.\n"
+ "\037Параметр\037 указывает какие опции или режимы канала должны быть\n"
+ "перепроверены. В качестве параметра могут быть указаны: SET, SECUREOPS,\n"
+ "RESTRICTED, MODES, или +R. Если параметр не указан, по-умолчанию будет SET.\n"
+ " \n"
+ "Если в качестве \037параметра\037 указано SET, будут перепроверены опции\n"
+ "SECUREOPS и RESTRICTED относительно пользователей на указанном канале\n"
+ "(при условии, что опции включены). Отдельно указанный параметр SECUREOPS\n"
+ "применит опцию SECUREOPS (даже если она \037НЕ\037 установлена). Параметр\n"
+ "RESTRICTED применит опцию RESTRICTED (даже если она \037НЕ\037 установлена)",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "Если в качестве \037параметра\037 указано MODES, будет перепроверен режим +R\n"
+ "(если он установлен). Отдельно указанный параметр \037+R\037 применит\n"
+ "канальный режим +R, даже если он не установлен, и забанит всех пользователей,\n"
+ "которые не идентифицировались к своему нику или не имеют зарегистрированного ника.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "Если в качестве \037параметра\037 указано MODES, перепроверка осуществлена\n"
+ "НЕ БУДЕТ, так как текущий IRCD не поддерживает необходимые режимы.\n"
+ "Отдельно указанный параметр \037+R\037 применит канальный режим, эквивалентный\n"
+ "режиму +R и забанит всех пользователей, которые не идентифицировались к своему\n"
+ "нику или не имеют зарегистрированного ника.",
+ /* LNG_CHAN_RESPONSE */
+ "Перепроверено: %s"
+ };
+
+ /* Italian (IT) */
+ char *langtable_it[] = {
+ /* LNG_CHAN_HELP */
+ " ENFORCE Forza diversi modi di canale ed opzioni SET",
+ /* LNG_ENFORCE_SYNTAX */
+ "Sintassi: \002ENFORCE \037canale\037 [\037cosa\037]\002",
+ /* LNG_CHAN_HELP_ENFORCE */
+ "Forza diversi modi di canale ed opzioni SET. Il parametro \037canale\037\n"
+ "indica il canale sul quale forzare i modi e le opzioni. Il parametro\n"
+ "\037cosa\037 indica i modi e le opzioni da forzare, e possono essere\n"
+ "qualsiasi delle opzioni SET, SECUREOPS, RESTRICTED, MODES, o +R.\n"
+ "Se non specificato, viene sottointeso SET.\n"
+ " \n"
+ "Se \037cosa\037 и SET, forzerа SECUREOPS e RESTRICTED sugli utenti\n"
+ "attualmente nel canale, se sono impostati. Specifica SECUREOPS per\n"
+ "forzare l'opzione SECUREOPS, anche se non и attivata. Specifica\n"
+ "RESTRICTED per forzare l'opzione RESTRICTED, anche se non и\n"
+ "attivata.",
+ /* LNG_CHAN_HELP_ENFORCE_R_ENABLED */
+ "Se \037cosa\037 и MODES, forzerа il modo del canale +R se и impostato.\n"
+ "Se +R и specificato per \037cosa\037, il modo del canale +R verrа\n"
+ "forzato, anche se non и impostato. Se non и impostato, gli utenti\n"
+ "verranno bannati per assicurare che non rientrino semplicemente.",
+ /* LNG_CHAN_HELP_ENFORCE_R_DISABLED */
+ "Se \037cosa\037 и MODES, niente verrа forzato, siccome forzerebbe\n"
+ "dei modi che l'ircd in uso non supporterebbe. Se +R и specificato\n"
+ "per \037cosa\037, un modo equivalente a +R sui altri ircd verrа\n"
+ "forzato. Tutti gli utenti presenti nel canale ma non identificati\n"
+ "per il loro nickname verranno bannati ed espulsi dal canale.\n",
+ /* LNG_CHAN_RESPONSE */
+ "Forzato %s"
+ };
+
+ moduleInsertLanguage(LANG_EN_US, LNG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_NL, LNG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_DE, LNG_NUM_STRINGS, langtable_de);
+ moduleInsertLanguage(LANG_PT, LNG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LNG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LNG_NUM_STRINGS, langtable_it);
+}
+
+/* EOF */
diff --git a/src/modules/cs_tban.c b/src/modules/cs_tban.c
new file mode 100644
index 000000000..9558c92fd
--- /dev/null
+++ b/src/modules/cs_tban.c
@@ -0,0 +1,253 @@
+/* cs_tban.c - Bans the user for a given length of time
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Based on the original module by Rob <rob@anope.org>
+ * Included in the Anope module pack since Anope 1.7.8
+ * Anope Coder: Rob <rob@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send bug reports to the Anope Coder instead of the module
+ * author, because any changes since the inclusion into anope
+ * are not supported by the original author.
+ *
+ */
+/*************************************************************************/
+
+#include "module.h"
+
+#define AUTHOR "Rob"
+#define VERSION "$Id$"
+
+void myHelp(User * u);
+void myFullHelpSyntax(User * u);
+int myFullHelp(User * u);
+void mySendResponse(User * u, char *channel, char *mask, char *time);
+
+int do_tban(User * u);
+void addBan(Channel * c, time_t timeout, char *banmask);
+int delBan(int argc, char **argv);
+int canBanUser(Channel * c, User * u, User * u2);
+
+void mAddLanguages(void);
+
+#define LANG_NUM_STRINGS 4
+#define TBAN_HELP 0
+#define TBAN_SYNTAX 1
+#define TBAN_HELP_DETAIL 2
+#define TBAN_RESPONSE 3
+
+int AnopeInit(int argc, char **argv)
+{
+ Command *c;
+ int status = 0;
+
+ moduleSetChanHelp(myHelp);
+ c = createCommand("TBAN", do_tban, NULL, -1, -1, -1, -1, -1);
+ moduleAddHelp(c, myFullHelp);
+ status = moduleAddCommand(CHANSERV, c, MOD_HEAD);
+
+ mAddLanguages();
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ if (status != MOD_ERR_OK) {
+ return MOD_STOP;
+ }
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ /* module is unloading */
+}
+
+void myHelp(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, TBAN_HELP);
+}
+
+void myFullHelpSyntax(User * u)
+{
+ moduleNoticeLang(s_ChanServ, u, TBAN_SYNTAX);
+}
+
+int myFullHelp(User * u)
+{
+ myFullHelpSyntax(u);
+ notice(s_ChanServ, u->nick, "");
+ moduleNoticeLang(s_ChanServ, u, TBAN_HELP_DETAIL);
+ return MOD_CONT;
+}
+
+void mySendResponse(User * u, char *channel, char *mask, char *time)
+{
+ moduleNoticeLang(s_ChanServ, u, TBAN_RESPONSE, mask, channel, time);
+}
+
+int do_tban(User * u)
+{
+ char mask[BUFSIZE];
+ Channel *c;
+ User *u2 = NULL;
+
+ char *buffer = moduleGetLastBuffer();
+ char *chan;
+ char *nick;
+ char *time;
+
+ chan = myStrGetToken(buffer, ' ', 0);
+ nick = myStrGetToken(buffer, ' ', 1);
+ time = myStrGetToken(buffer, ' ', 2);
+
+ if (time && chan && nick) {
+
+ if (!(c = findchan(chan))) {
+ notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan);
+ } else if (!(u2 = finduser(nick))) {
+ notice_lang(s_ChanServ, u, NICK_X_NOT_IN_USE, nick);
+ } else {
+ if (canBanUser(c, u, u2)) {
+ get_idealban(c->ci, u2, mask, sizeof(mask));
+ addBan(c, dotime(time), mask);
+ mySendResponse(u, chan, mask, time);
+ }
+ }
+ } else {
+ myFullHelpSyntax(u);
+ }
+ if (time)
+ free(time);
+ if (nick)
+ free(nick);
+ if (chan)
+ free(chan);
+
+ return MOD_CONT;
+}
+
+void addBan(Channel * c, time_t timeout, char *banmask)
+{
+ char *av[3];
+ char *cb[2];
+
+ cb[0] = c->name;
+ cb[1] = banmask;
+
+ av[0] = sstrdup("+b");
+ av[1] = banmask;
+
+ anope_cmd_mode(whosends(c->ci), c->name, "+b %s", av[1]);
+ chan_set_modes(s_ChanServ, c, 2, av, 1);
+
+ free(av[0]);
+ moduleAddCallback("tban", time(NULL) + timeout, delBan, 2, cb);
+}
+
+int delBan(int argc, char **argv)
+{
+ char *av[3];
+ Channel *c;
+
+ av[0] = sstrdup("-b");
+ av[1] = argv[1];
+
+ if ((c = findchan(argv[0])) && c->ci) {
+ anope_cmd_mode(whosends(c->ci), c->name, "-b %s", av[1]);
+ chan_set_modes(s_ChanServ, c, 2, av, 1);
+ }
+
+ free(av[0]);
+
+ return MOD_CONT;
+}
+
+int canBanUser(Channel * c, User * u, User * u2)
+{
+ ChannelInfo *ci;
+ int ok = 0;
+ 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, c->name);
+ } else if (!check_access(u, ci, CA_BAN)) {
+ notice_lang(s_ChanServ, u, ACCESS_DENIED);
+ } 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 {
+ ok = 1;
+ }
+
+ return ok;
+}
+
+
+void mAddLanguages(void)
+{
+ char *langtable_en_us[] = {
+ " TBAN Bans the user for a given length of time",
+ "Syntax: TBAN channel nick time",
+ "Bans the given user from a channel for a specified length of\n"
+ "time. If the ban is removed before by hand, it will NOT be replaced.",
+ "%s banned from %s, will auto-expire in %s"
+ };
+
+ char *langtable_nl[] = {
+ " TBAN Verban een gebruiker voor een bepaalde tijd",
+ "Syntax: TBAN kanaal nick tijd",
+ "Verbant de gegeven gebruiken van het gegeven kanaal voor de\n"
+ "gegeven tijdsduur. Als de verbanning eerder wordt verwijderd,\n"
+ "zal deze NIET worden vervangen.",
+ "%s verbannen van %s, zal verlopen in %s"
+ };
+
+ char *langtable_de[] = {
+ " TBAN Bant ein User fьr eine bestimmte Zeit aus ein Channel",
+ "Syntax: TBAN Channel Nickname Zeit",
+ "Bant ein User fьr eine bestimmte Zeit aus ein Channel\n"
+ "Wenn der Ban manuell entfernt wird, wird es NICHT ersetzt.",
+ "%s gebannt von %s, wird auto-auslaufen in %s"
+ };
+
+ char *langtable_pt[] = {
+ " TBAN Bane o usuбrio por um determinado perнodo de tempo",
+ "Sintaxe: TBAN canal nick tempo",
+ "Bane de um canal o usuбrio especificado por um determinado perнodo de\n"
+ "tempo. Se o ban for removido manualmente antes do tempo, ele nгo serб recolocado.",
+ "%s foi banido do %s, irб auto-expirar em %s"
+ };
+
+ char *langtable_ru[] = {
+ " TBAN Банит пользователя на указанный промежуток времени",
+ "Синтаксис: TBAN #канал ник время",
+ "Банит пользователя на указанный промежуток времени в секундах\n"
+ "Примечание: удаленный вручную (до своего истечения) бан НЕ БУДЕТ\n"
+ "переустановлен сервисами автоматически!",
+ "Установленный бан %s на канале %s истечет через %s секунд"
+ };
+
+ char *langtable_it[] = {
+ " TBAN Banna l'utente per un periodo di tempo specificato",
+ "Sintassi: TBAN canale nick tempo",
+ "Banna l'utente specificato da un canale per un periodo di tempo\n"
+ "specificato. Se il ban viene rimosso a mano prima della scadenza, NON verrа rimpiazzato.",
+ "%s bannato da %s, scadrа automaticamente tra %s"
+ };
+
+ moduleInsertLanguage(LANG_EN_US, LANG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_NL, LANG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_DE, LANG_NUM_STRINGS, langtable_de);
+ moduleInsertLanguage(LANG_PT, LANG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LANG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LANG_NUM_STRINGS, langtable_it);
+
+}
+
+
+/* EOF */
diff --git a/src/modules/demos/catserv/Makefile b/src/modules/demos/catserv/Makefile
new file mode 100644
index 000000000..5b2f4efa3
--- /dev/null
+++ b/src/modules/demos/catserv/Makefile
@@ -0,0 +1,9 @@
+SRCS= ircd_catserv.c \
+ catserv_messages.c \
+ meow.c \
+ purr.c
+
+TARGET=ircd_catserv
+
+include ../Makefile.sub
+
diff --git a/src/modules/demos/catserv/README b/src/modules/demos/catserv/README
new file mode 100644
index 000000000..c3d3f7084
--- /dev/null
+++ b/src/modules/demos/catserv/README
@@ -0,0 +1,4 @@
+This is an EXAMPLE module, it serves no real purpose.
+
+This module was broken down into multiple files to demonstrate how multiple files can be used.
+
diff --git a/src/modules/demos/catserv/catserv_extern.h b/src/modules/demos/catserv/catserv_extern.h
new file mode 100644
index 000000000..02c21addb
--- /dev/null
+++ b/src/modules/demos/catserv/catserv_extern.h
@@ -0,0 +1,11 @@
+#ifndef CATSERV_DEFS_H
+#define CATSERV_DEFS_H
+
+#ifdef _WIN32
+extern __declspec(dllexport) char *s_CatServ;
+#else
+E char *s_CatServ;
+#endif
+
+#endif
+
diff --git a/src/modules/demos/catserv/catserv_messages.c b/src/modules/demos/catserv/catserv_messages.c
new file mode 100644
index 000000000..e11235b4e
--- /dev/null
+++ b/src/modules/demos/catserv/catserv_messages.c
@@ -0,0 +1,14 @@
+#include "catserv_messages.h"
+#include "module.h"
+#include "meow.h"
+#include "purr.h"
+
+void addMessageList(void)
+{
+ Command *c;
+ c = createCommand("meow", do_meow, NULL, -1, -1, -1, -1, -1);
+ moduleAddCommand(Catserv_cmdTable, c, MOD_UNIQUE);
+ c = createCommand("purr", do_purr, NULL, -1, -1, -1, -1, -1);
+ moduleAddCommand(Catserv_cmdTable, c, MOD_UNIQUE);
+}
+
diff --git a/src/modules/demos/catserv/catserv_messages.h b/src/modules/demos/catserv/catserv_messages.h
new file mode 100644
index 000000000..bb3f82dd0
--- /dev/null
+++ b/src/modules/demos/catserv/catserv_messages.h
@@ -0,0 +1,10 @@
+#ifndef CATSERV_MESSAGES_H
+#define CATSERV_MESSAGES_H
+
+#include "module.h"
+
+CommandHash *Catserv_cmdTable[MAX_CMD_HASH];
+void addMessageList(void);
+
+#endif
+
diff --git a/src/modules/demos/catserv/ircd_catserv.c b/src/modules/demos/catserv/ircd_catserv.c
new file mode 100644
index 000000000..ae34d6161
--- /dev/null
+++ b/src/modules/demos/catserv/ircd_catserv.c
@@ -0,0 +1,112 @@
+/**
+ * Simple module to load up a client called CatServ and process commands for it
+ * This module is an example, and has no useful purpose!
+ *
+ * Please visit http://modules.anope.org for useful modules!
+ *
+ **/
+
+#include "module.h"
+#include "catserv_messages.h"
+
+#define AUTHOR "Anope"
+#define VERSION "$Id$"
+
+int my_privmsg(char *source, int ac, char **av);
+
+void addClient(char *nick, char *realname);
+void delClient(void);
+void catserv(User * u, char *buf);
+
+char *s_CatServ = "CatServ";
+
+int AnopeInit(int argc, char **argv)
+{
+ Message *msg = NULL;
+ int status;
+#ifdef IRC_UNREAL32
+ if (UseTokens) {
+ msg = createMessage("!", my_privmsg);
+ } else {
+ msg = createMessage("PRIVMSG", my_privmsg);
+ }
+#else
+ msg = createMessage("PRIVMSG", my_privmsg);
+#endif
+ status = moduleAddMessage(msg, MOD_HEAD);
+ if (status == MOD_ERR_OK) {
+ addClient(s_CatServ, "meow!");
+ addMessageList();
+ }
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ alog("ircd_catserv.so: loaded, message status [%d]", status);
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ delClient();
+}
+
+int my_privmsg(char *source, int ac, char **av)
+{
+ User *u;
+ char *s;
+
+ /* First, some basic checks */
+ if (ac != 2)
+ return MOD_CONT; /* bleh */
+ if (!(u = finduser(source))) {
+ return MOD_CONT;
+ } /* non-user source */
+ if (*av[0] == '#') {
+ return MOD_CONT;
+ }
+ /* Channel message */
+ /* we should prolly honour the ignore list here, but i cba for this... */
+ s = strchr(av[0], '@');
+ if (s) {
+ *s++ = 0;
+ if (stricmp(s, ServerName) != 0)
+ return MOD_CONT;
+ }
+ if ((stricmp(av[0], s_CatServ)) == 0) { /* its for US! */
+ catserv(u, av[1]);
+ return MOD_STOP;
+ } else { /* ok it isnt us, let the old code have it */
+ return MOD_CONT;
+ }
+}
+
+void addClient(char *nick, char *realname)
+{
+ anope_cmd_bot_nick(nick, "catserv", "meow.meow.land", realname, "+");
+}
+
+void delClient(void)
+{
+ anope_cmd_quit(s_CatServ, "QUIT :Module Unloaded!");
+}
+
+/*****************************************************************************/
+/* Main CatServ routine. */
+void catserv(User * u, char *buf)
+{
+ char *cmd, *s;
+
+ cmd = strtok(buf, " ");
+
+ if (!cmd) {
+ return;
+ } else if (stricmp(cmd, "\1PING") == 0) {
+ if (!(s = strtok(NULL, "")))
+ s = "\1";
+ notice(s_CatServ, u->nick, "\1PING %s", s);
+ } else if (skeleton) {
+ notice_lang(s_CatServ, u, SERVICE_OFFLINE, s_CatServ);
+ } else {
+ mod_run_cmd(s_CatServ, u, Catserv_cmdTable, cmd);
+ }
+}
+
diff --git a/src/modules/demos/catserv/makefile.win32 b/src/modules/demos/catserv/makefile.win32
new file mode 100644
index 000000000..638704440
--- /dev/null
+++ b/src/modules/demos/catserv/makefile.win32
@@ -0,0 +1,4 @@
+SRCS=ircd_catserv.c purr.c catserv_messages.c meow.c
+TARGET=ircd_catserv.dll
+
+include ..\Makefile.sub.win32
diff --git a/src/modules/demos/catserv/meow.c b/src/modules/demos/catserv/meow.c
new file mode 100644
index 000000000..9279eec0b
--- /dev/null
+++ b/src/modules/demos/catserv/meow.c
@@ -0,0 +1,9 @@
+#include "meow.h"
+
+#include "catserv_extern.h"
+
+int do_meow(User * u) {
+ notice(s_CatServ, u->nick, "MEOW!");
+ return MOD_STOP;
+}
+
diff --git a/src/modules/demos/catserv/meow.h b/src/modules/demos/catserv/meow.h
new file mode 100644
index 000000000..0f28673a0
--- /dev/null
+++ b/src/modules/demos/catserv/meow.h
@@ -0,0 +1,9 @@
+#ifndef CATSERV_MEOW_H
+#define CATSERV_MEOW_H
+
+#include "module.h"
+
+int do_meow(User * u);
+
+#endif
+
diff --git a/src/modules/demos/catserv/purr.c b/src/modules/demos/catserv/purr.c
new file mode 100644
index 000000000..5a39dc26e
--- /dev/null
+++ b/src/modules/demos/catserv/purr.c
@@ -0,0 +1,8 @@
+#include "purr.h"
+#include "catserv_extern.h"
+
+int do_purr(User * u)
+{
+ notice(s_CatServ, u->nick, "PURR!");
+ return MOD_STOP;
+}
diff --git a/src/modules/demos/catserv/purr.h b/src/modules/demos/catserv/purr.h
new file mode 100644
index 000000000..a92e421f6
--- /dev/null
+++ b/src/modules/demos/catserv/purr.h
@@ -0,0 +1,9 @@
+#ifndef CATSERV_PURR_H
+#define CATSERV_PURR_H
+
+#include "module.h"
+
+int do_purr(User * u);
+
+#endif
+
diff --git a/src/modules/demos/events.c b/src/modules/demos/events.c
new file mode 100644
index 000000000..dad0fd0e6
--- /dev/null
+++ b/src/modules/demos/events.c
@@ -0,0 +1,82 @@
+/**
+ * Simple module to show the usage of event messages and hooks
+ * This module is an example, and has no useful purpose!
+ *
+ * Please visit http://modules.anope.org for useful modules!
+ *
+ **/
+
+#include "module.h"
+
+#define AUTHOR "Anope"
+#define VERSION "$Id$"
+
+int my_nick(char *source, int ac, char **av);
+int my_save(int argc, char **argv);
+int do_moo(int argc, char **argv);
+
+int AnopeInit(int argc, char **argv)
+{
+ EvtMessage *msg = NULL;
+ EvtHook *hook = NULL;
+ int status;
+ msg = createEventHandler("NICK", my_nick);
+ status = moduleAddEventHandler(msg);
+
+ hook = createEventHook(EVENT_DB_SAVING, my_save);
+ status = moduleAddEventHook(hook);
+
+
+ hook = createEventHook(EVENT_BOT_FANTASY, do_moo);
+ status = moduleAddEventHook(hook);
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ /* unloading */
+}
+
+int my_nick(char *source, int ac, char **av)
+{
+ alog("Internal Event - nick is %s",av[0]);
+ return MOD_CONT;
+}
+
+int my_save(int argc, char **argv)
+{
+ if(argc>=1) {
+ if (!stricmp(argv[0], EVENT_START)) {
+ alog("Saving the databases! has started");
+ } else {
+ alog("Saving the databases is complete");
+ }
+ }
+ return MOD_CONT;
+}
+
+/**
+ * command to be called when a EVENT_BOT_FANTASY event is recived.
+ * @param argc The paramater count for this event.
+ * @param argv[0] The cmd used.
+ * @param argv[1] The nick of the command user.
+ * @param argv[2] The channel name the command was used in.
+ * @param argv[3] The rest of the text after the command.
+ * @return MOD_CONT or MOD_STOP
+ **/
+int do_moo(int argc, char **argv) {
+ ChannelInfo *ci;
+ if(argc>=3) { /* We need at least 3 arguments */
+ if(stricmp(argv[0],"moo")==0) { /* is it meant for us? */
+ if((ci = cs_findchan(argv[2]))) { /* channel should always exist */
+ anope_cmd_privmsg(ci->bi->nick, ci->name, "%cACTION moo's at %s %c",1,argv[1],1);
+ return MOD_STOP; /* We've dealt with it, dont let others */
+ }
+ }
+ }
+ return MOD_CONT; /* guess it wasnt for us, pass it on */
+}
+
diff --git a/src/modules/demos/hs_conf.c b/src/modules/demos/hs_conf.c
new file mode 100644
index 000000000..45b4bb330
--- /dev/null
+++ b/src/modules/demos/hs_conf.c
@@ -0,0 +1,74 @@
+#include "module.h"
+
+#define AUTHOR "Anope"
+#define VERSION "1"
+
+/**
+ * Default setting to be used if no confing value is found
+ **/
+#define DEFAULT_SETTING "moo"
+
+int mShowSetting(User *u);
+int mReadConfig(int argc, char **argv);
+
+char *setting;
+
+int AnopeInit(int argc, char **argv) {
+ Command *c;
+ EvtHook *hook;
+ int status = 0;
+
+ setting = NULL;
+
+ mReadConfig(0,NULL);
+
+ c = createCommand("SHOW",mShowSetting,NULL,-1,-1,-1,-1,-1);
+ status = moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ hook = createEventHook(EVENT_RELOAD, mReadConfig);
+ status = moduleAddEventHook(hook);
+
+ if(status!=MOD_ERR_OK) {
+ return MOD_STOP;
+ }
+ return MOD_CONT;
+}
+
+/**
+ * free the globals when we close
+ **/
+void AnopeFini(void) {
+ if(setting)
+ free(setting);
+}
+
+/**
+ * Simple function to show the user the current config setting
+ **/
+int mShowSetting(User *u) {
+ notice(s_HostServ,u->nick,"Setting in use is [%s]",setting);
+ return MOD_CONT;
+}
+
+/**
+ * Load the config setting up, this will be called whenever
+ * the EVENT_RELOAD event is recived.
+ **/
+int mReadConfig(int argc, char **argv) {
+ char *tmp=NULL;
+ Directive d[] = {{"HSConfigSetting", {{PARAM_STRING, PARAM_RELOAD, &tmp}}}};
+ moduleGetConfigDirective(d);
+
+ if(setting) {
+ free(setting);
+ }
+ if(tmp) {
+ setting = tmp;
+ } else {
+ setting = sstrdup(DEFAULT_SETTING);
+ }
+ return MOD_CONT;
+}
+
+
+/* EOF */
diff --git a/src/modules/demos/hs_moo.c b/src/modules/demos/hs_moo.c
new file mode 100644
index 000000000..b65e83bb6
--- /dev/null
+++ b/src/modules/demos/hs_moo.c
@@ -0,0 +1,119 @@
+/**
+ * This is an EXAMPLE module, which adds the "moo" command to HostServ
+ *
+ * This command does NOT do anything useful at all!
+ *
+ * Please visit http://modules.anope.org for useful modules!
+ *
+ **/
+#include "module.h"
+
+#define AUTHOR "Anope" /* Set the Author for a modinfo reply */
+#define VERSION "$Id$" /* Set the version for a modinfo reply */
+
+int hs_moo_show(User * u); /* Function to use when a /hs moo command is recived */
+int test(int argc, char **argv);
+void myHostServHelp(User *u); /* Function to display out help in a /hs help response */
+int myHostServMooHelp(User *u); /* Function to display help to _everyone_ when a /hs help moo is called*/
+int myHostServMooRegHelp(User *u); /* Function to display extra help to regular-users when a /hs help moo is called*/
+int myHostServMooOperHelp(User *u); /* Function to display extra help to opers when a /hs help moo is called*/
+int myHostServMooAdminHelp(User *u); /* Function to display extra help to admins when a /hs help moo is called*/
+int myHostServMooRootHelp(User *u); /* Function to display extra help to roors when a /hs help moo is called*/
+
+int AnopeInit(int argc, char **argv) /* This will be executed when the module is loaded */
+{
+ Command *c; /* Pointer to a Command */
+ int status = 0; /* the status of our new command */
+ c = createCommand("moo", hs_moo_show, NULL, -1, -1, -1, -1, -1); /* Create a new command "moo" pointing to hs_moo */
+
+ moduleAddHelp(c,myHostServMooHelp); /* add help for all users to this command */
+ moduleAddRegHelp(c,myHostServMooRegHelp); /* add extra regular-user only help to this command */
+ moduleAddOperHelp(c,myHostServMooOperHelp); /* add extra oper only help to this command */
+ moduleAddAdminHelp(c,myHostServMooAdminHelp); /* add extra admin only help to this command */
+ moduleAddRootHelp(c,myHostServMooRootHelp); /* add extra root only help to this command */
+
+ moduleSetHostHelp(myHostServHelp); /* add us to the .hs help list */
+
+ status = moduleAddCommand(HOSTSERV, c, MOD_HEAD); /* Add the command to the HOSTSERV cmd table */
+
+ /* Check if we have any argv's */
+ if(argc>0) {
+ /* we do, the first will be the nick of the person modload'ing us */
+ /* or NULL if we were auto-loaded */
+ if(argv[0]) {
+ alog("hs_moo was modloaded by: [%s]",argv[0]);
+ } else {
+ alog("hs_moo was automatically loaded by anope");
+ }
+ }
+ alog("hs_moo.so: Add Command 'moo' Status: %d",status); /* Log the command being added */
+
+ moduleAddCallback("test",time(NULL)+dotime("15s"),test,0,NULL); /* set a call-back function to exec in 3 mins time */
+ moduleDelCallback("test");
+ moduleAddAuthor(AUTHOR); /* tell Anope about the author */
+ moduleAddVersion(VERSION); /* Tell Anope about the verison */
+
+ if(status!=MOD_ERR_OK) {
+ return MOD_STOP;
+ }
+ return MOD_CONT;
+}
+
+int hs_moo_show(User * u)
+{
+ notice(s_HostServ, u->nick, "MOO! - This command was loaded via a module!"); /* Just notice the user */
+ return MOD_STOP; /* MOD_STOP means we will NOT pass control back to other */
+} /* modules waiting to handle the /hs moo command! */
+
+int test(int argc, char **argv) {
+ alog("CallBack from hs_moo with %d paramaters",argc);
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ /* module is unloading */
+}
+
+/***************************************************************************************************************************************/
+/* The code below here shows various ways of dealing with the module help system */
+/***************************************************************************************************************************************/
+
+void myHostServHelp(User *u) {
+ notice(s_HostServ,u->nick, " MOO Moo's at the user!"); /* this will appear in the help list */
+}
+
+int myHostServMooHelp(User *u) {
+ notice(s_HostServ,u->nick,"Syntax: Moo"); /* this will be sent to everyone who does /msg hostserv help moo */
+ notice(s_HostServ,u->nick,"This command is an example provided");
+ notice(s_HostServ,u->nick,"by the Anope development team.");
+ return MOD_CONT; /* allow any other module's with help for /hs moo to run */
+}
+
+int myHostServMooRootHelp(User *u) { /* this will only be sent to ROOTS ONLY who /msg hostserv moo */
+ myHostServMooAdminHelp(u); /* this line lets us show roots the ADMIN help as well as the root help */
+ notice(s_HostServ,u->nick,"Only roots will see this part of the help");
+ return MOD_CONT;
+}
+
+int myHostServMooAdminHelp(User *u) { /* this will only be sent to ADMINS ONLY who /msg hostserv moo */
+ myHostServMooOperHelp(u); /* this line lets us show admins the OPER help as well as the admin help */
+ notice(s_HostServ,u->nick,"Only admins will see this part of the help");
+ notice(s_HostServ,u->nick,"why not visit us on www.anope.org ?");
+ return MOD_CONT;
+}
+
+int myHostServMooOperHelp(User *u) { /* this will only be sent to OPERS ONLY who /msg hostserv moo */
+ notice(s_HostServ,u->nick,"Only opers will see this part of the help");
+ notice(s_HostServ,u->nick,"for more help/support with modules");
+ notice(s_HostServ,u->nick,"visit us on irc.anope.org #anope! :)");
+ return MOD_CONT;
+}
+
+int myHostServMooRegHelp(User *u) { /* this will only be sent to REGULAR USERS ONLY who /msg hostserv moo */
+ notice(s_HostServ,u->nick,"Only non-opers will see this part of the help");
+ notice(s_HostServ,u->nick,"as we've left it hidden from opers");
+ return MOD_CONT;
+}
+
+/* EOF */
diff --git a/src/modules/dummy/Makefile b/src/modules/dummy/Makefile
new file mode 100644
index 000000000..ec93af36d
--- /dev/null
+++ b/src/modules/dummy/Makefile
@@ -0,0 +1,6 @@
+all: DUMMY
+
+DUMMY:
+clean:
+distclean:
+install:
diff --git a/src/modules/hs_request.c b/src/modules/hs_request.c
new file mode 100644
index 000000000..dde94070c
--- /dev/null
+++ b/src/modules/hs_request.c
@@ -0,0 +1,986 @@
+/* hs_request.c - Add request and activate functionality to HostServ,
+ * along with adding +req as optional param to HostServ list.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Based on the original module by Rob <rob@anope.org>
+ * Included in the Anope module pack since Anope 1.7.11
+ * Anope Coder: GeniusDex <geniusdex@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send bug reports to the Anope Coder instead of the module
+ * author, because any changes since the inclusion into anope
+ * are not supported by the original author.
+ */
+
+#include "module.h"
+
+#define AUTHOR "Rob"
+#define VERSION "$Id$"
+
+/* Configuration variables */
+int HSRequestMemoUser = 0;
+int HSRequestMemoOper = 0;
+int HSRequestMemoSetters = 0;
+char *HSRequestDBName = NULL;
+
+#define HSREQ_DEFAULT_DBNAME "hs_request.db"
+
+/* Language defines */
+#define LNG_NUM_STRINGS 21
+
+#define LNG_REQUEST_SYNTAX 0
+#define LNG_REQUESTED 1
+#define LNG_REQUEST_WAIT 2
+#define LNG_REQUEST_MEMO 3
+#define LNG_ACTIVATE_SYNTAX 4
+#define LNG_ACTIVATED 5
+#define LNG_ACTIVATE_MEMO 6
+#define LNG_REJECT_SYNTAX 7
+#define LNG_REJECTED 8
+#define LNG_REJECT_MEMO 9
+#define LNG_REJECT_MEMO_REASON 10
+#define LNG_NO_REQUEST 11
+#define LNG_HELP 12
+#define LNG_HELP_SETTER 13
+#define LNG_HELP_REQUEST 14
+#define LNG_HELP_ACTIVATE 15
+#define LNG_HELP_ACTIVATE_MEMO 16
+#define LNG_HELP_REJECT 17
+#define LNG_HELP_REJECT_MEMO 18
+#define LNG_WAITING_SYNTAX 19
+#define LNG_HELP_WAITING 20
+
+int hs_do_request(User * u);
+int hs_do_activate(User * u);
+int hs_do_reject(User * u);
+int hs_do_list_out(User * u);
+
+int hs_help_request(User * u);
+int hs_help_activate(User * u);
+int hs_help_reject(User * u);
+int hs_help_waiting(User * u);
+void hs_help(User * u);
+
+void my_add_host_request(char *nick, char *vIdent, char *vhost,
+ char *creator, int32 tmp_time);
+int my_isvalidchar(const char c);
+void my_memo_lang(User * u, char *name, int z, int number, ...);
+void req_send_memos(User * u, char *vHost);
+void show_list(User * u);
+int hs_do_waiting(User * u);
+int ns_do_drop(User * u);
+
+void hsreq_save_db(void);
+void hsreq_load_db(void);
+int hsreqevt_db_saving(int argc, char **argv);
+int hsreqevt_db_backup(int argc, char **argv);
+
+void my_load_config(void);
+void my_add_languages(void);
+
+HostCore *hs_request_head;
+
+int AnopeInit(int argc, char **argv)
+{
+ Command *c;
+ EvtHook *hook;
+
+ c = createCommand("request", hs_do_request, nick_identified, -1, -1,
+ -1, -1, -1);
+ moduleAddHelp(c, hs_help_request);
+ moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ c = createCommand("activate", hs_do_activate, is_host_setter, -1, -1,
+ -1, -1, -1);
+ moduleAddHelp(c, hs_help_activate);
+ moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ c = createCommand("reject", hs_do_reject, is_host_setter, -1, -1, -1,
+ -1, -1);
+ moduleAddHelp(c, hs_help_reject);
+ moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ c = createCommand("waiting", hs_do_waiting, is_host_setter, -1, -1, -1,
+ -1, -1);
+ moduleAddHelp(c, hs_help_waiting);
+ moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ c = createCommand("list", hs_do_list_out, is_services_oper, -1, -1, -1,
+ -1, -1);
+ moduleAddCommand(HOSTSERV, c, MOD_HEAD);
+
+ c = createCommand("drop", ns_do_drop, NULL, -1, -1, -1, -1, -1);
+ moduleAddCommand(NICKSERV, c, MOD_HEAD);
+
+ hook = createEventHook(EVENT_DB_SAVING, hsreqevt_db_saving);
+ moduleAddEventHook(hook);
+
+ hook = createEventHook(EVENT_DB_BACKUP, hsreqevt_db_backup);
+ moduleAddEventHook(hook);
+
+ moduleSetHostHelp(hs_help);
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ my_load_config();
+ my_add_languages();
+ hs_request_head = NULL;
+
+ if (debug)
+ alog("[hs_request] Loading database...");
+ hsreq_load_db();
+ alog("hs_request loaded");
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ if (debug)
+ alog("[hs_request] Saving database...");
+ hsreq_save_db();
+
+ /* Clean up all open host requests */
+ while (hs_request_head)
+ hs_request_head = deleteHostCore(hs_request_head, NULL);
+
+ free(HSRequestDBName);
+ alog("hs_request un-loaded");
+}
+
+int hs_do_request(User * u)
+{
+ char *cur_buffer;
+ char *nick;
+ char *rawhostmask;
+ char hostmask[HOSTMAX];
+ NickAlias *na;
+ int32 tmp_time;
+ char *s;
+ char *vIdent = NULL;
+ time_t now = time(NULL);
+
+ cur_buffer = moduleGetLastBuffer();
+ nick = u->nick;
+ rawhostmask = myStrGetToken(cur_buffer, ' ', 0);
+
+ if (!nick || !rawhostmask) {
+ if (rawhostmask)
+ free(rawhostmask);
+ moduleNoticeLang(s_HostServ, u, LNG_REQUEST_SYNTAX);
+ 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) {
+ moduleNoticeLang(s_HostServ, u, LNG_REQUEST_SYNTAX);
+ free(vIdent);
+ return MOD_CONT;
+ }
+ if (strlen(vIdent) > USERMAX - 1) {
+ notice_lang(s_HostServ, u, HOST_SET_IDENTTOOLONG, USERMAX);
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ } else {
+ for (s = vIdent; *s; s++) {
+ if (!my_isvalidchar(*s)) {
+ notice_lang(s_HostServ, u, HOST_SET_IDENT_ERROR);
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ }
+ }
+ }
+ if (!ircd->vident) {
+ notice_lang(s_HostServ, u, HOST_NO_VIDENT);
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ }
+ }
+ if (strlen(rawhostmask) < HOSTMAX - 1) {
+ snprintf(hostmask, HOSTMAX, "%s", rawhostmask);
+ } else {
+ notice_lang(s_HostServ, u, HOST_SET_TOOLONG, HOSTMAX);
+ if (vIdent)
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ }
+
+ if (!isValidHost(hostmask, 3)) {
+ notice_lang(s_HostServ, u, HOST_SET_ERROR);
+ if (vIdent)
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ }
+
+ tmp_time = time(NULL);
+ if ((na = findnick(nick))) {
+ if (HSRequestMemoOper || HSRequestMemoSetters) {
+ if (MSSendDelay > 0 && u
+ && u->lastmemosend + MSSendDelay > now) {
+ moduleNoticeLang(s_HostServ, u, LNG_REQUEST_WAIT,
+ MSSendDelay);
+ u->lastmemosend = now;
+ if (vIdent)
+ free(vIdent);
+ free(rawhostmask);
+ return MOD_CONT;
+ }
+ }
+ my_add_host_request(nick, vIdent, hostmask, u->nick, tmp_time);
+
+ moduleNoticeLang(s_HostServ, u, LNG_REQUESTED);
+ req_send_memos(u, hostmask);
+ alog("New vHost Requested by %s", nick);
+ } else {
+ notice_lang(s_HostServ, u, HOST_NOREG, nick);
+ }
+
+ if (vIdent)
+ free(vIdent);
+ free(rawhostmask);
+
+ return MOD_CONT;
+}
+
+void my_memo_lang(User * u, char *name, int z, int number, ...)
+{
+ va_list va;
+ char buffer[4096], outbuf[4096];
+ char *fmt = NULL;
+ int lang = LANG_EN_US;
+ char *s, *t, *buf;
+ User *u2;
+
+ if ((mod_current_module_name)
+ && (!mod_current_module
+ || strcmp(mod_current_module_name, mod_current_module->name)))
+ mod_current_module = findModule(mod_current_module_name);
+
+ u2 = finduser(name);
+ /* Find the users lang, and use it if we cant */
+ if (u2 && u2->na && u2->na->nc)
+ lang = u2->na->nc->language;
+
+ /* If the users lang isnt supported, drop back to enlgish */
+ if (mod_current_module->lang[lang].argc == 0)
+ lang = LANG_EN_US;
+
+ /* If the requested lang string exists for the language */
+ if (mod_current_module->lang[lang].argc > number) {
+ fmt = mod_current_module->lang[lang].argv[number];
+
+ buf = sstrdup(fmt);
+ s = buf;
+ while (*s) {
+ t = s;
+ s += strcspn(s, "\n");
+ if (*s)
+ *s++ = '\0';
+ strscpy(outbuf, t, sizeof(outbuf));
+
+ va_start(va, number);
+ vsnprintf(buffer, 4095, outbuf, va);
+ va_end(va);
+ memo_send(u, name, buffer, z);
+ }
+ free(buf);
+ } else {
+ alog("%s: INVALID language string call, language: [%d], String [%d]", mod_current_module->name, lang, number);
+ }
+}
+
+
+void req_send_memos(User * u, char *vHost)
+{
+ int i;
+ int z = 2;
+
+ if (checkDefCon(DEFCON_NO_NEW_MEMOS))
+ return;
+
+ if (HSRequestMemoOper == 1) {
+ for (i = 0; i < servopers.count; i++) {
+ my_memo_lang(u, (((NickCore *) servopers.list[i])->display), z,
+ LNG_REQUEST_MEMO, vHost);
+ }
+ for (i = 0; i < servadmins.count; i++) {
+ my_memo_lang(u, (((NickCore *) servadmins.list[i])->display),
+ z, LNG_REQUEST_MEMO, vHost);
+ }
+ for (i = 0; i < RootNumber; i++) {
+ my_memo_lang(u, ServicesRoots[i], z, LNG_REQUEST_MEMO, vHost);
+ }
+ }
+ if (HSRequestMemoSetters == 1) {
+ for (i = 0; i < HostNumber; i++) {
+ my_memo_lang(u, HostSetters[i], z, LNG_REQUEST_MEMO, vHost);
+ }
+ }
+}
+
+int ns_do_drop(User * u)
+{
+ HostCore *tmp;
+ boolean found = false;
+ NickAlias *na;
+
+ na = findnick(u->nick);
+ tmp = findHostCore(hs_request_head, u->nick, &found);
+
+ if (found && na)
+ hs_request_head = deleteHostCore(hs_request_head, tmp);
+
+ return MOD_CONT;
+}
+
+int hs_do_reject(User * u)
+{
+ char *cur_buffer;
+ char *nick;
+ char *reason;
+ HostCore *tmp, *hc;
+ boolean found = false;
+
+ cur_buffer = moduleGetLastBuffer();
+ nick = myStrGetToken(cur_buffer, ' ', 0);
+ reason = myStrGetTokenRemainder(cur_buffer, ' ', 1);
+
+ if (!nick) {
+ moduleNoticeLang(s_HostServ, u, LNG_REJECT_SYNTAX);
+ if (reason)
+ free(reason);
+ return MOD_CONT;
+ }
+
+ tmp = findHostCore(hs_request_head, nick, &found);
+ if (found) {
+ if (!tmp)
+ hc = hs_request_head;
+ else
+ hc = tmp->next;
+
+ if (HSRequestMemoUser) {
+ if (reason)
+ my_memo_lang(u, hc->nick, 2, LNG_REJECT_MEMO_REASON,
+ reason);
+ else
+ my_memo_lang(u, hc->nick, 2, LNG_REJECT_MEMO);
+ }
+
+ hs_request_head = deleteHostCore(hs_request_head, tmp);
+ moduleNoticeLang(s_HostServ, u, LNG_REJECTED, nick);
+ alog("Host Request for %s rejected by %s (%s)", nick, u->nick,
+ reason ? reason : "");
+ } else {
+ moduleNoticeLang(s_HostServ, u, LNG_NO_REQUEST, nick);
+ }
+
+ free(nick);
+ if (reason)
+ free(reason);
+
+ return MOD_CONT;
+}
+
+int hs_do_activate(User * u)
+{
+ char *cur_buffer;
+ char *nick;
+ NickAlias *na;
+ HostCore *tmp, *hc;
+ boolean found = false;
+
+ cur_buffer = moduleGetLastBuffer();
+ nick = myStrGetToken(cur_buffer, ' ', 0);
+
+ if (!nick) {
+ moduleNoticeLang(s_HostServ, u, LNG_ACTIVATE_SYNTAX);
+ return MOD_CONT;
+ }
+
+ if ((na = findnick(nick))) {
+ tmp = findHostCore(hs_request_head, nick, &found);
+ if (found) {
+ if (!tmp)
+ hc = hs_request_head;
+ else
+ hc = tmp->next;
+
+ addHostCore(hc->nick, hc->vIdent, hc->vHost, u->nick,
+ time(NULL));
+
+ if (HSRequestMemoUser)
+ my_memo_lang(u, hc->nick, 2, LNG_ACTIVATE_MEMO);
+
+ hs_request_head = deleteHostCore(hs_request_head, tmp);
+ moduleNoticeLang(s_HostServ, u, LNG_ACTIVATED, nick);
+ alog("Host Request for %s activated by %s", nick, u->nick);
+ } else {
+ moduleNoticeLang(s_HostServ, u, LNG_NO_REQUEST, nick);
+ }
+ } else {
+ notice_lang(s_HostServ, u, NICK_X_NOT_REGISTERED, nick);
+ }
+
+ free(nick);
+ return MOD_CONT;
+}
+
+
+void my_add_host_request(char *nick, char *vIdent, char *vhost,
+ char *creator, int32 tmp_time)
+{
+ HostCore *tmp;
+ boolean found = false;
+
+ if (!hs_request_head) {
+ hs_request_head =
+ createHostCorelist(hs_request_head, nick, vIdent, vhost,
+ creator, tmp_time);
+ } else {
+ tmp = findHostCore(hs_request_head, nick, &found);
+ if (!found) {
+ hs_request_head =
+ insertHostCore(hs_request_head, tmp, nick, vIdent, vhost,
+ creator, tmp_time);
+ } else {
+ hs_request_head = deleteHostCore(hs_request_head, tmp); /* delete the old entry */
+ my_add_host_request(nick, vIdent, vhost, creator, tmp_time); /* recursive call to add new entry */
+ }
+ }
+}
+
+int my_isvalidchar(const char c)
+{
+ if (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'))
+ || ((c >= '0') && (c <= '9')) || (c == '.') || (c == '-'))
+ return 1;
+ else
+ return 0;
+}
+
+int hs_do_list_out(User * u)
+{
+ char *key;
+
+ key = moduleGetLastBuffer();
+ if (!key)
+ return MOD_CONT;
+
+ if (stricmp(key, "+req") != 0)
+ return MOD_CONT;
+
+ show_list(u);
+
+ return MOD_CONT;
+}
+
+int hs_do_waiting(User * u)
+{
+ show_list(u);
+
+ return MOD_CONT;
+}
+
+void show_list(User * u)
+{
+ struct tm *tm;
+ char buf[BUFSIZE];
+ int counter = 1;
+ int from = 0, to = 0;
+ int display_counter = 0;
+ HostCore *current;
+
+ current = hs_request_head;
+ while (current) {
+ if ((((counter >= from) && (counter <= to))
+ || ((from == 0) && (to == 0)))
+ && (display_counter < NSListMax)) {
+ display_counter++;
+ tm = localtime(&current->time);
+ strftime(buf, sizeof(buf),
+ getstring(NULL, 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;
+ }
+ notice_lang(s_HostServ, u, HOST_LIST_FOOTER, display_counter);
+}
+
+int hs_help_request(User * u)
+{
+ moduleNoticeLang(s_HostServ, u, LNG_REQUEST_SYNTAX);
+ notice(s_HostServ, u->nick, " ");
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_REQUEST);
+
+ return MOD_CONT;
+}
+
+int hs_help_activate(User * u)
+{
+ if (is_host_setter(u)) {
+ moduleNoticeLang(s_HostServ, u, LNG_ACTIVATE_SYNTAX);
+ notice(s_HostServ, u->nick, " ");
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_ACTIVATE);
+ if (HSRequestMemoUser)
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_ACTIVATE_MEMO);
+ } else {
+ notice_lang(s_HostServ, u, NO_HELP_AVAILABLE, "ACTIVATE");
+ }
+
+ return MOD_CONT;
+}
+
+int hs_help_reject(User * u)
+{
+ if (is_host_setter(u)) {
+ moduleNoticeLang(s_HostServ, u, LNG_REJECT_SYNTAX);
+ notice(s_HostServ, u->nick, " ");
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_REJECT);
+ if (HSRequestMemoUser)
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_REJECT_MEMO);
+ } else {
+ notice_lang(s_HostServ, u, NO_HELP_AVAILABLE, "REJECT");
+ }
+
+ return MOD_CONT;
+}
+
+int hs_help_waiting(User * u)
+{
+ if (is_host_setter(u)) {
+ moduleNoticeLang(s_HostServ, u, LNG_WAITING_SYNTAX);
+ notice(s_HostServ, u->nick, " ");
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_WAITING);
+ } else {
+ notice_lang(s_HostServ, u, NO_HELP_AVAILABLE, "WAITING");
+ }
+
+ return MOD_CONT;
+}
+
+void hs_help(User * u)
+{
+ moduleNoticeLang(s_HostServ, u, LNG_HELP);
+ if (is_host_setter(u))
+ moduleNoticeLang(s_HostServ, u, LNG_HELP_SETTER);
+}
+void hsreq_load_db(void)
+{
+ FILE *fp;
+ char *filename;
+ char readbuf[1024];
+ char *nick, *vident, *vhost, *creator, *tmp;
+ int32 tmp_time;
+ char *buf;
+
+ if (HSRequestDBName)
+ filename = HSRequestDBName;
+ else
+ filename = HSREQ_DEFAULT_DBNAME;
+
+ fp = fopen(filename, "r");
+ if (!fp) {
+ alog("[hs_request] Unable to open database ('%s') for reading",
+ filename);
+ return;
+ }
+
+ while (fgets(readbuf, 1024, fp)) {
+ buf = normalizeBuffer(readbuf);
+ if (buf || *buf) {
+ nick = myStrGetToken(buf, ':', 0);
+ vident = myStrGetToken(buf, ':', 1);
+ vhost = myStrGetToken(buf, ':', 2);
+ tmp = myStrGetToken(buf, ':', 3);
+ if (tmp) {
+ tmp_time = strtol(tmp, (char **) NULL, 16);
+ free(tmp);
+ } else {
+ tmp_time = 0;
+ }
+ creator = myStrGetToken(buf, ':', 4);
+ if (!nick || !vident || !vhost || !creator) {
+ alog("[hs_request] Error while reading database, skipping record");
+ continue;
+ }
+ if (stricmp(vident, "(null)") == 0) {
+ free(vident);
+ vident = NULL;
+ }
+ my_add_host_request(nick, vident, vhost, creator, tmp_time);
+ free(nick);
+ free(vhost);
+ free(creator);
+ if (vident)
+ free(vident);
+ }
+ free(buf);
+ }
+
+ fclose(fp);
+
+ if (debug)
+ alog("[hs_request] Succesfully loaded database");
+}
+
+void hsreq_save_db(void)
+{
+ FILE *fp;
+ char *filename;
+ char *vident;
+ HostCore *current;
+
+ if (HSRequestDBName)
+ filename = HSRequestDBName;
+ else
+ filename = HSREQ_DEFAULT_DBNAME;
+
+ fp = fopen(filename, "w");
+ if (!fp) {
+ alog("[hs_request] Unable to open database ('%s') for writing",
+ filename);
+ return;
+ }
+
+ current = hs_request_head;
+ while (current) {
+ vident = (current->vIdent ? current->vIdent : "(null)");
+ fprintf(fp, "%s:%s:%s:%X:%s\n", current->nick, vident,
+ current->vHost, (uint32) current->time, current->creator);
+ current = current->next;
+ }
+
+ fclose(fp);
+
+ if (debug)
+ alog("[hs_request] Succesfully saved database");
+}
+
+int hsreqevt_db_saving(int argc, char **argv)
+{
+ if ((argc >= 1) && (stricmp(argv[0], EVENT_START) == 0))
+ hsreq_save_db();
+
+ return MOD_CONT;
+}
+
+int hsreqevt_db_backup(int argc, char **argv)
+{
+ if ((argc >= 1) && (stricmp(argv[0], EVENT_START) == 0)) {
+ if (HSRequestDBName)
+ ModuleDatabaseBackup(HSRequestDBName);
+ else
+ ModuleDatabaseBackup(HSREQ_DEFAULT_DBNAME);
+ }
+
+ return MOD_CONT;
+}
+
+void my_load_config(void)
+{
+ int i;
+ char *tmp = NULL;
+
+ Directive confvalues[][1] = {
+ {{"HSRequestMemoUser",
+ {{PARAM_SET, PARAM_RELOAD, &HSRequestMemoUser}}}},
+ {{"HSRequestMemoOper",
+ {{PARAM_SET, PARAM_RELOAD, &HSRequestMemoOper}}}},
+ {{"HSRequestMemoSetters",
+ {{PARAM_SET, PARAM_RELOAD, &HSRequestMemoSetters}}}},
+ {{"HSRequestDBName", {{PARAM_STRING, PARAM_RELOAD, &tmp}}}}
+ };
+
+ for (i = 0; i < 4; i++)
+ moduleGetConfigDirective(confvalues[i]);
+
+ if (tmp) {
+ if (HSRequestDBName)
+ free(HSRequestDBName);
+ HSRequestDBName = sstrdup(tmp);
+ } else {
+ HSRequestDBName = sstrdup(HSREQ_DEFAULT_DBNAME);
+ }
+
+ if (debug)
+ alog("debug: [hs_request] Set config vars: MemoUser=%d MemoOper=%d MemoSetters=%d DBName='%s'", HSRequestMemoUser, HSRequestMemoOper, HSRequestMemoSetters, HSRequestDBName);
+}
+
+void my_add_languages(void)
+{
+ char *langtable_en_us[] = {
+ /* LNG_REQUEST_SYNTAX */
+ "Syntax: \002REQUEST \037vhost\037\002",
+ /* LNG_REQUESTED */
+ "Your vHost has been requested",
+ /* LNG_REQUEST_WAIT */
+ "Please wait %d seconds before requesting a new vHost",
+ /* LNG_REQUEST_MEMO */
+ "[auto memo] vHost \002%s\002 has been requested.",
+ /* LNG_ACTIVATE_SYNTAX */
+ "Syntax: \002ACTIVATE \037nick\037\002",
+ /* LNG_ACTIVATED */
+ "vHost for %s has been activated",
+ /* LNG_ACTIVATE_MEMO */
+ "[auto memo] Your requested vHost has been approved.",
+ /* LNG_REJECT_SYNTAX */
+ "Syntax: \002REJECT \037nick\037\002",
+ /* LNG_REJECTED */
+ "vHost for %s has been rejected",
+ /* LNG_REJECT_MEMO */
+ "[auto memo] Your requested vHost has been rejected.",
+ /* LNG_REJECT_MEMO_REASON */
+ "[auto memo] Your requested vHost has been rejected. Reason: %s",
+ /* LNG_NO_REQUEST */
+ "No request for nick %s found.",
+ /* LNG_HELP */
+ " REQUEST Request a vHost for your nick",
+ /* LNG_HELP_SETTER */
+ " ACTIVATE Approve the requested vHost of a user\n"
+ " REJECT Reject the requested vHost of a user\n"
+ " WAITING Convenience command for LIST +req",
+ /* LNG_HELP_REQUEST */
+ "Request the given vHost to be actived for your nick by the\n"
+ "network administrators. Please be patient while your request\n"
+ "is being considered.",
+ /* LNG_HELP_ACTIVATE */
+ "Activate the requested vHost for the given nick.",
+ /* LNG_HELP_ACTIVATE_MEMO */
+ "A memo informing the user will also be sent.",
+ /* LNG_HELP_REJECT */
+ "Reject the requested vHost for the given nick.",
+ /* LNG_HELP_REJECT_MEMO */
+ "A memo informing the user will also be sent.",
+ /* LNG_WAITING_SYNTAX */
+ "Syntax: \002WAITING\002",
+ /* LNG_HELP_WAITING */
+ "This command is provided for convenience. It is essentially\n"
+ "the same as performing a LIST +req ."
+ };
+
+ char *langtable_nl[] = {
+ /* LNG_REQUEST_SYNTAX */
+ "Gebruik: \002REQUEST \037vhost\037\002",
+ /* LNG_REQUESTED */
+ "Je vHost is aangevraagd",
+ /* LNG_REQUEST_WAIT */
+ "Wacht %d seconden voor je een nieuwe vHost aanvraagt",
+ /* LNG_REQUEST_MEMO */
+ "[auto memo] vHost \002%s\002 is aangevraagd.",
+ /* LNG_ACTIVATE_SYNTAX */
+ "Gebruik: \002ACTIVATE \037nick\037\002",
+ /* LNG_ACTIVATED */
+ "vHost voor %s is geactiveerd",
+ /* LNG_ACTIVATE_MEMO */
+ "[auto memo] Je aangevraagde vHost is geaccepteerd.",
+ /* LNG_REJECT_SYNTAX */
+ "Gebruik: \002REJECT \037nick\037\002",
+ /* LNG_REJECTED */
+ "vHost voor %s is afgekeurd",
+ /* LNG_REJECT_MEMO */
+ "[auto memo] Je aangevraagde vHost is afgekeurd.",
+ /* LNG_REJECT_MEMO_REASON */
+ "[auto memo] Je aangevraagde vHost is afgekeurd. Reden: %s",
+ /* LNG_NO_REQUEST */
+ "Geen aanvraag voor nick %s gevonden.",
+ /* LNG_HELP */
+ " REQUEST Vraag een vHost aan voor je nick",
+ /* LNG_HELP_SETTER */
+ " ACTIVATE Activeer de aangevraagde vHost voor een gebruiker\n"
+ " REJECT Keur de aangevraagde vHost voor een gebruiker af\n"
+ " WAITING Snelkoppeling naar LIST +req",
+ /* LNG_HELP_REQUEST */
+ "Verzoek de gegeven vHost te activeren voor jouw nick bij de\n"
+ "netwerk beheerders. Het kan even duren voordat je aanvraag\n"
+ "afgehandeld wordt.",
+ /* LNG_HELP_ACTIVATE */
+ "Activeer de aangevraagde vHost voor de gegeven nick.",
+ /* LNG_HELP_ACTIVATE_MEMO */
+ "Een memo die de gebruiker op de hoogste stelt zal ook worden verstuurd.",
+ /* LNG_HELP_REJECT */
+ "Keur de aangevraagde vHost voor de gegeven nick af.",
+ /* LNG_HELP_REJECT_MEMO */
+ "Een memo die de gebruiker op de hoogste stelt zal ook worden verstuurd.",
+ /* LNG_WAITING_SYNTAX */
+ "Gebruik: \002WAITING\002",
+ /* LNG_HELP_WAITING */
+ "Dit commando is beschikbaar als handigheid. Het is simpelweg\n"
+ "hetzelfde als LIST +req ."
+ };
+
+ char *langtable_pt[] = {
+ /* LNG_REQUEST_SYNTAX */
+ "Sintaxe: \002REQUEST \037vhost\037\002",
+ /* LNG_REQUESTED */
+ "Seu pedido de vHost foi encaminhado",
+ /* LNG_REQUEST_WAIT */
+ "Por favor, espere %d segundos antes de fazer um novo pedido de vHost",
+ /* LNG_REQUEST_MEMO */
+ "[Auto Memo] O vHost \002%s\002 foi solicitado.",
+ /* LNG_ACTIVATE_SYNTAX */
+ "Sintaxe: \002ACTIVATE \037nick\037\002",
+ /* LNG_ACTIVATED */
+ "O vHost para %s foi ativado",
+ /* LNG_ACTIVATE_MEMO */
+ "[Auto Memo] Seu pedido de vHost foi aprovado.",
+ /* LNG_REJECT_SYNTAX */
+ "Sintaxe: \002REJECT \037nick\037\002",
+ /* LNG_REJECTED */
+ "O vHost de %s foi recusado",
+ /* LNG_REJECT_MEMO */
+ "[Auto Memo] Seu pedido de vHost foi recusado.",
+ /* LNG_REJECT_MEMO_REASON */
+ "[Auto Memo] Seu pedido de vHost foi recusado. Motivo: %s",
+ /* LNG_NO_REQUEST */
+ "Nenhum pedido encontrado para o nick %s.",
+ /* LNG_HELP */
+ " REQUEST Request a vHost for your nick",
+ /* LNG_HELP_SETTER */
+ " ACTIVATE Aprova o pedido de vHost de um usuбrio\n"
+ " REJECT Recusa o pedido de vHost de um usuбrio\n"
+ " WAITING Comando para LISTAR +req",
+ /* LNG_HELP_REQUEST */
+ "Solicita a ativaзгo do vHost fornecido em seu nick pelos\n"
+ "administradores da rede. Por favor, tenha paciкncia\n"
+ "enquanto seu pedido й analisado.",
+ /* LNG_HELP_ACTIVATE */
+ "Ativa o vHost solicitado para o nick fornecido.",
+ /* LNG_HELP_ACTIVATE_MEMO */
+ "Um memo informando o usuбrio tambйm serб enviado.",
+ /* LNG_HELP_REJECT */
+ "Recusa o pedido de vHost para o nick fornecido.",
+ /* LNG_HELP_REJECT_MEMO */
+ "Um memo informando o usuбrio tambйm serб enviado.",
+ /* LNG_WAITING_SYNTAX */
+ "Sintaxe: \002WAITING\002",
+ /* LNG_HELP_WAITING */
+ "Este comando й usado por conveniкncia. Й essencialmente\n"
+ "o mesmo que fazer um LIST +req"
+ };
+
+ char *langtable_ru[] = {
+ /* LNG_REQUEST_SYNTAX */
+ "Синтаксис: \002REQUEST \037vHost\037\002",
+ /* LNG_REQUESTED */
+ "Ваш запрос на vHost отправлен.",
+ /* LNG_REQUEST_WAIT */
+ "Пожалуйста, подождите %d секунд, прежде чем запрашивать новый vHost",
+ /* LNG_REQUEST_MEMO */
+ "[авто-сообщение] Был запрошен vHost \002%s\002",
+ /* LNG_ACTIVATE_SYNTAX */
+ "Синтаксис: \002ACTIVATE \037ник\037\002",
+ /* LNG_ACTIVATED */
+ "vHost для %s успешно активирован",
+ /* LNG_ACTIVATE_MEMO */
+ "[авто-сообщение] Запрашиваемый вами vHost утвержден и активирован.",
+ /* LNG_REJECT_SYNTAX */
+ "Синтаксис: \002REJECT \037ник\037\002",
+ /* LNG_REJECTED */
+ "vHost для %s отклонен.",
+ /* LNG_REJECT_MEMO */
+ "[авто-сообщение] Запрашиваемый вами vHost отклонен.",
+ /* LNG_REJECT_MEMO_REASON */
+ "[авто-сообщение] Запрашиваемый вами vHost отклонен. Причина: %s",
+ /* LNG_NO_REQUEST */
+ "Запрос на vHost для ника %s не найден.",
+ /* LNG_HELP */
+ " REQUEST Запрос на vHost для вашего текущего ника",
+ /* LNG_HELP_SETTER */
+ " ACTIVATE Утвердить запрашиваемый пользователем vHost\n"
+ " REJECT Отклонить запрашиваемый пользователем vHost\n"
+ " WAITING Список запросов ожидающих обработки (аналог LIST +req)",
+ /* LNG_HELP_REQUEST */
+ "Отправляет запрос на активацию vHost, который будет рассмотрен одним из\n"
+ "администраторов сети. Просьба проявить терпение, пока запрос\n"
+ "рассматривается администрацией.",
+ /* LNG_HELP_ACTIVATE */
+ "Утвердить запрашиваемый vHost для указанного ника.",
+ /* LNG_HELP_ACTIVATE_MEMO */
+ "Пользователю будет послано авто-уведомление об активации его запроса.",
+ /* LNG_HELP_REJECT */
+ "Отклонить запрашиваемый vHost для указанного ника.",
+ /* LNG_HELP_REJECT_MEMO */
+ "Пользователю будет послано авто-уведомление об отклонении его запроса.",
+ /* LNG_WAITING_SYNTAX */
+ "Синтаксис: \002WAITING\002",
+ /* LNG_HELP_WAITING */
+ "Данная команда создана для удобства использования и выводит список запросов,\n"
+ "ожидающих обработки. Аналогичная команда: LIST +req ."
+ };
+
+ char *langtable_it[] = {
+ /* LNG_REQUEST_SYNTAX */
+ "Sintassi: \002REQUEST \037vhost\037\002",
+ /* LNG_REQUESTED */
+ "Il tuo vHost и stato richiesto",
+ /* LNG_REQUEST_WAIT */
+ "Prego attendere %d secondi prima di richiedere un nuovo vHost",
+ /* LNG_REQUEST_MEMO */
+ "[auto memo] и stato richiesto il vHost \002%s\002.",
+ /* LNG_ACTIVATE_SYNTAX */
+ "Sintassi: \002ACTIVATE \037nick\037\002",
+ /* LNG_ACTIVATED */
+ "Il vHost per %s и stato attivato",
+ /* LNG_ACTIVATE_MEMO */
+ "[auto memo] Il vHost da te richiesto и stato approvato.",
+ /* LNG_REJECT_SYNTAX */
+ "Sintassi: \002REJECT \037nick\037\002",
+ /* LNG_REJECTED */
+ "Il vHost per %s и stato rifiutato",
+ /* LNG_REJECT_MEMO */
+ "[auto memo] Il vHost da te richiesto и stato rifiutato.",
+ /* LNG_REJECT_MEMO_REASON */
+ "[auto memo] Il vHost da te richiesto и stato rifiutato. Motivo: %s",
+ /* LNG_NO_REQUEST */
+ "Nessuna richiesta trovata per il nick %s.",
+ /* LNG_HELP */
+ " REQUEST Richiede un vHost per il tuo nick",
+ /* LNG_HELP_SETTER */
+ " ACTIVATE Approva il vHost richiesto di un utente\n"
+ " REJECT Rifiuta il vHost richiesto di un utente\n"
+ " WAITING Comando per LIST +req",
+ /* LNG_HELP_REQUEST */
+ "Richiede l'attivazione del vHost specificato per il tuo nick da parte\n"
+ "degli amministratori di rete. Sei pregato di pazientare finchи la tua\n"
+ "richiesta viene elaborata.",
+ /* LNG_HELP_ACTIVATE */
+ "Attiva il vHost richiesto per il nick specificato.",
+ /* LNG_HELP_ACTIVATE_MEMO */
+ "Viene inviato un memo per informare l'utente.",
+ /* LNG_HELP_REJECT */
+ "Rifiuta il vHost richiesto per il nick specificato.",
+ /* LNG_HELP_REJECT_MEMO */
+ "Viene inviato un memo per informare l'utente.",
+ /* LNG_WAITING_SYNTAX */
+ "Sintassi: \002WAITING\002",
+ /* LNG_HELP_WAITING */
+ "Questo comando и per comoditа. Praticamente и la stessa cosa che\n"
+ "eseguire un LIST +req ."
+ };
+ moduleInsertLanguage(LANG_EN_US, LNG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_NL, LNG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_PT, LNG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LNG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LNG_NUM_STRINGS, langtable_it);
+}
+
+/* EOF */
diff --git a/src/modules/makefile.inc.win32 b/src/modules/makefile.inc.win32
new file mode 100644
index 000000000..f6a646329
--- /dev/null
+++ b/src/modules/makefile.inc.win32
@@ -0,0 +1,2 @@
+SRCS=cs_appendtopic.c cs_enforce.c cs_tban.c ns_maxemail.c hs_request.c os_info.c bs_fantasy_unban.c
+SUBS=test
diff --git a/src/modules/makefile.sub.win32 b/src/modules/makefile.sub.win32
new file mode 100644
index 000000000..4a811622e
--- /dev/null
+++ b/src/modules/makefile.sub.win32
@@ -0,0 +1,19 @@
+include ../../../Makefile.inc.win32
+
+OBJECTS= $(SRCS:.c=.obj)
+CFLAGS=/nologo /LD /MD /D MODULE_COMPILE $(CFLAGS) /I"../../../include" /I "../"
+LFLAGS=/nologo ../../anope.lib wsock32.lib $(LIBS) $(LFLAGS) $(MYSQL_LIB_PATH) /export:AnopeInit /export:AnopeFini /OUT:$(TARGET)
+
+all:
+ $(CC) $(SRCS) $(CFLAGS) ..\..\mod_version.c /link $(LFLAGS)
+
+distclean: clean spotless
+
+clean:
+ -@del *.obj
+
+spotless: clean
+ -@del *.dll *.lib *.exp *.manifest
+
+install:
+ -@copy *.dll ..\..\..\$(DATDEST)\modules
diff --git a/src/modules/makefile.win32 b/src/modules/makefile.win32
new file mode 100644
index 000000000..038ff25ba
--- /dev/null
+++ b/src/modules/makefile.win32
@@ -0,0 +1,41 @@
+include ../../Makefile.inc.win32
+include ./Makefile.inc.win32
+
+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) subs
+
+distclean: clean spotless
+
+.c.dll:
+ $(CC) $(CFLAGS) $(IRCTYPE) $< ..\mod_version.c $(LFLAGS)
+
+subs:
+ @for %i in ( $(SUBS) ); do \
+ @if exist %i; @cd %i && $(MAKE) $(MAKEARGS) && cd ..
+
+clean: subs-clean
+ -@del *.obj
+
+subs-clean:
+ @for %i in ( $(SUBS) ); do \
+ @if exist %i; @cd %i && $(MAKE) $(MAKEARGS) clean && cd ..
+
+spotless: clean subs-spotless
+ -@del *.dll *.lib *.exp *.manifest
+
+subs-spotless:
+ @for %i in ( $(SUBS) ); do \
+ @if exist %i; @cd %i && $(MAKE) $(MAKEARGS) spotless && cd ..
+
+install:
+ -@mkdir ..\..\$(DATDEST)\modules
+ -@mkdir ..\..\$(DATDEST)\modules\runtime
+ -@copy *.dll ..\..\$(DATDEST)\modules
+
+subs-install: install
+ @for %i in ( $(SUBS) ); do \
+ @if exist %i; @cd %i && $(MAKE) $(MAKEARGS) install && cd ..
+
diff --git a/src/modules/ns_maxemail.c b/src/modules/ns_maxemail.c
new file mode 100644
index 000000000..04747ff5a
--- /dev/null
+++ b/src/modules/ns_maxemail.c
@@ -0,0 +1,228 @@
+/* ns_maxemail.c - Limit the amount of times an email address
+ * can be used for a NickServ account.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: GeniusDex <geniusdex@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send any bug reports to the Anope Coder, as he will be able
+ * to deal with it best.
+ */
+
+#include "module.h"
+
+#define AUTHOR "Anope"
+#define VERSION "$Id$"
+
+void my_load_config(void);
+void my_add_languages(void);
+int my_ns_register(User * u);
+int my_ns_set(User * u);
+int my_event_reload(int argc, char **argv);
+
+int NSEmailMax = 0;
+
+#define LNG_NUM_STRINGS 2
+#define LNG_NSEMAILMAX_REACHED 0
+#define LNG_NSEMAILMAX_REACHED_ONE 1
+
+int AnopeInit(int argc, char **argv)
+{
+ Command *c;
+ EvtHook *evt;
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ c = createCommand("REGISTER", my_ns_register, NULL, -1, -1, -1, -1,
+ -1);
+ if ((status = moduleAddCommand(NICKSERV, c, MOD_HEAD))) {
+ alog("[ns_maxemail] Unable to create REGISTER command: %d",
+ status);
+ return MOD_STOP;
+ }
+
+ c = createCommand("SET", my_ns_set, NULL, -1, -1, -1, -1, -1);
+ if ((status = moduleAddCommand(NICKSERV, c, MOD_HEAD))) {
+ alog("[ns_maxemail] Unable to create SET command: %d", status);
+ return MOD_STOP;
+ }
+
+ evt = createEventHook(EVENT_RELOAD, my_event_reload);
+ if ((status = moduleAddEventHook(evt))) {
+ alog("[ns_maxemail] Unable to hook to EVENT_RELOAD: %d", status);
+ return MOD_STOP;
+ }
+
+ my_load_config();
+ my_add_languages();
+
+ return MOD_CONT;
+}
+
+void AnopeFini(void)
+{
+ /* Nothing to do while unloading */
+}
+
+int count_email_in_use(char *email, User * u)
+{
+ NickCore *nc;
+ int i;
+ int count = 0;
+
+ if (!email)
+ return 0;
+
+ for (i = 0; i < 1024; i++) {
+ for (nc = nclists[i]; nc; nc = nc->next) {
+ if (!(u->na && u->na->nc && (u->na->nc == nc)) && nc->email && (stricmp(nc->email, email) == 0))
+ count++;
+ }
+ }
+
+ return count;
+}
+
+int check_email_limit_reached(char *email, User * u)
+{
+ if ((NSEmailMax < 1) || !email || is_services_admin(u))
+ return MOD_CONT;
+
+ if (count_email_in_use(email, u) < NSEmailMax)
+ return MOD_CONT;
+
+ if (NSEmailMax == 1)
+ moduleNoticeLang(s_NickServ, u, LNG_NSEMAILMAX_REACHED_ONE);
+ else
+ moduleNoticeLang(s_NickServ, u, LNG_NSEMAILMAX_REACHED,
+ NSEmailMax);
+
+ return MOD_STOP;
+}
+
+int my_ns_register(User * u)
+{
+ char *cur_buffer;
+ char *email;
+ int ret;
+
+ cur_buffer = moduleGetLastBuffer();
+ email = myStrGetToken(cur_buffer, ' ', 1);
+ if (!email)
+ return MOD_CONT;
+
+ ret = check_email_limit_reached(email, u);
+ free(email);
+
+ return ret;
+}
+
+int my_ns_set(User * u)
+{
+ char *cur_buffer;
+ char *set;
+ char *email;
+ int ret;
+
+ cur_buffer = moduleGetLastBuffer();
+ set = myStrGetToken(cur_buffer, ' ', 0);
+
+ if (!set)
+ return MOD_CONT;
+
+ if (stricmp(set, "email") != 0) {
+ free(set);
+ return MOD_CONT;
+ }
+
+ free(set);
+ email = myStrGetToken(cur_buffer, ' ', 1);
+ if (!email)
+ return MOD_CONT;
+
+ ret = check_email_limit_reached(email, u);
+ free(email);
+
+ return ret;
+}
+
+int my_event_reload(int argc, char **argv)
+{
+ if ((argc > 0) && (stricmp(argv[0], EVENT_START) == 0))
+ my_load_config();
+
+ return MOD_CONT;
+}
+
+void my_load_config(void)
+{
+ Directive confvalues[] = {
+ {"NSEmailMax", {{PARAM_INT, PARAM_RELOAD, &NSEmailMax}}}
+ };
+
+ moduleGetConfigDirective(confvalues);
+
+ if (debug)
+ alog("debug: [ns_maxemail] NSEmailMax set to %d", NSEmailMax);
+}
+
+void my_add_languages(void)
+{
+ char *langtable_en_us[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "The given email address has reached it's usage limit of %d users.",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "The given email address has reached it's usage limit of 1 user."
+ };
+
+ char *langtable_nl[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "Het gegeven email adres heeft de limiet van %d gebruikers bereikt.",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "Het gegeven email adres heeft de limiet van 1 gebruiker bereikt."
+ };
+
+ char *langtable_de[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "Die angegebene eMail hat die limit Begrenzung von %d User erreicht.",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "Die angegebene eMail hat die limit Begrenzung von 1 User erreicht."
+ };
+
+ char *langtable_pt[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "O endereзo de email fornecido alcanзou seu limite de uso de %d usuбrios.",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "O endereзo de email fornecido alcanзou seu limite de uso de 1 usuбrio."
+ };
+
+ char *langtable_ru[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "Указанный вами email-адрес используется максимально допустимое кол-во раз: %d",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "Указанный вами email-адрес уже кем-то используется."
+ };
+
+ char *langtable_it[] = {
+ /* LNG_NSEMAILMAX_REACHED */
+ "L'indirizzo email specificato ha raggiunto il suo limite d'utilizzo di %d utenti.",
+ /* LNG_NSEMAILMAX_REACHED_ONE */
+ "L'indirizzo email specificato ha raggiunto il suo limite d'utilizzo di 1 utente."
+ };
+
+ moduleInsertLanguage(LANG_EN_US, LNG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_NL, LNG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_DE, LNG_NUM_STRINGS, langtable_de);
+ moduleInsertLanguage(LANG_PT, LNG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LNG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LNG_NUM_STRINGS, langtable_it);
+}
+
+/* EOF */
diff --git a/src/modules/ns_noop_convert.c b/src/modules/ns_noop_convert.c
new file mode 100644
index 000000000..2858bef1e
--- /dev/null
+++ b/src/modules/ns_noop_convert.c
@@ -0,0 +1,173 @@
+/* ns_noop.c - Allows users to optionaly set autoop to off
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Based on the original module by Rob <rob@anope.org>
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: DrStein <drstein@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send bug reports to the Anope Coder instead of the module
+ * author, because any changes since the inclusion into anope
+ * are not supported by the original author.
+ *
+ */
+/*************************************************************************/
+
+#include "module.h"
+
+#define AUTHOR "Rob"
+#define VERSION "$Id$"
+
+/* The name of the default database to save info to */
+#define DEFAULT_DB_NAME "autoop.db"
+
+/* Multi-language stuff */
+#define LANG_NUM_STRINGS 8
+
+#define AUTOOP_SYNTAX 0
+#define AUTOOP_STATUS_ON 1
+#define AUTOOP_STATUS_OFF 2
+#define AUTOOP_NO_NICK 3
+#define AUTOOP_ON 4
+#define AUTOOP_OFF 5
+#define AUTOOP_DESC 6
+#define AUTOOP_HELP 7
+
+/*************************************************************************/
+
+User *currentUser;
+int m_isIRCop = 0;
+
+char *NSAutoOPDBName;
+
+int myNickServAutoOpHelp(User * u);
+void myNickServHelp(User * u);
+
+int noop(User * u);
+int mEventJoin(int argc, char **argv);
+int setAutoOp(User * u);
+int UnsetAutoOp(User * u);
+
+int mLoadData(void);
+int mSaveData(int argc, char **argv);
+int mLoadConfig(int argc, char **argv);
+
+void m_AddLanguages(void);
+
+/*************************************************************************/
+
+/**
+ * AnopeInit is called when the module is loaded
+ * @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)
+{
+ NSAutoOPDBName = NULL;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ if (mLoadConfig(0, NULL))
+ return MOD_STOP;
+
+ mLoadData();
+
+ alog("ns_noop_convert: Your auto-op database has been converted and this module will now");
+ alog("ns_noop_convert: unload itself. You can now remove this module from your config");
+
+ return MOD_STOP;
+}
+
+/**
+ * Unload the module
+ **/
+void AnopeFini(void)
+{
+ if (NSAutoOPDBName)
+ free(NSAutoOPDBName);
+}
+
+/*************************************************************************/
+
+/**
+ * Load data from the db file, and populate the autoop setting
+ * @return 0 for success
+ **/
+int mLoadData(void)
+{
+ int ret = 0;
+ int len = 0;
+
+ char *name = NULL;
+
+ NickAlias *na = NULL;
+ FILE *in;
+
+ /* will _never_ be this big thanks to the 512 limit of a message */
+ char buffer[2000];
+ if ((in = fopen(NSAutoOPDBName, "r")) == NULL) {
+ alog("ns_noop: WARNING: Can not open database file! (it might not exist, this is not fatal)");
+ ret = 1;
+ } else {
+ while (fgets(buffer, 1500, in)) {
+ name = myStrGetToken(buffer, ' ', 0);
+ if (name) {
+ len = strlen(name);
+ /* Take the \n from the end of the line */
+ name[len - 1] = '\0';
+ if ((na = findnick(name))) {
+ na->nc->flags |= NI_AUTOOP;
+ }
+ free(name);
+ }
+ }
+ }
+ return ret;
+}
+
+/*************************************************************************/
+
+/**
+ * Load the configuration directives from Services configuration file.
+ * @return 0 for success
+ **/
+int mLoadConfig(int argc, char **argv)
+{
+ char *tmp = NULL;
+
+ Directive d[] = {
+ {"NSAutoOPDBName", {{PARAM_STRING, PARAM_RELOAD, &tmp}}},
+ };
+
+ moduleGetConfigDirective(d);
+
+ if (NSAutoOPDBName)
+ free(NSAutoOPDBName);
+
+ if (tmp) {
+ NSAutoOPDBName = tmp;
+ } else {
+ NSAutoOPDBName = sstrdup(DEFAULT_DB_NAME);
+ alog("ns_noop: NSAutoOPDBName is not defined in Services configuration file, using default %s", NSAutoOPDBName);
+ }
+
+ if (!NSAutoOPDBName) {
+ alog("ns_noop: FATAL: Can't read required configuration directives!");
+ return MOD_STOP;
+ } else {
+ alog("ns_noop: Directive NSAutoOPDBName loaded (%s)...",
+ NSAutoOPDBName);
+ }
+
+ return MOD_CONT;
+}
+
+/*************************************************************************/
+
+/* EOF */
diff --git a/src/modules/os_ignore_db.c b/src/modules/os_ignore_db.c
new file mode 100644
index 000000000..474959068
--- /dev/null
+++ b/src/modules/os_ignore_db.c
@@ -0,0 +1,545 @@
+/* os_ignore_db.c - Provides a database backend for OS IGNORE.
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Included in the Anope module pack since Anope 1.7.23
+ * Anope Coder: Viper <viper@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ */
+/* ------------------------------------------------------------------------------- */
+
+#include "module.h"
+
+#define AUTHOR "Viper"
+#define VERSION "$Id$"
+
+/* Default database name */
+#define DefIgnoreDB "os_ignore.db"
+#define IGNOREDBVERSION 1
+
+/* Database seperators */
+#define SEPARATOR '^' /* End of a key, seperates keys from values */
+#define BLOCKEND '\n' /* End of a block, e.g. a whole ignore */
+#define VALUEEND '\000' /* End of a value */
+#define SUBSTART '\010' /* Beginning of a new subblock, closed by a BLOCKEND */
+
+/* Database reading return values */
+#define DB_READ_SUCCESS 0
+#define DB_READ_ERROR 1
+#define DB_EOF_ERROR 2
+#define DB_VERSION_ERROR 3
+#define DB_READ_BLOCKEND 4
+#define DB_READ_SUBSTART 5
+
+#define DB_WRITE_SUCCESS 0
+#define DB_WRITE_ERROR 1
+#define DB_WRITE_NOVAL 2
+
+/* Database Key, Value max length */
+#define MAXKEYLEN 128
+#define MAXVALLEN 1024
+
+/* Structs */
+typedef struct db_file_ DBFile;
+
+struct db_file_ {
+ FILE *fptr; /* Pointer to the opened file */
+ int db_version; /* The db version of the datafiles (only needed for reading) */
+ int core_db_version; /* The current db version of this anope source */
+ char service[256]; /* StatServ/etc. */
+ char filename[256]; /* Filename of the database */
+ char temp_name[262]; /* Temp filename of the database */
+};
+
+
+/* Variables */
+char *IgnoreDB;
+
+/* Functions */
+int new_open_db_read(DBFile *dbptr, char **key, char **value);
+int new_open_db_write(DBFile *dbptr);
+void new_close_db(FILE *fptr, char **key, char **value);
+int new_read_db_entry(char **key, char **value, FILE * fptr);
+int new_write_db_entry(const char *key, DBFile *dbptr, const char *fmt, ...);
+int new_write_db_endofblock(DBFile *dbptr);
+void fill_db_ptr(DBFile *dbptr, int version, int core_version, char service[256], char filename[256]);
+
+int save_ignoredb(int argc, char **argv);
+int backup_ignoredb(int argc, char **argv);
+void load_ignore_db(void);
+void save_ignore_db(void);
+void load_config(void);
+int reload_config(int argc, char **argv);
+
+/* ------------------------------------------------------------------------------- */
+
+/**
+ * AnopeInit is called when the module is loaded
+ * @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;
+ IgnoreDB = NULL;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ hook = createEventHook(EVENT_RELOAD, reload_config);
+ if (moduleAddEventHook(hook) != MOD_ERR_OK) {
+ alog("[\002os_ignore_db\002] Can't hook to EVENT_RELOAD event");
+ return MOD_STOP;
+ }
+
+ hook = createEventHook(EVENT_DB_SAVING, save_ignoredb);
+ if (moduleAddEventHook(hook) != MOD_ERR_OK) {
+ alog("[\002os_ignore_db\002] Can't hook to EVENT_DB_SAVING event");
+ return MOD_STOP;
+ }
+
+ hook = createEventHook(EVENT_DB_BACKUP, backup_ignoredb);
+ if (moduleAddEventHook(hook) != MOD_ERR_OK) {
+ alog("[\002os_ignore_db\002] Can't hook to EVENT_DB_BACKUP event");
+ return MOD_STOP;
+ }
+
+ load_config();
+ /* Load the ignore database and re-add them to anopes ignorelist. */
+ load_ignore_db();
+
+ return MOD_CONT;
+}
+
+/**
+ * Unload the module
+ **/
+void AnopeFini(void) {
+ /* Save the ignore database before bailing out.. */
+ save_ignore_db();
+
+ if (IgnoreDB)
+ free(IgnoreDB);
+}
+
+/* ------------------------------------------------------------------------------- */
+
+void load_config(void) {
+ int i;
+
+ Directive confvalues[][1] = {
+ {{"OSIgnoreDBName", {{PARAM_STRING, PARAM_RELOAD, &IgnoreDB}}}},
+ };
+
+ if (IgnoreDB)
+ free(IgnoreDB);
+ IgnoreDB = NULL;
+
+ for (i = 0; i < 1; i++)
+ moduleGetConfigDirective(confvalues[i]);
+
+ if (!IgnoreDB)
+ IgnoreDB = sstrdup(DefIgnoreDB);
+
+ if (debug)
+ alog("[os_ignore_db] debug: Set config vars: OSIgnoreDBName='%s'", IgnoreDB);
+}
+
+/**
+ * Upon /os reload call the routines for reloading the configuration directives
+ **/
+int reload_config(int argc, char **argv) {
+ if (argc >= 1) {
+ if (!stricmp(argv[0], EVENT_START)) {
+ load_config();
+ }
+ }
+ return MOD_CONT;
+}
+
+/**
+ * When anope saves her databases, we do the same.
+ **/
+int save_ignoredb(int argc, char **argv) {
+ if ((argc >= 1) && (!stricmp(argv[0], EVENT_STOP)))
+ save_ignore_db();
+
+ return MOD_CONT;
+}
+
+
+/**
+ * When anope backs her databases up, we do the same.
+ **/
+int backup_ignoredb(int argc, char **argv) {
+ if ((argc >= 1) && (!stricmp(argv[0], EVENT_STOP))) {
+ if (debug)
+ alog("[os_ignore_db] debug: Backing up %s database...", IgnoreDB);
+ ModuleDatabaseBackup(IgnoreDB);
+ }
+ return MOD_CONT;
+}
+
+/* ------------------------------------------------------------------------------- */
+
+/**************************************************************************
+ * DataBase Handling
+ **************************************************************************/
+
+void load_ignore_db(void) {
+ DBFile *dbptr = scalloc(1, sizeof(DBFile));
+ char *key, *value, *mask = NULL;
+ int retval = 0;
+ time_t expiry_time;
+ IgnoreData *ign;
+
+ expiry_time = time(NULL);
+ fill_db_ptr(dbptr, 0, IGNOREDBVERSION, s_OperServ, IgnoreDB);
+
+ /* let's remove existing temp files here, because we only load dbs on startup */
+ remove(dbptr->temp_name);
+
+ /* Open the db, fill the rest of dbptr and allocate memory for key and value */
+ if (new_open_db_read(dbptr, &key, &value)) {
+ free(dbptr);
+ return; /* Bang, an error occurred */
+ }
+
+ while (1) {
+ /* read a new entry and fill key and value with it -Certus */
+ retval = new_read_db_entry(&key, &value, dbptr->fptr);
+
+ if (retval == DB_READ_ERROR) {
+ new_close_db(dbptr->fptr, &key, &value);
+ free(dbptr);
+ return;
+
+ } else if (retval == DB_EOF_ERROR) {
+ new_close_db(dbptr->fptr, &key, &value);
+ free(dbptr);
+ return;
+ } else if (retval == DB_READ_BLOCKEND) { /* DB_READ_BLOCKEND */
+ /* Check if we have everything to add the ignore..
+ * We shouldn't bother with already expired ignores either.. */
+ if (mask && (expiry_time > time(NULL) || expiry_time == 0)) {
+ /* We should check for double entries.. */
+ for (ign = ignore; ign; ign = ign->next)
+ if (!stricmp(ign->mask, mask))
+ break;
+
+ if (!ign) {
+ /* Create a fresh entry.. */
+ ign = scalloc(sizeof(*ign), 1);
+ ign->mask = sstrdup(mask);
+ ign->time = expiry_time;
+ ign->prev = NULL;
+ ign->next = ignore;
+ if (ignore)
+ ignore->prev = ign;
+ ignore = ign;
+ if (debug)
+ alog("[os_ignore_db] debug: Added new ignore entry for %s", mask);
+ } else {
+ /* Update time on existing entry.
+ * The longest expiry time survives.. */
+ if (expiry_time == 0 || ign->time == 0)
+ ign->time = 0;
+ else if (expiry_time > ign->time)
+ ign->time = expiry_time;
+ }
+ }
+
+ if (mask) free(mask);
+ mask = NULL;
+ expiry_time = time(NULL);
+ } else { /* DB_READ_SUCCESS */
+ if (!*key || !*value)
+ continue;
+
+ /* mask */
+ if (!stricmp(key, "m")) {
+ if (mask)
+ free(mask);
+ mask = sstrdup(value);
+
+ /* expiry time */
+ } else if (!stricmp(key, "t")) {
+ expiry_time = atoi(value);
+
+ } else if (!stricmp(key, "IGNORE_DB_VERSION")) {
+ if ((int)atoi(value) != IGNOREDBVERSION) {
+ alog("[\002os_ignore_db\002] Database version does not match any database versions supported by this module.");
+ alog("[\002os_ignore_db\002] Continuing with clean database...");
+ break;
+ }
+ }
+ } /* else */
+ } /* while */
+
+ free(dbptr);
+}
+
+
+void save_ignore_db(void) {
+ DBFile *dbptr = scalloc(1, sizeof(DBFile));
+ time_t now;
+ IgnoreData *ign, *next;
+
+ now = time(NULL);
+ fill_db_ptr(dbptr, 0, IGNOREDBVERSION, s_OperServ, IgnoreDB);
+
+ /* time to backup the old db */
+ rename(IgnoreDB, dbptr->temp_name);
+
+ if (new_open_db_write(dbptr)) {
+ rename(dbptr->temp_name, IgnoreDB);
+ free(dbptr);
+ return; /* Bang, an error occurred */
+ }
+
+ /* Store the version of the DB in the DB as well...
+ * This will make stuff a lot easier if the database scheme needs to modified. */
+ new_write_db_entry("IGNORE_DB_VERSION", dbptr, "%d", IGNOREDBVERSION);
+ new_write_db_endofblock(dbptr);
+
+ /* Go over the entire ignorelist, check whether each entry is still valid
+ * and write it to the database if it is.*/
+ for (ign = ignore; ign; ign = next) {
+ next = ign->next;
+
+ if (ign->time != 0 && ign->time <= now) {
+ if (debug)
+ alog("[os_ignore_db] debug: Expiring ignore entry %s", ign->mask);
+ if (ign->prev)
+ ign->prev->next = ign->next;
+ else if (ignore == ign)
+ ignore = ign->next;
+ if (ign->next)
+ ign->next->prev = ign->prev;
+ free(ign->mask);
+ free(ign);
+ ign = NULL;
+ } else {
+ new_write_db_entry("m", dbptr, "%s", ign->mask);
+ new_write_db_entry("t", dbptr, "%d", ign->time);
+ new_write_db_endofblock(dbptr);
+ }
+ }
+
+ if (dbptr) {
+ new_close_db(dbptr->fptr, NULL, NULL); /* close file */
+ remove(dbptr->temp_name); /* saved successfully, no need to keep the old one */
+ free(dbptr); /* free the db struct */
+ }
+}
+
+
+/* ------------------------------------------------------------------------------- */
+
+/**************************************************************************
+ * Generic DataBase Functions (Borrowed this from Trystan :-) )
+ **************************************************************************/
+
+
+int new_open_db_read(DBFile *dbptr, char **key, char **value) {
+ *key = malloc(MAXKEYLEN);
+ *value = malloc(MAXVALLEN);
+
+ if (!(dbptr->fptr = fopen(dbptr->filename, "rb"))) {
+ if (debug) {
+ alog("debug: Can't read %s database %s : errno(%d)", dbptr->service,
+ dbptr->filename, errno);
+ }
+ free(*key);
+ *key = NULL;
+ free(*value);
+ *value = NULL;
+ return DB_READ_ERROR;
+ }
+ dbptr->db_version = fgetc(dbptr->fptr) << 24 | fgetc(dbptr->fptr) << 16
+ | fgetc(dbptr->fptr) << 8 | fgetc(dbptr->fptr);
+
+ if (ferror(dbptr->fptr)) {
+ if (debug) {
+ alog("debug: Error reading version number on %s", dbptr->filename);
+ }
+ free(*key);
+ *key = NULL;
+ free(*value);
+ *value = NULL;
+ return DB_READ_ERROR;
+ } else if (feof(dbptr->fptr)) {
+ if (debug) {
+ alog("debug: Error reading version number on %s: End of file detected",
+ dbptr->filename);
+ }
+ free(*key);
+ *key = NULL;
+ free(*value);
+ *value = NULL;
+ return DB_EOF_ERROR;
+ } else if (dbptr->db_version < 1) {
+ if (debug) {
+ alog("debug: Invalid version number (%d) on %s", dbptr->db_version, dbptr->filename);
+ }
+ free(*key);
+ *key = NULL;
+ free(*value);
+ *value = NULL;
+ return DB_VERSION_ERROR;
+ }
+ return DB_READ_SUCCESS;
+}
+
+
+int new_open_db_write(DBFile *dbptr) {
+ if (!(dbptr->fptr = fopen(dbptr->filename, "wb"))) {
+ if (debug) {
+ alog("debug: %s Can't open %s database for writing", dbptr->service, dbptr->filename);
+ }
+ return DB_WRITE_ERROR;
+ }
+
+ if (fputc(dbptr->core_db_version >> 24 & 0xFF, dbptr->fptr) < 0 ||
+ fputc(dbptr->core_db_version >> 16 & 0xFF, dbptr->fptr) < 0 ||
+ fputc(dbptr->core_db_version >> 8 & 0xFF, dbptr->fptr) < 0 ||
+ fputc(dbptr->core_db_version & 0xFF, dbptr->fptr) < 0) {
+ if (debug) {
+ alog("debug: Error writing version number on %s", dbptr->filename);
+ }
+ return DB_WRITE_ERROR;
+ }
+ return DB_WRITE_SUCCESS;
+}
+
+
+void new_close_db(FILE *fptr, char **key, char **value) {
+ if (key && *key) {
+ free(*key);
+ *key = NULL;
+ }
+ if (value && *value) {
+ free(*value);
+ *value = NULL;
+ }
+
+ if (fptr) {
+ fclose(fptr);
+ }
+}
+
+
+int new_read_db_entry(char **key, char **value, FILE *fptr) {
+ char *string = *key;
+ int character;
+ int i = 0;
+
+ **key = '\0';
+ **value = '\0';
+
+ while (1) {
+ if ((character = fgetc(fptr)) == EOF) { /* a problem occurred reading the file */
+ if (ferror(fptr)) {
+ return DB_READ_ERROR; /* error! */
+ }
+ return DB_EOF_ERROR; /* end of file */
+ } else if (character == BLOCKEND) { /* END OF BLOCK */
+ return DB_READ_BLOCKEND;
+ } else if (character == VALUEEND) { /* END OF VALUE */
+ string[i] = '\0'; /* end of value */
+ return DB_READ_SUCCESS;
+ } else if (character == SEPARATOR) { /* END OF KEY */
+ string[i] = '\0'; /* end of key */
+ string = *value; /* beginning of value */
+ i = 0; /* start with the first character of our value */
+ } else {
+ if ((i == (MAXKEYLEN - 1)) && (string == *key)) { /* max key length reached, continuing with value */
+ string[i] = '\0'; /* end of key */
+ string = *value; /* beginning of value */
+ i = 0; /* start with the first character of our value */
+ } else if ((i == (MAXVALLEN - 1)) && (string == *value)) { /* max value length reached, returning */
+ string[i] = '\0';
+ return DB_READ_SUCCESS;
+ } else {
+ string[i] = character; /* read string (key or value) */
+ i++;
+ }
+ }
+ }
+}
+
+
+int new_write_db_entry(const char *key, DBFile *dbptr, const char *fmt, ...) {
+ char string[MAXKEYLEN + MAXVALLEN + 2], value[MAXVALLEN]; /* safety byte :P */
+ va_list ap;
+ unsigned int length;
+
+ if (!dbptr) {
+ return DB_WRITE_ERROR;
+ }
+
+ va_start(ap, fmt);
+ vsnprintf(value, MAXVALLEN, fmt, ap);
+ va_end(ap);
+
+ if (!stricmp(value, "(null)")) {
+ return DB_WRITE_NOVAL;
+ }
+ snprintf(string, MAXKEYLEN + MAXVALLEN + 1, "%s%c%s", key, SEPARATOR, value);
+ length = strlen(string);
+ string[length] = VALUEEND;
+ length++;
+
+ if (fwrite(string, 1, length, dbptr->fptr) < length) {
+ if (debug) {
+ alog("debug: Error writing to %s", dbptr->filename);
+ }
+ new_close_db(dbptr->fptr, NULL, NULL);
+ if (debug) {
+ alog("debug: Restoring backup.");
+ }
+ remove(dbptr->filename);
+ rename(dbptr->temp_name, dbptr->filename);
+ free(dbptr);
+ dbptr = NULL;
+ return DB_WRITE_ERROR;
+ }
+ return DB_WRITE_SUCCESS;
+}
+
+
+int new_write_db_endofblock(DBFile *dbptr) {
+ if (!dbptr) {
+ return DB_WRITE_ERROR;
+ }
+ if (fputc(BLOCKEND, dbptr->fptr) == EOF) {
+ if (debug) {
+ alog("debug: Error writing to %s", dbptr->filename);
+ }
+ new_close_db(dbptr->fptr, NULL, NULL);
+ return DB_WRITE_ERROR;
+ }
+ return DB_WRITE_SUCCESS;
+}
+
+
+
+void fill_db_ptr(DBFile *dbptr, int version, int core_version,
+ char service[256], char filename[256]) {
+ dbptr->db_version = version;
+ dbptr->core_db_version = core_version;
+ if (!service)
+ strcpy(dbptr->service, service);
+ else
+ strcpy(dbptr->service, "");
+
+ strcpy(dbptr->filename, filename);
+ snprintf(dbptr->temp_name, 261, "%s.temp", filename);
+ return;
+}
+
+/* EOF */
diff --git a/src/modules/os_info.c b/src/modules/os_info.c
new file mode 100644
index 000000000..0343f957e
--- /dev/null
+++ b/src/modules/os_info.c
@@ -0,0 +1,780 @@
+/* os_info.c - Adds oper information lines to nicks/channels
+ *
+ * (C) 2003-2008 Anope Team
+ * Contact us at info@anope.org
+ *
+ * Based on the original module by Rob <rob@anope.org>
+ * Included in the Anope module pack since Anope 1.7.9
+ * Anope Coder: DrStein <drstein@anope.org>
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Send bug reports to the Anope Coder instead of the module
+ * author, because any changes since the inclusion into anope
+ * are not supported by the original author.
+ *
+ */
+/*************************************************************************/
+
+#include "module.h"
+
+#define AUTHOR "Rob"
+#define VERSION "$Id$"
+
+/* Default database name */
+#define DEFAULT_DB_NAME "os_info.db"
+
+/* Multi-language stuff */
+#define LANG_NUM_STRINGS 10
+
+#define OINFO_SYNTAX 0
+#define OINFO_ADD_SUCCESS 1
+#define OINFO_DEL_SUCCESS 2
+#define OCINFO_SYNTAX 3
+#define OCINFO_ADD_SUCCESS 4
+#define OCINFO_DEL_SUCCESS 5
+#define OINFO_HELP 6
+#define OCINFO_HELP 7
+#define OINFO_HELP_CMD 8
+#define OCINFO_HELP_CMD 9
+
+/*************************************************************************/
+
+char *OSInfoDBName = NULL;
+
+int myAddNickInfo(User * u);
+int myAddChanInfo(User * u);
+int myNickInfo(User * u);
+int myChanInfo(User * u);
+
+int mNickHelp(User * u);
+int mChanHelp(User * u);
+void mMainChanHelp(User * u);
+void mMainNickHelp(User * u);
+void m_AddLanguages(void);
+
+int mLoadData(void);
+int mSaveData(int argc, char **argv);
+int mBackupData(int argc, char **argv);
+int mLoadConfig();
+int mEventReload(int argc, char **argv);
+
+/*************************************************************************/
+
+/**
+ * AnopeInit is called when the module is loaded
+ * @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;
+ EvtHook *hook = NULL;
+
+ int status;
+
+ moduleAddAuthor(AUTHOR);
+ moduleAddVersion(VERSION);
+ moduleSetType(SUPPORTED);
+
+ alog("os_info: Loading configuration directives...");
+ if (mLoadConfig()) {
+ return MOD_STOP;
+ }
+
+ c = createCommand("oInfo", myAddNickInfo, is_oper, -1, -1, -1, -1, -1);
+ moduleAddHelp(c, mNickHelp);
+ status = moduleAddCommand(NICKSERV, c, MOD_HEAD);
+
+ c = createCommand("Info", myNickInfo, NULL, -1, -1, -1, -1, -1);
+ status = moduleAddCommand(NICKSERV, c, MOD_TAIL);
+
+ c = createCommand("oInfo", myAddChanInfo, is_oper, -1, -1, -1, -1, -1);
+ moduleAddHelp(c, mChanHelp);
+ status = moduleAddCommand(CHANSERV, c, MOD_HEAD);
+
+ c = createCommand("Info", myChanInfo, NULL, -1, -1, -1, -1, -1);
+ status = moduleAddCommand(CHANSERV, c, MOD_TAIL);
+
+ hook = createEventHook(EVENT_DB_SAVING, mSaveData);
+ status = moduleAddEventHook(hook);
+
+ hook = createEventHook(EVENT_DB_BACKUP, mBackupData);
+ status = moduleAddEventHook(hook);
+
+ hook = createEventHook(EVENT_RELOAD, mEventReload);
+ status = moduleAddEventHook(hook);
+
+ moduleSetNickHelp(mMainNickHelp);
+ moduleSetChanHelp(mMainChanHelp);
+
+ mLoadData();
+ m_AddLanguages();
+
+ return MOD_CONT;
+}
+
+/**
+ * Unload the module
+ **/
+void AnopeFini(void)
+{
+ char *av[1];
+
+ av[0] = sstrdup(EVENT_START);
+ mSaveData(1, av);
+ free(av[0]);
+
+ if (OSInfoDBName)
+ free(OSInfoDBName);
+}
+
+/*************************************************************************/
+
+/**
+ * Provide the user interface to add/remove/update oper information
+ * about a nick.
+ * We are going to assume that anyone who gets this far is an oper;
+ * the createCommand should have handled this checking for us and its
+ * tedious / a waste to do it twice.
+ * @param u The user who executed this command
+ * @return MOD_CONT if we want to process other commands in this command
+ * stack, MOD_STOP if we dont
+ **/
+int myAddNickInfo(User * u)
+{
+ char *text = NULL;
+ char *cmd = NULL;
+ char *nick = NULL;
+ char *info = NULL;
+ NickAlias *na = NULL;
+
+ /* Get the last buffer anope recived */
+ text = moduleGetLastBuffer();
+ if (text) {
+ cmd = myStrGetToken(text, ' ', 0);
+ nick = myStrGetToken(text, ' ', 1);
+ info = myStrGetTokenRemainder(text, ' ', 2);
+ if (cmd && nick) {
+ if (strcasecmp(cmd, "ADD") == 0) {
+ /* Syntax error, again! */
+ if (info) {
+ /* ok we've found the user */
+ if ((na = findnick(nick))) {
+ /* Add the module data to the user */
+ moduleAddData(&na->nc->moduleData, "info", info);
+ moduleNoticeLang(s_NickServ, u,
+ OINFO_ADD_SUCCESS, nick);
+ /* NickCore not found! */
+ } else {
+ notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED,
+ nick);
+ }
+ free(info);
+ }
+ } else if (strcasecmp(cmd, "DEL") == 0) {
+ /* ok we've found the user */
+ if ((na = findnick(nick))) {
+ moduleDelData(&na->nc->moduleData, "info");
+ moduleNoticeLang(s_NickServ, u,
+ OINFO_DEL_SUCCESS, nick);
+ /* NickCore not found! */
+ } else {
+ notice_lang(s_NickServ, u, NICK_X_NOT_REGISTERED,
+ nick);
+ }
+ /* another syntax error! */
+ } else {
+ moduleNoticeLang(s_NickServ, u, OINFO_SYNTAX);
+ }
+ free(cmd);
+ free(nick);
+ /* Syntax error */
+ } else if (cmd) {
+ moduleNoticeLang(s_NickServ, u, OINFO_SYNTAX);
+ free(cmd);
+ /* Syntax error */
+ } else {
+ moduleNoticeLang(s_NickServ, u, OINFO_SYNTAX);
+ }
+ }
+ return MOD_CONT;
+}
+
+/**
+ * Provide the user interface to add/remove/update oper information
+ * about a channel.
+ * We are going to assume that anyone who gets this far is an oper;
+ * the createCommand should have handled this checking for us and
+ * its tedious / a waste to do it twice.
+ * @param u The user who executed this command
+ * @return MOD_CONT if we want to process other commands in this command
+ * stack, MOD_STOP if we dont
+ **/
+int myAddChanInfo(User * u)
+{
+ char *text = NULL;
+ char *cmd = NULL;
+ char *chan = NULL;
+ char *info = NULL;
+ ChannelInfo *ci = NULL;
+
+ /* Get the last buffer anope recived */
+ text = moduleGetLastBuffer();
+ if (text) {
+ cmd = myStrGetToken(text, ' ', 0);
+ chan = myStrGetToken(text, ' ', 1);
+ info = myStrGetTokenRemainder(text, ' ', 2);
+ if (cmd && chan) {
+ if (strcasecmp(cmd, "ADD") == 0) {
+ if (info) {
+ if ((ci = cs_findchan(chan))) {
+ /* Add the module data to the channel */
+ moduleAddData(&ci->moduleData, "info", info);
+ moduleNoticeLang(s_ChanServ, u,
+ OCINFO_ADD_SUCCESS, chan);
+ /* ChanInfo */
+ } else {
+ notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED,
+ chan);
+ }
+ free(info);
+ }
+ } else if (strcasecmp(cmd, "DEL") == 0) {
+ if ((ci = cs_findchan(chan))) {
+ /* Del the module data from the channel */
+ moduleDelData(&ci->moduleData, "info");
+ moduleNoticeLang(s_ChanServ, u,
+ OCINFO_DEL_SUCCESS, chan);
+ /* ChanInfo */
+ } else {
+ notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED,
+ chan);
+ }
+ /* another syntax error! */
+ } else {
+ moduleNoticeLang(s_ChanServ, u, OCINFO_SYNTAX);
+ }
+ free(cmd);
+ free(chan);
+ /* Syntax error */
+ } else if (cmd) {
+ moduleNoticeLang(s_ChanServ, u, OCINFO_SYNTAX);
+ free(cmd);
+ /* Syntax error */
+ } else {
+ moduleNoticeLang(s_ChanServ, u, OCINFO_SYNTAX);
+ }
+ }
+ return MOD_CONT;
+}
+
+/*************************************************************************/
+
+/**
+ * Called after a user does a /msg nickserv info [nick]
+ * @param u The user who requested info
+ * @return MOD_CONT to continue processing commands or MOD_STOP to stop
+ **/
+int myNickInfo(User * u)
+{
+ char *text = NULL;
+ char *nick = NULL;
+ char *info = NULL;
+ NickAlias *na = NULL;
+
+ /* Only show our goodies to opers */
+ if (is_oper(u)) {
+ /* Get the last buffer anope recived */
+ text = moduleGetLastBuffer();
+ if (text) {
+ nick = myStrGetToken(text, ' ', 0);
+ if (nick) {
+ /* ok we've found the user */
+ if ((na = findnick(nick))) {
+ /* If we have any info on this user */
+ if ((info = moduleGetData(&na->nc->moduleData, "info"))) {
+ notice_user(s_NickServ, u, " OperInfo: %s", info);
+ free(info);
+ }
+ /* NickCore not found! */
+ } else {
+ /* we dont care! */
+ }
+ free(nick);
+ }
+ }
+ }
+ return MOD_CONT;
+}
+
+/**
+ * Called after a user does a /msg chanserv info chan
+ * @param u The user who requested info
+ * @return MOD_CONT to continue processing commands or MOD_STOP to stop
+ **/
+int myChanInfo(User * u)
+{
+ char *text = NULL;
+ char *chan = NULL;
+ char *info = NULL;
+ ChannelInfo *ci = NULL;
+
+ /* Only show our goodies to opers */
+ if (is_oper(u)) {
+ /* Get the last buffer anope recived */
+ text = moduleGetLastBuffer();
+ if (text) {
+ chan = myStrGetToken(text, ' ', 0);
+ if (chan) {
+ if ((ci = cs_findchan(chan))) {
+ /* If we have any info on this channel */
+ if ((info = moduleGetData(&ci->moduleData, "info"))) {
+ notice_user(s_ChanServ, u, " OperInfo: %s", info);
+ free(info);
+ }
+ }
+ free(chan);
+ }
+ }
+ }
+ return MOD_CONT;
+}
+
+/*************************************************************************/
+
+/**
+ * Load data from the db file, and populate our OperInfo lines
+ * @return 0 for success
+ **/
+int mLoadData(void)
+{
+ int ret = 0;
+ FILE *in;
+
+ char *type = NULL;
+ char *name = NULL;
+ char *info = NULL;
+ int len = 0;
+
+ ChannelInfo *ci = NULL;
+ NickAlias *na = NULL;
+
+ /* will _never_ be this big thanks to the 512 limit of a message */
+ char buffer[2000];
+ if ((in = fopen(OSInfoDBName, "r")) == NULL) {
+ alog("os_info: WARNING: can not open the database file! (it might not exist, this is not fatal)");
+ ret = 1;
+ } else {
+ while (fgets(buffer, 1500, in)) {
+ type = myStrGetToken(buffer, ' ', 0);
+ name = myStrGetToken(buffer, ' ', 1);
+ info = myStrGetTokenRemainder(buffer, ' ', 2);
+ if (type) {
+ if (name) {
+ if (info) {
+ len = strlen(info);
+ /* Take the \n from the end of the line */
+ info[len - 1] = '\0';
+ if (stricmp(type, "C") == 0) {
+ if ((ci = cs_findchan(name))) {
+ moduleAddData(&ci->moduleData, "info",
+ info);
+ }
+ } else if (stricmp(type, "N") == 0) {
+ if ((na = findnick(name))) {
+ moduleAddData(&na->nc->moduleData, "info",
+ info);
+ }
+ }
+ free(info);
+ }
+ free(name);
+ }
+ free(type);
+ }
+ }
+ }
+ return ret;
+}
+
+/**
+ * Save all our data to our db file
+ * First walk through the nick CORE list, and any nick core which has
+ * oper info attached to it, write to the file.
+ * Next do the same again for ChannelInfos
+ * @return 0 for success
+ **/
+int mSaveData(int argc, char **argv)
+{
+ ChannelInfo *ci = NULL;
+ NickCore *nc = NULL;
+ int i = 0;
+ int ret = 0;
+ FILE *out;
+ char *info = NULL;
+
+ if (argc >= 1) {
+ if (!stricmp(argv[0], EVENT_START)) {
+ if ((out = fopen(OSInfoDBName, "w")) == NULL) {
+ alog("os_info: ERROR: can not open the database file!");
+ anope_cmd_global(s_OperServ,
+ "os_info: ERROR: can not open the database file!");
+ ret = 1;
+ } else {
+ for (i = 0; i < 1024; i++) {
+ for (nc = nclists[i]; nc; nc = nc->next) {
+ /* If we have any info on this user */
+ if ((info = moduleGetData(&nc->moduleData, "info"))) {
+ fprintf(out, "N %s %s\n", nc->display, info);
+ free(info);
+ }
+ }
+ }
+
+
+ for (i = 0; i < 256; i++) {
+ for (ci = chanlists[i]; ci; ci = ci->next) {
+ /* If we have any info on this channel */
+ if ((info = moduleGetData(&ci->moduleData, "info"))) {
+ fprintf(out, "C %s %s\n", ci->name, info);
+ free(info);
+ }
+ }
+ }
+ fclose(out);
+ }
+ } else {
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Backup our databases using the commands provided by Anope
+ * @return MOD_CONT
+ **/
+int mBackupData(int argc, char **argv)
+{
+ ModuleDatabaseBackup(OSInfoDBName);
+
+ return MOD_CONT;
+}
+
+/**
+ * Load the configuration directives from Services configuration file.
+ * @return 0 for success
+ **/
+int mLoadConfig(void)
+{
+ char *tmp = NULL;
+
+ Directive directivas[] = {
+ {"OSInfoDBName", {{PARAM_STRING, PARAM_RELOAD, &tmp}}},
+ };
+
+ Directive *d = &directivas[0];
+ moduleGetConfigDirective(d);
+
+ if (OSInfoDBName)
+ free(OSInfoDBName);
+
+ if (tmp) {
+ OSInfoDBName = tmp;
+ } else {
+ OSInfoDBName = sstrdup(DEFAULT_DB_NAME);
+ alog("os_info: OSInfoDBName is not defined in Services configuration file, using default %s", OSInfoDBName);
+ }
+
+ alog("os_info: Directive OSInfoDBName loaded (%s)...", OSInfoDBName);
+
+ return 0;
+}
+
+/**
+ * Manage the RELOAD EVENT
+ * @return MOD_CONT
+ **/
+int mEventReload(int argc, char **argv)
+{
+ int ret = 0;
+ if (argc >= 1) {
+ if (!stricmp(argv[0], EVENT_START)) {
+ alog("os_info: Reloading configuration directives...");
+ ret = mLoadConfig();
+ } else {
+ /* Nothing for now */
+ }
+ }
+
+ if (ret)
+ alog("os_info.c: ERROR: An error has occured while reloading the configuration file");
+
+ return MOD_CONT;
+}
+
+/*************************************************************************/
+
+/**
+ * manages the multilanguage stuff
+ **/
+void m_AddLanguages(void)
+{
+ char *langtable_en_us[] = {
+ /* OINFO_SYNTAX */
+ "Syntax: OINFO [ADD|DEL] nick <info>",
+ /* OINFO_ADD_SUCCESS */
+ "OperInfo line has been added to nick %s",
+ /* OINFO_DEL_SUCCESS */
+ "OperInfo line has been removed from nick %s",
+ /* OCINFO_SYNTAX */
+ "Syntax: OINFO [ADD|DEL] chan <info>",
+ /* OCINFO_ADD_SUCCESS */
+ "OperInfo line has been added to channel %s",
+ /* OCINFO_DEL_SUCCESS */
+ "OperInfo line has been removed from channel %s",
+ /* OINFO_HELP */
+ "Syntax: OINFO [ADD|DEL] nick <info>\n"
+ "Add or Delete Oper information for the given nick\n"
+ "This will show up when any oper /ns info nick's the user.\n"
+ "and can be used for 'tagging' users etc....",
+ /* OCINFO_HELP */
+ "Syntax: OINFO [ADD|DEL] chan <info>\n"
+ "Add or Delete Oper information for the given channel\n"
+ "This will show up when any oper /cs info's the channel.\n"
+ "and can be used for 'tagging' channels etc....",
+ /* OINFO_HELP_CMD */
+ " OINFO Add / Del an OperInfo line to a nick",
+ /* OCINFO_HELP_CMD */
+ " OINFO Add / Del an OperInfo line to a channel"
+ };
+
+ char *langtable_es[] = {
+ /* OINFO_SYNTAX */
+ "Sintaxis: OINFO [ADD|DEL] nick <info>",
+ /* OINFO_ADD_SUCCESS */
+ "Una linea OperInfo ha sido agregada al nick %s",
+ /* OINFO_DEL_SUCCESS */
+ "La linea OperInfo ha sido removida del nick %s",
+ /* OCINFO_SYNTAX */
+ "Sintaxis: OINFO [ADD|DEL] chan <info>",
+ /* OCINFO_ADD_SUCCESS */
+ "Linea OperInfo ha sido agregada al canal %s",
+ /* OCINFO_DEL_SUCCESS */
+ "La linea OperInfo ha sido removida del canal %s",
+ /* OINFO_HELP */
+ "Sintaxis: OINFO [ADD|DEL] nick <info>\n"
+ "Agrega o elimina informacion para Operadores al nick dado\n"
+ "Esto se mostrara cuando cualquier operador haga /ns info nick\n"
+ "y puede ser usado para 'marcado' de usuarios, etc....",
+ /* OCINFO_HELP */
+ "Sintaxis: OINFO [ADD|DEL] chan <info>\n"
+ "Agrega o elimina informacion para Operadores al canal dado\n"
+ "Esto se mostrara cuando cualquier operador haga /cs info canal\n"
+ "y puede ser usado para 'marcado' de canales, etc....",
+ /* OINFO_HELP_CMD */
+ " OINFO Agrega / Elimina una linea OperInfo al nick",
+ /* OCINFO_HELP_CMD */
+ " OINFO Agrega / Elimina una linea OperInfo al canal"
+ };
+
+ char *langtable_nl[] = {
+ /* OINFO_SYNTAX */
+ "Gebruik: OINFO [ADD|DEL] nick <info>",
+ /* OINFO_ADD_SUCCESS */
+ "OperInfo regel is toegevoegd aan nick %s",
+ /* OINFO_DEL_SUCCESS */
+ "OperInfo regel is weggehaald van nick %s",
+ /* OCINFO_SYNTAX */
+ "Gebruik: OINFO [ADD|DEL] kanaal <info>",
+ /* OCINFO_ADD_SUCCESS */
+ "OperInfo regel is toegevoegd aan kanaal %s",
+ /* OCINFO_DEL_SUCCESS */
+ "OperInfo regel is weggehaald van kanaal %s",
+ /* OINFO_HELP */
+ "Gebruik: OINFO [ADD|DEL] nick <info>\n"
+ "Voeg een Oper informatie regel toe aan de gegeven nick, of\n"
+ "verwijder deze. Deze regel zal worden weergegeven wanneer\n"
+ "een oper /ns info nick doet voor deze gebruiker, en kan worden\n"
+ "gebruikt om een gebruiker te 'markeren' etc...",
+ /* OCINFO_HELP */
+ "Gebruik: OINFO [ADD|DEL] kanaal <info>\n"
+ "Voeg een Oper informatie regel toe aan de gegeven kanaal, of\n"
+ "verwijder deze. Deze regel zal worden weergegeven wanneer\n"
+ "een oper /cs info kanaal doet voor dit kanaal, en kan worden\n"
+ "gebruikt om een kanaal te 'markeren' etc...",
+ /* OINFO_HELP_CMD */
+ " OINFO Voeg een OperInfo regel toe aan een nick of verwijder deze",
+ /* OCINFO_HELP_CMD */
+ " OINFO Voeg een OperInfo regel toe aan een kanaal of verwijder deze"
+ };
+
+ char *langtable_de[] = {
+ /* OINFO_SYNTAX */
+ "Syntax: OINFO [ADD|DEL] Nickname <Information>",
+ /* OINFO_ADD_SUCCESS */
+ "Eine OperInfo Linie wurde zu den Nicknamen %s hinzugefьgt",
+ /* OINFO_DEL_SUCCESS */
+ "Die OperInfo Linie wurde von den Nicknamen %s enfernt",
+ /* OCINFO_SYNTAX */
+ "Syntax: OINFO [ADD|DEL] Channel <Information>",
+ /* OCINFO_ADD_SUCCESS */
+ "Eine OperInfo Linie wurde zu den Channel %s hinzugefьgt",
+ /* OCINFO_DEL_SUCCESS */
+ "Die OperInfo Linie wurde von den Channel %s enfernt",
+ /* OINFO_HELP */
+ "Syntax: OINFO [ADD|DEL] Nickname <Information>\n"
+ "Addiert oder lцscht eine OperInfo Linie zu den angegebenen\n"
+ "Nicknamen.Sie wird angezeigt wenn ein Oper mit /ns info sich\n"
+ "ьber den Nicknamen informiert.",
+ /* OCINFO_HELP */
+ "Syntax: OINFO [ADD|DEL] chan <info>\n"
+ "Addiert oder lцscht eine OperInfo Linie zu den angegebenen\n"
+ "Channel.Sie wird angezeigt wenn ein Oper mit /cs info sich\n"
+ "ьber den Channel informiert.",
+ /* OINFO_HELP_CMD */
+ " OINFO Addiert / Lцscht eine OperInfo Linie zu / von einen Nicknamen",
+ /* OCINFO_HELP_CMD */
+ " OINFO Addiert / Lцscht eine OperInfo Linie zu / von einen Channel"
+ };
+
+ char *langtable_pt[] = {
+ /* OINFO_SYNTAX */
+ "Sintaxe: OINFO [ADD|DEL] nick <informaзгo>",
+ /* OINFO_ADD_SUCCESS */
+ "A linha OperInfo foi adicionada ao nick %s",
+ /* OINFO_DEL_SUCCESS */
+ "A linha OperInfo foi removida do nick %s",
+ /* OCINFO_SYNTAX */
+ "Sintaxe: OINFO [ADD|DEL] canal <informaзгo>",
+ /* OCINFO_ADD_SUCCESS */
+ "A linha OperInfo foi adicionada ao canal %s",
+ /* OCINFO_DEL_SUCCESS */
+ "A linha OperInfo foi removida do canal %s",
+ /* OINFO_HELP */
+ "Sintaxe: OINFO [ADD|DEL] nick <informaзгo>\n"
+ "Adiciona ou apaga informaзгo para Operadores ao nick fornecido\n"
+ "Isto serб mostrado quando qualquer Operador usar /ns info nick\n"
+ "e pode ser usado para 'etiquetar' usuбrios etc...",
+ /* OCINFO_HELP */
+ "Sintaxe: OINFO [ADD|DEL] canal <informaзгo>\n"
+ "Adiciona ou apaga informaзгo para Operadores ao canal fornecido\n"
+ "Isto serб mostrado quando qualquer Operador usar /cs info canal\n"
+ "e pode ser usado para 'etiquetar' canais etc...",
+ /* OINFO_HELP_CMD */
+ " OINFO Adiciona ou Apaga a linha OperInfo para um nick",
+ /* OCINFO_HELP_CMD */
+ " OINFO Adiciona ou Apaga a linha OperInfo para um canal"
+ };
+
+ char *langtable_ru[] = {
+ /* OINFO_SYNTAX */
+ "Синтаксис: OINFO ADD|DEL ник тест",
+ /* OINFO_ADD_SUCCESS */
+ "Опер-Информация для ника %s добавлена",
+ /* OINFO_DEL_SUCCESS */
+ "Опер-Информация для ника %s была удалена",
+ /* OCINFO_SYNTAX */
+ "Синтаксис: OINFO ADD|DEL #канал текст",
+ /* OCINFO_ADD_SUCCESS */
+ "Опер-Информация для канала %s успешно установлена",
+ /* OCINFO_DEL_SUCCESS */
+ "Опер-Информация для канала %s была удалена",
+ /* OINFO_HELP */
+ "Синтаксис: OINFO ADD|DEL ник текст\n"
+ "Устанавливает или удаляет Опер-Информацию для указанного ника,\n"
+ "которая будет показана любому оператору, запрашивающему INFO ника.\n"
+ "Может быть использована для 'пометки' пользователей и т. д...",
+ /* OCINFO_HELP */
+ "Синтаксис: OINFO ADD|DEL #канал текст\n"
+ "Устанавливает или удаляет Опер-Информацию для указанного канала,\n"
+ "которая будет показана любому оператору, запрашивающему INFO канала.\n"
+ "Может быть использована для 'пометки' каналов и т. д...",
+ /* OINFO_HELP_CMD */
+ " OINFO Добавляет/Удаляет опер-инфо для ника",
+ /* OCINFO_HELP_CMD */
+ " OINFO Добавляет/Удаляет опер-инфо для канала"
+ };
+
+ char *langtable_it[] = {
+ /* OINFO_SYNTAX */
+ "Sintassi: OINFO [ADD|DEL] nick <info>",
+ /* OINFO_ADD_SUCCESS */
+ "Linea OperInfo aggiunta al nick %s",
+ /* OINFO_DEL_SUCCESS */
+ "Linea OperInfo rimossa dal nick %s",
+ /* OCINFO_SYNTAX */
+ "Sintassi: OINFO [ADD|DEL] chan <info>",
+ /* OCINFO_ADD_SUCCESS */
+ "Linea OperInfo aggiunta al canale %s",
+ /* OCINFO_DEL_SUCCESS */
+ "Linea OperInfo rimossa dal canale %s",
+ /* OINFO_HELP */
+ "Sintassi: OINFO [ADD|DEL] nick <info>\n"
+ "Aggiunge o rimuove informazioni Oper per il nick specificato\n"
+ "Queste vengono mostrate quando un oper esegue il comando /ns info <nick>\n"
+ "e possono essere utilizzate per 'marchiare' gli utenti ecc...",
+ /* OCINFO_HELP */
+ "Sintassi: OINFO [ADD|DEL] chan <info>\n"
+ "Aggiunge o rimuove informazioni Oper per il canale specificato\n"
+ "Queste vengono mostrate quando un oper esegue il comando /cs info <canale>\n"
+ "e possono essere utilizzate per 'marchiare' i canali ecc...",
+ /* OINFO_HELP_CMD */
+ " OINFO Aggiunge/Rimuove una linea OperInfo ad/da un nick",
+ /* OCINFO_HELP_CMD */
+ " OINFO Aggiunge/Rimuove una linea OperInfo ad/da un canale"
+ };
+
+ moduleInsertLanguage(LANG_EN_US, LANG_NUM_STRINGS, langtable_en_us);
+ moduleInsertLanguage(LANG_ES, LANG_NUM_STRINGS, langtable_es);
+ moduleInsertLanguage(LANG_NL, LANG_NUM_STRINGS, langtable_nl);
+ moduleInsertLanguage(LANG_DE, LANG_NUM_STRINGS, langtable_de);
+ moduleInsertLanguage(LANG_PT, LANG_NUM_STRINGS, langtable_pt);
+ moduleInsertLanguage(LANG_RU, LANG_NUM_STRINGS, langtable_ru);
+ moduleInsertLanguage(LANG_IT, LANG_NUM_STRINGS, langtable_it);
+}
+
+/*************************************************************************/
+
+int mNickHelp(User * u)
+{
+ if (is_oper(u)) {
+ moduleNoticeLang(s_NickServ, u, OINFO_HELP);
+ } else {
+ notice_lang(s_NickServ, u, NO_HELP_AVAILABLE, "OINFO");
+ }
+ return MOD_CONT;
+}
+
+int mChanHelp(User * u)
+{
+ if (is_oper(u)) {
+ moduleNoticeLang(s_ChanServ, u, OCINFO_HELP);
+ } else {
+ notice_lang(s_ChanServ, u, NO_HELP_AVAILABLE, "OINFO");
+ }
+ return MOD_CONT;
+}
+
+/* This help will be added to the main NickServ list */
+void mMainNickHelp(User * u)
+{
+ if (is_oper(u)) {
+ moduleNoticeLang(s_NickServ, u, OINFO_HELP_CMD);
+ }
+}
+
+/* This help will be added to the main NickServ list */
+void mMainChanHelp(User * u)
+{
+ if (is_oper(u)) {
+ moduleNoticeLang(s_ChanServ, u, OCINFO_HELP_CMD);
+ }
+}
+
+/*************************************************************************/
+
+/* EOF */