--- /dev/null
+Copyright (c) 1997 - 2002 by the StarChat IRC Network
+
+This or any file contained in this distribution is copyrighted by the StarChat
+IRC Network. You are NOT allowed to run, modify or distribute this software or
+any of its components in any way without explicit written permission from the
+StarChat administration (StarCouncil and/or the Network Administrator).
--- /dev/null
+# Which compiler
+CC=gcc
+
+# Include files
+INCLUDE=../include
+
+# Source files
+SRC=src
+
+# Install location
+INSTDIR=../services
+
+# Compiler flags
+CFLAGS=-O -Wall -g
+
+# To compile with libefence for memory debuging
+# uncomment the following line
+#LDFLAGS=-lefence -lcrypt
+# Or use this one
+LDFLAGS=-lcrypt
+
+# Tools
+RM=rm
+CP=cp
+MKDIR=mkdir
+TOUCH=touch
+
+# Arguments to pass on...
+MAKEARGS='CFLAGS=$(CFLAGS)' 'CC=$(CC)' 'INCLUDE=$(INCLUDE)' \
+ 'RM=$(RM)' 'CP=$(CP)' 'MKDIR=$(MKDIR)' 'TOUCH=$(TOUCH)' \
+ 'LDFLAGS=$(LDFLAGS)'
+
+all: services
+
+services:
+ @echo "Building services..."; \
+ ( cd $(SRC); ${MAKE} ${MAKEARGS} services; )
+
+clean:
+ @echo "Cleaning..."
+ ( cd $(SRC); ${MAKE} ${MAKEARGS} clean; )
+
+install: services
+ @echo "Installing services..."; \
+ if [ -d $(INSTDIR) ]; then \
+ $(CP) $(SRC)/services $(INSTDIR); \
+ echo "Installed services in $(INSTDIR)"; \
+ if [ -d $(INSTDIR)/logs ]; then \
+ echo "Finished!"; \
+ else \
+ echo "Looks like services have not been installed to $(INSTDIR) before..."; \
+ echo "I'll create the necessary directories now..."; \
+ $(MKDIR) $(INSTDIR)/logs; \
+ $(MKDIR) $(INSTDIR)/db; \
+ echo "Finished!"; \
+ fi \
+ else \
+ echo "$(INSTDIR) is not a directory! Installation aborted!"; \
+ fi
--- /dev/null
+/* $Id: acconfig.h,v 1.1.1.1 2002/02/05 12:34:19 remmy Exp $ */
+
+/*
+ * This is in the top level so that it is in the same "local" directory
+ * * as aclocal.m4, so autoreconf causes autoheader to find it. Nothing
+ * * actually includes this file, it is always processed into something else.
+ */
+
+/*
+ * Don't use too large a block, because the autoheader processing can't
+ * handle it on some systems.
+ */
+
+/* define if your headers do not define sys_errlist */
+#undef NEED_SYS_ERRLIST
+
+/* define if your lex defines yylineno */
+#undef HAVE_YYLINENO
+
+/* define if you need u_int32_t */
+#undef u_int32_t
+
+/* define if you need int32_t */
+#undef int32_t
+
+/* define if you need u_int16_t */
+#undef u_int16_t
+
+/* define if you need int16_t */
+#undef int16_t
+
+/* define if you need u_int8_t */
+#undef u_int8_t
+
+/* define if you need int8_t */
+#undef int8_t
--- /dev/null
+#ifndef __BAN_H
+#define __BAN_H
+
+int is_ip_address(char *);
+void mask(char *, char *, int, char *);
+
+#endif
--- /dev/null
+#ifndef __CHANSERV_H
+#define __CHANSERV_H
+
+/* mode flags */
+#define PM_I 0x00000001
+#define PM_K 0x00000002
+#define PM_L 0x00000004
+#define PM_M 0x00000008
+#define PM_N 0x00000010
+#define PM_P 0x00000020
+#define PM_S 0x00000040
+#define PM_T 0x00000080
+#define MM_I 0x00000100
+#define MM_K 0x00000200
+#define MM_L 0x00000400
+#define MM_M 0x00000800
+#define MM_N 0x00001000
+#define MM_P 0x00002000
+#define MM_S 0x00004000
+#define MM_T 0x00008000
+#define PM_C 0x00010000
+#define MM_C 0x00020000
+#define PM_R 0x00040000
+#define MM_R 0x00080000
+
+/* Channel flags */
+#define COPGUARD 0x00000001
+#define CKTOPIC 0x00000002
+#define CLEAVEOPS 0x00000004
+#define CQUIET 0x00000008
+#define CIDENT 0x00000020
+#define CHOLD 0x00000040
+#define CREG 0x00000080
+#define CBANISH 0x00000100
+#define CPROTOP 0x00000200
+#define CCLASSIC 0x00000400
+#define CFEXEMPT 0x00000800
+#define CPRIVATE 0x00001000
+#define CNOTICE 0x00002000
+#define CFORCES 0x00004000
+#define CFREEZE 0x00008000
+#define CFORUM 0x00010000
+#define CCLOSED 0x00020000
+#define CSCAN 0x00040000
+
+/*
+ * op levels.
+ *
+ * Anything named OPxx is an open field.
+ * feel free to fill open fields with whatever you want
+ * For more information, see docs/levelscheme.
+ */
+#define OPNONE 0
+#define OP1 1
+#define OP2 2
+#define MAOP 3
+#define OP4 4
+#define AOP 5
+#define OP6 6
+#define OP7 7
+#define MSOP 8
+#define OP9 9
+#define SOP 10
+#define OP11 11
+#define OP12 12
+#define MFOUNDER 13
+#define OP14 14
+#define FOUNDER 15
+
+typedef struct cnicklist_struct cNickList;
+
+struct cnicklist_struct {
+ UserList *person; /* Pointer to persons user info */
+ int op;
+ cNickList *next;
+ cNickList *previous;
+ cNickList *hashnext;
+ cNickList *hashprev;
+};
+
+typedef struct cnicklisthashent_struct {
+ cNickList *item;
+ cNickList *lastitem;
+} cNickListHashEnt;
+
+/*
+ * This is used for AOP/SOP/Foundererer lists
+ */
+typedef struct caccesslist_struct cAccessList;
+
+struct caccesslist_struct {
+ char nick[NICKLEN];
+ short uflags; /* flags: AOP/SOP/CFOUNDER/RFOUNDER */
+ int index;
+ cAccessList *next;
+ cAccessList *previous;
+ cAccessList *hashnext;
+ cAccessList *hashprev;
+};
+
+typedef struct caccesslisthashent_struct {
+ cAccessList *item, *lastitem;
+} cAccessListHashEnt;
+
+/*
+ * Special list for AKicked lusers, }:>
+ */
+typedef struct cakicklist_struct cAkickList;
+
+struct cakicklist_struct {
+ char mask[USERLEN+HOSTLEN+3];
+ char reason[51 + NICKLEN]; /* Why they're AKicked */
+ int index;
+ time_t added; /* When it was set */
+ cAkickList *next;
+ cAkickList *previous;
+};
+
+/*
+ * Ban item
+ */
+typedef struct cbanlist_struct cBanList;
+
+struct cbanlist_struct {
+ char ban[NICKLEN + USERLEN + HOSTLEN]; /* the ban */
+ cBanList *next;
+ cBanList *previous;
+};
+
+/*
+ * tis a channel we see...arr me maties...
+ */
+typedef struct regchanlist_struct RegChanList;
+
+struct chanlist_struct {
+ char name[CHANLEN];
+ cBanList *firstBan; /* list of banned people */
+ cBanList *lastBan;
+ cBanList *firstExempt; /* list of exempted people */
+ cBanList *lastExempt;
+ cNickList *firstUser;
+ cNickList *lastUser;
+ long modes;
+ RegChanList *reg;
+ ChanList *next, *previous, *hashnext, *hashprev;
+};
+
+struct regchanlist_struct {
+ char name[CHANLEN]; /* channel name */
+ char founder[NICKLEN];
+ int facc;
+ char desc[101]; /* description */
+ char topic[310]; /* the topic */
+ char tsetby[NICKLEN]; /* Who set the topic */
+ char url[128];
+ char password[16];
+ time_t ttimestamp; /* when the topic was set */
+ long mlock; /* modelocks (+/-) */
+ long flags; /* Channel flags */
+ time_t timereg;
+ time_t timestamp;
+ char key[23]; /* Channel key */
+ long limit; /* limit */
+ int ops; /* how many of each are there */
+ int akicks;
+ int tlocklevel;
+ int restrictlevel;
+ cAkickList *firstAkick; /* Banned users */
+ cAkickList *lastAkick;
+ /*
+ * hashes for users/ChanOps
+ */
+ cAccessList *firstOp;
+ cAccessList *lastOp;
+ RegChanList *next;
+ RegChanList *previous;
+ RegChanList *hashnext;
+ RegChanList *hashprev;
+};
+
+typedef struct forcelist_struct ForceList;
+
+struct forcelist_struct {
+ char mask[CHANLEN];
+ ForceList *next, *prev;
+};
+
+void addForce(char *);
+int isForced(char *);
+
+typedef struct banchanlist_struct BanChannelList;
+
+struct banchanlist_struct {
+ char mask[CHANLEN];
+ BanChannelList *next, *prev;
+};
+
+void addBanChannel(char *);
+int isBanChannel(char *);
+
+void sendToChanServ(UserList *, char **, int);
+void addUserToChan(UserList *, char *);
+void remUserFromChan(UserList *, char *);
+void doKick(UserList *, UserList *, char *);
+void remFromAllChans(UserList *);
+void changeNickOnAllChans(UserList *, UserList *);
+void setChanMode(char **, int);
+void setChanTopic(char **, int);
+void sendToChanOps(ChanList *, char *,...);
+void cleanChanList(void);
+void addChan(ChanList *);
+void delChan(ChanList *);
+void addRegChan(RegChanList *);
+void delRegChan(RegChanList *);
+void addChanAkick(RegChanList *, cAkickList *);
+void delChanAkick(RegChanList *, cAkickList *);
+void addChanOp(RegChanList *, cAccessList *);
+void delChanOp(RegChanList *, cAccessList *);
+void initRegChanData(RegChanList *);
+void addChanUser(ChanList *, cNickList *);
+void delChanUser(ChanList *, cNickList *);
+void addChanBan(ChanList *, cBanList *);
+void delChanBan(ChanList *, cBanList *);
+ChanList *getChanData(char *);
+RegChanList *getRegChanData(char *);
+cNickList *getChanUserData(ChanList *, UserList *);
+cBanList *getChanBan(ChanList *, char *);
+cBanList *getChanExempt(ChanList *, char *);
+int getChanOp(RegChanList *, char *);
+cAccessList *getChanOpData(RegChanList *, char *);
+cAkickList *getChanAKick(RegChanList *, char *);
+void syncChanData(time_t);
+int check_mask(char *, int);
+int countRegChans(char *);
+void remfromallchanops(char *);
+void ParseSJOIN(char *, char*);
+void addUserToChanSJ(UserList *, char *, int);
+
+/* chanserv commands prototypes: */
+
+void CclistCmd(UserList *, char **, int);
+void CinfoCmd(UserList *, char **, int);
+void CregisterCmd(UserList *, char **, int);
+void CdropCmd(UserList *, char **, int);
+void CaccessCmd(UserList *, char **, int);
+void CaddopCmd(UserList *, char **, int);
+void CaddakCmd(UserList *, char **, int);
+void CdelopCmd(UserList *, char **, int);
+void CdelakCmd(UserList *, char **, int);
+void ClistopCmd(UserList *, char **, int);
+void ClistopNCmd(UserList *, char **, int);
+void ClistopLCmd(UserList *, char **, int);
+void ClistakCmd(UserList *, char **, int);
+void CopCmd(UserList *, char **, int);
+void CdeopCmd(UserList *, char **, int);
+void CmodelockCmd(UserList *, char **, int);
+void CrestrictCmd(UserList *, char **, int);
+void CtopiclockCmd(UserList *, char **, int);
+void CsetCmd(UserList *, char **, int);
+void CsaveCmd(UserList *, char **, int);
+void CinviteCmd(UserList *, char **, int);
+void CunbanCmd(UserList *, char **, int);
+void ClistCmd(UserList *, char **, int);
+void CdeleteCmd(UserList *, char **, int);
+void CmassdeopCmd(UserList *, char **, int);
+void CmasskickCmd(UserList *, char **, int);
+void CmodeclearCmd(UserList *, char **, int);
+void CfounderCmd(UserList *, char **, int);
+void CcloseCmd(UserList *, char **, int);
+
+#define CHANOP 0x0001
+#define CHANVOICE 0x0002
+
+#endif /* __CHANSERV_H */
--- /dev/null
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+/* Policy used for dlopen() mode */
+/* #undef DLOPEN_POLICY */
+
+/* define if you lack socklen_t */
+/* #undef socklen_t */
+
+/* Installation Prefix */
+/* #undef INSTALL_PREFIX */
+
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define if your <sys/time.h> declares struct tm. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Define if you have the hstrerror function. */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the inet_addr function. */
+#define HAVE_INET_ADDR 1
+
+/* Define if you have the inet_aton function. */
+#define HAVE_INET_ATON 1
+
+/* Define if you have the mktime function. */
+#define HAVE_MKTIME 1
+
+/* Define if you have the readdir_r function. */
+#define HAVE_READDIR_R 1
+
+/* Define if you have the select function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the strdup function. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Name of package */
+#define PACKAGE "services"
+
+/* Version number of package */
+#define VERSION "0.8.2-pre1"
+
+
+#endif /* _CONFIG_H */
+
--- /dev/null
+#ifndef __DB_H
+#define __DB_H
+
+/* void saveRegData(nRegList *); */
+void saveNickData(RegNickList *);
+void saveChanData(RegChanList *);
+/* void readRegData(void); */
+void readNickData(void);
+void readChanData(void);
+void sync_cfg(char *);
+void saveMemoData(RegNickList *);
+void readMemoData(void);
+
+void do_remaining_backup(char *);
+
+#endif /* __DB_H */
--- /dev/null
+#ifndef __HASH_H
+#define __HASH_H
+
+/*
+ * in this I use hash tables for nicks and channels, speed up searching
+ * and the like...
+ */
+
+/*
+ * nickname hash entry
+ */
+typedef struct nickhashent {
+ RegNickList *nick, *lastnick;
+} RegNickHashEnt;
+
+typedef struct userhashent {
+ UserList *nick, *lastnick;
+} UserHashEnt;
+
+/*
+ * channel hash entry
+ */
+typedef struct chanhashent {
+ ChanList *chan, *lastchan;
+} ChanHashEnt;
+typedef struct regchanhashent {
+ RegChanList *chan, *lastchan;
+} RegChanHashEnt;
+
+typedef struct clonehashent {
+ HostClone *clone, *lastclone;
+} CloneHashEnt;
+
+long getHashKey(char *);
+void cleanNickHash(void);
+void cleanChanHash(void);
+
+#endif /* __HASH_H */
--- /dev/null
+#ifndef __HELP_H
+#define __HELP_H
+
+void showMotd(char *);
+void sendHelp(char *, char *, char *[255], int);
+void WSsendHelp(char *, char *, char *[255], int);
+
+#endif
--- /dev/null
+#ifndef __JINX
+#define __JINX
+/* JINX list and PERMJINX list
+ */
+void checkPermJinx(char *);
+void CheckHostJinx(char *, char *, int);
+void savePermJinxes();
+void loadPermJinxes();
+void loadHostJinxes();
+void saveHostJinxes();
+void SynchHJinxes();
+
+/* New JINX structs, vars and all the other stuff we need */
+
+typedef struct Jinx aJinx;
+struct Jinx {
+ char nick[NICKLEN];
+ char by[NICKLEN];
+ time_t time;
+ char reason[512];
+ aJinx *next, *prev;
+};
+aJinx *JinxList;
+
+void AddJinx(char *, char *, char *);
+int CheckJinx(char *);
+void DeleteJinx(char *);
+void free_jinx(aJinx *);
+aJinx *make_jinx();
+
+typedef struct PJinx aPJinx;
+struct PJinx {
+ char nick[NICKLEN];
+ char by[NICKLEN];
+ time_t time;
+ char reason[512];
+ aPJinx *next, *prev;
+};
+aPJinx *PJinxList;
+
+void AddPJinx(char *, char *, char *);
+void AddPJinxTime(char *, char *, char *, long);
+int CheckPJinx(char *);
+void DeletePJinx(char *);
+void free_pjinx(aPJinx *);
+aPJinx *make_pjinx();
+
+typedef struct HJinx aHJinx;
+struct HJinx {
+ char host[120];
+ char by[NICKLEN];
+ time_t time;
+ char reason[512];
+ aHJinx *next, *prev;
+};
+aHJinx *HJinxList;
+
+void AddHJinx(char *, char *, char *);
+void AddHJinxTime(char *, char *, char *, long);
+int CheckHJinx(char *);
+void DeleteHJinx(char *);
+void free_hjinx(aHJinx *);
+aHJinx *make_hjinx();
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Language Format Table: Cajun
+ *
+ * Revised November 2000 - jinxi
+ */
+
+#ifndef CAJUN__H
+#define CAJUN__H
+
+#include "services.h"
+
+struct FormatTable CajunReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Custom Message" },
+{ ERR_NEEDREGNICK, "Ain? Mais, register de nick to do dat." },
+{ ERR_NEEDACTNICK, "Ain? Mais, activate de nick to do dat." },
+{ ERR_NEEDSRA, "Dôn be so coo-yôn! I dôn tink yo a Services Rôt Administratah." },
+{ ERR_NEEDSERVOP, "Dôn be so coo-yôn! I dôn tink yo a Services Operatah." },
+{ ERR_NEEDOPER, "Dôn be so coo-yôn! I dôn tink yo one dem Ayarzee Operatahs." },
+{ ERR_UNKNOWNCOMMAND, "\002%s\002 dôn make no sense. Pass by #starchat to axe for help." },
+{ RPL_MOREHELP, "\002/msg %s help\002 for dat chôse." },
+{ RPL_DEBUGHEADER, "[%s De Bebette]" },
+{ RPL_DEBUGFOOTER, "[End De Bebette]" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "I dôn know what dat is. Dey want mo informashun." },
+{ RPL_PASSOKAY, "Dass de rite password for \002%s\002." },
+{ RPL_YOUAREROOT, "Ga lee luk at de size o dat gator!" },
+{ RPL_YOUARESERVOP, "Coooh luk at da size o dat crawfish!" },
+{ RPL_NOCHANGEPASS, "Serenity-IRC says change yo password afor a peeshwank go get yo nick." },
+{ RPL_MOREHELPCMD, "\002/msg %s help %s\002 for dat informashun o pass by #starchat to axe for help." },
+{ RPL_PASSNOTOKAY, "Passé! Dat is no de right password for \002%s\002." },
+{ RPL_EMAILHACK1, "Ain? Dass no de right one! Dôn do dat!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "De correct password got sent to de Email address for dis nick." },
+{ RPL_EMAILHACK3, "What you was tinking? Dôn identify 'til yo see de Email." },
+{ RPL_EMAILHACK4, "Pass by " NETCHAN " if yo dôn receive de Email in 15 minutes." },
+{ RPL_EMAILHACK5, "Meenoo! Serenity-IRC put da gree gree on yo if yo continue enter de incorrect password." },
+{ RPL_EMAILHACK6, "Dôn boude'! I told yo dôn do dat an now yo make a big bahbin!" },
+{ ERR_NICKNOTREGGED, "\002%s\002 dôn be a registered nick." },
+{ RPL_INFOHEADER, "[\002%s\002 NickServ Informashun]" },
+{ RPL_INFOFOOTER, "[End NickServ Informashun]" },
+{ RPL_INFOBANISHED, "Dat nick dôn be used on Serenity-IRC." },
+{ RPL_INFONOWON, "[Currently on Serenity-IRC] - For mo informashun: /whois %s" },
+{ RPL_INFODEREG, "Dat nick be deregistered by Serenity-IRC." },
+{ RPL_INFOLASTSEEN1, "Last Address - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Last Here - %s" },
+{ RPL_INFOREGGEDON, "Registered - %s" },
+{ RPL_INFOEMAIL, "Email Address - %s" },
+{ RPL_INFOACCESS, "Services Axes - %s" },
+{ RPL_INFOOPTIONS, "De Options - %s" },
+{ RPL_INFOMEMO, "Meenoo Tings - %s" },
+{ RPL_INFOLINKID, "Remote Hidee - %s" },
+{ RPL_INFOCURRENTACC, "Axes Now - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Ayarzee Tings - [Bayous: %i] [Meenoos: %i] [Masks: %i] [Swamplevel: %i]" },
+{ RPL_INFOSTATUS, "Status Now - %s" },
+{ RPL_INFOREGBY, "Registered - %s@%s" },
+{ RPL_INFOTIMENOW, "De Time Now - %s" },
+{ ERR_NEEDID, "Identify to NickServ afor using dat chôse." },
+{ RPL_NSETIS, "\002%s\002 be set to \002%s\002 for dis nick." },
+{ RPL_NSETNOW, "\002%s\002 now be set to \002%s\002 for dis nick." },
+{ ERR_BADSETTING, "Ain? \002%s\002 dôn be a ting I know." },
+{ ERR_BADPASSWORD, "Dat not a good chôse. Get anudder password." },
+{ RPL_PASSWORDNOW, "\002%s\002 is de nick password." },
+{ ERR_VALIDEMAIL, "Ain? Dat not a good chôse. Say annuder Email address like de form o user@host." },
+{ ERR_NICKLIMIT, "Shah gator! Serenity-IRC say no mo dan five (5) nicks per Email address." },
+{ ERR_NOWEBMAIL, "Beb, Serenity-IRC prefers no web-based Email for registration." },
+{ RPL_TEMPDEAC1, "Nick dôn work til yo get yo new Email authorized." },
+{ RPL_TEMPDEAC2, "Reactivate dat nick by use de activation ting in de Email." },
+{ RPL_TEMPDEAC3, "All de tings for yo nick be saved I guawantee." },
+{ RPL_TEMPDEAC4, "Mais, de registration key be at \002%s\002." },
+{ ERR_NOMAILSENT, "Ain? Mais, dat Email did not go to de specified address. Pass by " NETCHAN " now." },
+{ ERR_ALREADYREG, "Dat nick be registered and yo dôn be registered again." },
+{ ERR_NEEDTOACT, "Dat nick be registered, yo can only activate dat now." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Dôn be so coo-yôn! Dat nick dôn be registered here, get annudder one." },
+{ ERR_BANNEDEMAIL, "Dat Email dôn be used on Serenity-IRC, get annudder one." },
+{ ERR_CANNOTGHOSTSELF, "Yo cannot haunt yo'self." },
+{ ERR_NOTONLINE, "\002%s\002 dôn be here, yo can't haunt it." },
+{ ERR_ACCESSDENIED, "Dôn do dat meenoo!" },
+{ RPL_NICKGHOSTED, "\002%s\002 be gone now. Yo can get it now." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "Dat bayou be +s ting for de bonne homme. Dat means de channel dôn be seen on dat parrish list chôse." },
+{ RPL_NOOPSFROZEN, "Dat bayou be frozen an yo dôn go shwrimpin dare." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Yo dôn have dat parrish operator ting in dat bayou." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "\002%s\002 dôn be a parrish." },
+{ RPL_NEXTDBSYNC, "Dat database gonna do dat synch ding in annudder %d minutes." },
+{ RPL_CHANINFO1, "[\002%s\002 ChanServ Informashun]" },
+{ 76, "\002%s\002 done be registered an activated." },
+{ 77, "\002%s\002 be yo axes mask. To get mo masks" },
+{ 78, "say: /ns addmask" },
+{ 79, "De registration time is %s " },
+/* 80 - 99 */
+{ 80, "\002%s\002 be yo nick password." },
+{ 81, "Bienvenue to Serenity-IRC" },
+{ 82, "Dat nick be reactivated." },
+{ 83, "Dat nick already be activated an dôn be activated again." },
+{ RPL_NICKDROPPED, "\002%s\002 dôn be registered." },
+{ RPL_YOURACCESSIS, "Axes level be \002%i\002." },
+{ RPL_CHANINFO2, "De Foundah - %s" },
+{ RPL_CHANINFO3, "Descripshun - %s" },
+{ RPL_CHANINFO4, "De Topic - %s (%s)" },
+{ RPL_CHANINFO5, "De Option Tings - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "De Settings - [Topic Level: %i+] [Restrict Level: %i+] [Mode: %s]" },
+{ RPL_CHANINFO7, "Parrish Registered - %s GMT" },
+{ RPL_CHANINFO8, "Parrish Last Used - %s GMT" },
+{ RPL_CHANINFO9, "Ayarzee Tings - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "[End ChanServ Informashun]" },
+{ RPL_CHANACCESS1, "%s got %s axes in %s" },
+{ RPL_CHANACCESS2, "Yo got %s axes in %s" },
+{ ERR_NOTOPEDINCHAN, "Shah meenoo! Be inside an get dat op ting in de bayou yo want to register." },
+{ ERR_CHANALREADYREG, "Dat bayou be a registered parrish an dôn be registered no mo." },
+{ ERR_TOMANYREGCHAN1, "Shah gator! Serenity-IRC say no mo dan five (5) parrish for yo." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s done registered five (5) bayous." },
+{ RPL_CHANNOWREG, "\002%s\002 be a parrish an \002%s\002 is de foundah." },
+{ RPL_CHANREGNOTE, "Dat parrish be modelocked \002+tn-k\002 an de topic preservashun be on." },
+{ ERR_CHANFROZEN, "Dôn do dat meenoo! Dat bayou be frozen." },
+{ ERR_NOOPON, "%s dôn be added to yo parrish, dey done locked their nick." },
+{ RPL_CHANTRANS, "\002%s\002 foundah gone to \002%s\002." },
+{ RPL_ACCESSHEADER, "[\002%s\002 Axes Tings]" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "[End Axes Tinks]" },
+{ ERR_NOREMOTEACC, "Shah gator! Dôn be lukin at de axes tinks for \002%s\002." },
+{ RPL_CURRENTACC, "%s axes level be \002%i\002." },
+{ RPL_LISTOPHEADER, "[Ayarzee Operatahs In De Bayou]" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "[End Ayarzee Operatahs]" },
+{ ERR_BADACCMASK, "Passé! Dat Axes mask be too long!" },
+{ ERR_TOOMANYACCMASKS, "Passé! Mais, yo can't have no mo! Yo got de maximum number o axes masks." },
+{ ERR_CHANAXTOOLOW, "Mais, yo axes be too low for dat chôse." },
+{ ERR_CHANNOMOREOPS, "\002%s\002 has de maximum parrish op tinks." },
+{ ERR_UNKAXLEVEL, "\002%s\002 dôn be a good axes chôse." },
+{ ERR_NOAXCGFOUNDER, "\002%s\002 be de foundah an dôn be bag daer lower in \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Changed axes for \002%s\002 to \002%s\002" },
+{ RPL_CHANOPADDED, "#%i \002%s\002 done be added as \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "\002%s\002 got de maximum akicks." },
+{ ERR_THISEXISTS, "\002%s\002 already be dare in de %s tinks." },
+{ ERR_INVALIDAKICK, "%s dôn be a good akick chôse." },
+{ RPL_CHANAKICKADDED, "\002%s\002 be added to de \002%s\002 akick chôse." },
+{ ERR_NOTINOPSLIST, "\002%s\002 dôn be in de \002%s\002 parrish ops." },
+{ RPL_CHANOPDELED, "Mais, done took out \002%s\002 parrish ops from \002%s\002." },
+{ ERR_AKICKNOTEXIST, "\002%s\002 dôn be in de akick chôse for \002%s\002." },
+{ RPL_CHANAKICKDELED, "Took out dat akick \002%s\002 from \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "[\002%s\002 Parrish Ops]" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 done match de \002%i\002 tinks I luk at." },
+{ RPL_CHANOPSLISTEND, "[End Parrish Ops]" },
+{ RPL_CHANAKLISTHEAD1, "[\002%s\002 Akicks]" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "[End Akicks]" },
+{ RPL_CHANDROP, "\002%s\002 gone from de ChanServ registrashun." },
+{ ERR_NICKNOTINCHAN, "\002%s\002 dôn be in de \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "\002%s\002 parrish op be good." },
+{ RPL_NOTCHANOPERATOR, "\002%s\002 parrish op dôn be good." },
+{ ERR_NOSUCHCHAN, "\002%s\002 dôn be here." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 tings be in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Ma cher, say de key to modelock de parrish +k." },
+{ ERR_MISSINGLIMIT, "Ma cher, say de nummer to modelock de parrish +l." },
+{ RPL_MLOCKSETTO, "\002%s\002 done modelocked to \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 done set to \002%i+\002 level parrish ops." },
+{ RPL_TOPICLOCKSETTO, "\002%s\002 topic chôse set to \002%i+\002 level parrish ops." },
+{ RPL_CHANSETSTATUS, "\002%s\002 for \002%s\002 done be \002%s\002." },
+{ RPL_CHANSETDESC, "\002%s\002 descripshun: %s" },
+{ RPL_CHANSETDESCCLEAR, "\002%s\002 descripshun cleared." },
+{ RPL_REMCHANBANS, "Mais, removed bans: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "Deopped: %s" },
+{ RPL_CHANMASSDEVOICE, "Devoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "\002%i\002 chôse masskicked, \002%s\002 be clear." },
+{ RPL_CHANMODECLEAR, "\002%s\002 modes done be clear." },
+{ ERR_BADMASK, "What you was tinking? \002%s\002 dôn be right mask ting."},
+{ RPL_AKILLADDED, "Added %s for \002%s\002 for \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "De mask \002%s\002 already be in de %s list." },
+{ ERR_INVALIDMODES, "%s dôn be a good mode chôse." },
+{ ERR_NOSUCHSERVER, "Dare dôn be a server \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "\002%s\002 already be in SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "\002%s\002 dôn be in SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "De Dynamic EKILL list be empty." },
+{ RPL_EKILLHEAD, "[Dynamic Ekills]" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "[End Dynamic Ekills]" },
+{ ERR_NOSUCHEKILL, "\002%s\002 ekill dôn be dare." },
+{ RPL_EKILLDELED, "\002%s\002 ekill done gone." },
+{ ERR_EKILLEXISTS, "\002%s\002 ekill be dare." },
+{ RPL_EKILLADDED, "\002%s\002 ekill done added." },
+{ RPL_RESTARTING, "Starting Again." },
+{ RPL_SHUTTINGDOWN, "Shutting Down." },
+{ RPL_PERMCLONEIGNHEAD, "[Perm Clone Ignores]" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "\002%s\002 dôn be added to de axes list. Dat dôn be de right chôse or it already be dare." },
+{ RPL_ACCMASKADDED, "\002%s\002 added to de axes list." },
+{ RPL_ACCLISTCLEARED, "Axes list be clear." },
+{ RPL_ACCMASKREMOVED, "\002%s\002 removed from axes list." },
+{ ERR_ACCENTRYNOTFOUND, "#%s was not found in de axes list." },
+{ ERR_ACCMASKNOTFOUND, "\002%s\002 dôn be in de axes list." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Say de hostmask in de form of nick!user@host." },
+{ ERR_WIDEHOST, "Luk at de size o dat gator! Parameters too wide, please narrow dem." },
+{ RPL_NLISTHEADER, "[Start \002%s\002]" },
+{ RPL_NLISTFOOTER, "[End \002%i\002 of \002%i\002 matched \002%s\002]" },
+{ ERR_NLISTEMPTY, "Search dôn return no matches." },
+{ RPL_NICKRELEASED, "\002%s\002 done left an be available for yo." },
+{ ERR_NICKNOTHELD, "\002%s\002 dôn be held by Services." },
+{ ERR_BADFLAG, "Ain? \002%c\002 is sumting I dôn know." },
+{ RPL_CHANGEDFLAGS, "Flags for \002%s\002 done been changed to \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "\002%s\002 be banned from further use." },
+{ RPL_GETPASS, "\002%s\002 password was pass to \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "[End Perm Ignores]" },
+{ RPL_UPTIME1, "Services be here for:" },
+{ RPL_UPTIME2, "%i days, %i hours, %i minutes, and %i seconds." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Called %i times" },
+{ RPL_ALLOCSTAT2, "sfree() info: Called %i times" },
+{ RPL_CLONESTATUS1, "%s@%s has %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s has %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Say de proper trigger level." },
+{ ERR_NOSUCHTRIGGER, "No such user@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s has no cloneflag settings." },
+{ RPL_HASCLONEFLAGS, "%s has flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s already be on permanent ignore." },
+{ ERR_NOSUCHPERMIGN, "%s dôn be on permanent ignore." },
+{ ERR_UNKNOWNFLAG, "What dat? Unknown flag %s." },
+{ ERR_UNKNOWHOST, "What dat? Unknown host %s." },
+{ ERR_NOMATCH, "No matches for %s@%s" },
+{ RPL_MAPHEAD, "[Connected Servers]" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Say de hostmask in de form of user@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "Activashun key for \002%s\002 be \002%s\002." },
+{ RPL_GETREALPASS, "\002%s\002 password be \002%s\002." },
+{ RPL_DELETE, "\002%s\002 gone from databases." },
+{ RPL_SAVE, "NickServ database synched to disk." },
+{ ERR_ALREADYLINKID, "\002%s\002 already be identified." },
+{ ERR_MAXLINKID, "Serenity-IRC say yo can only identificashun to \002%i\002 nicks." },
+{ RPL_NICKWARN1, "Mais, dat be a registered nick, identify to de NickServ now." },
+{ RPL_NICKWARN2, "Nick will be switched in 30 seconds if yo dôn identify." },
+{ RPL_NICKWARN3, "To identify, say \002/ns id <password>\002" },
+{ RPL_NICKWARN4, "Nick will be switched in 15 seconds if yo dôn identify." },
+{ RPL_NICKWARN5, "Nick done switched. Get a nick dat dôn be registered." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "Yo got \002%i\002 new meenoo(s). (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Came at %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Meenoo \002%i\002 dôn be here." },
+{ RPL_MLISTHEADER, "[\002%s\002 Meenoos]" },
+{ RPL_MLIST1, "\002%2i\002. Came at %-30s from \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "[End Meenoos]" },
+{ ERR_MLISTEMPTY, "Yo dôn have any meenoos." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Ain? Dat meenoo be too long, say less dan \002%i\002 chôses." },
+{ ERR_ISNOMEMO, "\002%s\002 dôn get meenoos." },
+{ ERR_MEMOBOXFULL, "\002%s\002's meenoobox be full. " },
+{ ERR_TOOMANYMEMOS, "Too many meenoos sent. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 sent yo a meenoo. To see: \002/ms read %i\002" },
+{ RPL_SENTMEMO, "Memo sent to \002%s\002" },
+{ ERR_ISNOFORWARD, "\002%s\002 dôn accept sent meenoos." },
+{ RPL_MEMOFORWARDED, "\002%i\002 meenoo%s sent to \002%s\002." },
+{ ERR_NOFWDTOSELF, "Coo-yôn! Meenoos dôn be sent to yoself. " },
+{ RPL_DELMEMO, "Deleted \002%s\002 meenoos." },
+{ RPL_DELMEMONR, "Deleted meenoo \002%i\002." },
+{ RPL_MAPEND, "[End Servers]" },
+{ RPL_MMAX, "\002%s\002 is currently set to \002%i\002 for dis nick." },
+{ ERR_MMAXSET, "Pick a number between\002 1\002 an \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 be set to \002%i\002 for dis nick." },
+{ RPL_MFORWARD, "Meenoos be sent to \002%s\002." },
+{ RPL_MFORWARDNOW, "Meenoos done be sent to \002%s\002." },
+{ ERR_NOFWDMEMOS, "\002%s\002 dôn accept redirected memos." },
+{ RPL_MEMOSRETRIEVED, "Dem meenoos Emailed to \002%s\002." },
+{ ERR_MNEEDLEVEL, "Say de parrish ops level chôse." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Meenoos sent to \002%i\002 of \002%i\002 chôses." },
+{ ERR_JINXEXIST, "\002%s\002 for \002%s\002 already be dare." },
+{ ERR_NOSUCHNICK, "\002%s\002 dôn be on Serenity-IRC." },
+{ ERR_CANTJINXSRA, "Services Rôt Administratah dôn be jinxed." },
+{ ERR_NOSUCHJINX, "\002%s\002 for \002%s\002 dôn be dare." },
+{ RPL_JINXLISTEMPTY, "No \002%s\002 be dare." },
+{ RPL_JINXLISTHEADER, "[\002%s\002]" },
+{ RPL_JINXLISTFOOTER, "[End \002%s\002]" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "\002%s\002 be added for \002%s\002." },
+{ RPL_JINXREMOVED, "\002%s\002 done gone for \002%s\002." },
+{ ERR_NEEDUSERHOST, "Say de mask in de form of user@host." },
+{ ERR_THISISNONICKDUMMY,"NickServ Enforcer - not a real user." },
+{ ERR_NOHELPONTHAT, "No help be available for \002%s\002. Pass by " NETCHAN " for assistance." },
+{ ERR_BADCHANNELNAME, "\002%s\002 dôn be a good bayou name." },
+{ RPL_CHANCLOSED, "\002%s\002 be closed." },
+{ ERR_CHANNOTCLOSED, "\002%s\002 dôn be closed." },
+{ RPL_CHANUNCLOSED, "\002%s\002 be opened." },
+{ RPL_GLOBALNOTICE, "Bienvenue to Serenity-IRC - Laissez les bons temps rouler!" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Services Language Format Tables: Dutch Language.
+ *
+ * Translated to Dutch by Remmy (July 29, 2000)
+ * Based on english.h by GZ (April 2000)
+ */
+
+#ifndef DUTCH__H
+#define DUTCH__H
+
+#include "services.h"
+
+struct FormatTable DutchReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Dit is een op maat gemaakt bericht." },
+{ ERR_NEEDREGNICK, "Je hebt een geregistreerde nick nodig voor dit commando." },
+{ ERR_NEEDACTNICK, "Je hebt een geactiveerde nick nodig voor dit commando." },
+{ ERR_NEEDSRA, "Je hebt Services Root Administrator privileges nodig voor dit commando." },
+{ ERR_NEEDSERVOP, "Je hebt Services Operator privileges nodig voor dit commando." },
+{ ERR_NEEDOPER, "Je hebt IRC Operator privileges nodig voor dit commando." },
+{ ERR_UNKNOWNCOMMAND, "Sorry, maar \002%s\002 is een commando dat ik niet ken." },
+{ RPL_MOREHELP, "Probeer \002/msg %s HELP\002 voor meer hulp met deze Service." },
+{ RPL_DEBUGHEADER, "-=- [%s Debug Informatie] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [Einde van de Debug Informatie] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "Je hebt te weinig argumenten voor dit commando gegeven." },
+{ RPL_PASSOKAY, "Je wachtwoord voor de nick \002%s\002 is geaccepteerd." },
+{ RPL_YOUAREROOT, "Je bent nu een \002Services Root Administrator.\002" },
+{ RPL_YOUARESERVOP, "Je bent nu een \002Services Operator.\002" },
+{ RPL_NOCHANGEPASS, "Je hebt je wachtwoord voor je nick niet recentelijk meer veranderd." },
+{ RPL_MOREHELPCMD, "Probeer \002/msg %s HELP\002 voor meer hulp met dit commando." },
+{ RPL_PASSNOTOKAY, "Het opgegeven wachtwoord is \002NIET\002 correct voor de nick \002%s\002." },
+{ RPL_EMAILHACK1, "\002LET OP!\002 Je hebt te vaak een foutief wachtwoord voor deze nick gegeven!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Een notificatie is per email naar de eigenaar van deze nick gestuurd." },
+{ RPL_EMAILHACK3, "\002Stop je pogingen om je te identificeren\002 tot je deze email ontvangen hebt." },
+{ RPL_EMAILHACK4, "In het geval dat je deze email niet ontvangt kan je je tot #starchat vervoegen voor verdere hulp." },
+{ RPL_EMAILHACK5, "Iedere verdere poging om je met een foutief wachtwoord te identificeren zal resulteren in \002gedwongen verwijdering van het netwerk.\002" },
+{ RPL_EMAILHACK6, "Je wordt nu van het netwerk verwijderd voor het pogen van het kraken van een nickname. Je was gewaarschuwd!" },
+{ ERR_NICKNOTREGGED, "De nick \002%s\002 is niet geregistreerd bij NickServ" },
+{ RPL_INFOHEADER, "-=[ NickServ Informatie voor \002%s\002 ]=-" },
+{ RPL_INFOFOOTER, "-=[ Einde van de NickServ Informatie ]=-" },
+{ RPL_INFOBANISHED, "Deze nick is permanent \002VERBANNEN\002 door de Serenity-IRC beheerders." },
+{ RPL_INFONOWON, "(Is NU op IRC) Voor meer informatie: /whois %s" },
+{ RPL_INFODEREG, "Deze nick is \002GEDEREGISTREERD\002 door de Serenity-IRC beheerders." },
+{ RPL_INFOLASTSEEN1, "Laatst gezien vanaf adres - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Om - %s" },
+{ RPL_INFOREGGEDON, "Geregistreerd op - %s" },
+{ RPL_INFOEMAIL, "Email adres - %s" },
+{ RPL_INFOACCESS, "Services Toegang - %s" },
+{ RPL_INFOOPTIONS, "Geactiveerde Opties - %s" },
+{ RPL_INFOMEMO, "Memo Instellingen - %s" },
+{ RPL_INFOLINKID, "Andere ID's - %s" },
+{ RPL_INFOCURRENTACC, "Huidige Toegang - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "IRCop data - [kanalen: %i] [memo's: %i] [maskers: %i] [floodniveau: %i]" },
+{ RPL_INFOSTATUS, "Huidige status - %s" },
+{ RPL_INFOREGBY, "Geregistreerd door - %s@%s" },
+{ RPL_INFOTIMENOW, "De tijd nu is - %s" },
+{ ERR_NEEDID, "Sorry, maar je moet je voor deze nick identificeren voordat je dit commando kunt gebruiken." },
+{ RPL_NSETIS, "\002%s\002 is voor deze nick ingesteld op \002%s\002." },
+{ RPL_NSETNOW, "\002%s\002 is voor deze nick nu ingesteld op \002%s\002." },
+{ ERR_BADSETTING, "Sorry, maar \002%s\002 is een mij onbekende instelling." },
+{ ERR_BADPASSWORD, "Sorry, maar dat is geen goed wachtwoord. Kies een ander alsjeblieft." },
+{ RPL_PASSWORDNOW, "Het wachtwoord voor je nick is nu ingesteld op \002%s\002." },
+{ ERR_VALIDEMAIL, "Geef alsjeblieft een geldig email adres in het formaat: gebruiker@host." },
+{ ERR_NICKLIMIT, "Sorry, maar je hebt het maximaal aantal toegestaande nick registraties bereikt. Je kunt er niet meer registreren." },
+{ ERR_NOWEBMAIL, "Sorry, maar Serenity-IRC accepteert geen gratis web gebaseerde email adressen voor het registreren van nicks." },
+{ RPL_TEMPDEAC1, "Je nick is tijdelijk gedeactiveerd om je nieuwe email adres te kunnen controleren." },
+{ RPL_TEMPDEAC2, "Om je nick weer te reactiveren wordt het zelfde proces gevolgd als toen je deze nick voor het eerst registreerde." },
+{ RPL_TEMPDEAC3, "Alle huidige instellingen voor deze nick blijven gewoon bewaard." },
+{ RPL_TEMPDEAC4, "De nieuwe registratie sleutel is verstuurd naar \002%s\002." },
+{ ERR_NOMAILSENT, "Sorry, maar de mail kon niet op het opgegeven email adres afgeleverd worden." },
+{ ERR_ALREADYREG, "Deze nick is al geregistreerd en kan niet opnieuw geregistreerd worden." },
+{ ERR_NEEDTOACT, "Deze nick is al geregistreerd en kan nu alleen geactiveerd worden met de toegezonden activatie sleutel." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Deze nick kan niet geregistreerd worden. Kies een ander alsjeblieft." },
+{ ERR_BANNEDEMAIL, "Het gebruik van dit email adres voor Serenity-IRC is \002VERBODEN\002. Kies een ander alsjeblieft." },
+{ ERR_CANNOTGHOSTSELF, "Sorry, maar je kunt je huidige nick niet om zeep helpen." },
+{ ERR_NOTONLINE, "De nick \002%s\002 is momenteel niet in gebruik; je kunt deze dus niet om zeep helpen." },
+{ ERR_ACCESSDENIED, "Sorry, je hebt niet de juiste privileges voor deze bewerking." },
+{ RPL_NICKGHOSTED, "De nick \002%s\002 is om zeep geholpen en is nu weer vrij voor gebruik." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "Dit kanaal is automatisch ingesteld op modus +s (geheim kanaal) als bescherming voor onze jongere gebruikers. Dit heeft geen enkel effect op het gebruik van het kanaal anders dan het onzichtbaar maken ervan in een lijst met de kanaal namen." },
+{ RPL_NOOPSFROZEN, "Je hebt geen operator privileges in dit kanaal. Het kanaal is \002BEVROREN\002." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Sorry, je hebt geen operator privileges in dit kanaal." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "Het kanaal \002%s\002 is niet geregistreerd bij ChanServ." },
+{ RPL_NEXTDBSYNC, "Volgende database synchronisatie is in %d minuten." },
+{ RPL_CHANINFO1, "-=[ ChanServ Informatie voor \002%s\002 ]=-" },
+{ 76, "Je nick \002%s\002 is nu succesvol geregistreerd en geactiveerd!" },
+{ 77, "Je eerste toegangsmasker is \002%s\002. Indien je meer toegangsmaskers nodig hebt," },
+{ 78, "kan je deze toevoegen met: /ns \002ADDMASK\002" },
+{ 79, "Het tijdstip van je registratie is: %s " },
+/* 80 - 99 */
+{ 80, "Het wachtwoord voor je nick is \002%s\002. Maak hier nu ergens een notitie van zodat je hem niet kwijt kunt raken." },
+{ 81, "Welkom op het Serenity-IRC IRC Network! We hopen dat je veel plezier hebt zolang je hier bent!" },
+{ 82, "Je nick is met succes gereactiveerd!" },
+{ 83, "Deze nick is al geactiveerd. Je kan hem niet nogmaals activeren." },
+{ RPL_NICKDROPPED, "Je nick \002%s\002 is niet langer geregistreerd." },
+{ RPL_YOURACCESSIS, "Je huidige toegangsniveau is \002%i\002." },
+{ RPL_CHANINFO2, "Oprichter - %s" },
+{ RPL_CHANINFO3, "Omschrijving - %s" },
+{ RPL_CHANINFO4, "Onderwerp - %s (%s)" },
+{ RPL_CHANINFO5, "Opties - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Instellingen - [Topic Level: %i+] [Restrict Level: %i+] [Modus: %s]" },
+{ RPL_CHANINFO7, "Kanaal geregistreerd - %s GMT" },
+{ RPL_CHANINFO8, "Laatst gebruikt - %s GMT" },
+{ RPL_CHANINFO9, "IRCop data - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ Einde van de ChanServ Informatie ]=-" },
+{ RPL_CHANACCESS1, "%s heeft %s privileges op %s" },
+{ RPL_CHANACCESS2, "Je hebt %S privileges op %s" },
+{ ERR_NOTOPEDINCHAN, "Je moet je met operator status in het kanaal bevinden dat je wenst te registreren." },
+{ ERR_CHANALREADYREG, "Dit kanaal is al geregistreerd. Je kunt het niet nogmaals registeren." },
+{ ERR_TOMANYREGCHAN1, "Je hebt teveel kanalen geregistreerd." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s heeft al teveel geregistreerde kanalen." },
+{ RPL_CHANNOWREG, "Kanaal \002%s\002 is nu geregistreerd onder je nick \002%s\002 met OPRICHTER(15) privileges." },
+{ RPL_CHANREGNOTE, "Je kanaal heeft de modus vaststaan op \002+tn-k\002 en behoud van het onderwerp staat \002AAN\002." },
+{ ERR_CHANFROZEN, "Toegang verboden. Dit kanaal is \002BEVROREN\002." },
+{ ERR_NOOPON, "%s kan niet aan de lijst met kanaal operators toegevoegd worden. Je moet aan deze persoon vragen om de nick te 'unlocken'." },
+{ RPL_CHANTRANS, "Oprichter status van \002%s\002 is overgedragen aan \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Privilege-lijst voor \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "Masker %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ Einde van de Privilege-lijst ]=-" },
+{ ERR_NOREMOTEACC, "Sorry, je hebt niet de juiste privileges om de privilege lijst voor \002%s\002 op te vragen." },
+{ RPL_CURRENTACC, "Het huidige privilege niveau voor %s is \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ Lijst van alle IRC Operators die Online zijn ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ Einde van de Operators Lijst ]=-" },
+{ ERR_BADACCMASK, "Sorry, maar dat toegangsmasker is veel te lang." },
+{ ERR_TOOMANYACCMASKS, "Je hebt de limiet bereikt van het maximaal aantal toegestane toegangsmaskers. Verwijder er eerst een paar voor je nieuwe toevoegt." },
+{ ERR_CHANAXTOOLOW, "Je hebt te weinig privileges voor dat commando." },
+{ ERR_CHANNOMOREOPS, "Helaas pindakaas, \002%s\002 heeft het maximale aantal operators bereikt. Ik kan er niet meer toevoegen." },
+{ ERR_UNKAXLEVEL, "Het opgegeven niveau \002(%s)\002 is geen geldig niveau." },
+{ ERR_NOAXCGFOUNDER, "Sorry, \002%s\002 is de oprichter van het kanaal en dit kan niet aangepast worden op \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Privileges voor \002%s\002 veranderd naar \002%s\002" },
+{ RPL_CHANOPADDED, "Op #%i \002%s\002 toegevoegd als \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "Sorry, \002%s\002 heeft de akick limiet bereikt. Ik kan geen akicks meer toevoegen." },
+{ ERR_THISEXISTS, "Sorry, \002%s\002 bestaat al in de %s lijst." },
+{ ERR_INVALIDAKICK, "Sorry, %s is een ongeldige akick." },
+{ RPL_CHANAKICKADDED, "Akick \002%s\002 toegevoegd aan \002%s\002" },
+{ ERR_NOTINOPSLIST, "Sorry, \002%s\002 komt niet voor in de operator lijst voor \002%s\002." },
+{ RPL_CHANOPDELED, "Operator \002%s\002 verwijderd van \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Sorry, \002%s\002 komt niet voor in de akick lijst voor \002%s\002." },
+{ RPL_CHANAKICKDELED, "Akick \002%s\002 verwijderd van \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ Ops lijst voor \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Niveau" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 overeenkomst gevonden in de \002%i\002 doorzochte elementen." },
+{ RPL_CHANOPSLISTEND, "-=[ Einde Ops lijst ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Akick lijst voor \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Masker)" },
+{ RPL_CHANAKLISTHEAD3, "(Tijd [GMT]) (Reden)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ Einde Akick lijst ]=-" },
+{ RPL_CHANDROP, "Kanaal \002%s\002 is niet langer geregistreerd." },
+{ ERR_NICKNOTINCHAN, "Sorry, \002%s\002 is niet in \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "Je bent nu een operator in kanaal \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "Je bent niet langer een operator in kanaal \002%s\002." },
+{ ERR_NOSUCHCHAN, "Sorry, \002%s\002 bestaat niet." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 gebruikers in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Je moet een sleutel (wachtwoord) opgeven om een kanaal met modus +k vast te zetten." },
+{ ERR_MISSINGLIMIT, "Om een kanaal vast te zetten met modus +l moet je ook een limiet opgeven." },
+{ RPL_MLOCKSETTO, "De modi voor \002%s\002 zijn nu vastgezet op \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 is nu alleen toegankelijk voor gebruikers van het \002%i+\002 niveau." },
+{ RPL_TOPICLOCKSETTO, "In \002%s\002 kunnen alleen gebruikers van niveau \002%i+\002 het onderwerp veranderen." },
+{ RPL_CHANSETSTATUS, "\002%s\002 voor \002%s\002 is \002%s\002." },
+{ RPL_CHANSETDESC, "De omschrijving voor \002%s\002 is: %s" },
+{ RPL_CHANSETDESCCLEAR, "De omschrijving voor \002%s\002 is verwijderd." },
+{ RPL_REMCHANBANS, "Bans verwijderd: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "DeOp'ed: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Massa kick uitgevoerd, \002%i\002 mensen gekicked, \002%s\002 opgeschoond." },
+{ RPL_CHANMODECLEAR, "Modeclear voor \002%s\002 was succesvol." },
+{ ERR_BADMASK, "Sorry, \002%s\002 is geen goed masker."},
+{ RPL_AKILLADDED, "%s toegevoegd voor \002%s\002 voor \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "Het masker \002%s\002 bestaat al in de %s lijst." },
+{ ERR_INVALIDMODES, "Sorry, %s is een ongeldige modus." },
+{ ERR_NOSUCHSERVER, "Sorry, ik ken deze server niet: \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "Sorry, \002%s\002 is al in SVSNOOP modus." },
+{ ERR_NOTSVNOOP, "Sorry, \002%s\002 is niet in SVSNOOP modus." },
+{ RPL_EKILLEMPTY, "Dynamische EKILL lijst is leeg." },
+{ RPL_EKILLHEAD, "-=[ Dynamische Ekill lijst ]=-" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "-=[ Einde Ekill lijst ]=-" },
+{ ERR_NOSUCHEKILL, "Sorry, er is geen EKILL: \002%s\002." },
+{ RPL_EKILLDELED, "EKILL verwijderd voor \002%s\002" },
+{ ERR_EKILLEXISTS, "EKILL bestaat al: \002%s\002" },
+{ RPL_EKILLADDED, "EKILL toegevoegd voor \002%s\002." },
+{ RPL_RESTARTING, "Aan het herstarten." },
+{ RPL_SHUTTINGDOWN, "Aan het afsluiten." },
+{ RPL_PERMCLONEIGNHEAD, "-=[ Perm Clone negeer lijst ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Sorry, maar ik hebt het masker \002%s\002 niet toegevoegd omdat deze een foutief formaat heeft of al present was." },
+{ RPL_ACCMASKADDED, "Het masker \002%s\002 is met succes toegevoegd aan je toegangslijst." },
+{ RPL_ACCLISTCLEARED, "Je toegangslijst is volledig opgeschoond." },
+{ RPL_ACCMASKREMOVED, "Het masker \002%s\002 is verwijderd van je toegangslijst." },
+{ ERR_ACCENTRYNOTFOUND, "Sorry, de entry #%s is niet gevonden in je toegangslijst." },
+{ ERR_ACCMASKNOTFOUND, "Sorry, het masker \002%s\002 komt niet voor in je toegangslijst." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Sorry, maar je moet een hostmasker gebruiken van het formaat nick!gebruiker@host." },
+{ ERR_WIDEHOST, "Sorry, maar je masker is niet specifiek genoeg. Probeer deze zo te zetten dat deze een stuk smaller wordt." },
+{ RPL_NLISTHEADER, "-=[ Start van de Lijst (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ Einde van de Lijst \002%i\002 van de \002%i\002 die doorzocht waren komen overeen met het zoekcriterium \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Sorry, maar je zoekopdracht heeft geen enkele overeenkomst opgeleverd." },
+{ RPL_NICKRELEASED, "De nick \002%s\002 is vrijgegeven en weer beschikbaar voor gebruik." },
+{ ERR_NICKNOTHELD, "Sorry, maar de nick %s wordt momenteel niet vastgehouden door de services." },
+{ ERR_BADFLAG, "Sorry, maar \002%c\002 is een mij onbekende vlag." },
+{ RPL_CHANGEDFLAGS, "Je hebt de vlaggen voor \002%s\002 veranderd naar \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "Je hebt de nick \002%s\002 verbannen voor ieder verder gebruik." },
+{ RPL_GETPASS, "Het wachtwoord voor de nick \002%s\002 is verstuurd naar email adres \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ Einde Perm ignore lijst ]=-" },
+{ RPL_UPTIME1, "Services zijn al" },
+{ RPL_UPTIME2, "%i dagen, %i uur, %i minuten, en %i secondes online." },
+{ RPL_ALLOCSTAT1, "smalloc() info: %i keer aangeroepen" },
+{ RPL_ALLOCSTAT2, "sfree() info: %i keer aangeroepen" },
+{ RPL_CLONESTATUS1, "%s@%s heeft %i/%i clones (totaal/trigger)" },
+{ RPL_CLONESTATUS2, "%s heeft %i/%i clones (totaal/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Geef alsjeblieft een correct trigger niveau." },
+{ ERR_NOSUCHTRIGGER, "Er is niet zulk een gebruiker@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s heeft geen clone vlag instellingen." },
+{ RPL_HASCLONEFLAGS, "%s heeft vlaggen: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s wordt al permanent genegeerd." },
+{ ERR_NOSUCHPERMIGN, "%s wordt niet permanent genegeerd." },
+{ ERR_UNKNOWNFLAG, "%s is een onbekende vlag." },
+{ ERR_UNKNOWHOST, "%s is een onbekende host." },
+{ ERR_NOMATCH, "Geen overeenkomsten voor %s@%s" },
+{ RPL_MAPHEAD, "-=[ Verbonden Server lijst ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Sorry, maar je moet een hostmasker gebruiken van het formaat gebruiker@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "De activatiesleutel voor de nick \002%s\002 is \002%s\002." },
+{ RPL_GETREALPASS, "Het wachtwoord voor de nick \002%s\002 is \002%s\002." },
+{ RPL_DELETE, "De nick \002%s\002 is uit de databases verwijderd." },
+{ RPL_SAVE, "De NickServ database is naar disk weggeschreven." },
+{ ERR_ALREADYLINKID, "Je hebt je al vanaf afstand geidentificeerd voor de nick \002%s\002." },
+{ ERR_MAXLINKID, "Je kunt je niet vanaf afstand identificeren voor meer dan \002%i\002 nicks." },
+{ RPL_NICKWARN1, "Deze nick is geregistreerd. Als deze nick jou toebehoort moet je je nu bij NickServ identificeren." },
+{ RPL_NICKWARN2, "Wanneer je je niet identificeert zal binnen 30 seconden je nick veranderd worden." },
+{ RPL_NICKWARN3, "Om je te identificeren kun je het \002IDENTIFY\002 commando gebruiken: \002/ns IDENTIFY <je wachtwoord>\002" },
+{ RPL_NICKWARN4, "Je hebt nog 15 seconden over om je te identificeren voordat je nick veranderd wordt." },
+{ RPL_NICKWARN5, "Je nick is veranderd. Gebruik alsjeblieft een nick die nog niet geregistreerd is." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "Je hebt \002%i\002 nieuwe memo(s) die op je wachten. (\002%i\002 totaal)" },
+{ RPL_MEMO1, "\002%2i\002. Ontvangen op %-30s [%s]" },
+{ RPL_MEMO2, "\002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Sorry, maar memo \002%i\002 bestaat niet." },
+{ RPL_MLISTHEADER, "-=[ Memo-overzicht voor \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Ontvangen op %-30s van \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ Einde van memo-overzicht ]=-" },
+{ ERR_MLISTEMPTY, "Sorry, maar je memo-overzicht is leeg." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Sorry, maar je memo is te lang, probeer je memo binnen \002%i\002 karakters te houden." },
+{ ERR_ISNOMEMO, "Sorry, maar \002%s\002 staat je niet toe om memo's naar hen te sturen." },
+{ ERR_MEMOBOXFULL, "Sorry, maar \002%s\002's memobox is vol. " },
+{ ERR_TOOMANYMEMOS, "Sorry, maar je hebt al teveel memo's verstuurd. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 heeft je zojuist een memo toegestuurd, om deze te lezen: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Je memo is met succes verstuurd aan \002%s\002" },
+{ ERR_ISNOFORWARD, "Sorry, maar \002%s\002 staat je niet toe om doorgestuurde memo's naar hen te sturen." },
+{ RPL_MEMOFORWARDED, "Je hebt met succes \002%i\002 memo%s doorgestuurd aan \002%s\002", },
+{ ERR_NOFWDTOSELF, "Sorry, maar memo's doorsturen aan jezelf lijkt mij een beetje vreemd." },
+{ RPL_DELMEMO, "Je hebt \002%s\002 memo's verwijderd." },
+{ RPL_DELMEMONR, "Je hebt memo \002%i\002 verwijderd." },
+{ RPL_MAPEND, "-=[ Einde Server lijst ]=-" },
+{ RPL_MMAX, "\002%s\002 is momenteel ingesteld op \002%i\002 voor deze nick." },
+{ ERR_MMAXSET, "Sorry, maar je moet een nummer kiezen tussen\002 1\002 en \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 is nu ingesteld op \002%i\002 voor deze nick." },
+{ RPL_MFORWARD, "Je memo's worden nu doorgestuurd naar \002%s\002." },
+{ RPL_MFORWARDNOW, "Je memo's worden nu doorgestuurd naar \002%s\002." },
+{ ERR_NOFWDMEMOS, "Sorry, maar \002%s\002 staat je niet toe om memo's naar hen te sturen." },
+{ RPL_MEMOSRETRIEVED, "Al je memo's zijn met succes per email gestuurd naar \002%s\002." },
+{ ERR_MNEEDLEVEL, "Sorry, maar je moet een niveau van channel ops specificeren." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Je memo is afgeleverd bij \002%i\002 van de \002%i\002 ontvangers." },
+{ ERR_JINXEXIST, "Sorry, maar de \002%s\002 voor \002%s\002 bestaat al." },
+{ ERR_NOSUCHNICK, "Sorry, maar \002%s\002 lijkt niet online te zijn." },
+{ ERR_CANTJINXSRA, "Sorry, maar je kan een Services Root Administrator niet jinxen." },
+{ ERR_NOSUCHJINX, "Sorry, maar er lijkt geen \002%s\002 te zijn voor \002%s\002." },
+{ RPL_JINXLISTEMPTY, "Sorry, maar er zijn op dit moment geen \002%s\002 gezet." },
+{ RPL_JINXLISTHEADER, "-=[ Lijst van alle \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ Einde van \002%s\002 lijst ]=-" },
+{ RPL_JINXLIST1, "%-25s [gezet door %s] (%s) %s" },
+{ RPL_JINXADDED, "Je hebt met succes een \002%s\002 toegevoegd voor de nick \002%s\002." },
+{ RPL_JINXREMOVED, "je hebt met succes de \002%s\002 verwijderd voor de nick \002%s\002." },
+{ ERR_NEEDUSERHOST, "Sorry, maar je moet een masker specificeren in het formaat van gebruiker@host." },
+{ ERR_THISISNONICKDUMMY,"Dit is een door NickServ geregistreerde '\002nick enforcer\002,' en niet een echte gebruiker." },
+{ ERR_NOHELPONTHAT, "Sorry, er is geen hulp aanwezig voor \002%s\002. Ga naar #cservice voor hulp." },
+{ ERR_BADCHANNELNAME, "Sorry, maar \002%s\002 is een ongeldige kanaal naam." },
+{ RPL_CHANCLOSED, "Het kanaal \002%s\002 is \002GESLOTEN\002." },
+{ ERR_CHANNOTCLOSED, "Het kanaal \002%s\002 is niet \002GESLOTEN\002." },
+{ RPL_CHANUNCLOSED, "Het kanaal \002%s\002 is \002HEROPEND\002." },
+{ RPL_GLOBALNOTICE, "\002Welkom bij Serenity-IRC!\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is niet een geldig getal." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "Je hebt de opdracht %s verkeerd gebruikt."},
+{ RPL_INFOREMARK, "\002Opmerking #%i\002 door %s op %s: %s"},
+{ RPL_DELREMARK, "De opgegeven opmerking voor \002%s\002 is verwijderd."},
+{ RPL_ADDREMARK, "Opmerking voor \002%s\002 toegevoegd."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Language Format Table: English
+ *
+ * Revised November 2000 - jinxi
+ */
+
+#ifndef ENGLISH__H
+#define ENGLISH__H
+
+#include "../services.h"
+
+struct FormatTable EnglishReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Custom Message" },
+{ ERR_NEEDREGNICK, "You need to have a registered nickname." },
+{ ERR_NEEDACTNICK, "Activated nickname required." },
+{ ERR_NEEDSRA, "Services Root Administrator access required." },
+{ ERR_NEEDSERVOP, "Services Operator access required." },
+{ ERR_NEEDOPER, "IRC Operator access required." },
+{ ERR_UNKNOWNCOMMAND, "\002%s\002 is an unknown command." },
+{ RPL_MOREHELP, "\002/msg %s help\002 for assistance." },
+{ RPL_DEBUGHEADER, "[%s Debug]" },
+{ RPL_DEBUGFOOTER, "[End Debug]" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "More information required." },
+{ RPL_PASSOKAY, "Password for \002%s\002 accepted." },
+{ RPL_YOUAREROOT, "\002SRA Access Granted\002" },
+{ RPL_YOUARESERVOP, "\002SO Access Granted\002" },
+{ RPL_NOCHANGEPASS, "Serenity-IRC recommends periodic nick password changes." },
+{ RPL_MOREHELPCMD, "\002/msg %s help %s\002 for assistance." },
+{ RPL_PASSNOTOKAY, "Password for \002%s\002 is incorrect." },
+{ RPL_EMAILHACK1, "\002-WARNING-\002 You are not entering the correct password." },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Correct password sent to the Email address for this nick." },
+{ RPL_EMAILHACK3, "\002-STOP-\002 attempting to identify until you view the Email." },
+{ RPL_EMAILHACK4, "Join " NETCHAN " if you do not receive the Email in 15 minutes." },
+{ RPL_EMAILHACK5, "\002-WARNING-\022 do not continue to enter the incorrect password." },
+{ RPL_EMAILHACK6, "Removed from the network for incorrect password attempts." },
+{ ERR_NICKNOTREGGED, "\002%s\002 is not a registered nickname." },
+{ RPL_INFOHEADER, "[\002%s\002 NickServ Information]" },
+{ RPL_INFOFOOTER, "[End NickServ Information]" },
+{ RPL_INFOBANISHED, "This nick cannot be used on Serenity-IRC." },
+{ RPL_INFONOWON, "[Currently on Serenity-IRC] - For more information: /whois \002%s\002" },
+{ RPL_INFODEREG, "This nick was deregistered by Serenity-IRC." },
+{ RPL_INFOLASTSEEN1, "Last Address - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Last Seen - %s" },
+{ RPL_INFOREGGEDON, "Registered - %s" },
+{ RPL_INFOEMAIL, "Email Address - %s" },
+{ RPL_INFOACCESS, "Services Access - %s" },
+{ RPL_INFOOPTIONS, "Options Set - %s" },
+{ RPL_INFOMEMO, "Memo Settings - %s" },
+{ RPL_INFOLINKID, "Remote ID - %s" },
+{ RPL_INFOCURRENTACC, "Current Access - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "IRC Op Data - [Channels: %i] [Memos: %i] [Masks: %i] [Floodlevel: %i]" },
+{ RPL_INFOSTATUS, "Current Status - %s" },
+{ RPL_INFOREGBY, "Registered - %s@%s" },
+{ RPL_INFOTIMENOW, "Current Time - %s" },
+{ ERR_NEEDID, "Identify to NickServ before using that command." },
+{ RPL_NSETIS, "\002%s\002 is currently set to \002%s\002 for this nick." },
+{ RPL_NSETNOW, "\002%s\002 has now been set to \002%s\002 for this nick." },
+{ ERR_BADSETTING, "\002%s\002 is not a known setting." },
+{ ERR_BADPASSWORD, "Please choose another password." },
+{ RPL_PASSWORDNOW, "\002%s\002 is the nick password." },
+{ ERR_VALIDEMAIL, "Please specify a valid Email address in the form of user@host." },
+{ ERR_NICKLIMIT, "Serenity-IRC restricts to five (5) nick registrations per Email address." },
+{ ERR_NOWEBMAIL, "Serenity-IRC prefers non web-based Email for nick registration." },
+{ RPL_TEMPDEAC1, "Nick temporarily deactivated to verify new Email address." },
+{ RPL_TEMPDEAC2, "Reactivate nick using the activation numbers in the Email." },
+{ RPL_TEMPDEAC3, "Current settings for nick are saved." },
+{ RPL_TEMPDEAC4, "Registration key sent to \002%s\002." },
+{ ERR_NOMAILSENT, "Email could not be delivered to the specified address." },
+{ ERR_ALREADYREG, "This nick is registered and cannot be registered again." },
+{ ERR_NEEDTOACT, "This nick is registered, it can only be activated now." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "This nick cannot be registered, please choose another." },
+{ ERR_BANNEDEMAIL, "This Email cannot be used on Serenity-IRC, please use another." },
+{ ERR_CANNOTGHOSTSELF, "You cannot ghost yourself." },
+{ ERR_NOTONLINE, "\002%s\002 is not being used and cannot be ghosted." },
+{ ERR_ACCESSDENIED, "Access denied." },
+{ RPL_NICKGHOSTED, "\002%s\002 ghosted and is available for use." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "This channel is set mode +s as a courtesy to our younger users. This will not affect the channel in any way, other than to make it invisible on a channel list." },
+{ RPL_NOOPSFROZEN, "This channel is frozen and does not allow channel ops." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "You do not have channel operator privileges in this channel." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "\002%s\002 is not a registered channel." },
+{ RPL_NEXTDBSYNC, "Database synch in %d minutes." },
+{ RPL_CHANINFO1, "[\002%s\002 ChanServ Information]" },
+{ 76, "\002%s\002 is registered and activated." },
+{ 77, "\002%s\002 is your access mask. To add additional masks" },
+{ 78, "type: /ns addmask" },
+{ 79, "Registration time is %s " },
+/* 80 - 99 */
+{ 80, "\002%s\002 is your nick password." },
+{ 81, "Welcome to Serenity-IRC" },
+{ 82, "Nick reactivated." },
+{ 83, "This nick is activated and cannot be activated again." },
+{ RPL_NICKDROPPED, "\002%s\002 is no longer registered." },
+{ RPL_YOURACCESSIS, "Access level is \002%i\002." },
+{ RPL_CHANINFO2, "Founder - %s" },
+{ RPL_CHANINFO3, "Description - %s" },
+{ RPL_CHANINFO4, "Topic - %s (%s)" },
+{ RPL_CHANINFO5, "Options - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Settings - [Topic Level: %i+] [Restrict Level: %i+] [Mode: %s]" },
+{ RPL_CHANINFO7, "Channel Registered - %s GMT" },
+{ RPL_CHANINFO8, "Channel Last Used - %s GMT" },
+{ RPL_CHANINFO9, "IRC Op Data - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "[End ChanServ Information]" },
+{ RPL_CHANACCESS1, "%s has %s access on %s" },
+{ RPL_CHANACCESS2, "You have %s access on %s" },
+{ ERR_NOTOPEDINCHAN, "Be inside and oped in the channel you wish to register." },
+{ ERR_CHANALREADYREG, "This channel is registered and cannot be registered again." },
+{ ERR_TOMANYREGCHAN1, "Serenity-IRC restricts to five (5) registered channels per nick." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s has registered five (5) channels." },
+{ RPL_CHANNOWREG, "\002%s\002 is registered with \002%s\002 as founder." },
+{ RPL_CHANREGNOTE, "Channel is modelocked \002+tn-k\002 and topic preservation is set \002ON\002." },
+{ ERR_CHANFROZEN, "Access denied. This channel is frozen." },
+{ ERR_NOOPON, "%s has locked their nick and cannot be added as a channel op." },
+{ RPL_CHANTRANS, "\002%s\002 founder transferred to \002%s\002." },
+{ RPL_ACCESSHEADER, "[\002%s\002 Access List]" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "[End Access List]" },
+{ ERR_NOREMOTEACC, "Cannot list access masks for \002%s\002." },
+{ RPL_CURRENTACC, "%s current access level is \002%i\002." },
+{ RPL_LISTOPHEADER, "[IRC Operators Currently Online]" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "[End IRC Operators]" },
+{ ERR_BADACCMASK, "Access mask too long." },
+{ ERR_TOOMANYACCMASKS, "Maximum number of access masks reached." },
+{ ERR_CHANAXTOOLOW, "Access too low for that command." },
+{ ERR_CHANNOMOREOPS, "\002%s\002 has reached the maximum number of channel ops." },
+{ ERR_UNKAXLEVEL, "\002%s\002 is not a valid level." },
+{ ERR_NOAXCGFOUNDER, "\002%s\002 is founder and cannot be adjusted on \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Changed access for \002%s\002 to \002%s\002" },
+{ RPL_CHANOPADDED, "#%i \002%s\002 added as \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "\002%s\002 has reached the maximum number of akicks." },
+{ ERR_THISEXISTS, "\002%s\002 already exists in the %s list." },
+{ ERR_INVALIDAKICK, "%s is an invalid akick." },
+{ RPL_CHANAKICKADDED, "\002%s\002 added to \002%s\002 akick list." },
+{ ERR_NOTINOPSLIST, "\002%s\002 does not exist \002%s\002 channel ops list." },
+{ RPL_CHANOPDELED, "Deleted \002%s\002 channel ops from \002%s\002." },
+{ ERR_AKICKNOTEXIST, "\002%s\002 does not exist in the akick list for \002%s\002." },
+{ RPL_CHANAKICKDELED, "Deleted akick \002%s\002 from \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "[\002%s\002 Channel Ops]" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 match of \002%i\002 elements searched." },
+{ RPL_CHANOPSLISTEND, "[End Channel Ops]" },
+{ RPL_CHANAKLISTHEAD1, "[\002%s\002 Akicks]" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "[End Akicks]" },
+{ RPL_CHANDROP, "\002%s\002 deleted from ChanServ registration." },
+{ ERR_NICKNOTINCHAN, "\002%s\002 is not in \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "\002%s\002 channel op granted." },
+{ RPL_NOTCHANOPERATOR, "\002%s\002 channel op denied." },
+{ ERR_NOSUCHCHAN, "\002%s\002 does not exist." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 users in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Specify key to mode lock a channel +k." },
+{ ERR_MISSINGLIMIT, "Specify numerical limit to mode lock a channel +l." },
+{ RPL_MLOCKSETTO, "\002%s\002 modelocked to \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 restricted to \002%i+\002 level channel ops." },
+{ RPL_TOPICLOCKSETTO, "\002%s\002 topic change restricted to \002%i+\002 level channel ops." },
+{ RPL_CHANSETSTATUS, "\002%s\002 for \002%s\002 is \002%s\002." },
+{ RPL_CHANSETDESC, "\002%s\002 description: %s" },
+{ RPL_CHANSETDESCCLEAR, "\002%s\002 description cleared." },
+{ RPL_REMCHANBANS, "Removed bans: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "Deopped: %s" },
+{ RPL_CHANMASSDEVOICE, "Devoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "\002%i\002 users masskicked, \002%s\002 cleared." },
+{ RPL_CHANMODECLEAR, "\002%s\002 modes cleared." },
+{ ERR_BADMASK, "\002%s\002 is an improper mask format."},
+{ RPL_AKILLADDED, "Added %s for \002%s\002 for \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "The mask \002%s\002 already exists in the %s list." },
+{ ERR_INVALIDMODES, "%s is an invalid mode list." },
+{ ERR_NOSUCHSERVER, "There is no such server \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "\002%s\002 is already in SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "\002%s\002 is not in SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "Dynamic EKILL list is empty." },
+{ RPL_EKILLHEAD, "[Dynamic Ekills]" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "[End Dynamic Ekills]" },
+{ ERR_NOSUCHEKILL, "\002%s\002 ekill does not exist." },
+{ RPL_EKILLDELED, "\002%s\002 ekill removed." },
+{ ERR_EKILLEXISTS, "\002%s\002 ekill exists." },
+{ RPL_EKILLADDED, "\002%s\002 ekill added." },
+{ RPL_RESTARTING, "Restarting." },
+{ RPL_SHUTTINGDOWN, "Shutting Down." },
+{ RPL_PERMCLONEIGNHEAD, "[Perm Clone Ignores]" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "\002%s\002 not added to access list. Improper format or already present." },
+{ RPL_ACCMASKADDED, "\002%s\002 added to access list." },
+{ RPL_ACCLISTCLEARED, "Access list cleared." },
+{ RPL_ACCMASKREMOVED, "\002%s\002 removed from access list." },
+{ ERR_ACCENTRYNOTFOUND, "#%s was not found in access list." },
+{ ERR_ACCMASKNOTFOUND, "\002%s\002 was not found in access list." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Use a hostmask in the form of nick!user@host." },
+{ ERR_WIDEHOST, "Parameters too wide, please narrow them." },
+{ RPL_NLISTHEADER, "[Start \002%s\002]" },
+{ RPL_NLISTFOOTER, "[End \002%i\002 of \002%i\002 matched \002%s\002]" },
+{ ERR_NLISTEMPTY, "Search did not return any matches." },
+{ RPL_NICKRELEASED, "\002%s\002 is released and available for use." },
+{ ERR_NICKNOTHELD, "\002%s\002 is not held by Services." },
+{ ERR_BADFLAG, "\002%c\002 is an unknown flag." },
+{ RPL_CHANGEDFLAGS, "Flags for \002%s\002 changed to \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "\002%s\002 banned from further use." },
+{ RPL_GETPASS, "\002%s\002 password sent to \002%s\002." },
+/* 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "[End Perm Ignores]" },
+{ RPL_UPTIME1, "Services online:" },
+{ RPL_UPTIME2, "%i days, %i hours, %i minutes, and %i seconds." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Called %i times" },
+{ RPL_ALLOCSTAT2, "sfree() info: Called %i times" },
+{ RPL_CLONESTATUS1, "%s@%s has %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s has %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Please specify proper trigger level." },
+{ ERR_NOSUCHTRIGGER, "No such user@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s has no cloneflag settings." },
+{ RPL_HASCLONEFLAGS, "%s has flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s is already on permanent ignore." },
+{ ERR_NOSUCHPERMIGN, "%s is not on permanent ignore." },
+{ ERR_UNKNOWNFLAG, "Unknown flag %s." },
+{ ERR_UNKNOWHOST, "Unknown host %s." },
+{ ERR_NOMATCH, "No matches for %s@%s" },
+{ RPL_MAPHEAD, "[Connected Servers]" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Use a hostmask in the form of user@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "Activation key for \002%s\002 is \002%s\002." },
+{ RPL_GETREALPASS, "\002%s\002 password is \002%s\002." },
+{ RPL_DELETE, "\002%s\002 removed from databases." },
+{ RPL_SAVE, "NickServ database synched to disk." },
+{ ERR_ALREADYLINKID, "\002%s\002 is already remotely identified." },
+{ ERR_MAXLINKID, "Serenity-IRC restricts remote identification to \002%i\002 nicks." },
+{ RPL_NICKWARN1, "This is a registered nick, please identify to NickServ now." },
+{ RPL_NICKWARN2, "Nick will be changed in 30 seconds if you do not identify." },
+{ RPL_NICKWARN3, "To identify, use \002/ns id <password>\002" },
+{ RPL_NICKWARN4, "Nick will be changed in 15 seconds if you do not identify." },
+{ RPL_NICKWARN5, "Nick changed. Please use a nick that is not registered." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "You have \002%i\002 new memo(s). (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Received at %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Memo \002%i\002 does not exist." },
+{ RPL_MLISTHEADER, "[\002%s\002 Memos]" },
+{ RPL_MLIST1, "\002%2i\002. Received at %-30s from \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "[End Memos]" },
+{ ERR_MLISTEMPTY, "You have no memos." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Memo too long, please use less than \002%i\002 characters." },
+{ ERR_ISNOMEMO, "\002%s\002 does not accept memos." },
+{ ERR_MEMOBOXFULL, "\002%s\002's memobox is full. " },
+{ ERR_TOOMANYMEMOS, "Too many memos sent. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 sent you a memo. To read: \002/ms read %i\002" },
+{ RPL_SENTMEMO, "Memo sent to \002%s\002" },
+{ ERR_ISNOFORWARD, "\002%s\002 does not accept forwarded memos." },
+{ RPL_MEMOFORWARDED, "\002%i\002 memo%s forwarded to \002%s\002." },
+{ ERR_NOFWDTOSELF, "Memos cannot be forwarded to yourself. " },
+{ RPL_DELMEMO, "Deleted \002%s\002 memos." },
+{ RPL_DELMEMONR, "Deleted memo \002%i\002." },
+{ RPL_MAPEND, "[End Servers]" },
+{ RPL_MMAX, "\002%s\002 is currently set to \002%i\002 for this nick." },
+{ ERR_MMAXSET, "Select a number between\002 1\002 and \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 has now been set to \002%i\002 for this nick." },
+{ RPL_MFORWARD, "Memos are forwarded to \002%s\002." },
+{ RPL_MFORWARDNOW, "Memos are being forwarded to \002%s\002." },
+{ ERR_NOFWDMEMOS, "\002%s\002 does not accept redirected memos." },
+{ RPL_MEMOSRETRIEVED, "All memos Emailed to \002%s\002." },
+{ ERR_MNEEDLEVEL, "Specify channel ops level." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Memo delivered to \002%i\002 of \002%i\002 targets." },
+{ ERR_JINXEXIST, "\002%s\002 for \002%s\002 already exists." },
+{ ERR_NOSUCHNICK, "\002%s\002 is not on Serenity-IRC." },
+{ ERR_CANTJINXSRA, "Services Root Administrators cannot be jinxed." },
+{ ERR_NOSUCHJINX, "\002%s\002 for \002%s\002 does not exist." },
+{ RPL_JINXLISTEMPTY, "No \002%s\002 set." },
+{ RPL_JINXLISTHEADER, "[\002%s\002]" },
+{ RPL_JINXLISTFOOTER, "[End \002%s\002]" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "\002%s\002 added for \002%s\002." },
+{ RPL_JINXREMOVED, "\002%s\002 removed for \002%s\002." },
+{ ERR_NEEDUSERHOST, "Supply a mask in the form of user@host." },
+{ ERR_THISISNONICKDUMMY,"NickServ Enforcer - not a real user." },
+{ ERR_NOHELPONTHAT, "No help available for \002%s\002. Please join " NETCHAN " for assistance." },
+{ ERR_BADCHANNELNAME, "\002%s\002 is not a valid channel name." },
+{ RPL_CHANCLOSED, "\002%s\002 closed." },
+{ ERR_CHANNOTCLOSED, "\002%s\002 is not closed." },
+{ RPL_CHANUNCLOSED, "\002%s\002 reopened." },
+{ RPL_GLOBALNOTICE, "Welcome to the Serenity-IRC IRC Network!" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" } };
+
+#endif
--- /dev/null
+#ifndef FRENCH__H
+#define FRENCH__H
+
+#include "services.h"
+
+struct FormatTable FrenchReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "This is a custom message" },
+{ ERR_NEEDREGNICK, "Vous avez besoin d'un nick enregistré pour faire cette commande." },
+{ ERR_NEEDACTNICK, "Vous avez besoin d'un nick activé pour faire cette commande." },
+{ ERR_NEEDSRA, "Vous devez etre Service Root Administrator pour faire cette commande." },
+{ ERR_NEEDSERVOP, "Vous devez etre Service Operator pour faire cette commande." },
+{ ERR_NEEDOPER, "Vous devez etre IRC Opérateur pour faire cette commande." },
+{ ERR_UNKNOWNCOMMAND, "Désolé, mais la commande \002%s\002 est inconnue." },
+{ RPL_MOREHELP, " \002/msg %s HELP\002 pour plus d'informations sur ce service." },
+{ RPL_DEBUGHEADER, "-=- [%s Debug Information] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [Fin de Debug Information] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "Il vous manque quelques paramètres pour cette commande." },
+{ RPL_PASSOKAY, "Votre mot de passe a été accepté \002%s\002." },
+{ RPL_YOUAREROOT, "Vous êtes maintenant \002Services Root Administrator.\002" },
+{ RPL_YOUARESERVOP, "Vous êtes maintenant \002Services Operator.\002" },
+{ RPL_NOCHANGEPASS, "Il est recommandé de changer de mot de passe de temps en temps." },
+{ RPL_MOREHELPCMD, "Vous pouvez essayer \002/msg %s HELP %s\002 pour plus d'informations sur cette commande." },
+{ RPL_PASSNOTOKAY, "Le mot de passe \002N'EST PAS\002 est refus pour le nick \002%s\002." },
+{ RPL_EMAILHACK1, "\002Attention!\002 Vous avez entré le mot de passe incorrectement trop de fois!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Un email a été envoyé au propriétaire du nick." },
+{ RPL_EMAILHACK3, "\002Ne tentez plus de vous identifier\002 avant de recevoir l'email." },
+{ RPL_EMAILHACK4, "Si vous ne recevez pas un email, veuillez joindre #Serenity-IRC pour de l'assistance." },
+{ RPL_EMAILHACK5, "Ne tapez plus le mot de passe mauvais, ou vous vous trouverez \002enlevé du réseau par force.\002" },
+{ RPL_EMAILHACK6, "Vous serez enlevé du réseau pour piratage de nick. Vous avez déjà été averti!" },
+{ ERR_NICKNOTREGGED, "Le nick \002%s\002 n'est pas enregistré à NickServ." },
+{ RPL_INFOHEADER, "-=[ NickServ Information pour \002%s\002 ]=-" },
+{ RPL_INFOFOOTER, "-=[ Fin de NickServ Information ]=-" },
+{ RPL_INFOBANISHED, "Ce nick a été \002BANNI\002 en permanence par l'administration de Serenity-IRC." },
+{ RPL_INFONOWON, "(En ce moment sur IRC) Pour plus d'informations: /whois %s" },
+{ RPL_INFODEREG, "Ce nick a été \002ANNULÉ\002 par l'administration de Serenity-IRC." },
+{ RPL_INFOLASTSEEN1, "Dernière adresse vue - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Dernière fois vue - %s" },
+{ RPL_INFOREGGEDON, "Enregistré le - %s" },
+{ RPL_INFOEMAIL, "Adresse email - %s" },
+{ RPL_INFOACCESS, "Accès aux services - %s" },
+{ RPL_INFOOPTIONS, "Changer d'Options - %s" },
+{ RPL_INFOMEMO, "Settings de Memo - %s" },
+{ RPL_INFOLINKID, "Remote ID's - %s" },
+{ RPL_INFOCURRENTACC, "Accès Courant - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Information IRCop - [channels: %i] [memos: %i] [masks: %i] [floodlevel: %i]" },
+{ RPL_INFOSTATUS, "Statut courant - %s" },
+{ RPL_INFOREGBY, "Enregistré par - %s@%s" },
+{ RPL_INFOTIMENOW, "Heure - %s" },
+{ ERR_NEEDID, "Désolé, mais vous devez être identifié pour faire cette commande." },
+{ RPL_NSETIS, "\002%s\002 est maintenant \002%s\002 pour ce surnom." },
+{ RPL_NSETNOW, "\002%s\002 est maintenant \002%s\002 pour ce surnom." },
+{ ERR_BADSETTING, "Désolé, mais \002%s\002 est inconnue pour moi." },
+{ ERR_BADPASSWORD, "Désolé, mais ce n'est pas un bon mot de passe, choississez-en un autre." },
+{ RPL_PASSWORDNOW, "Le mot de passe de votre nick est maintenant\002%s\002." },
+{ ERR_VALIDEMAIL, "Précisez un email valable sous la forme utilisateur@hôte." },
+{ ERR_NICKLIMIT, "Désolé, vous avez dépassé votre limite pour enregistrer un surnom. Vous ne pouvez en enregistrer d'autre." },
+{ ERR_NOWEBMAIL, "Désolé, mais Serenity-IRC exige que vous utilisiez l'addresse e-mail fournie par votre FAI/ISP pour enregistrer un nick." },
+{ RPL_TEMPDEAC1, "Votre nick a été désactivé pour vérifier le nouvel email." },
+{ RPL_TEMPDEAC2, "Pour réactiver votre nick, suivez les conseils du message e-mail." },
+{ RPL_TEMPDEAC3, "Toutes vos configurations ont été sauvée." },
+{ RPL_TEMPDEAC4, "La nouvelle clé d'activation a été envoyé à \002%s\002." },
+{ ERR_NOMAILSENT, "Désolé, nous ne pouvons pas envoyer d'email à cette addresse." },
+{ ERR_ALREADYREG, "Ce nick est déjà enregistré et ne peut pas être enregistré à nouveau." },
+{ ERR_NEEDTOACT, "Ce nick est déja enregistré, mais doit être activé." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Ce nick ne peut pas être enregistré, il faut en choisir un autre." },
+{ ERR_BANNEDEMAIL, "Cette addresse email est \002BANNIE\002 sur Serenity-IRC. Il faut en choisir une autre." },
+{ ERR_CANNOTGHOSTSELF, "Désolé, il n'est pas permis de se tuer soi-même." },
+{ ERR_NOTONLINE, "Le nick \002%s\002 n'est pas en utilisation et donc ne peut pas être tué." },
+{ ERR_ACCESSDENIED, "Désolé, accès refus pour cette opération." },
+{ RPL_NICKGHOSTED, "Le nick \002%s\002 est dégagé, il est maintenant disponible." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "Ce canal est automatiquement mis sur +s pour la protection des enfants. Cela n'aura d'autre effet sur le canal que de le rendre invisible sur les listes." },
+{ RPL_NOOPSFROZEN, "Désolé, vous n'avez pas le status d'opérateur, le canal est \002FROZEN\002." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Désolé, vous n'avez pas le statut d'opérateur sur ce canal." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "Le canal \002%s\002 n'est pas enregistré avec ChanServ." },
+{ RPL_NEXTDBSYNC, "Prochain base de données synch(sauvegarde) dans %d minutes." },
+{ RPL_CHANINFO1, "-=[ ChanServ Information pour \002%s\002 ]=-" },
+{ 76, "Votre surnom \002%s\002 est maintenant enregistré et activé!" },
+{ 77, "Votre premier access-mask est \002%s\002. Si vous voulez plus de access-mask," },
+{ 78, "Utilisez: /ns \002ADDMASK\002" },
+{ 79, "L'heure de votre enregistrement est %s " },
+/* 80 - 99 */
+{ 80, "Le mot de passe de votre nick est \002%s\002. Notez-le bien, pour ne pas le perdre." },
+{ 81, "Bienvenue sur le réseau IRC Serenity-IRC, amusez-vous bien!" },
+{ 82, "Votre surnom a été réactivé" },
+{ 83, "Ce surnom est déjà activé, vous ne pouvez pas le réactiver à nouveau." },
+{ RPL_NICKDROPPED, "Votre surnom \002%s\002 n'est pas enregistré." },
+{ RPL_YOURACCESSIS, "Votre niveau d'accès est \002%i\002." },
+{ RPL_CHANINFO2, "Fondateur - %s" },
+{ RPL_CHANINFO3, "Description - %s" },
+{ RPL_CHANINFO4, "Sujet - %s (%s)" },
+{ RPL_CHANINFO5, "Options - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Settings - [Topic Level: %i+] [Restrict Level: %i+] [Mode: %s]" },
+{ RPL_CHANINFO7, "Enregistrement du canal - %s GMT" },
+{ RPL_CHANINFO8, "Dernière utilisation du canal - %s GMT" },
+{ RPL_CHANINFO9, "IRCop information - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ Fin de ChanServ Information ]=-" },
+{ RPL_CHANACCESS1, "%s a %s d'accès sur %s" },
+{ RPL_CHANACCESS2, "Vous avez %s d'accès sur %s" },
+{ ERR_NOTOPEDINCHAN, "Il faut être dans le canal et avoir le statut d'opérateur pour enregistrer ce canal." },
+{ ERR_CHANALREADYREG, "Ce canal est déjà enregistré, vous ne pouvez l'enregistrer de nouveau." },
+{ ERR_TOMANYREGCHAN1, "Vous avez enregistré trop de canaux." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s a déjà enregistré trop de canaux." },
+{ RPL_CHANNOWREG, "Le canal \002%s\002 est maintenant enregistré sous votre nick \002%s\002 avec l'accès FONDATEUR(15)." },
+{ RPL_CHANREGNOTE, "Votre canal est modelocked \002+tn-k\002 et votre topic est préservé à \002ON\002." },
+{ ERR_CHANFROZEN, "Accès refus, ce canal est \002FROZEN\002." },
+{ ERR_NOOPON, "%s ne peut pas être ajouté a la liste des opérateurs du canal, vous devez lui demander d'annuler le mode NOOP." },
+{ RPL_CHANTRANS, "L'accès fondateur de \002%s\002 a été transféré à \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Liste-d'Access pour \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ Fin de Access-list ]=-" },
+{ ERR_NOREMOTEACC, "Désolé, vous ne pouvez obtenir la liste des accès masks pour \002%s\002." },
+{ RPL_CURRENTACC, "Niveau d'accès pour %s est \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ liste des IRC Opérateurs en ligne ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ Fin de la liste des IRC Opérateurs ]=-" },
+{ ERR_BADACCMASK, "Désolé, le mask est trop long." },
+{ ERR_TOOMANYACCMASKS, "Vous avez dépassé votre limite de l'accès mask, enlevez-en avant d'en remettre." },
+{ ERR_CHANAXTOOLOW, "Votre niveau d'accès ne suffit pas pour faire cette commande." },
+{ ERR_CHANNOMOREOPS, "Désolé, \002%s\002 vous avez dépassé votre limite d'opérateur, vous ne pouvez en rajouter." },
+{ ERR_UNKAXLEVEL, "Le niveau que vous avez précisé \002%s\002 n'est pas un niveau valide." },
+{ ERR_NOAXCGFOUNDER, "Désolé, \002%s\002 est le fondateur, et ne peut etre ajusté \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Accès changé de \002%s\002 à \002%s\002" },
+{ RPL_CHANOPADDED, "Addition de ops #%i \002%s\002 Ã \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "Désolé, \002%s\002 a atteint sa limite de akick, vous ne pouvez en ajouter d'autre." },
+{ ERR_THISEXISTS, "Désolé, \002%s\002 existe déjà sur la liste des accès de %s." },
+{ ERR_INVALIDAKICK, "Désolé, %s n'est pas un akick valable.." },
+{ RPL_CHANAKICKADDED, "Addition d'akick de \002%s\002 to \002%s\002" },
+{ ERR_NOTINOPSLIST, "Désolé, \002%s\002 n'existe pas sur la liste des ops de \002%s\002." },
+{ RPL_CHANOPDELED, "Supression du ops \002%s\002 sur \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Désolé, \002%s\002 n'existe pas sur la liste des akicks de \002%s\002." },
+{ RPL_CHANAKICKDELED, "Supression d'un akicks \002%s\002 de \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ liste des ops de \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 jumelage de \002%i\002 élément recherché." },
+{ RPL_CHANOPSLISTEND, "-=[ Fin de la liste des ops ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Liste des akicks de \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ Fin de la liste des akicks ]=-" },
+{ RPL_CHANDROP, "L'enregistrement du canal \002%s\002 a été suprimé." },
+{ ERR_NICKNOTINCHAN, "Désolé, \002%s\002 n'est pas dans \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "Vous êtes maintenant IRC Opérateur dans \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "Vous n'avez pas le statut d'opérateur sur \002%s\002." },
+{ ERR_NOSUCHCHAN, "Désolé, \002%s\002 n'existe pas." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 utilisateurs dans \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Vous devez préciser le mot de passe pour mettre le modelock +k." },
+{ ERR_MISSINGLIMIT, "Vous devez préciser la limite d'usagers pour mettre le modelock +l." },
+{ RPL_MLOCKSETTO, "Mode pour \002%s\002 est maintenant barré à \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 est maintenant restreint à \002%i+\002 niveau d'accès." },
+{ RPL_TOPICLOCKSETTO, "La restreinte du topic sur \002%s\002 est maintenant à \002%i+\002 niveau d'accès." },
+{ RPL_CHANSETSTATUS, "\002%s\002 pour \002%s\002 est \002%s\002." },
+{ RPL_CHANSETDESC, "La description de \002%s\002 est: %s" },
+{ RPL_CHANSETDESCCLEAR, "La description pour \002%s\002 est dégagée." },
+{ RPL_REMCHANBANS, "Supression du ban: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "DeOp'ed: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Masskick complété, \002%i\002 kickés, \002%s\002 dégagés." },
+{ RPL_CHANMODECLEAR, "Modeclear pour \002%s\002 réussi." },
+{ ERR_BADMASK, "Désolé, \002%s\002 n'est pas un format valable pour le mask."},
+{ RPL_AKILLADDED, "Addition %s pour \002%s\002 pour \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "Le mask \002%s\002 est déjà dans la liste %s." },
+{ ERR_INVALIDMODES, "Désolé, %s n'est pas un mode valable." },
+{ ERR_NOSUCHSERVER, "Désolé, serveur \002%s\002 est introuvable." },
+{ ERR_ALREADYSVSNOOP, "Désolé, \002%s\002 est déjà en SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "Désolé, \002%s\002 n'est pas en SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "La liste des EKill est vide." },
+{ RPL_EKILLHEAD, "-=[ Liste des Ekill ]=-" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "-=[ Fin de la liste des Ekills ]=-" },
+{ ERR_NOSUCHEKILL, "Désolé, ce Ekill est introuvable: \002%s\002." },
+{ RPL_EKILLDELED, "Supression du Ekill \002%s\002" },
+{ ERR_EKILLEXISTS, "EKILL existe déjà : \002%s\002" },
+{ RPL_EKILLADDED, "Addition du Ekill \002%s\002." },
+{ RPL_RESTARTING, "Redémarrage." },
+{ RPL_SHUTTINGDOWN, "Fermeture." },
+{ RPL_PERMCLONEIGNHEAD, "-=[ ignore list permanent ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Désolé - mais le mask \002%s\002 n'a pas été ajouté, il n'est pas de format valable ou bien il est déja présent." },
+{ RPL_ACCMASKADDED, "Le mask \002%s\002 a été additionné a votre liste d'accès." },
+{ RPL_ACCLISTCLEARED, "Votre liste d'accès a été dégagé." },
+{ RPL_ACCMASKREMOVED, "Le mask \002%s\002 a été suprimé de votre liste d'accès." },
+{ ERR_ACCENTRYNOTFOUND, "Désolé, l'entrée #%s n'est pas trouvable sur votre liste d'accès." },
+{ ERR_ACCMASKNOTFOUND, "Désolé, le mask \002%s\002 n'est pas trouvable sur votre liste d'accès." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Désolé, vous devez entrer le utilisateur@hôte de ce format - nick!utilisatuer@hôte." },
+{ ERR_WIDEHOST, "Paramètres trop larges, il faut les reserrer." },
+{ RPL_NLISTHEADER, "-=[ Début de la liste (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ Fin de la liste \002%i\002 dehors de \002%i\002 jumelage par condition \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Désolé, mais aucune de vos recherches a été trouvée." },
+{ RPL_NICKRELEASED, "Le nick \002%s\002 est à nouveau prêt à être utilisé." },
+{ ERR_NICKNOTHELD, "Désolé, le nick %s n'est pas retenu par les services." },
+{ ERR_BADFLAG, "Désolé, mais \002%c\002 est un flag inconnu." },
+{ RPL_CHANGEDFLAGS, "Les flags de \002%s\002 changés à \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "Vous avez banni le nick \002%s\002 et il n'est plus valable." },
+{ RPL_GETPASS, "Le mot de passe du nick \002%s\002 a été envoyé par courrier électronique \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ Fin de la l'ignore liste permanente ]=-" },
+{ RPL_UPTIME1, "Services ont été en ligne:" },
+{ RPL_UPTIME2, "%i jours, %i heures, %i minutes, et %i secondes." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Appelé %i fois" },
+{ RPL_ALLOCSTAT2, "sfree() info: Appelé %i fois" },
+{ RPL_CLONESTATUS1, "%s@%s a %i/%i clones (total/déclic)" },
+{ RPL_CLONESTATUS2, "%s a %i/%i clones (total/déclic)" },
+{ ERR_INVALIDTRIGLEVEL, "Il faut préciser les niveaux de déclic" },
+{ ERR_NOSUCHTRIGGER, "Utilisateur@hôte est introuvable (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s n'a pas de marque de privilège clone enregistré." },
+{ RPL_HASCLONEFLAGS, "%s a les marques de privilège: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s est déja sur la liste 'ignore' permanente." },
+{ ERR_NOSUCHPERMIGN, "%s n'est pas sur la liste 'ignore' permanente." },
+{ ERR_UNKNOWNFLAG, "Marque de privilège inconnu %s." },
+{ ERR_UNKNOWHOST, "Hôte inconnu %s." },
+{ ERR_NOMATCH, "Pas de jumelage pour %s@%s" },
+{ RPL_MAPHEAD, "-=[ liste des serveurs connectés ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Désolé, il faut composer l'addresse dans ce format - utilisateur@hôte." },
+/* 220 - 239 */
+{ RPL_GETKEY, "La clé d'activation pour le nick \002%s\002 est \002%s\002." },
+{ RPL_GETREALPASS, "Le mot de passe pour le nick \002%s\002 est \002%s\002." },
+{ RPL_DELETE, "Le nick \002%s\002 a été suprimé des bases de données." },
+{ RPL_SAVE, "La base de données de NickServ a été synchronisé sur le disque." },
+{ ERR_ALREADYLINKID, "Votre authenticité a déjà été établie sur le surnom \002%s\002." },
+{ ERR_MAXLINKID, "Vous ne pouvez pas vous identifier plus de \002%i\002 fois par nick." },
+{ RPL_NICKWARN1, "Ce nick est enregistré, s'il est le votre, identifiez-vous à NickServ." },
+{ RPL_NICKWARN2, "Si vous ne vous identifiez pas, le nick sera changé dans 30 secondes." },
+{ RPL_NICKWARN3, "Pour vous identifier utilisez la commande \002IDENTIFY\002: \002/ns IDENTIFY <Votre mot de passe>\002" },
+{ RPL_NICKWARN4, "Il vous reste 15 secondes pour vous identifier avant le changement de votre nick." },
+{ RPL_NICKWARN5, "Votre surnom a été changé, veuillez le changer pour un autre nick non-enregistré." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "Vous avez \002%i\002 nouveau memo(s) en attente. (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Reçu à %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Désolé, mais il n'a pas de memo \002%i\002." },
+{ RPL_MLISTHEADER, "-=[ Liste des memos pour \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Reçu à %-30s de \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ Fin de la liste des memos ]=-" },
+{ ERR_MLISTEMPTY, "Désolé votre liste des memos est vide.." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Désolé, votre memo est trop long. Veuillez prendre moins de \002%i\002 charactères." },
+{ ERR_ISNOMEMO, "Désolé, mais \002%s\002 vous empeche d'envoyer un memo a cette personne." },
+{ ERR_MEMOBOXFULL, "Désolé, mais la boite de memo de \002%s\002 est vide. " },
+{ ERR_TOOMANYMEMOS, "Désolé, vous avez envoyé trop de memos. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 vient juste de vous envoyer un memo; pour le lire, tapez : \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Votre memo a été envoyé à \002%s\002." },
+{ ERR_ISNOFORWARD, "Désolé, mais \002%s\002 n'accepte pas les memos." },
+{ RPL_MEMOFORWARDED, "Vous avez réussi à faire suivre \002%i\002 memo%s à \002%s\002", },
+{ ERR_NOFWDTOSELF, "Veuillez préciser un autre nick auquel envoyer le memo." },
+{ RPL_DELMEMO, "Vous avez suprimé \002%s\002 memos." },
+{ RPL_DELMEMONR, "Vous avez suprimé le memo \002%i\002." },
+{ RPL_MAPEND, "-=[ Fin de la liste des serveurs ]=-" },
+{ RPL_MMAX, "\002%s\002 est actuellement mis à \002%i\002 pour ce nick." },
+{ ERR_MMAXSET, "Désolé, mais il faut choisir un nombre entre \002 1\002 et \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 est maintenant mis à \002%i\002 pour ce nick." },
+{ RPL_MFORWARD, "Vos memos ont été retournés à \002%s\002." },
+{ RPL_MFORWARDNOW, "Vos memos ont été retournés à \002%s\002." },
+{ ERR_NOFWDMEMOS, "Désolé, mais \002%s\002 n'accepte pas les renvois de memos." },
+{ RPL_MEMOSRETRIEVED, "Tous vos memos ont été envoyés à \002%s\002." },
+{ ERR_MNEEDLEVEL, "Désolé, mais il faut préciser un niveau d'accès pour ce canal." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Votre memo a été envoyé à \002%i\002 de \002%i\002." },
+{ ERR_JINXEXIST, "Désolé, mais \002%s\002 pour \002%s\002 existe déjà ." },
+{ ERR_NOSUCHNICK, "Désolé, mais \002%s\002 n'est pas en ligne." },
+{ ERR_CANTJINXSRA, "Désolé, vous ne pouvez pas ajouter un JINX à un Services Root Administrator." },
+{ ERR_NOSUCHJINX, "Désolé, il n'y a pas de \002%s\002 pour \002%s\002." },
+{ RPL_JINXLISTEMPTY, "Désolé, mais il n'a pas de JINX \002%s\002 en ce moment." },
+{ RPL_JINXLISTHEADER, "-=[ Listes de tout \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ Fin de \002%s\002 liste ]=-" },
+{ RPL_JINXLIST1, "%-25s [mis par %s] (%s) %s" },
+{ RPL_JINXADDED, "Vous avez ajouté un \002%s\002 pour le nick \002%s\002." },
+{ RPL_JINXREMOVED, "Vous avez supprimé un \002%s\002 pour le nick \002%s\002." },
+{ ERR_NEEDUSERHOST, "Désolé, mais il faut fournir un utilisateur@hôte sous cette forme." },
+{ ERR_THISISNONICKDUMMY,"Ceci est un \002nick enforcer\002, pas un véritable utilisateur." },
+{ ERR_NOHELPONTHAT, "Désolé, mais \002%s\002 n'est pas disponible. Veuillez joindre le canal #cservice pour de l'assistance." },
+{ ERR_BADCHANNELNAME, "Désolé, \002%s\002 n'est pas un nom de canal valable." },
+{ RPL_CHANCLOSED, "Le canal \002%s\002 a été \002FERMÉ\002." },
+{ ERR_CHANNOTCLOSED, "Le canal \002%s\002 n'a pas été \002FERMÉ\002." },
+{ RPL_CHANUNCLOSED, "Le canal \002%s\002 a été \002ROUVERT\002." },
+{ RPL_GLOBALNOTICE, "\002Bienvenue sur Serenity-IRC!\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Services Language Format Tables: Galactica Language.
+ *
+ * Added by Cassandra (November 2000)
+ */
+
+#ifndef ENGLISH__H
+#define ENGLISH__H
+
+#include "services.h"
+
+struct FormatTable EnglishReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "This is a custom message" },
+{ ERR_NEEDREGNICK, "You must be a Colonial Warrior to access this comlink." },
+{ ERR_NEEDACTNICK, "You must be an active Colonial Warrior to access this comlink." },
+{ ERR_NEEDSRA, "You must be a Commander for this command." },
+{ ERR_NEEDSERVOP, "You must be a Colonel for this command." },
+{ ERR_NEEDOPER, "You must be a Captain for this command." },
+{ ERR_UNKNOWNCOMMAND, "\002%s\002 is an unknown command." },
+{ RPL_MOREHELP, "\002/msg %s HELP\002 for information about this comlink." },
+{ RPL_DEBUGHEADER, "-=- [%s Recon Information] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [End of Recon Information] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "You specified too little arguments for this command." },
+{ RPL_PASSOKAY, "Colonial Warrior \002%s\002 Identified" },
+{ RPL_YOUAREROOT, "Welcome Aboard Commander" },
+{ RPL_YOUARESERVOP, "Welcome Aboard Colonel" },
+{ RPL_NOCHANGEPASS, "You have not changed your nickname-password recently." },
+{ RPL_MOREHELPCMD, "Please try \002/msg %s HELP %s\002 for more help with this command." },
+{ RPL_PASSNOTOKAY, "\002WARNING\002 The supplied password is \002NOT\002 correct for the nickname \002%s\002." },
+{ RPL_EMAILHACK1, "\002WARNING\002 You have entered an incorrect password too many times!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "An email notification has been sent to the owner of this nickname." },
+{ RPL_EMAILHACK3, "Please \002cease your attempts to identify\002 until you receive this email." },
+{ RPL_EMAILHACK4, "If you do not receive this email, please join " NETCHAN " for assistance." },
+{ RPL_EMAILHACK5, "Any further attempts to identify will result in \002removal from the network by force.\002" },
+{ RPL_EMAILHACK6, "You will now be removed from the network for nickname hacking. You were warned!" },
+{ ERR_NICKNOTREGGED, "\002%s\002 is not a known Colonial Warrior." },
+{ RPL_INFOHEADER, "[ Colonial Warrior \002%s\002 Database ]" },
+{ RPL_INFOFOOTER, "[ End Colonial Warrior Database ]" },
+{ RPL_INFOBANISHED, "\002WARNING CYLON RAIDER\002" },
+{ RPL_INFONOWON, "[ Currently in Quadrant ] For Colonial Warrior Database: /whois %s" },
+{ RPL_INFODEREG, "This Cylon \002DESTROYED\002 by the Colonial Battlestar." },
+{ RPL_INFOLASTSEEN1, "Last seen address - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Last seen at - %s" },
+{ RPL_INFOREGGEDON, "Registered at - %s" },
+{ RPL_INFOEMAIL, "Email address - %s" },
+{ RPL_INFOACCESS, "Battlestar Access - %s" },
+{ RPL_INFOOPTIONS, "Viper Options - %s" },
+{ RPL_INFOMEMO, "Comlink Reception - %s" },
+{ RPL_INFOLINKID, "Remote Comlink - %s" },
+{ RPL_INFOCURRENTACC, "Current Squadron - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Colonial Data - [Squadrons: %i] [Comlinks: %i] [Vipers: %i] [Tylenium Level: %i]" },
+{ RPL_INFOSTATUS, "Current Rank - %s" },
+{ RPL_INFOREGBY, "Registered by - %s@%s" },
+{ RPL_INFOTIMENOW, "Time now - %s" },
+{ ERR_NEEDID, "Warrior must identify prior to issuing this command." },
+{ RPL_NSETIS, "\002%s\002 is currently set to \002%s\002 for this nick." },
+{ RPL_NSETNOW, "\002%s\002 has now been set to \002%s\002 for this nick." },
+{ ERR_BADSETTING, "Sorry, but \002%s\002 is an unknown setting to me." },
+{ ERR_BADPASSWORD, "Sorry, but that is not a good password. Please choose another." },
+{ RPL_PASSWORDNOW, "Your nickname-password has now been set to \002%s\002." },
+{ ERR_VALIDEMAIL, "Please specify a valid email-address in the form of user@host." },
+{ ERR_NICKLIMIT, "Warrior has reached your nickname registration limit. You can not register any more nicknames." },
+{ ERR_NOWEBMAIL, "Sorry, but Serenity-IRC does not accept web-based email for nickname registration." },
+{ RPL_TEMPDEAC1, "Your nickname has been temporarily deactivated to verify the new email address." },
+{ RPL_TEMPDEAC2, "The process to reactivate your nickname will be the same as when you first registered your nickname." },
+{ RPL_TEMPDEAC3, "All of your current settings for your nickname will remain saved." },
+{ RPL_TEMPDEAC4, "The new registration key has been sent to \002%s\002." },
+{ ERR_NOMAILSENT, "Sorry, but the mail could not be delivered to the specified address." },
+{ ERR_ALREADYREG, "You are already a Colonial Warrior. You can not apply again." },
+{ ERR_NEEDTOACT, "This nickname is already registered, it can only be activated now." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "This nickname can not be registered, please choose another one." },
+{ ERR_BANNEDEMAIL, "This email is \002BANNED\002 for use on Serenity-IRC. Please use another." },
+{ ERR_CANNOTGHOSTSELF, "There is no self-destruct mechanism on your Viper" },
+{ ERR_NOTONLINE, "\002%s\002 is currently not being used - you can not ghost it." },
+{ ERR_ACCESSDENIED, "Access Denied" },
+{ RPL_NICKGHOSTED, "\002%s\002 is destroyed. It is now available for use again." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "This channel is auto set to mode +s as a precaution for our younger users. This will not affect the channel in any way, other than to make it invisible on a channel list." },
+{ RPL_NOOPSFROZEN, "You are not allowed operator privileges in this channel, it has been \002FROZEN\002." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Sorry, You are not allowed channel operator privileges in this channel." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "\002%s\002 is not registered with ChanServ." },
+{ RPL_NEXTDBSYNC, "Database synch in %d centons." },
+{ RPL_CHANINFO1, "[ Battlestar \002%s\002 Database ]" },
+{ 76, "\002%s\002 is now a Colonial Warrior" },
+{ 77, "Your first access-mask is \002%s\002. If you want more access-masks," },
+{ 78, "Try using: /ns \002ADDMASK\002" },
+{ 79, "Your registration time is %s " },
+/* 80 - 99 */
+{ 80, "Your nickname password is \002%s\002. Please write it down now, so you won't lose it." },
+{ 81, "Welcome to the Serenity-IRC IRC Network, enjoy your stay!" },
+{ 82, "Your nickname has been succesfully reactivated!" },
+{ 83, "This nickname is already activated. You can not activate it again." },
+{ RPL_NICKDROPPED, "Your nickname \002%s\002 is no longer registered." },
+{ RPL_YOURACCESSIS, "Your current access level is \002%i\002." },
+{ RPL_CHANINFO2, "Founder - %s" },
+{ RPL_CHANINFO3, "Desc - %s" },
+{ RPL_CHANINFO4, "Topic - %s (%s)" },
+{ RPL_CHANINFO5, "Options - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Settings - [Topic Level: %i+] [Restrict Level: %i+] [Mode: %s]" },
+{ RPL_CHANINFO7, "Channel Registered - %s GMT" },
+{ RPL_CHANINFO8, "Channel Last Used - %s GMT" },
+{ RPL_CHANINFO9, "IRCop data - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ End of ChanServ Information ]=-" },
+{ RPL_CHANACCESS1, "%s has %s access on %s" },
+{ RPL_CHANACCESS2, "You have %s access on %s" },
+{ ERR_NOTOPEDINCHAN, "You must be both inside, and oped, in the channel you wish to register." },
+{ ERR_CHANALREADYREG, "This channel is already registered. You can not register it again." },
+{ ERR_TOMANYREGCHAN1, "You have registered too many channels." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s already has too many registered channels." },
+{ RPL_CHANNOWREG, "Channel \002%s\002 is now registered under your nick \002%s\002 with FOUNDER(15) access." },
+{ RPL_CHANREGNOTE, "Your channel is modelocked \002+tn-k\002 and topic preservation is set \002ON\002." },
+{ ERR_CHANFROZEN, "Access denied. This channel is \002FROZEN\002." },
+{ ERR_NOOPON, "%s can not be added to the chanop-list. You must ask them to unlock their nick first." },
+{ RPL_CHANTRANS, "Founder status of \002%s\002 transferred to \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Access-list for \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ End of Access-list ]=-" },
+{ ERR_NOREMOTEACC, "Sorry - you have can not list the access masks for \002%s\002." },
+{ RPL_CURRENTACC, "The current access level for %s is \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ List of all IRC Operators Online ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ End of Operators List ]=-" },
+{ ERR_BADACCMASK, "Sorry, but that access mask is way too long." },
+{ ERR_TOOMANYACCMASKS, "You have reached your access-mask limit, please remove some before adding a new one." },
+{ ERR_CHANAXTOOLOW, "Your access is too low to perform that command." },
+{ ERR_CHANNOMOREOPS, "Sorry, \002%s\002 has reached the Op Limit. I cannot add any more Ops." },
+{ ERR_UNKAXLEVEL, "The level you specified \002%s\002 is not a valid level." },
+{ ERR_NOAXCGFOUNDER, "Sorry, \002%s\002 is the channel founder and cannot be adjusted on \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Changed access for \002%s\002 to \002%s\002" },
+{ RPL_CHANOPADDED, "Added op #%i \002%s\002 as \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "Sorry, \002%s\002 has reached the akick limit. I cannot add any more akicks." },
+{ ERR_THISEXISTS, "Sorry, \002%s\002 already exists in the %s list." },
+{ ERR_INVALIDAKICK, "Sorry, %s is an invalid akick." },
+{ RPL_CHANAKICKADDED, "Added Akick \002%s\002 to \002%s\002" },
+{ ERR_NOTINOPSLIST, "Sorry, \002%s\002 does not exist in the ops list for \002%s\002." },
+{ RPL_CHANOPDELED, "Deleted op \002%s\002 on \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Sorry, \002%s\002 does not exist in the akick list for \002%s\002." },
+{ RPL_CHANAKICKDELED, "Deleted akick \002%s\002 from \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ Ops list for \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 match of \002%i\002 elements searched." },
+{ RPL_CHANOPSLISTEND, "-=[ End Ops list ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Akick list for \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ End Akick list ]=-" },
+{ RPL_CHANDROP, "Channel registration for \002%s\002 has been discontinued." },
+{ ERR_NICKNOTINCHAN, "Sorry, \002%s\002 is not in \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "You are now a channel operator in \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "You are no longer a channel operator in \002%s\002." },
+{ ERR_NOSUCHCHAN, "Sorry, \002%s\002 does not exist." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 users in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "You must specify a key to mode lock a channel +k." },
+{ ERR_MISSINGLIMIT, "You must specify a limit to mode lock a channel +l." },
+{ RPL_MLOCKSETTO, "Mode for \002%s\002 is now locked to \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 is now restricted to \002%i+\002 level users." },
+{ RPL_TOPICLOCKSETTO, "Topic change restriction for \002%s\002 has been set to \002%i+\002 levels." },
+{ RPL_CHANSETSTATUS, "\002%s\002 for \002%s\002 is \002%s\002." },
+{ RPL_CHANSETDESC, "The description of \002%s\002 is: %s" },
+{ RPL_CHANSETDESCCLEAR, "Description of \002%s\002 cleared." },
+{ RPL_REMCHANBANS, "Removed bans: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "DeOp'ed: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Masskick complete, \002%i\002 people kicked, \002%s\002 cleared." },
+{ RPL_CHANMODECLEAR, "Modeclear for \002%s\002 successful." },
+{ ERR_BADMASK, "Sorry, \002%s\002 is an improper mask format."},
+{ RPL_AKILLADDED, "Added %s for \002%s\002 for \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "The mask \002%s\002 already exists in the %s list." },
+{ ERR_INVALIDMODES, "Sorry, %s is an invalid mode list." },
+{ ERR_NOSUCHSERVER, "Sorry, there is no such server \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "Sorry, \002%s\002 is already in SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "Sorry, \002%s\002 is not in SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "Dynamic EKILL list is empty." },
+{ RPL_EKILLHEAD, "-=[ Dynamic Ekill list ]=-" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "-=[ End Ekill list ]=-" },
+{ ERR_NOSUCHEKILL, "Sorry, There is no such EKILL: \002%s\002." },
+{ RPL_EKILLDELED, "Removed EKILL for \002%s\002" },
+{ ERR_EKILLEXISTS, "EKILL already exists: \002%s\002" },
+{ RPL_EKILLADDED, "Added EKILL for \002%s\002." },
+{ RPL_RESTARTING, "Restarting." },
+{ RPL_SHUTTINGDOWN, "Shutting Down." },
+{ RPL_PERMCLONEIGNHEAD, "-=[ Perm Clone ignore list ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Sorry - but the mask \002%s\002 has not been added, it's improper format or already present." },
+{ RPL_ACCMASKADDED, "The mask \002%s\002 has been succesfully added to your access-list." },
+{ RPL_ACCLISTCLEARED, "Your access-list has been fully cleared." },
+{ RPL_ACCMASKREMOVED, "The mask \002%s\002 has been succesfully removed from your access-list." },
+{ ERR_ACCENTRYNOTFOUND, "Sorry, the entry #%s was not found in your access-list." },
+{ ERR_ACCMASKNOTFOUND, "Sorry, the mask \002%s\002 was not found in your access-list." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Sorry, but you will have to use a hostmask in the form of nick!user@host." },
+{ ERR_WIDEHOST, "Sorry, but your range is too wide, please try to narrow it down." },
+{ RPL_NLISTHEADER, "-=[ Start of List (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ End of List \002%i\002 out of \002%i\002 matched the condition \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Sorry, but your search did not return any matches." },
+{ RPL_NICKRELEASED, "The nickname \002%s\002 has been released and is available for use again." },
+{ ERR_NICKNOTHELD, "Sorry, but the nickname %s is currently not being held by Services." },
+{ ERR_BADFLAG, "Sorry, but \002%c\002 is an unknown flag to me." },
+{ RPL_CHANGEDFLAGS, "You have changed the flags for \002%s\002 to \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "You have permanently banned the nickname \002%s\002 from any further use." },
+{ RPL_GETPASS, "The password for the nickname \002%s\002 has been sent to the email address \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ End Perm ignore list ]=-" },
+{ RPL_UPTIME1, "Services has been online for:" },
+{ RPL_UPTIME2, "%i Days, %i hours, %i minutes, and %i seconds." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Called %i times" },
+{ RPL_ALLOCSTAT2, "sfree() info: Called %i times" },
+{ RPL_CLONESTATUS1, "%s@%s has %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s has %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Please specify a proper trigger level." },
+{ ERR_NOSUCHTRIGGER, "No such user@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s has no cloneflag settings." },
+{ RPL_HASCLONEFLAGS, "%s has flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s is already on permanent ignore." },
+{ ERR_NOSUCHPERMIGN, "%s is not on permanent ignore." },
+{ ERR_UNKNOWNFLAG, "Unknown flag %s." },
+{ ERR_UNKNOWHOST, "Unknown host %s." },
+{ ERR_NOMATCH, "No matches for %s@%s" },
+{ RPL_MAPHEAD, "-=[ Connected Server list ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Sorry, but you will have to use a hostmask in the form of user@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "The activation key for the nickname \002%s\002 is \002%s\002." },
+{ RPL_GETREALPASS, "The password for the nickname \002%s\002 is \002%s\002." },
+{ RPL_DELETE, "The nickname \002%s\002 has been removed from the databases." },
+{ RPL_SAVE, "The NickServ database has been synched to disk." },
+{ ERR_ALREADYLINKID, "You have already remotely identified for the nickname \002%s\002." },
+{ ERR_MAXLINKID, "You can not remotely identify for more than \002%i\002 nicknames." },
+{ RPL_NICKWARN1, "This nickname is registered. If this is your nickname, please identify to NickServ now." },
+{ RPL_NICKWARN2, "If you do not identify, your nickname will be changed in 30 seconds." },
+{ RPL_NICKWARN3, "To identify, use the \002IDENTIFY\002 command: \002/ns IDENTIFY <your password>\002" },
+{ RPL_NICKWARN4, "You have 15 seconds remaining to identify before your nickname is changed." },
+{ RPL_NICKWARN5, "Your nickname has been changed. Please use a nickname that is not yet registered." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "You have \002%i\002 new memo(s) waiting. (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Received at %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Sorry, but there is no memo \002%i\002." },
+{ RPL_MLISTHEADER, "-=[ Listing memos for \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Received at %-30s from \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ End of memo-list ]=-" },
+{ ERR_MLISTEMPTY, "Sorry, but your memo-list is empty." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Sorry, but your memo is too long, please try to keep it less than \002%i\002 characters." },
+{ ERR_ISNOMEMO, "Sorry, but \002%s\002 does not allow you to send any memos to them." },
+{ ERR_MEMOBOXFULL, "Sorry, but \002%s\002's memobox is full. " },
+{ ERR_TOOMANYMEMOS, "Sorry, but you have sent too many memos. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 has just sent you a memo, to read it: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Your memo has been succesfully sent to \002%s\002" },
+{ ERR_ISNOFORWARD, "Sorry, but \002%s\002 does not allow you to send any forwarded memos to them." },
+{ RPL_MEMOFORWARDED, "You have succesfully forwarded \002%i\002 memo%s to \002%s\002", },
+{ ERR_NOFWDTOSELF, "Sorry, but forwarding memos to yourself seems a bit silly to me. " },
+{ RPL_DELMEMO, "You have now deleted \002%s\002 memos." },
+{ RPL_DELMEMONR, "You have now deleted memo \002%i\002." },
+{ RPL_MAPEND, "-=[ End Server list ]=-" },
+{ RPL_MMAX, "\002%s\002 is currently set to \002%i\002 for this nick." },
+{ ERR_MMAXSET, "Sorry, but you will have to pick a number between\002 1\002 and \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 has now been set to \002%i\002 for this nick." },
+{ RPL_MFORWARD, "Your memos are currently being forwarded to \002%s\002." },
+{ RPL_MFORWARDNOW, "Your memos are now being forwarded to \002%s\002." },
+{ ERR_NOFWDMEMOS, "Sorry, but \002%s\002 does not allow you to redirect memos to them." },
+{ RPL_MEMOSRETRIEVED, "All of your memos have been succesfully emailed to \002%s\002." },
+{ ERR_MNEEDLEVEL, "Sorry, but you need to specify a level of channel ops." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Your memo has been delivered to \002%i\002 out of \002%i\002 targets." },
+{ ERR_JINXEXIST, "Sorry, but that \002%s\002 for \002%s\002 already exists." },
+{ ERR_NOSUCHNICK, "Sorry, but \002%s\002 does not appear to be online." },
+{ ERR_CANTJINXSRA, "Sorry, but you can not jinx a Services Root Administrator." },
+{ ERR_NOSUCHJINX, "Sorry, but there doesnt seem to be a \002%s\002 for \002%s\002." },
+{ RPL_JINXLISTEMPTY, "Sorry, but there are currently no \002%s\002 set." },
+{ RPL_JINXLISTHEADER, "-=[ Listing all \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ End of \002%s\002 list ]=-" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "You have succesfully added a \002%s\002 for the nickname \002%s\002." },
+{ RPL_JINXREMOVED, "You have succesfully removed the \002%s\002 for the nickname \002%s\002." },
+{ ERR_NEEDUSERHOST, "Sorry, but you will have to supply a mask in the form of user@host." },
+{ ERR_THISISNONICKDUMMY,"This is a NickServ registered \002nick enforcer\002, and not a real user." },
+{ ERR_NOHELPONTHAT, "Sorry, there is no help available on \002%s\002. Please join " NETCHAN " for help." },
+{ ERR_BADCHANNELNAME, "Sorry, but \002%s\002 is not a valid channelname." },
+{ RPL_CHANCLOSED, "The channel \002%s\002 has been \002CLOSED\002." },
+{ ERR_CHANNOTCLOSED, "The channel \002%s\002 has not been \002CLOSED\002." },
+{ RPL_CHANUNCLOSED, "The channel \002%s\002 has been \002REOPENED\002." },
+{ RPL_GLOBALNOTICE, "\002Welcome to Serenity-IRC!\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Services Language Format Tables: English Language.
+ */
+
+#ifndef GERMAN__H
+#define GERMAN__H
+
+#include "services.h"
+
+struct FormatTable GermanReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Dies ist eine generische Nachricht" },
+{ ERR_NEEDREGNICK, "Für dieses Befehl müssen Sie Ihren Nicknamen registrieren." },
+{ ERR_NEEDACTNICK, "Für dieses Befehl müssen Sie Ihren Nicknamen aktivieren." },
+{ ERR_NEEDSRA, "Für dieses Befehl brauchen Sie Services Root Administrator Zugriff." },
+{ ERR_NEEDSERVOP, "Für dieses Befehl brauchen Sie Services Operator Zugriff." },
+{ ERR_NEEDOPER, "Für dieses Befehl brauchen Sie IRC Operator Zugriff." },
+{ ERR_UNKNOWNCOMMAND, "\002%s\002 ist ein unbekanntes Befehl." },
+{ RPL_MOREHELP, "Bitte geben Sie \002/msg %s HELP\002 ein, um mehr Hilfe über diesen Service zu bekommen." },
+{ RPL_DEBUGHEADER, "-=- [%s Debug Information] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [Ende der Debug Information] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "Sie haben zu wenige Argumente für dieses Befehl angegeben." },
+{ RPL_PASSOKAY, "Ihr Kennwort für Nickname \002%s\002 wurde akzeptiert." },
+{ RPL_YOUAREROOT, "Sie sind jetzt ein \002Services Root Administrator.\002" },
+{ RPL_YOUARESERVOP, "Sie sind jetzt ein \002Services Operator.\002" },
+{ RPL_NOCHANGEPASS, "Sie haben das Kennwort für Ihren Nicknamen kurzlich nicht gendert." },
+{ RPL_MOREHELPCMD, "Bitte geben Sie \002/msg %s HELP %s\002 ein, um mehr Hilfe zu diesem Befehl zu erhalten." },
+{ RPL_PASSNOTOKAY, "Das angegebene Kennwort für den Nicknamen \002%s\002 stimmt \002NICHT\002." },
+{ RPL_EMAILHACK1, "\002Warnung!\002 Sie haben zu oft ein falsches Kennwort angegeben!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Eine E-Mail wurde an den Eigentmer dieses Nicknames geschickt." },
+{ RPL_EMAILHACK3, "Bitte \002beenden Sie weitere Versuche, sich zu identifizieren\002 bis sie die E-Mail erhalten haben." },
+{ RPL_EMAILHACK4, "Falls Sie diese E-Mail nicht erhalten, bitten sie auf Kanal " NETCHAN " um Hilfe." },
+{ RPL_EMAILHACK5, "Jeder weitere Versuch der Identifizierung wird zu Ihrer \002gewaltsamen Entfernung aus dem Netz\002 fhren." },
+{ RPL_EMAILHACK6, "Sie werden jetzt aufgrund von Nickname Hacking aus dem Netz entfernt. Sie wurden gewarnt!" },
+{ ERR_NICKNOTREGGED, "Der Nickname \002%s\002 ist bei NickServ nicht registriert." },
+{ RPL_INFOHEADER, "-=[ NickServ Informationen für \002%s\002 ]=-" },
+{ RPL_INFOFOOTER, "-=[ Ende der NickServ Informationen ]=-" },
+{ RPL_INFOBANISHED, "Dieser Nickname wurde durch die Serenity-IRC Administration permanent \002VERBANNT\002." },
+{ RPL_INFONOWON, "(Im Moment im IRC) Für mehr Informationen: /whois %s" },
+{ RPL_INFODEREG, "Dieser Nickname wurde durch die Serenity-IRC Administration \002DEREGISTRIERT\002." },
+{ RPL_INFOLASTSEEN1, "Zuletzt gesehene Adresse - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Zuletzt gesehen am - %s" },
+{ RPL_INFOREGGEDON, "Registriert am - %s" },
+{ RPL_INFOEMAIL, "E-Mail Adresse - %s" },
+{ RPL_INFOACCESS, "Services Zugriff - %s" },
+{ RPL_INFOOPTIONS, "Gesetzte Optionen - %s" },
+{ RPL_INFOMEMO, "Memo Einstellungen - %s" },
+{ RPL_INFOLINKID, "Entfernte IDs - %s" },
+{ RPL_INFOCURRENTACC, "Zugriff im Moment - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "IRCop Daten - [Kanle: %i] [Memos: %i] [Masken: %i] [Floodlevel: %i]" },
+{ RPL_INFOSTATUS, "Momentaner Status - %s" },
+{ RPL_INFOREGBY, "Registriert unter - %s@%s" },
+{ RPL_INFOTIMENOW, "Aktuelle Zeit - %s" },
+{ ERR_NEEDID, "Sie können dieses Befehl erst benutzen, wenn sich sich für diesen Nicknamen identifiziert haben." },
+{ RPL_NSETIS, "\002%s\002 steht im Moment für diesen Nicknamen auf \002%s\002." },
+{ RPL_NSETNOW, "\002%s\002 wurde jetzt für diesen Nicknamen auf \002%s\002 gesetzt." },
+{ ERR_BADSETTING, "\002%s\002 ist leider eine unbekannte Einstellung." },
+{ ERR_BADPASSWORD, "Sie haben leider kein gutes Kennwort gewählt. Bitte versuchen Sie ein anderes." },
+{ RPL_PASSWORDNOW, "Ihr Nickname Kennwort wurde auf \002%s\002 gesetzt." },
+{ ERR_VALIDEMAIL, "Bitte geben Sie eine gültige E-Mail Adresse in der Form user@host an." },
+{ ERR_NICKLIMIT, "Sie haben das Registrierungslimit für Nicknamen erreicht. Sie dürfen keine weiteren Nicknamen registrieren." },
+{ ERR_NOWEBMAIL, "Serenity-IRC akzeptiert leider keine Web-basierte E-Mail Adresse für die Nickname Registrierungen." },
+{ RPL_TEMPDEAC1, "Ihr Nickname wurde kurzzeitig deaktiviert, um die neue E-Mail Adresse zu überprüfen." },
+{ RPL_TEMPDEAC2, "Der Ablauf der Reaktivierung des Nicknamens ist der gleiche wie bei der erstmaligen Registrierung." },
+{ RPL_TEMPDEAC3, "Alle momentanen Einstellungen für Ihren Nicknamen bleiben erhalten." },
+{ RPL_TEMPDEAC4, "Der neue Registrierungsschülssel wurde an \002%s\002 verschickt." },
+{ ERR_NOMAILSENT, "Die E-Mail konnte leider nicht an die angegebene Adresse verschickt werden." },
+{ ERR_ALREADYREG, "Dieser Nickname wurde bereits registriert. Sie können ihn nicht erneut registrieren." },
+{ ERR_NEEDTOACT, "Dieser Nickname wurde bereits registriert, er kann nur aktiviert werden." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Dieser Nickname kann nicht registriert werden, bitte wählen Sie einen anderen." },
+{ ERR_BANNEDEMAIL, "Diese E-Mail Adresse wurde vom Serenity-IRC \002VERBANNT\002. Bitte benutzen Sie eine andere." },
+{ ERR_CANNOTGHOSTSELF, "Das \002ghost\002 Befehl kann nicht auf Sie selbst angewendet werden." },
+{ ERR_NOTONLINE, "Der Nickname \002%s\002 wird im Moment nicht verwendet - Sie können ihn nicht entfernen." },
+{ ERR_ACCESSDENIED, "Auf diese Operation haben Sie leider keinen Zugriff." },
+{ RPL_NICKGHOSTED, "Der Nickname \002%s\002 wurde entfernt. Er ist jetzt wieder benutzbar." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "Dieser Kanal wurde automatisch auf +s als Vorsichtsmaname für jüngere Benutzer gesetzt. Dies wird den Kanal in keine Weise beeinflussen, aber da er auf der Kanalliste unsichtbar ist." },
+{ RPL_NOOPSFROZEN, "Sie können im Moment auf diesem Kanal keinen Operatorstatus erhalten, da er \002EINGEFROREN\002 wurde." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Sie können auf diesem Kanal leider keinen Operatorstatus erhalten." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "Der Kanal \002%s\002 ist nicht bei ChanServ registriert." },
+{ RPL_NEXTDBSYNC, "Nächste Synchronisation mit der Datenbank(save) in %d Minuten." },
+{ RPL_CHANINFO1, "-=[ ChanServ Information fr \002%s\002 ]=-" },
+{ 76, "Ihr Nickname \002%s\002 wurde erfolgreich registriert und aktiviert!" },
+{ 77, "Ihre erste Maske für den Zugriff ist \002%s\002. Falls Sie weitere Masken bentigen," },
+{ 78, "Geben Sie folgendes ein: /msg NickServ \002ADDMASK\002" },
+{ 79, "Ihre Registrierungszeit ist %s " },
+/* 80 - 99 */
+{ 80, "Das Kennwort für Ihren Nicknamen ist \002%s\002. Bitte notieren Sie es sich, damit Sie es nicht verlieren." },
+{ 81, "Willkommen auf dem Serenity-IRC IRC Netzwerk, geniessen Sie den Aufenthalt!" },
+{ 82, "Ihr Nickname wurde erfolgreich reaktiviert!" },
+{ 83, "Ihr Nickname ist bereits reaktiviert. Sie können ihn nicht erneut aktivieren." },
+{ RPL_NICKDROPPED, "Ihr Nickname \002%s\002 ist ist nicht mehr registriert." },
+{ RPL_YOURACCESSIS, "Ihre derzeitiger Zugriffsstufe ist \002%i\002." },
+{ RPL_CHANINFO2, "Gründer - %s" },
+{ RPL_CHANINFO3, "Beschreibung - %s" },
+{ RPL_CHANINFO4, "Topic - %s (%s)" },
+{ RPL_CHANINFO5, "Optionen - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Einstellungen - [Wechsel des Topics (Stufe): %i+] [Zugangsbeschränkung (Stufe): %i+] [Modi: %s]" },
+{ RPL_CHANINFO7, "Kanal registriert - %s GMT" },
+{ RPL_CHANINFO8, "Kanal zuletzt benutzt - %s GMT" },
+{ RPL_CHANINFO9, "IRCop Daten - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ Ende der ChanServ Informationen ]=-" },
+{ RPL_CHANACCESS1, "%s hat %s Zugriff auf %s" },
+{ RPL_CHANACCESS2, "Sie haben %s Zugriff auf %s" },
+{ ERR_NOTOPEDINCHAN, "Wenn Sie einen Kanal registrieren möchten, müssen Sie sowohl auf dem Kanal als auch dort geoppt sein." },
+{ ERR_CHANALREADYREG, "Dieser Kanal ist bereits registriert. Sie können ihn nicht erneut registrieren." },
+{ ERR_TOMANYREGCHAN1, "Sie haben bereits zu viele Kanle registriert." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s hat bereits zu viele Kanle registriert." },
+{ RPL_CHANNOWREG, "Kanal \002%s\002 wurde eben von \002%s\002 als FOUNDER(15) registriert." },
+{ RPL_CHANREGNOTE, "Ihr Kanal wurde mit den Einstellungen \002+tn-k\002 gespeichert und Fixierung des Topics steht auf \002ON\002." },
+{ ERR_CHANFROZEN, "Zugriff verweigert. Dieser Kanal ist \002EINGEFROREN\002." },
+{ ERR_NOOPON, "%s kann der Chanop-Liste nicht hinzugefügt werden. Sie müssen ihn erst bitten, seinen Nicknamen wieder freizuschalten." },
+{ RPL_CHANTRANS, "Gründerstatus von \002%s\002 bertragen auf \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Zugriffsliste fr \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "Maske %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ Ende der Zugriffsliste ]=-" },
+{ ERR_NOREMOTEACC, "Sie können leider die Zugriffsliste fr \002%s\002 nicht einsehen." },
+{ RPL_CURRENTACC, "Die momentane Zugrifsstufe fr %s ist \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ Liste aller Online IRC Operatoren ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ Ende der Operatorenliste ]=-" },
+{ ERR_BADACCMASK, "Die Zugriffsmaske ist leider viel zu lang." },
+{ ERR_TOOMANYACCMASKS, "Die haben das Maximum Ihrer Zugriffsmasken erreicht, bitte löschen Sie ein paar bevor Sie neue hinzufgen." },
+{ ERR_CHANAXTOOLOW, "Ihre Zugriffsrechte sind zu niedrig, um dieses Befehl auszufhren." },
+{ ERR_CHANNOMOREOPS, "Kanal \002%s\002 hat das Op Limit erreicht, es können keine weiteren Ops hinzugefgt werden." },
+{ ERR_UNKAXLEVEL, "Die Stufe die Sie angegeben haben (\002%s\002) ist keine gültige Stufe." },
+{ ERR_NOAXCGFOUNDER, "\002%s\002 ist der Kanalgründer und kann nicht auf \002%s\002 gesetzt werden." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Zugriff fr \002%s\002 geändert auf \002%s\002" },
+{ RPL_CHANOPADDED, "Operator Nummer %i \002%s\002 als \002%s\002 hinzugefügt." },
+{ ERR_CHANNOMOREAKICK, "\002%s\002 hat das Limit der AKicks erreicht. Ich kann keine weiteren AKicks hinzufügen." },
+{ ERR_THISEXISTS, "\002%s\002 existiert bereits in der Liste von %s." },
+{ ERR_INVALIDAKICK, "%s ist leider ein ungültiger AKick." },
+{ RPL_CHANAKICKADDED, "AKick \002%s\002 wurde dem Kanal \002%s\002 hinzugefügt." },
+{ ERR_NOTINOPSLIST, "\002%s\002 existiert in der Op Liste fr \002%s\002 nicht." },
+{ RPL_CHANOPDELED, "Op \002%s\002 von Kanal \002%s\002 gelscht." },
+{ ERR_AKICKNOTEXIST, "\002%s\002 existiert in der AKick Liste fr \002%s\002 nicht." },
+{ RPL_CHANAKICKDELED, "AKick fr \002%s\002 auf \002%s\002 gelscht" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ Opliste fr \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nickname Stufe" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 Treffer bei \002%i\002 durchsuchten Einträgen." },
+{ RPL_CHANOPSLISTEND, "-=[ Ende der Opliste ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Akickliste für \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Maske)" },
+{ RPL_CHANAKLISTHEAD3, "(Zeit [GMT]) (Grund)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ Ende der AKickliste ]=-" },
+{ RPL_CHANDROP, "Kanalregistrierung für \002%s\002 wurde aufgehoben." },
+{ ERR_NICKNOTINCHAN, "\002%s\002 ist nicht auf \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "Sie sind nun Kanaloperator auf \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "Sie sind nun kein Kanaloperator mehr auf \002%s\002." },
+{ ERR_NOSUCHCHAN, "\002%s\002 existiert leider nicht." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 Benutzer auf \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Sie müssen einen Schlüssel angeben, um den Kanal im Modus +k zu halten." },
+{ ERR_MISSINGLIMIT, "Sie müssen ein Maximum angeben, um den Kanal im Modus +l zu halten." },
+{ RPL_MLOCKSETTO, "Modus für \002%s\002 wird jetzt auf \002%s\002 gehalten." },
+{ RPL_RESTRICTSETTO, "\002%s\002 ist jetzt begrenzt auf Nutzer der Stufe \002%i+\002." },
+{ RPL_TOPICLOCKSETTO, "Wechsel des Kanaltopics für \002%s\002 wurde gesetzt auf die Stufen \002%i+\002 ." },
+{ RPL_CHANSETSTATUS, "\002%s\002 auf \002%s\002 ist \002%s\002." },
+{ RPL_CHANSETDESC, "Die Beschreibung für \002%s\002 ist: %s" },
+{ RPL_CHANSETDESCCLEAR, "Beschreibung für \002%s\002 gelöscht." },
+{ RPL_REMCHANBANS, "Gelöschte Bannungen: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "Deopped: %s" },
+{ RPL_CHANMASSDEVOICE, "Devoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Massenkick beendet, \002%i\002 Leute gekickt, \002%s\002 befreit." },
+{ RPL_CHANMODECLEAR, "Moduslöschung für \002%s\002 erfolgreich." },
+{ ERR_BADMASK, "\002%s\002 hat ein ungültiges Format für eine Maske."},
+{ RPL_AKILLADDED, "%s für \002%s\002 unter \002%s\002 [%s] wurde hinzugefügt." },
+{ ERR_MASKEXISTS, "Die Maske \002%s\002 existiert bereits in der %s Liste." },
+{ ERR_INVALIDMODES, "%s ist eine ungültige Modusliste." },
+{ ERR_NOSUCHSERVER, "Es gibt leider keinen Server mit Namen \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "\002%s\002 ist bereits im SVSNOOP Modus." },
+{ ERR_NOTSVNOOP, "\002%s\002 ist nicht im SVSNOOP Modus." },
+{ RPL_EKILLEMPTY, "Dynamische EKILL Liste ist leer." },
+{ RPL_EKILLHEAD, "-=[ Dynamische EKill Liste ]=-" },
+{ RPL_EKILLDATA, "%-25s (gesetzt von %s) %s %s" },
+{ RPL_EKILLEND, "-=[ Ende der EKill Liste ]=-" },
+{ ERR_NOSUCHEKILL, "Diesen EKILL gibt es leider nicht: \002%s\002." },
+{ RPL_EKILLDELED, "EKILL für \002%s\002 entfernt." },
+{ ERR_EKILLEXISTS, "EKILL existiert bereits: \002%s\002" },
+{ RPL_EKILLADDED, "EKILL für \002%s\002 hinzugefügt." },
+{ RPL_RESTARTING, "Starte erneut." },
+{ RPL_SHUTTINGDOWN, "Fahre herunter." },
+{ RPL_PERMCLONEIGNHEAD, "-=[ Permanente Liste der ignorierten Klone ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Die Maske \002%s\002 wurde nicht hinzugefügt, sie hat entweder das falsche Format oder existiert bereits." },
+{ RPL_ACCMASKADDED, "Die Maske \002%s\002 wurde Ihrer Zugriffsliste erfolgreich hinzugefügt." },
+{ RPL_ACCLISTCLEARED, "Ihre Zugriffsliste wurde vollstndig gelscht." },
+{ RPL_ACCMASKREMOVED, "Die Maske \002%s\002 wurde erfolgreich aus Ihrer Zugriffsliste entfernt." },
+{ ERR_ACCENTRYNOTFOUND, "Der Eintrag Nummer %s wurde leider in Ihrer Zugriffsliste nicht gefunden." },
+{ ERR_ACCMASKNOTFOUND, "Die Maske \002%s\002 wurde leider in Ihrer Zugriffsliste nicht gefunden." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Sie müssen leider eine Hostmaske der Form nick!user@host verwenden." },
+{ ERR_WIDEHOST, "Ihr angegebener Bereich ist leider zu gross. Bitte versuchen Sie ihn zu verkleinern." },
+{ RPL_NLISTHEADER, "-=[ Anfang der Liste (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ Ende der Liste - \002%i\002 von \002%i\002 Einträgen trafen auf diese Bedingung zu: \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Ihre Suche brachte leider keine Ergebnisse." },
+{ RPL_NICKRELEASED, "Der Nickname \002%s\002 wurde freigegeben und ist wieder verfügbar." },
+{ ERR_NICKNOTHELD, "Der Nickname %s wird im Moment nicht von Services gehalten." },
+{ ERR_BADFLAG, "\002%c\002 ist leider ein unbekanntes Flag." },
+{ RPL_CHANGEDFLAGS, "Sie haben die Flags für \002%s\002 auf \002%s%s%s%s\002 gesetzt." },
+{ RPL_BANNEDNICK, "Sie haben den Nicknamen \002%s\002 dauerhaft von weiterer Benutzung ausgeschlossen." },
+{ RPL_GETPASS, "Das Kennwort für den Nicknamen \002%s\002 wurde an die E-Mail Adresse \002%s\002 verschickt." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ Ende der Permanenten ignorieren Liste ]=-" },
+{ RPL_UPTIME1, "Services luft seit:" },
+{ RPL_UPTIME2, "%i Tagen, %i Stunden, %i Minuten, and %i Sekunden." },
+{ RPL_ALLOCSTAT1, "smalloc() info: %i Aufrufe" },
+{ RPL_ALLOCSTAT2, "sfree() info: %i Aufrufe" },
+{ RPL_CLONESTATUS1, "%s@%s hat %i/%i Klone (Total/Aufrufe)" },
+{ RPL_CLONESTATUS2, "%s hat %i/%i Klone (Total/Aufrufe)" },
+{ ERR_INVALIDTRIGLEVEL, "Bitte geben Sie einen vernünftigen Wert für den Aufruf an." },
+{ ERR_NOSUCHTRIGGER, "Kein user@host vorhanden (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s hat keine Kloneflag Einträge." },
+{ RPL_HASCLONEFLAGS, "%s hat folgende Flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s wird bereits dauerhaft ignoriert." },
+{ ERR_NOSUCHPERMIGN, "%s wird nicht dauerhaft ignoriert." },
+{ ERR_UNKNOWNFLAG, "Unbekanntes Flag %s." },
+{ ERR_UNKNOWHOST, "Unbekannter Host %s." },
+{ ERR_NOMATCH, "Keine bereinstimmungen für %s@%s" },
+{ RPL_MAPHEAD, "-=[ Liste der verbundenen Server ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Sie müssen leider eine Hostmaske der Form user@host verwenden." },
+/* 220 - 239 */
+{ RPL_GETKEY, "Der Aktivierungsschlüssel für den Nicknamen \002%s\002 ist \002%s\002." },
+{ RPL_GETREALPASS, "Das Kennwort für den Nicknamen \002%s\002 ist \002%s\002." },
+{ RPL_DELETE, "Der Nickname \002%s\002 wurde aus den Datenbanken entfernt." },
+{ RPL_SAVE, "Die NickServ Datenbank wurde synchronisiert." },
+{ ERR_ALREADYLINKID, "Sie haben sich bereits für den Nicknamen \002%s\002 fernidentifiziert." },
+{ ERR_MAXLINKID, "Sie können sich nicht für mehr als \002%i\002 Nicknamen fernidentifizieren." },
+{ RPL_NICKWARN1, "Dieser Nickname ist registriert. Falls dies Ihr Nickname ist, identifizieren Sie sich bitte jetzt bei NickServ." },
+{ RPL_NICKWARN2, "Falls Sie sich nicht identifizieren, wird Ihr Nickname in 30 Sekunden geändert." },
+{ RPL_NICKWARN3, "Um sich zu identifizieren, benutzen Sie bitte das \002IDENTIFY\002 Befehl: \002/msg NickServ IDENTIFY <your password>\002" },
+{ RPL_NICKWARN4, "Sie haben noch 15 Sekunden, um sich zu identifizieren bevor Ihr Nickname geändert wird." },
+{ RPL_NICKWARN5, "Ihr Nickname wurde geändert. Bitte benutzen Sie einen Nicknamen, der noch nicht registriert wurde." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "Auf Sie warten \002%i\002 neue Memos. (Gesamt: \002%i\002)" },
+{ RPL_MEMO1, "\002%2i\002. Empfangen am %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Es gibt leider keine Memo \002%i\002." },
+{ RPL_MLISTHEADER, "-=[ Liste der Memos fr \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Empfangen am %-30s von \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ Ende der Memoliste ]=-" },
+{ ERR_MLISTEMPTY, "Ihre Memoliste ist leider leer." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Ihre Memo ist leider zu lang, bitte versuchen Sie sie auf mindestens \002%i\002 Zeichen zu kürzen." },
+{ ERR_ISNOMEMO, "\002%s\002 erlaubt Ihnen leider nicht, eine Memo an ihn zu versenden." },
+{ ERR_MEMOBOXFULL, "Die Memobox von \002%s\002 ist leider voll. " },
+{ ERR_TOOMANYMEMOS, "Sie haben leider zu viele Memos verschickt. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 hat Ihnen gerade eine neue Memo geschickt. Um sie zu lesen, geben Sie bitte ein: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Ihre Memo wurde erfolgreich an \002%s\002 verschickt." },
+{ ERR_ISNOFORWARD, "\002%s\002 erlaubt es Ihnen leider nicht, weitergeleitete Memos an Ihn zu schicken." },
+{ RPL_MEMOFORWARDED, "Sie haben erfolgreich \002%i\002 Memo%s an \002%s\002 weitergeleitet.", },
+{ ERR_NOFWDTOSELF, "Memos an sich selbst weiterzuleiten ist etwas komisch, oder? " },
+{ RPL_DELMEMO, "Sie haben \002%s\002 Memos gelöscht." },
+{ RPL_DELMEMONR, "Sie haben Memo \002%i\002 gelöscht." },
+{ RPL_MAPEND, "-=[ Ende der Serverliste ]=-" },
+{ RPL_MMAX, "\002%s\002 ist im Moment für diesen Nicknamen auf \002%i\002 gesetzt." },
+{ ERR_MMAXSET, "Sie müssen eine Zahl zwischen\002 1\002 und \002%i\002 verwenden." },
+{ RPL_MMAXNOW, "\002%s\002 wurde jetzt für diesen Nicknamen auf \002%i\002 gesetzt." },
+{ RPL_MFORWARD, "Ihre Memos werden im Moment an \002%s\002 weitergeleitet." },
+{ RPL_MFORWARDNOW, "Ihre Memos werden nun an \002%s\002 weitergeleitet." },
+{ ERR_NOFWDMEMOS, "\002%s\002 erlaubt es leider nicht, Memos an Ihn weiterzuleiten." },
+{ RPL_MEMOSRETRIEVED, "Alle Memos wurden erfolgreich per E-Mail an \002%s\002 verschickt." },
+{ ERR_MNEEDLEVEL, "Sie müssen eine Stufe der Kanaloperatoren festlegen." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Ihre Memo wurde an \002%i\002 von \002%i\002 Zielen geliefert." },
+{ ERR_JINXEXIST, "Das \002%s\002 fr \002%s\002 existiert bereits." },
+{ ERR_NOSUCHNICK, "\002%s\002 scheint im Moment nicht Online zu sein." },
+{ ERR_CANTJINXSRA, "Es ist nicht erlaubt, einen Services Root Administrator zu Jinxen." },
+{ ERR_NOSUCHJINX, "Es scheint keinen \002%s\002 fr \002%s\002 zu geben." },
+{ RPL_JINXLISTEMPTY, "Im Moment sind keine \002%s\002 gesetzt." },
+{ RPL_JINXLISTHEADER, "-=[ Liste aller \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ Ende der \002%s\002 Liste ]=-" },
+{ RPL_JINXLIST1, "%-25s [gesetzt von %s] (%s) %s" },
+{ RPL_JINXADDED, "Ein \002%s\002 wurde für den Nicknamen \002%s\002 erfolgreich hinzugefügt." },
+{ RPL_JINXREMOVED, "Das \002%s\002 wurde erfolgreich für den Nicknamen \002%s\002 entfernt." },
+{ ERR_NEEDUSERHOST, "Sie müssen eine Maske der Form user@host angeben." },
+{ ERR_THISISNONICKDUMMY,"Dies ist ein registrierter \002nick enforcer\002 und kein normaler Benutzer." },
+{ ERR_NOHELPONTHAT, "Es gibt leider keine Hilfe zu \002%s\002. Bitte fragen Sie auf " NETCHAN " nach Hilfe." },
+{ ERR_BADCHANNELNAME, "\002%s\002 ist leider kein gültiger Kanalname." },
+{ RPL_CHANCLOSED, "Der Kanal \002%s\002 wurde \002GESCHLOSSEN\002." },
+{ ERR_CHANNOTCLOSED, "Der Kanal \002%s\002 wurde nicht \002GESCHLOSSEN\002." },
+{ RPL_CHANUNCLOSED, "Der Kanal \002%s\002 wurde wieder \002GEOEFFNET\002." },
+{ RPL_GLOBALNOTICE, "Wilkommen zu Serenity-IRC" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Services Language Format Tables: English Language.
+ *
+ * Added by GZ (April 2000)
+ */
+
+#ifndef ENGLISH__H
+#define ENGLISH__H
+
+#include "services.h"
+
+struct FormatTable EnglishReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Th|s |s a cust0m m3ssag3" },
+{ ERR_NEEDREGNICK, "j00 n33d a r3gg3d nickx0r f0r th|s c0mm4nd." },
+{ ERR_NEEDACTNICK, "j00 n33d an activated nickname f0r th|s c0mm4nd." },
+{ ERR_NEEDSRA, "j00 n33d S3rv R3wt Adm|n acc3ss f0r th|s c0mm4nd." },
+{ ERR_NEEDSERVOP, "j00 n33d S3rv0p acc3ss f0r th|s c0mm4nd." },
+{ ERR_NEEDOPER, "j00 n33d IRC 0per acc3ss f0r this c0mm4nd." },
+{ ERR_UNKNOWNCOMMAND, "S0rry d00d, but \002%s\002 isn't a l33t c0mm4nd." },
+{ RPL_MOREHELP, "y0, checkx0r \002/msg %s HELP\002 for more help with this S3rv|ce, d00d." },
+{ RPL_DEBUGHEADER, "-=- [%s l33t D3BuG Info] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [End of Debug Info] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "j00 didn't add 3nough 4gru3m3nts to this line, d00d." },
+{ RPL_PASSOKAY, "j00r n0w l33t (Identified). \002%s\002." },
+{ RPL_YOUAREROOT, "j00 R n0w a Badazz m0f0. \002Services Root Administrator.\002" },
+{ RPL_YOUARESERVOP, "j00 R n0w a l33t m0f0 \002Services Operator.\002" },
+{ RPL_NOCHANGEPASS, "y0 d00d, j00r nix0r's p4ss h4s n0t b33n ch4ng3d l4t3ly.." },
+{ RPL_MOREHELPCMD, "Please try \002/msg %s HELP %s\002 for more help with this command." },
+{ RPL_PASSNOTOKAY, "\002Wrong pass d00d!\002 Nickname: \002%s\002." },
+{ RPL_EMAILHACK1, "\002D00D!\002 You have ntered an inc0rr3ct p4ssw3rd t00 many tim3s! That Iz n0t l33t." },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Th3 d00d that 0wnz th|s nick has b33n emailed. " },
+{ RPL_EMAILHACK3, "D00D! \002Cease your attempts to identify\002 until j00 r3c3iv3 th|s 3mail." },
+{ RPL_EMAILHACK4, "If j00 d0n't get this Email, please join " NETCHAN " for help." },
+{ RPL_EMAILHACK5, "Any further 4tt3mpts to ID will result in \002j00r ASC|| b3ing killed 0ffa th|s n3tw3rk, d00d!\002" },
+{ RPL_EMAILHACK6, "d00d, j00 were warned, and j00 have n0w b33n kill3d for nick hax0ring" },
+{ ERR_NICKNOTREGGED, "\002%s\002 is not r3gg3d with NickServ." },
+{ RPL_INFOHEADER, "-=[ NickServ Information for \002%s\002 ]=-" },
+{ RPL_INFOFOOTER, "-=[ End of NickServ Information ]=-" },
+{ RPL_INFOBANISHED, "Sorry d00d, but this nix0r haz b33n banished." },
+{ RPL_INFONOWON, "0p3n j00r eyes! \002/whois %s\002 f0r more inf0" },
+{ RPL_INFODEREG, "Th|s nic|<n4me hax b33n p3rmanan7ly d3r3gister3d by the St4rCh4t 4dm|n|str4ti0n" },
+{ RPL_INFOLASTSEEN1, "Packeting Target: - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Last s33n - %s" },
+{ RPL_INFOREGGEDON, "R3gged 0n - %s" },
+{ RPL_INFOEMAIL, "Flaming Target - %s" },
+{ RPL_INFOACCESS, "S3rv Acc3ss - %s" },
+{ RPL_INFOOPTIONS, "0pti0ns S3t - %s" },
+{ RPL_INFOMEMO, "M3m0 S3ttingz - %s" },
+{ RPL_INFOLINKID, "Other Personalities - %s" },
+{ RPL_INFOCURRENTACC, "Level-o-L33tn3ss - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Eliteist's data - [Ch4nn3lz: %i] [M3m0z: %i] [M4skz: %i] [Eviln3ss: %i]" },
+{ RPL_INFOSTATUS, "Curr3nt st4tus - %s" },
+{ RPL_INFOREGBY, "R3gg3d by - %s@%s" },
+{ RPL_INFOTIMENOW, "Tim3 n0w - %s" },
+{ ERR_NEEDID, "d00d, ID t0 nickserv b3f0re trying t0 use s3rvic3s commands." },
+{ RPL_NSETIS, "\002%s\002 is curr3ntly s3t to \002%s\002 for this nix0r." },
+{ RPL_NSETNOW, "\002%s\002 has now been s3t to \002%s\002 for this nix0r." },
+{ ERR_BADSETTING, "S0rry d00d, \002%s\002 is an unkn0wn s3tting." },
+{ ERR_BADPASSWORD, "Pick a l3ss h4ckabl3 p4ssw3rd, d00d." },
+{ RPL_PASSWORDNOW, "j00r n3w passw3rd iz \002%s\002." },
+{ ERR_VALIDEMAIL, "j00 g0tt4 us3 a pr0per email addr3ss, d00d. EX: us3r@h0st." },
+{ ERR_NICKLIMIT, "J00 c4n't r3g anymor3 nix0rz, d00d." },
+{ ERR_NOWEBMAIL, "R3al hax0rz h4ve l33t ISP email addr3ss3s. R3g with 1 0f th0s3, d00d." },
+{ RPL_TEMPDEAC1, "Nix0r t3mp. d3activ4t3d to c3rify j00r n3w Email." },
+{ RPL_TEMPDEAC2, "j00r r3activ4tion of th|s nix0r will b3 the same 4s wh3n j00 r3gg3d it." },
+{ RPL_TEMPDEAC3, "All j00r nick s3tt|ngs be sav3d." },
+{ RPL_TEMPDEAC4, "j00r n3w r3g k3y h4s b33n s3nt to \002%s\002." },
+{ ERR_NOMAILSENT, "d00d, the m4il c0uldn't be d3l|v3r3d t0 th3 sp3c|f|3d 4ddr3ss." },
+{ ERR_ALREADYREG, "Th|s nix0r is 4lr3ady r3g|st3r3d, d00d. Y0u can't r3g|st3r it 4g4in." },
+{ ERR_NEEDTOACT, "This nix0r is alr34dy r3gg3d, it can only be activated now." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "This nix0r can not be r3gg3d, please ch00se another 0n3, d00d." },
+{ ERR_BANNEDEMAIL, "This email is \002BANNX0RED\002, d00d. Pick an0th3r." },
+{ ERR_CANNOTGHOSTSELF, "j00 st00pid? j00 c4n't k|llx0r j00rs3lf.." },
+{ ERR_NOTONLINE, "%s |z n0t b3ing us3d, d00d, j00 c4n't gh0st it." },
+{ ERR_ACCESSDENIED, "Sorry d00d, acc3ss d3ni3d." },
+{ RPL_NICKGHOSTED, "The nickname \002%s\002 has been ghosted. It is now available for use again." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "This channel is auto set to mode +s as a precaution for our younger users. This will not affect the channel in any way, other than to make it invisible on a channel list." },
+{ RPL_NOOPSFROZEN, "You are not allowed operator privileges in this channel, it has been \002FROZEN\002." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Sorry d00d, j00 aren't all0wed opx0rz in this ch4nn3l." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "%s is not r3gg3ed with Ch4nS3rv." },
+{ RPL_NEXTDBSYNC, "Next database synch(save) in %d minutes." },
+{ RPL_CHANINFO1, "-=[ Ch4nS3rv Inf0rm4t|0n for \002%s\002 ]=-" },
+{ 76, "j00r nix0r (\002%s\002) is now succsfully registered and activated!" },
+{ 77, "j00r 1st access-mask is \002%s\002. If you want more access-masks," },
+{ 78, "Try using: /ns \002ADDMASK\002" },
+{ 79, "Your registration time is %s " },
+/* 80 - 99 */
+{ 80, "j00r nix0r password is \002%s\002. Please write it down now, so you won't lose it." },
+{ 81, "W3lc0me t0 St4rCh4t! B3 a nic3 littl3 hax0r, and j00 w0n't g3t /killed!" },
+{ 82, "Your nickname has been succesfully reactivated!" },
+{ 83, "This nickname is already activated. You can not activate it again." },
+{ RPL_NICKDROPPED, "Your nickname \002%s\002 is no longer registered." },
+{ RPL_YOURACCESSIS, "Your current access level is \002%i\002." },
+{ RPL_CHANINFO2, "F0und3r - %s" },
+{ RPL_CHANINFO3, "D3sc - %s" },
+{ RPL_CHANINFO4, "T0p|c - %s (%s)" },
+{ RPL_CHANINFO5, "0pti0ns - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "S3ttingz - [Topic Level: %i+] [Restrict Level: %i+] [Mode: %s]" },
+{ RPL_CHANINFO7, "Ch4nn3l R3gg3d - %s GMT" },
+{ RPL_CHANINFO8, "Ch4nn3l L4st Us3d - %s GMT" },
+{ RPL_CHANINFO9, "L33t m0f0 inf0 - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ 3nd 0f Ch4nS3rv Inf0 ]=-" },
+{ RPL_CHANACCESS1, "%s h4s %s 4cc3ss 0n %s" },
+{ RPL_CHANACCESS2, "j00 have %s access on %s" },
+{ ERR_NOTOPEDINCHAN, "j00 must be b0th inside, and 0p3d, in the ch4nn3l you wish to r3ggx0r, d00d." },
+{ ERR_CHANALREADYREG, "This ch4nn3l is alr34dy r3gg3d. j00 c4n n0t r3g it ag4in." },
+{ ERR_TOMANYREGCHAN1, "j00 h4v3 r3gg3d t00 m4ny ch4nn3lz." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s alr34dy h4s t00 m4ny r3gg3d ch4nz." },
+{ RPL_CHANNOWREG, "\002%s\002 iz n0w r3gg3d under j00r nix0r \002%s\002 with r3wt acc3ss [Founder(15)]." },
+{ RPL_CHANREGNOTE, "j00r ch4n is m0d3l0ck3d to \002+tn-k\002 4nd t0pic pr3s3rv4ti0n is s3t \0020N\002." },
+{ ERR_CHANFROZEN, "Acc3ss d3ni3d, d00d. This ch4n is \002PHR0Z3N\002." },
+{ ERR_NOOPON, "%s c4n't b3 4dd3d t0 th3 ch4n0p-listx0r. j00 g0tta ask 'em to unl0ck th3ir nix0r f|rst." },
+{ RPL_CHANTRANS, "F0und3r st4tus 0f \002%s\002 tr4nsf3rr3d t0 \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Acc3ss-list f0r \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "M4sk %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ 3nd 0f Acc3ss-listx0r ]=-" },
+{ ERR_NOREMOTEACC, "D00d, j00 c4n't l|st th3 acc3ss m4sks f0r \002%s\002." },
+{ RPL_CURRENTACC, "The curr3nt acc3ss l3v3l for %s is \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ Listx0r of all l33t ph33kz 0nlin3 ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ End of l33t phr33kz listx0r ]=-" },
+{ ERR_BADACCMASK, "d00d, sh0rt3n j00r vh0st, it's t00 long." },
+{ ERR_TOOMANYACCMASKS, "j00 have r34ched j00r acc3ss-m4sk l|m|t, r3mov3 sOm3 b3for3 4dding a n3w on3." },
+{ ERR_CHANAXTOOLOW, "j00r acc3ss is t00 l0w t0 p3rf0rm th4t c0mm4nd, d00d." },
+{ ERR_CHANNOMOREOPS, "S0rry d00d, j00 h4v3 t00 many ops in \002%s\002. j00 can't add anym0r3." },
+{ ERR_UNKAXLEVEL, "j00 specified an invalid l3v3l (\002%s\002)" },
+{ ERR_NOAXCGFOUNDER, "S0rry d00d, \002%s\002 is th3 ch4nn3l f0und3r and c4nn0t b3 4djust3d 0n \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Ch4ng3d acc3ss f0r \002%s\002 t0 \002%s\002" },
+{ RPL_CHANOPADDED, "Add3d 0p #%i \002%s\002 as \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "Sorry d00d, but \002%s\002 has reached th3 ak|ck l|m|t. j00 cann0t 4dd 4ny m0re ak|cks." },
+{ ERR_THISEXISTS, "0p3n j00r 3y3z. \002%s\002 already 3xists in the %s l|st." },
+{ ERR_INVALIDAKICK, "d00d, %s is an inv4l|d ak|ck." },
+{ RPL_CHANAKICKADDED, "Add3d Akick \002%s\002 t0 \002%s\002" },
+{ ERR_NOTINOPSLIST, "y0.. \002%s\002 does not exist in the 0px0r list for \002%s\002." },
+{ RPL_CHANOPDELED, "D3l3ted 0p \002%s\002 0n \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Sorry, \002%s\002 does n0t exist in the akick list for \002%s\002." },
+{ RPL_CHANAKICKDELED, "D3l3t3d ak|ck \002%s\002 fr0m \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ Opx0r list f0r \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 match 0f \002%i\002 3l3m3nts s34rched." },
+{ RPL_CHANOPSLISTEND, "-=[ End Ops list ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Ak|ck list for \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ End Akick list ]=-" },
+{ RPL_CHANDROP, "Channel registration for \002%s\002 has been discontinued." },
+{ ERR_NICKNOTINCHAN, "S0rry, \002%s\002 is not in \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "j00r n0w a ch4nn3l opx0r in \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "j00r l0st j00r opz in \002%s\002." },
+{ ERR_NOSUCHCHAN, "Sorry, \002%s\002 does not exist." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 users in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "j00 must specify a key t0 m0de l0ck a channel +k." },
+{ ERR_MISSINGLIMIT, "j00 must specify a limit t0 m0de l0ck a channel +l." },
+{ RPL_MLOCKSETTO, "Mode for \002%s\002 is now locked to \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 is now restricted to \002%i+\002 level users." },
+{ RPL_TOPICLOCKSETTO, "Topic change restriction for \002%s\002 has been set to \002%i+\002 levels." },
+{ RPL_CHANSETSTATUS, "\002%s\002 for \002%s\002 is \002%s\002." },
+{ RPL_CHANSETDESC, "The description of \002%s\002 is: %s" },
+{ RPL_CHANSETDESCCLEAR, "Description of \002%s\002 cleared." },
+{ RPL_REMCHANBANS, "Removed bans: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "DeOp'ed: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Masskick complete, \002%i\002 people kicked, \002%s\002 cleared." },
+{ RPL_CHANMODECLEAR, "Modeclear for \002%s\002 successful." },
+{ ERR_BADMASK, "Sorry, \002%s\002 is an improper mask format."},
+{ RPL_AKILLADDED, "Added %s for \002%s\002 for \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "The mask \002%s\002 already exists in the %s list." },
+{ ERR_INVALIDMODES, "Sorry, %s is an invalid mode list." },
+{ ERR_NOSUCHSERVER, "Sorry, there is no such server \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "Sorry, \002%s\002 is already in SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "Sorry, \002%s\002 is not in SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "Dynamic EKILL list is empty." },
+{ RPL_EKILLHEAD, "-=[ Dynamic Ekill list ]=-" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "-=[ End Ekill list ]=-" },
+{ ERR_NOSUCHEKILL, "Sorry, There is no such EKILL: \002%s\002." },
+{ RPL_EKILLDELED, "Removed EKILL for \002%s\002" },
+{ ERR_EKILLEXISTS, "EKILL already exists: \002%s\002" },
+{ RPL_EKILLADDED, "Added EKILL for \002%s\002." },
+{ RPL_RESTARTING, "R3st4rtx0rizing" },
+{ RPL_SHUTTINGDOWN, "Shuttin D0wnx0r" },
+{ RPL_PERMCLONEIGNHEAD, "-=[ Perm Clone ignore list ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Sorry - but the mask \002%s\002 has not been added, it's improper format or already present." },
+{ RPL_ACCMASKADDED, "The mask \002%s\002 has been succesfully added to your access-list." },
+{ RPL_ACCLISTCLEARED, "Your access-list has been fully cleared." },
+{ RPL_ACCMASKREMOVED, "The mask \002%s\002 has been succesfully removed from your access-list." },
+{ ERR_ACCENTRYNOTFOUND, "Sorry, the entry #%s was not found in your access-list." },
+{ ERR_ACCMASKNOTFOUND, "Sorry, the mask \002%s\002 was not found in your access-list." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Sorry, but you will have to use a hostmask in the form of nick!user@host." },
+{ ERR_WIDEHOST, "Sorry, but your range is too wide, please try to narrow it down." },
+{ RPL_NLISTHEADER, "-=[ Start of List (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ End of List \002%i\002 out of \002%i\002 matched the condition \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Sorry, but your search did not return any matches." },
+{ RPL_NICKRELEASED, "The nickname \002%s\002 has been released and is available for use again." },
+{ ERR_NICKNOTHELD, "Sorry, but the nickname %s is currently not being held by Services." },
+{ ERR_BADFLAG, "Sorry, but \002%c\002 is an unknown flag to me." },
+{ RPL_CHANGEDFLAGS, "You have changed the flags for \002%s\002 to \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "You have permanently banned the nickname \002%s\002 from any further use." },
+{ RPL_GETPASS, "The password for the nickname \002%s\002 has been sent to the email address \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ End Perm ignore list ]=-" },
+{ RPL_UPTIME1, "Services has been online for:" },
+{ RPL_UPTIME2, "%i Days, %i hours, %i minutes, and %i seconds." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Called %i times" },
+{ RPL_ALLOCSTAT2, "sfree() info: Called %i times" },
+{ RPL_CLONESTATUS1, "%s@%s has %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s has %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Please specify a proper trigger level." },
+{ ERR_NOSUCHTRIGGER, "No such user@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s has no cloneflag settings." },
+{ RPL_HASCLONEFLAGS, "%s has flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s is already on permanent ignore." },
+{ ERR_NOSUCHPERMIGN, "%s is not on permanent ignore." },
+{ ERR_UNKNOWNFLAG, "Unknown flag %s." },
+{ ERR_UNKNOWHOST, "Unknown host %s." },
+{ ERR_NOMATCH, "No matches for %s@%s" },
+{ RPL_MAPHEAD, "-=[ Connected Server list ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Sorry, but you will have to use a hostmask in the form of user@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "The activation key for the nickname \002%s\002 is \002%s\002." },
+{ RPL_GETREALPASS, "Nick-p4ss h4x0ring compl3t3. \002%s\002's password is \002%s\002." },
+{ RPL_DELETE, "The nix0r \002%s\002 has b33n d3l3t3d fr0m th3 d4t4b4s3s." },
+{ RPL_SAVE, "The NickServ database has been synched to disk." },
+{ ERR_ALREADYLINKID, "j00 h4ve alr34ady r3m0t3ly IDed for the nix0r \002%s\002." },
+{ ERR_MAXLINKID, "j00 cann't r3mot3ly ID for more than \002%i\002 nix0rz." },
+{ RPL_NICKWARN1, "d00d, this nix0r is r3gg3d. If j00 0wn it, ID n0w." },
+{ RPL_NICKWARN2, "If j00 don't ID, j00r nix0r will be changed in 30 seconds." },
+{ RPL_NICKWARN3, "To identify, use the \002IDENTIFY\002 command: \002/ns IDENTIFY j00rp4ssw0rd\002" },
+{ RPL_NICKWARN4, "j00 h4v3 15 s3conds t0 chang3 j00r nix0r, d00d..." },
+{ RPL_NICKWARN5, "j00r nix0r h4s b33n ch4ng3d. Use a nix0r that is not yet r3gg3d, d00d." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "D00D! j00 h4v3 \002%i\002 new m3m0(z). (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Received at %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Sorry, but there is no m3m0 \002%i\002." },
+{ RPL_MLISTHEADER, "-=[ Listing memos for \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Received at %-30s from \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ End of memo-list ]=-" },
+{ ERR_MLISTEMPTY, "Sorry, but your memo-list is empty." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Sorry, but your memo is too long, please try to keep it less than \002%i\002 characters." },
+{ ERR_ISNOMEMO, "Sorry, but \002%s\002 does not allow you to send any memos to them." },
+{ ERR_MEMOBOXFULL, "Sorry, but \002%s\002's memobox is full. " },
+{ ERR_TOOMANYMEMOS, "Sorry, but you have sent too many memos. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 has just sent you a memo, to read it: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Your memo has been succesfully sent to \002%s\002" },
+{ ERR_ISNOFORWARD, "Sorry, but \002%s\002 does not allow you to send any forwarded memos to them." },
+{ RPL_MEMOFORWARDED, "You have succesfully forwarded \002%i\002 memo%s to \002%s\002", },
+{ ERR_NOFWDTOSELF, "Sorry, but forwarding memos to yourself seems a bit silly to me. " },
+{ RPL_DELMEMO, "You have now deleted \002%s\002 memos." },
+{ RPL_DELMEMONR, "You have now deleted memo \002%i\002." },
+{ RPL_MAPEND, "-=[ End Server list ]=-" },
+{ RPL_MMAX, "\002%s\002 is currently set to \002%i\002 for this nick." },
+{ ERR_MMAXSET, "Sorry, but you will have to pick a number between\002 1\002 and \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 has now been set to \002%i\002 for this nick." },
+{ RPL_MFORWARD, "Your memos are currently being forwarded to \002%s\002." },
+{ RPL_MFORWARDNOW, "Your memos are now being forwarded to \002%s\002." },
+{ ERR_NOFWDMEMOS, "Sorry, but \002%s\002 does not allow you to redirect memos to them." },
+{ RPL_MEMOSRETRIEVED, "All of your memos have been succesfully emailed to \002%s\002." },
+{ ERR_MNEEDLEVEL, "Sorry, but you need to specify a level of channel ops." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Your memo has been delivered to \002%i\002 out of \002%i\002 targets." },
+{ ERR_JINXEXIST, "d00d, that \002%s\002 f0r \002%s\002 already exists." },
+{ ERR_NOSUCHNICK, "d00d, \002%s\002 ain't online." },
+{ ERR_CANTJINXSRA, "d00d, j00r St3wpid! j00 can't jinx a SRA! Silly m0f0." },
+{ ERR_NOSUCHJINX, "Sorry, but there doesnt seem to be a \002%s\002 for \002%s\002." },
+{ RPL_JINXLISTEMPTY, "Sorry, but there are currently no \002%s\002 set." },
+{ RPL_JINXLISTHEADER, "-=[ Listing all \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ End of \002%s\002 list ]=-" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "You have succesfully added a \002%s\002 for the nickname \002%s\002." },
+{ RPL_JINXREMOVED, "You have succesfully removed the \002%s\002 for the nickname \002%s\002." },
+{ ERR_NEEDUSERHOST, "Sorry, but you will have to supply a mask in the form of user@host." },
+{ ERR_THISISNONICKDUMMY,"This is a NickServ registered \002nick enforcer\002, and not a real user." },
+{ ERR_NOHELPONTHAT, "Sorry, there is no help available on \002%s\002. Please join " NETCHAN " for help." },
+{ ERR_BADCHANNELNAME, "Sorry, but \002%s\002 is not a valid channelname." },
+{ RPL_CHANCLOSED, "The chanx0r \002%s\002 h4s b33n \002CL0X0R3D\002. Mwahahahaha." },
+{ ERR_CHANNOTCLOSED, "The chanx0r \002%s\002 has n0t been \002CLOX0R3D\002. Mwahahahaha." },
+{ RPL_CHANUNCLOSED, "The chanx0r \002%s\002 has been \002R30P3N3D\002. Mwahahahaha." },
+{ RPL_GLOBALNOTICE, "\002W3lc0m3 t0 St4rCh4t, d00d!\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/*
+ * Serenity-IRC Language Format Table: LCARS (StarTrek) Protocol.
+ * Modified by jinxi (November 2000)
+ */
+
+#ifndef LCARS__H
+#define LCARS__H
+
+#include "services.h"
+
+struct FormatTable LcarsReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Custom Transmission" },
+{ ERR_NEEDREGNICK, "Access Denied. Restricted to registered command codes." },
+{ ERR_NEEDACTNICK, "Access Denied. Restricted to activated command codes." },
+{ ERR_NEEDSRA, "Fleet Commander access required. " },
+{ ERR_NEEDSERVOP, "Fleet Commander Ajudant access required. " },
+{ ERR_NEEDOPER, "Commanding Officer access required. " },
+{ ERR_UNKNOWNCOMMAND, "Access Denied. \002%s\002 is an unknown parameter." },
+{ RPL_MOREHELP, "Access Denied. \002/msg %s help\002 for additional information." },
+{ RPL_DEBUGHEADER, "[%s Long-Range Scans]" },
+{ RPL_DEBUGFOOTER, "[Long-Range Scans Complete]" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "Access Denied. Additional parameters required." },
+{ RPL_PASSOKAY, "Access Granted. Command code accepted for \002%s\002." },
+{ RPL_YOUAREROOT, "Welcome aboard Admiral." },
+{ RPL_YOUARESERVOP, "Welcome aboard Commander." },
+{ RPL_NOCHANGEPASS, "Serenity-IRC requests periodic command code change as per Serenity-IRC protocol." },
+{ RPL_MOREHELPCMD, "Access Denied. \002/msg %s help %s\002 for required data parameters." },
+{ RPL_PASSNOTOKAY, "Access Denied. \002%s\002 authorization code invalid." },
+{ RPL_EMAILHACK1, "\002-WARNING-\002 Invalid authorization code attempts." },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Serenity-IRC subspace transmission dispatched to secured channel." },
+{ RPL_EMAILHACK3, "\002-WARNING-\002 Auto shutdown sequence initiated. Security notified. Discontinue access attempts." },
+{ RPL_EMAILHACK4, "Transport to " NETCHAN " if secure subspace transmission not received in 15 minutes." },
+{ RPL_EMAILHACK5, "\002-WARNING-\002 Continued access attempts will result in immediate termination of subspace link." },
+{ RPL_EMAILHACK6, "\002-WARNING-\002 Subspace link terminated." },
+{ ERR_NICKNOTREGGED, "Access Denied. \002%s\002 does not have registered command code." },
+{ RPL_INFOHEADER, "[\002%s\002 NickServ Database]" },
+{ RPL_INFOFOOTER, "[End NickServ Database]" },
+{ RPL_INFOBANISHED, "Access Denied. Assimilated by the Borg." },
+{ RPL_INFONOWON, "[Onboard] - To Access Data: /whois %s" },
+{ RPL_INFODEREG, "Access Denied. Borg assimilated, terminated by Serenity-IRC." },
+{ RPL_INFOLASTSEEN1, "Last Known Coordinates - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Last Stardate Contact - %s" },
+{ RPL_INFOREGGEDON, "Authorized Given - %s" },
+{ RPL_INFOEMAIL, "Transmission Frequency - %s" },
+{ RPL_INFOACCESS, "Serenity-IRC Command Rank - %s" },
+{ RPL_INFOOPTIONS, "Authorization Parameters - %s" },
+{ RPL_INFOMEMO, "Communication Parameters - %s" },
+{ RPL_INFOLINKID, "Remote Authorization - %s" },
+{ RPL_INFOCURRENTACC, "Current Authorization - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Command Data - [Assignments: %i] [Transmissions: %i] [Remote Coordinates: %i] [Warp Level: %i]" },
+{ RPL_INFOSTATUS, "Current Status - %s" },
+{ RPL_INFOREGBY, "Authorization - %s@%s" },
+{ RPL_INFOTIMENOW, "Current Stardate - %s" },
+{ ERR_NEEDID, "Access Denied. Input command code to access." },
+{ RPL_NSETIS, "\002%s\002 set to \002%s\002." },
+{ RPL_NSETNOW, "\002%s\002 is set to \002%s\002." },
+{ ERR_BADSETTING, "Unable to Comply, \002%s\002 is an unknown parameter." },
+{ ERR_BADPASSWORD, "" },
+{ RPL_PASSWORDNOW, "\002%s\002 is your new command code." },
+{ ERR_VALIDEMAIL, "Invalid subspace transmission address, user@host frequency required." },
+{ ERR_NICKLIMIT, "Access restricted to five identities per personnel." },
+{ ERR_NOWEBMAIL, "Serenity-IRC Command requests non web-based transmission frequencies for registration." },
+{ RPL_TEMPDEAC1, "Authorization temporarily suspended to verify new transmission frequency." },
+{ RPL_TEMPDEAC2, "Reactivate authorization code using data transmitted to new frequency." },
+{ RPL_TEMPDEAC3, "All previous personnel codes will remain intact." },
+{ RPL_TEMPDEAC4, "New code authorization transmitted to \002%s\002." },
+{ ERR_NOMAILSENT, "Unable to Comply. Subspace transmission frequency is not accessable." },
+{ ERR_ALREADYREG, "Code access exists in database and cannot be registered again." },
+{ ERR_NEEDTOACT, "Code access exists in database and must be activated for clearance." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Unable to Comply. Serenity-IRC Command prohibits this identity. Select new identity now." },
+{ ERR_BANNEDEMAIL, "Subspace frequency transmission prohibited for this address. Select new subspace frequency." },
+{ ERR_CANNOTGHOSTSELF, "Access Denied. You cannot terminate yourself." },
+{ ERR_NOTONLINE, "\002%s\002 is not onboard." },
+{ ERR_ACCESSDENIED, "Access Denied. Restricted data." },
+{ RPL_NICKGHOSTED, "\002%s\002 is now available for use." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "This sector set to mode +s as a courtesy for our junior officers. This does not affect the sector in any way, other than to cloak it on the sector scans." },
+{ RPL_NOOPSFROZEN, "Access Denied. Channel frozen by Serenity-IRC Command." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Access Denied. Command level clearance not authorized." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "\002%s\002 is not registered." },
+{ RPL_NEXTDBSYNC, "Database synch in %d minutes." },
+{ RPL_CHANINFO1, "[\002%s\002 ChanServ Database]" },
+{ 76, "Access Granted. \002%s\002 command code authorized." },
+{ 77, "Primary coordinate is \002%s\002." },
+{ 78, "Use /ns \002ADDMASK\002 to add additional coordinates." },
+{ 79, "Authorization Stardate: %s" },
+/* 80 - 99 */
+{ 80, "Secure channel code is \002%s\002. Enter into your data padd for reference, Encryption protocols reccommended." },
+{ 81, "Welcome aboard." },
+{ 82, "Command functions have been re-routed successfully, Access restored." },
+{ 83, "Unable to Comply. Command functions are already enabled. Activation protocols are no longer required. " },
+{ RPL_NICKDROPPED, "Diagnostic complete. Command functions for \002%s\002 are no longer active." },
+{ RPL_YOURACCESSIS, "Access level is \002%i\002." },
+{ RPL_CHANINFO2, "Commanding Officer - %s" },
+{ RPL_CHANINFO3, "Plaque Description - %s" },
+{ RPL_CHANINFO4, "Transmission Data - %s (%s)" },
+{ RPL_CHANINFO5, "Access Options - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Sector Options - [Transmission Access: %i+] [Restriction Access: %i+] [Domain: %s]" },
+{ RPL_CHANINFO7, "Sector Secured - %s GMT" },
+{ RPL_CHANINFO8, "Last Accessed - %s GMT" },
+{ RPL_CHANINFO9, "StarFleet Data - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "[End ChanServ Database]" },
+{ RPL_CHANACCESS1, "%s has %s access on %s" },
+{ RPL_CHANACCESS2, "You have %s access on %s" },
+{ ERR_NOTOPEDINCHAN, "Unable to Comply. Be inside the sector and have command code clearance to register." },
+{ ERR_CHANALREADYREG, "This sector is registered." },
+{ ERR_TOMANYREGCHAN1, "Serenity-IRC Command restricts to five sectors per commanding officer." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s has too many sectors." },
+{ RPL_CHANNOWREG, "\002%s\002 is now under the command of \002%s\002." },
+{ RPL_CHANREGNOTE, "The sector is under martial law in mode \002+tn-k\002 Topic restrictions apply and set to \002ON\002" },
+{ ERR_CHANFROZEN, "Access Denied. This sector frozen by Serenity-IRC Command." },
+{ ERR_NOOPON, "Unable to Comply. %s can not be added to the chanop-list. Request unlock of access from user." },
+{ RPL_CHANTRANS, "\002%s\002 command transferred to \002%s\002." },
+{ RPL_ACCESSHEADER, "[\002%s\002 Access Coordinates]" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "[End Access Coordinates]" },
+{ ERR_NOREMOTEACC, "Access Denied. List the access masks for \002%s\002 requires security clearence." },
+{ RPL_CURRENTACC, "The current access level for %s is \002%i\002." },
+{ RPL_LISTOPHEADER, "[Commanding Officers Online]" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "[End Commanding Officers List]" },
+{ ERR_BADACCMASK, "\002-WARNING-\002 Access coordinate exceeds safety parameters." },
+{ ERR_TOOMANYACCMASKS, "\002-WARNING-\002 Maximum access coordinates reached." },
+{ ERR_CHANAXTOOLOW, "Access Denied. Restricted materials. Clearance level too low." },
+{ ERR_CHANNOMOREOPS, "Unable to Comply. \002%s\002 has maximum number of command staff." },
+{ ERR_UNKAXLEVEL, "Unable to Comply. \002%s\002 is an invalid parameter." },
+{ ERR_NOAXCGFOUNDER, "\002%s\002 is the commanding officer and cannot be demoted in \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Access for \002%s\002 changed to \002%s\002." },
+{ RPL_CHANOPADDED, "Added op #%i \002%s\002 as \002%s\002." },
+{ ERR_CHANNOMOREAKICK, "Unable to Comply. \002%s\002 has maximum number of drones." },
+{ ERR_THISEXISTS, "Unable to Comply. \002%s\002 exists in %s." },
+{ ERR_INVALIDAKICK, "Error: %s is an invalid akick." },
+{ RPL_CHANAKICKADDED, "Added Akick \002%s\002 to \002%s\002" },
+{ ERR_NOTINOPSLIST, "Error: \002%s\002 does not exist in the ops list for \002%s\002." },
+{ RPL_CHANOPDELED, "Deleted op \002%s\002 on \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Error: \002%s\002 does not exist in the akick list for \002%s\002." },
+{ RPL_CHANAKICKDELED, "Deleted akick \002%s\002 from \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "[\002%s\002 Command Staff]" },
+{ RPL_CHANOPSLISTHEAD2, "(Index) Nick Level" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 match of \002%i\002 elements searched." },
+{ RPL_CHANOPSLISTEND, "[End Command Staff]" },
+{ RPL_CHANAKLISTHEAD1, "[\002%s\002 Drones]" },
+{ RPL_CHANAKLISTHEAD2, "(Index) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Time [GMT]) (Reason)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "[End Drones]" },
+{ RPL_CHANDROP, "Unit \002%s\002 of borg, adjunct of tertiary matrix 7 has been severed from the collective" },
+{ ERR_NICKNOTINCHAN, "Error, \002%s\002 is not on scans in \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "You are now a command level officer in \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "You are no longer a command level officer in \002%s\002." },
+{ ERR_NOSUCHCHAN, "Unable to Comply, \002%s\002 information is not on file." },
+{ RPL_NUMUSERSINCHAN, "Scan Complete: \002%d\002 lifeforms found in \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Unable to Comply. Specify key parameter to restrict sector." },
+{ ERR_MISSINGLIMIT, "Unable to Comply. Specify limit parameter to restrict sector." },
+{ RPL_MLOCKSETTO, "\002%s\002 restricted to \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 restricted to \002%i+\002 level officers." },
+{ RPL_TOPICLOCKSETTO, "\002%s\002 topic change restricted to \002%i+\002 level officers." },
+{ RPL_CHANSETSTATUS, "\002%s\002 for \002%s\002 is \002%s\002." },
+{ RPL_CHANSETDESC, "\002%s\002 Database: %s" },
+{ RPL_CHANSETDESCCLEAR, "\002%s\002 Database cleared." },
+{ RPL_REMCHANBANS, "Removed bans: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "DeOpped: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoiced: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Evacuation Complete. \002%i\002 crew accounted for, all decks of \002%s\002 cleared. " },
+{ RPL_CHANMODECLEAR, "Command modes for \002%s\002 cleared successfully." },
+{ ERR_BADMASK, "ERROR: \002%s\002 is not a recognized mask format. "},
+{ RPL_AKILLADDED, "Added %s for \002%s\002 for \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "The mask \002%s\002 currently exists in %s databanks" },
+{ ERR_INVALIDMODES, "Unable to Comply: %s is an invalid mode list." },
+{ ERR_NOSUCHSERVER, "Unable to Comply, there is no such server \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "Unable to Comply: \002%s\002 is already in SVSNOOP mode." },
+{ ERR_NOTSVNOOP, "Unable to Comply: \002%s\002 is not in SVSNOOP mode." },
+{ RPL_EKILLEMPTY, "Dynamic EKILL Information Purged From LCARS Database." },
+{ RPL_EKILLHEAD, "[Dynamic Ekill Database]" },
+{ RPL_EKILLDATA, "%-25s (set by %s) %s %s" },
+{ RPL_EKILLEND, "[End Ekill Database]" },
+{ ERR_NOSUCHEKILL, "ERROR: EKILL: \002%s\002 Does Not Exist." },
+{ RPL_EKILLDELED, "Program Complete: EKILL Removed For \002%s\002" },
+{ ERR_EKILLEXISTS, "EKILL Data Exists: \002%s\002" },
+{ RPL_EKILLADDED, "EKILL Data For \002%s\002 Activated." },
+{ RPL_RESTARTING, "Self destruct sequence initiated." },
+{ RPL_SHUTTINGDOWN, "Shutting Down." },
+{ RPL_PERMCLONEIGNHEAD, "[Perm Drone Ignores]" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Fascinating - the mask \002%s\002 has not been added, it is illogical or alredy exists." },
+{ RPL_ACCMASKADDED, "Captain, sensors indicate that \002%s\002 has been successfully added to the access-list." },
+{ RPL_ACCLISTCLEARED, "Command access-list has been fully cleared." },
+{ RPL_ACCMASKREMOVED, "Incoming message from StarFleet: \002%s\002 has been succesfully removed from your access-list." },
+{ ERR_ACCENTRYNOTFOUND, "ERROR: the entry #%s was not found in your command access-list." },
+{ ERR_ACCMASKNOTFOUND, "ERROR: the mask \002%s\002 was not found in your command access-list." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Unable to Comply: You will have to use a sub-space channel in the form of nick!user@host." },
+{ ERR_WIDEHOST, "Unable to Comply: Your range is too wide, please respecify more specific coordinates." },
+{ RPL_NLISTHEADER, "[Start \002%s\002]" },
+{ RPL_NLISTFOOTER, "[End \002%i\002 of \002%i\002 matched \002%s\002]" },
+{ ERR_NLISTEMPTY, "Specified parameters not found." },
+{ RPL_NICKRELEASED, "\002%s\002 released by Serenity-IRC Command." },
+{ ERR_NICKNOTHELD, "%s is not held by Serenity-IRC Command. " },
+{ ERR_BADFLAG, "Unable to comply. \002%c\002 is an unknown parameter." },
+{ RPL_CHANGEDFLAGS, "You have altered your security clearance flags for \002%s\002 to \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "You have permanently revoked access for \002%s\002 for interstellar travel." },
+{ RPL_GETPASS, "Command authorization codes for the nickname \002%s\002 have been sent to the subspace address \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "[End Drones]" },
+{ RPL_UPTIME1, "LCARS online:" },
+{ RPL_UPTIME2, "%i Days, %i hours, %i minutes, and %i seconds." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Called %i times" },
+{ RPL_ALLOCSTAT2, "sfree() info: Called %i times" },
+{ RPL_CLONESTATUS1, "%s@%s has %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s has %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Please specify a proper trigger level." },
+{ ERR_NOSUCHTRIGGER, "No such user@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s has no cloneflag settings." },
+{ RPL_HASCLONEFLAGS, "%s has flags: %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s is already had their stellar access revoked." },
+{ ERR_NOSUCHPERMIGN, "%s is not on permanent ignore." },
+{ ERR_UNKNOWNFLAG, "Unknown flag %s." },
+{ ERR_UNKNOWHOST, "Unknown host %s." },
+{ ERR_NOMATCH, "No matches for %s@%s" },
+{ RPL_MAPHEAD, "[Connected Servers]" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Unable to Comply: You will have to use a sub-space channel in the form of user@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "Command authorization code for \002%s\002 is \002%s\002." },
+{ RPL_GETREALPASS, "Security code for \002%s\002 is \002%s\002." },
+{ RPL_DELETE, "\002%s\002 deleted from NickServ database." },
+{ RPL_SAVE, "NickServ database transported to disk." },
+{ ERR_ALREADYLINKID, "Security already remotely identified for nickname \002%s\002." },
+{ ERR_MAXLINKID, "Authorization Denied. Remote identification for more than \002%i\002 nicknames is not allowed." },
+{ RPL_NICKWARN1, "Long range scans indicate this nickname is registered. If this is your nickname, please identify to NickServ now." },
+{ RPL_NICKWARN2, "\002WARNING\002 Unknown Person. Identify to StarFleet or you will be \002ASSIMILATED\002 in 30 seconds." },
+{ RPL_NICKWARN3, "Unable to Comply, to authorize, use the \002IDENTIFY\002 command: \002/ns IDENTIFY <your password>\002" },
+{ RPL_NICKWARN4, "\002WARNING\002 Unknown Person. Identify to StarFleet or you will be \002ASSIMILATED\002 in 15 seconds." },
+{ RPL_NICKWARN5, "\002WARNING\002 This person has been assimilated. Please select a nickname that is not yet registered." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "You have \002%i\002 new subspace transmission(s) waiting. (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Received at %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "There are no subspace messages. \002%i\002." },
+{ RPL_MLISTHEADER, "[\002%s\002 Subspace Messages]" },
+{ RPL_MLIST1, "\002%2i\002. Received at %-30s from \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "[End Subspace Messages]" },
+{ ERR_MLISTEMPTY, "Your subspace terminal PADD is empty." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "ERROR: Subspace message is too long, limit it to \002%i\002 characters." },
+{ ERR_ISNOMEMO, "Access Denied. \002%s\002 has denied you to send any subspace messages to them." },
+{ ERR_MEMOBOXFULL, "Access Denied. \002%s\002's Subspace Terminal is Full. " },
+{ ERR_TOOMANYMEMOS, "Access Denied. Your subspace terminal has sent too many messages." },
+{ RPL_GOTNEWMEMO, "ALERT! Incoming Subspace message from \002%s\002, to read it: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Subspace message has been successfully sent to \002%s\002" },
+{ ERR_ISNOFORWARD, "Access Denied \002%s\002 denied your access to send forwarded subspace messages to them." },
+{ RPL_MEMOFORWARDED, "Subspace transmission forwarded \002%i\002 memo%s to \002%s\002." },
+{ ERR_NOFWDTOSELF, "You try to forward subspace message to yourself." },
+{ RPL_DELMEMO, "\002%s\002 subspace messages removed from PADD." },
+{ RPL_DELMEMONR, "Subspace message \002%i\002 removed from PADD." },
+{ RPL_MAPEND, "[End Servers]" },
+{ RPL_MMAX, "\002%s\002 set to \002%i\002 for this personnel." },
+{ ERR_MMAXSET, "Select numerical parameter between \002 1\002 and \002%i\002." },
+{ RPL_MMAXNOW, "\002%s\002 has now been set to \002%i\002 for this nick." },
+{ RPL_MFORWARD, "Subspace messages forwarded to \002%s\002." },
+{ RPL_MFORWARDNOW, "Subspace messages now forwarded to \002%s\002." },
+{ ERR_NOFWDMEMOS, "Access Denied. \002%s\002 has revoked access to redirect memos to them." },
+{ RPL_MEMOSRETRIEVED, "Subspace messages transmitted to \002%s\002." },
+{ ERR_MNEEDLEVEL, "Unable to comply. Specify level parameter for command access" },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Subspace message report: \002%i\002 of \002%i\002 messages transmitted." },
+{ ERR_JINXEXIST, "Unable to comply. \002%s\002 for \002%s\002 already exists." },
+{ ERR_NOSUCHNICK, "\002%s\002 is not onboard." },
+{ ERR_CANTJINXSRA, "Access Denied. You cannot assimilate a Fleet Commander." },
+{ ERR_NOSUCHJINX, "Unable to comply. The \002%s\002 for \002%s\002 does not exist." },
+{ RPL_JINXLISTEMPTY, "No parameters for \002%s\002 exist." },
+{ RPL_JINXLISTHEADER, "[\002%s\002]" },
+{ RPL_JINXLISTFOOTER, "[End \002%s\002]" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "\002%s\002 added for \002%s\002." },
+{ RPL_JINXREMOVED, "\002%s\002 removed for \002%s\002." },
+{ ERR_NEEDUSERHOST, "Unable to comply. Parameter must be in user@host format." },
+{ ERR_THISISNONICKDUMMY,"Serenity-IRC Enforcer Android - not real personnel." },
+{ ERR_NOHELPONTHAT, "Unable to comply. Specified parameter \002%s\002 is invalid. Transport to #starchat for assistance." },
+{ ERR_BADCHANNELNAME, "\002%s\002 is not a valid sector name." },
+{ RPL_CHANCLOSED, "\002%s\002 sector closed by Serenity-IRC Command." },
+{ ERR_CHANNOTCLOSED, "\002%s\002 sector remains open." },
+{ RPL_CHANUNCLOSED, "\002%s\002 sector reopened by Serenity-IRC Command." },
+{ RPL_GLOBALNOTICE, "\002Serenity-IRC welcomes you aboard. Enjoy your mission.\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid protocol number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "Unable to comply. %s command syntax incorrect."},
+{ RPL_INFOREMARK, "\002Log entry #%i\002 by %s on StarDate %s: %s"},
+{ RPL_DELREMARK, "The specified log entry for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Log entry on \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+/* This is where the more crucial defines are done. Don't start messing with
+ * these unless you are sure about what you are doing. Also don't add things
+ * here that are likely to change, such as paths or debug-settings.
+ *
+ * - GZ
+ */
+
+#ifndef __SERVICES_H
+#define __SERVICES_H
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <time.h>
+#include "options.h" /* Include the rest of our settings */
+
+#ifdef WIN32
+#define strcasecmp(a,b) stricmp(a,b)
+#define strncasecmp(a,b,n) strnicmp(a,b,n)
+#define bzero(a,n) memset(a,0,n)
+#define bcopy(s,d,n) memcpy(d,s,n)
+#define vsnprintf(a,b,c,d) _vsnprintf(a,b,c,d)
+#define index(s,c) strchr(s,c)
+#define rindex(s,c) strrchr(s,c)
+#define srandom(a) srand(a)
+#define random() rand()
+#endif
+
+/* Define some standard lengths */
+#define NICKLEN 31
+#define USERLEN 15
+#define HOSTLEN 64
+#define EMAILLEN 80
+#define CHANLEN 33
+#define MEMOLEN 350
+
+/* Hash table defines */
+#define NICKHASHSIZE 6007 /* How many nicks in the hash array */
+#define CHANHASHSIZE 2003 /* How many channels in the hash array */
+#define CHANUSERHASHSIZE 547 /* How many users in a channel */
+#define OPHASHSIZE 547 /* How many ops in a hash entry */
+#define VARHASHSIZE NICKHASHSIZE /* Just leave this the same as nick */
+#define NICKCHANHASHSIZE 10
+#define CLONEHASHSIZE 2003
+
+/* Define structures etc here */
+#define A_AKILL 0x01
+#define A_IGNORE 0x02
+#define CLONE_KILLFLAG 0x01
+#define CLONE_IGNOREFLAG 0x02
+#define CLONE_PERMIGNORE 0x04
+
+typedef struct userlist_struct UserList;
+
+typedef struct service_struct {
+ char name[21];
+ char uname[11];
+ char host[67];
+ char rname[51];
+ char mode[10];
+} Service;
+
+typedef struct database_struct {
+ FILE *ns;
+ FILE *cs;
+ FILE *os;
+ FILE *nsreg;
+ FILE *ms;
+ FILE *w;
+} database;
+
+/* Global function prototypes */
+
+void flushLogs(void);
+void expireChans(void);
+void expireNicks(void);
+void sshutdown(int);
+void srestart(void);
+void disk_synch(void);
+void addUser(char *, char *, char *, char *, char *);
+int listenOnPort(int);
+int ConnectToServer(char *, int);
+struct hostent *resolve(char *);
+struct hostent *lookupHost(char *);
+struct hostent *lookupIP(char *);
+void sSend(char *,...);
+void uSend(char *, UserList *, char *, ...);
+void sockSend(int, char *,...);
+void killUser(Service, UserList *, char *);
+void userMode(UserList *, char *);
+void logDump(FILE *, char *,...);
+int sendMail(char *, char *, char *, char *,...);
+void breakLine(char *);
+void parseLine(char *);
+void segvdie(int);
+int cancel_timer(unsigned int);
+unsigned int timer(long, void (*func) (char *), char *, char *);
+void checktimers(void);
+int breakString(int, char *, char **, char *);
+int match(char *, char *);
+void strtolower(char *);
+void doTfunc(char *);
+char *sfgets(char *, int, FILE *);
+int check_match(char *);
+int exp_match(char *, char *);
+void *smalloc(size_t);
+void sfree(void *);
+void loadPermJinxes();
+void listAkills(char *from, char type, char *mask);
+void addakill(long length, char *mask, char *by, char type, char *reason);
+void removeakill(char *from, char *mask);
+int findakill(char *mask);
+void saveakills();
+void loadakills();
+
+/* Global variables */
+
+int antiloop;
+char datadir[512];
+char timerbuff[512];
+char debugbuff[512];
+time_t debugtime;
+time_t timertime;
+char myname[64];
+char mypass[33];
+char hostname[10][64];
+char hostservername[64];
+int port[10];
+int server, synched;
+Service services[20];
+database db;
+FILE *operlog, *nicklog, *chanlog, *corelog, /**servout,*/ *rootlog;
+long totalusers, mostusers, mostnicks, mostchans, mostmemos, startup;
+unsigned int AllocCalled, FreeCalled;
+char *OperServ, *NickServ, *ChanServ, *MemoServ, *LogServ, coreBuffer[512];
+int AccessLimit, OpLimit, AkickLimit, ChanLimit, NickLimit;
+time_t CTime; /* current time, keep this in mind... */
+typedef struct regnicklist_struct RegNickList;
+struct regnicklist_struct *firstRegNick, *lastRegNick;
+struct userlist_struct *firstUser, *lastUser;
+struct nreglist_struct *firstReg, *lastReg;
+struct chanlist_struct *firstChan, *lastChan;
+struct regchanlist_struct *firstRegChan, *lastRegChan;
+typedef struct chanlist_struct ChanList;
+
+
+#include "stuff.h"
+#include "memoserv.h"
+#include "nickserv.h"
+#include "chanserv.h"
+#include "operserv.h"
+#include "logserv.h"
+#include "help.h"
+#include "db.h"
+#include "ban.h"
+#include "replies.h"
+#include "webtv.h"
+#include "jinx.h"
+#include "msgtab.h"
+#include "hash.h"
+#include "numeric.h"
+
+UserHashEnt UserHash[NICKHASHSIZE];
+RegNickHashEnt RegNickHash[NICKHASHSIZE];
+ChanHashEnt ChanHash[CHANHASHSIZE];
+RegChanHashEnt RegChanHash[CHANHASHSIZE];
+CloneHashEnt CloneHash[CLONEHASHSIZE];
+
+#ifdef TELNET
+#include "telnet.h"
+ int telnetsock;
+#endif
+
+time_t nextNsync, nextCsync;
+time_t nextMsync;
+
+#ifndef WIN32
+int cslock,mslock,nslock, pidlock;
+#endif
+
+char *WebServ;
+char *Serenity-IRC;
+
+/*
+ * other MemoServ things you'll need:
+ * MS_DEF_RCV_MAX = The *default* number of memos a max recieved field
+ * will be set to
+ * MS_RCV_MAX_HIGHEST = The highest a USER can set his max received field to
+ * MS_SENT_MAX = The most memos a person can send out per hour.
+ * IRCops are exempt, and forward groups and CSENDS count as 1.
+ */
+
+#define MS_DEF_RCV_MAX 50
+#define MS_RCV_MAX_HIGHEST 200
+#define MS_SENT_MAX 6
+
+#define MAXFLOODLEVEL 100
+#define NICKDROPTIME (14*24*3600)
+#define CHANDROPTIME (14*24*3600)
+#define PASSWARNTIME (60*24*3600)
+#define MEMODROPTIME (10*24*3600)
+#define SYNCTIME (15*60) /* Define time between synchs to disk */
+
+/* SHOWSYNCH - globops each time databases are saves */
+/* SHOWSYNCHALL - notice to users showing how long until next save*/
+
+#undef SHOWSYNCH
+#ifdef SHOWSYNCH
+ #undef SHOWSYNCHALL
+#endif
+
+/*
+ * default clone flags:
+ * 0 for none
+ * CLONE_KILLFLAG to autokill for every host
+ * CLONE_IGNOREFLAG to autoignore for every host
+ * CLONE_PERMTRIGGER to make ALL triggers permanet (including unchaged)
+ *
+ * DEFHOSTCLONETRIGGER = Warning level for clones from *@host
+ * DEFUSERCLONETRIGGER = Warning level for clones from user@host
+ * DEFHOSTILEHOSTCLONES = Akill level for clones from *@host
+ * DEFHOSTILEUSERCLONES = Akill level for clones from user@host
+ */
+
+#define DEFCLONEFLAGS 0
+#define DEFHOSTCLONETRIGGER 5
+#define DEFUSERCLONETRIGGER 5
+#define DEFHOSTILEHOSTCLONES 20
+#define DEFHOSTILEUSERCLONES 10
+
+char retnum[2048];
+
+int ToRecvQ(char *);
+int FromRecvQ(void);
+int ToSendQ(char *);
+int FromSendQ(void);
+
+struct SOCKETSTR
+{
+ short int family;
+ short int port;
+ long int ip;
+ char pad[8];
+};
+
+struct CLIENT
+{
+ struct CLIENT *prev,*next;
+ int socket;
+ char name[32];
+ char ident[32];
+ char host[128];
+ char info[256];
+ char *bfr;
+ int bfrx;
+ long int hash;
+};
+
+struct ArecvQ { /* Incoming traffic. */
+ int messages;
+ int length;
+ char buffer[MAXRQ];
+} recvQ;
+
+struct AsendQ { /* Outgoing traffic. */
+ int messages;
+ int length;
+ char buffer[MAXSQ];
+} sendQ;
+
+#define MAXREMOTEID 5 /* Define the maximum remote ID's per nick */
+
+char ftrack[512]; /* To store a function name here */
+
+typedef struct ftrackstruct aftrackstruct;
+
+struct ftrackstruct {
+ unsigned long starttime;
+ char function[512];
+ aftrackstruct *next, *prev;
+};
+
+aftrackstruct ftracklist;
+
+#endif /* __SERVICES_H */
--- /dev/null
+/*
+ * Serenity-IRC Services Language Format Tables: Spanish Language.
+ *
+ */
+
+#ifndef SPANISH__H
+#define SPANISH__H
+
+#include "services.h"
+
+struct FormatTable SpanishReplies[] = {
+/* 0 - 19 */
+{ RPL_CUSTOM, "Este es un mensaje personalizado" },
+{ ERR_NEEDREGNICK, "Necesitas un nick registrado para este comando." },
+{ ERR_NEEDACTNICK, "Necesitas un nick activado para este comando." },
+{ ERR_NEEDSRA, "Necesitas acceso de Service Root para este comando." },
+{ ERR_NEEDSERVOP, "Necesitas acceso de Service Operator para este comando." },
+{ ERR_NEEDOPER, "Necesitas acceso de IRC operator para este comando." },
+{ ERR_UNKNOWNCOMMAND, "Lo siento, pero \002%s\002 es un comando desconocido para mi." },
+{ RPL_MOREHELP, "Por favor intenta \002/msg %s HELP\002 para mas ayuda con este servicio." },
+{ RPL_DEBUGHEADER, "-=- [%s Debug Information] -=-" },
+{ RPL_DEBUGFOOTER, "-=- [End of Debug Information] -=-" },
+{ RPL_DEBUGLINE1, "%-15s %-15s %-15s %-15s" },
+{ RPL_DEBUGLINE2, "\002%-15s\002 %-15d %-15d %-15d" },
+{ ERR_BADPARAMS, "Especificaste muy pocos argumentos para este comando." },
+{ RPL_PASSOKAY, "El password ha sido aceptado para el nick \002%s\002." },
+{ RPL_YOUAREROOT, "Tu eres ahora un \002Services Root Administrator.\002" },
+{ RPL_YOUARESERVOP, "Tu eres ahora un \002Services Operator.\002" },
+{ RPL_NOCHANGEPASS, "No has cambiado el password de tu nick recientemente." },
+{ RPL_MOREHELPCMD, "Por favor intenta \002/msg %s HELP %s\002 para mas ayuda con este comando." },
+{ RPL_PASSNOTOKAY, "El password proporcionado \002NO\002 es correcto para el nick \002%s\002." },
+{ RPL_EMAILHACK1, "\002Cuidado!\002 Haz puesto un password incorrecto muchas veces!" },
+/* 20 - 39 */
+{ RPL_EMAILHACK2, "Una notificación por email ha sido enviada a el dueño de este nick." },
+{ RPL_EMAILHACK3, "Por favor \002detén tus intentos de identificarte\002 hasta que recibas este email." },
+{ RPL_EMAILHACK4, "Si no recibes este email, entra a " NETCHAN " para asistencia." },
+{ RPL_EMAILHACK5, "Otros intentos mas de identificarte resultarán en la \002desconexión de la red por la fuerza.\002" },
+{ RPL_EMAILHACK6, "Ahora serás desconectado de la red por hackear un nick. Fuiste avisado!" },
+{ ERR_NICKNOTREGGED, "El nick \002%s\002 no está registrado con NickServ." },
+{ RPL_INFOHEADER, "-=[ Información de NickServ para \002%s\002 ]=-" },
+{ RPL_INFOFOOTER, "-=[ Fin de la información ]=-" },
+{ RPL_INFOBANISHED, "Este nick ha sido permanentemente \002BANEADO\002 por la administración de Serenity-IRC." },
+{ RPL_INFONOWON, "(Ahora en IRC) Para mas información: /whois %s" },
+{ RPL_INFODEREG, "Este nick ha sido \002DEREGISTRADO\002 por la administración se Serenity-IRC." },
+{ RPL_INFOLASTSEEN1, "Última dirección vista - %s@%s [%s]" },
+{ RPL_INFOLASTSEEN2, "Visto últimamente - %s" },
+{ RPL_INFOREGGEDON, "Registrado en - %s" },
+{ RPL_INFOEMAIL, "Dirección de email - %s" },
+{ RPL_INFOACCESS, "Acceso a servicios - %s" },
+{ RPL_INFOOPTIONS, "Opciones puestas - %s" },
+{ RPL_INFOMEMO, "Configuración de memo - %s" },
+{ RPL_INFOLINKID, "ID's remotas - %s" },
+{ RPL_INFOCURRENTACC, "Acceso Actual - %s" },
+/* 40 - 59 */
+{ RPL_INFODATA, "Datos de IRCop - [channels: %i] [memos: %i] [masks: %i] [floodlevel: %i]" },
+{ RPL_INFOSTATUS, "Status actual - %s" },
+{ RPL_INFOREGBY, "Registrado por - %s@%s" },
+{ RPL_INFOTIMENOW, "Tiempo ahora - %s" },
+{ ERR_NEEDID, "Lo siento, pero necesitas estar identificado con este nick antes de usar este comando." },
+{ RPL_NSETIS, "\002%s\002 está actualmente puesto en \002%s\002 para este nick." },
+{ RPL_NSETNOW, "\002%s\002 ha sido cambiado a \002%s\002 para este nick." },
+{ ERR_BADSETTING, "Lo siento, pero \002%s\002 es una configuración desconocida para mi." },
+{ ERR_BADPASSWORD, "Lo siento, pero ese no es un password aceptable, por favor escoge otro." },
+{ RPL_PASSWORDNOW, "El password de tu nick ha sido cambiado a \002%s\002." },
+{ ERR_VALIDEMAIL, "Por favor, especifica una dirección de email válida en la forma usuario@host." },
+{ ERR_NICKLIMIT, "Lo siento, pero haz alcanzado el lÃmite de registros de nick. No puedes registrar mas." },
+{ ERR_NOWEBMAIL, "Lo siento, pero Serenity-IRC no acepta correos basados en Web, para el registro de nicks." },
+{ RPL_TEMPDEAC1, "Tu nick ha sido temporalmente desactivado para verificar la nueva dirección de email.." },
+{ RPL_TEMPDEAC2, "El proceso para reactivar tu nick será el mismo que cuando lo registraste." },
+{ RPL_TEMPDEAC3, "Toda la configuración del nick será guardada para cuando lo reactives." },
+{ RPL_TEMPDEAC4, "El nuevo número de activación fue mandado a \002%s\002." },
+{ ERR_NOMAILSENT, "Lo siento, pero el email no pudo ser enviado a la dirección especificada." },
+{ ERR_ALREADYREG, "El nick ya está registrado. No puedes registrarlo otra vez." },
+{ ERR_NEEDTOACT, "El nick ya está registrado, ahora solo puede ser activado." },
+/* 60 - 79 */
+{ ERR_CANNOTREGTHIS, "Este nick no puede ser registrado, por favor escoge otro." },
+{ ERR_BANNEDEMAIL, "Este email está \002BANEADO\002 para usarse en Serenity-IRC. Por favor usa otro." },
+{ ERR_CANNOTGHOSTSELF, "Lo siento, pero no puedes darte kill a ti mismo." },
+{ ERR_NOTONLINE, "El nick \002%s\002 no está siendo usado - no puedes usar ghost." },
+{ ERR_ACCESSDENIED, "Lo siento, acceso denegado para esta operación." },
+{ RPL_NICKGHOSTED, "El nick \002%s\002 ha recibido el ghost. Ahora puede ser usado." },
+{ RPL_TOCHANOPS, "\002(Ops:%s)\002 %s" },
+{ RPL_AUTOSET_S, "Este canal está puesto en modo +s para usuarios mas jóvenes. Esto no afectará al canal de otra manera que, hacerlo invisible en la lista de canales." },
+{ RPL_NOOPSFROZEN, "No se te permiten privilegios de op en este canl, ha sido \002CONGELADO\002." },
+{ RPL_CHANDESC, "(\002%s\002): %s" },
+{ RPL_NOOPS, "Lo siento, no se te permiten privilegios de op en este canal." },
+{ RPL_PING1, "\001PING %s\001" },
+{ RPL_PING2, "\001PING %s %s\001" },
+{ ERR_CHANNOTREGGED, "El canal \002%s\002 No está registrado con ChanServ." },
+{ RPL_NEXTDBSYNC, "Siguiente database Synch(save) en %d minutos." },
+{ RPL_CHANINFO1, "-=[ Información de ChanServ para \002%s\002 ]=-" },
+{ 76, "Tu nick \002%s\002 Está ahora exitosamente registrado y activado!" },
+{ 77, "Tu primera access-mask es \002%s\002. Si quieres agregar mas access-masks," },
+{ 78, "Intenta usando: /ns \002ADDMASK\002" },
+{ 79, "La hora de tu registro es %s " },
+/* 80 - 99 */
+{ 80, "El password de tu nick es \002%s\002. por favor, escrÃbelo, para que no se te pierda." },
+{ 81, "Bienvenido a la red de IRC de Serenity-IRC, disfruten su estancia!" },
+{ 82, "Tu nick ha sido exitosamente reactivado!" },
+{ 83, "Este nick ya está activado. No puedes activarlo otra vez." },
+{ RPL_NICKDROPPED, "Tu nick \002%s\002 ya no está registrado." },
+{ RPL_YOURACCESSIS, "Tu actual nivel de acceso es \002%i\002." },
+{ RPL_CHANINFO2, "Fundador - %s" },
+{ RPL_CHANINFO3, "Desc - %s" },
+{ RPL_CHANINFO4, "Topic - %s (%s)" },
+{ RPL_CHANINFO5, "Opciones - %s%s%s%s%s%s%s%s" },
+{ RPL_CHANINFO6, "Configurarción - [Nivel de topic: %i+] [Nivel de restricción: %i+] [Modos: %s]" },
+{ RPL_CHANINFO7, "Canal registrado - %s GMT" },
+{ RPL_CHANINFO8, "Última vez usado - %s GMT" },
+{ RPL_CHANINFO9, "Datos de IRCop - %s%s%s%s[Ops: %i] [Akicks: %i]" },
+{ RPL_CHANINFO10, "-=[ Fin de la información de ChanServ ]=-" },
+{ RPL_CHANACCESS1, "%s tiene nivel de acceso %s en %s" },
+{ RPL_CHANACCESS2, "Tu tienes nivel de acceso %s en %s" },
+{ ERR_NOTOPEDINCHAN, "Tienes que estar dentro del canal y tener op, si quieres registrarlo." },
+{ ERR_CHANALREADYREG, "Este canal ya fue registrado, no puedes registrarlo otra vez." },
+{ ERR_TOMANYREGCHAN1, "Haz registrado demasiados canales." },
+/* 100 - 119 */
+{ ERR_TOMANYREGCHAN2, "%s tiene demasiados canales registrados." },
+{ RPL_CHANNOWREG, "El canal \002%s\002 está ahora registrado bajo el nick \002%s\002 con acceso FOUNDER(15)." },
+{ RPL_CHANREGNOTE, "Tu canal tiene modelock para \002+tn-k\002 y la preservación de topic está en \002ON\002." },
+{ ERR_CHANFROZEN, "Acceso denegado. Este canal está \002CONGELADO\002." },
+{ ERR_NOOPON, "%s No puede ser agregado a la lista de ops. Debes pedirles que quiten el seguro de su nick primero." },
+{ RPL_CHANTRANS, "El status de founder de \002%s\002 es transferido a \002%s\002." },
+{ RPL_ACCESSHEADER, "-=[ Lista de accesos para \002%s\002 ]=-" },
+{ RPL_ACCESSLIST1, "Mask %i) \002%s\002" },
+{ RPL_ACCESSFOOTER, "-=[ Fin de la lista de accesos ]=-" },
+{ ERR_NOREMOTEACC, "Lo siento, no puedes ver la lista de accesos para \002%s\002." },
+{ RPL_CURRENTACC, "El nivel actual para %s es \002%i\002." },
+{ RPL_LISTOPHEADER, "-=[ Lista de todos los IRC operators en lÃnea ]=-" },
+{ RPL_LISTOP1, "(%-2i) %-30s %s%s" },
+{ RPL_LISTOPFOOTER, "-=[ Fin de la lista de operadores ]=-" },
+{ ERR_BADACCMASK, "Lo siento, pero esa access-mask es muy larga." },
+{ ERR_TOOMANYACCMASKS, "Haz alcanzado el lÃmite de access-masks, por favor borra algunas antes de agregar otras." },
+{ ERR_CHANAXTOOLOW, "Tu acceso es muy bajo para realizar este comando." },
+{ ERR_CHANNOMOREOPS, "Lo siento, \002%s\002 ha alcanzado el lÃmite de ops. No puedo agregar mas ops." },
+{ ERR_UNKAXLEVEL, "El nivel que tu especificaste \002%s\002 no es un nivel válido." },
+{ ERR_NOAXCGFOUNDER, "Lo siento, \002%s\002 es el fundador del canal y no puede ser ajustado en \002%s\002." },
+/* 120 - 139 */
+{ RPL_CHANAXCHANGE, "Acceso cambiado de \002%s\002 a \002%s\002" },
+{ RPL_CHANOPADDED, "Op agregado #%i \002%s\002 como \002%s\002" },
+{ ERR_CHANNOMOREAKICK, "Lo siento, \002%s\002 ha alcanzado el lÃmite de akicks. No puedo agregar mas akicks." },
+{ ERR_THISEXISTS, "Lo siento, \002%s\002 ya existe en la lista %s." },
+{ ERR_INVALIDAKICK, "Lo siento, %s no es un akick válido." },
+{ RPL_CHANAKICKADDED, "Akick agregado \002%s\002 a \002%s\002" },
+{ ERR_NOTINOPSLIST, "Lo siento, \002%s\002 no existe en la lista de ops para \002%s\002." },
+{ RPL_CHANOPDELED, "Op borrado \002%s\002 en \002%s\002." },
+{ ERR_AKICKNOTEXIST, "Lo siento, \002%s\002 no existe en la lista de akicks en\002%s\002." },
+{ RPL_CHANAKICKDELED, "Akick borrado \002%s\002 de \002%s\002" },
+{ RPL_CHANOPSLISTHEAD1, "-=[ Lista de ops pars \002%s\002 ]=-" },
+{ RPL_CHANOPSLISTHEAD2, "(Indice) Nick Nivel" },
+{ RPL_CHANOPSLISTDATA, "(%-3i) %-30s [%s]" },
+{ RPL_LISTSEARCHNUM, "\002%i\002 corresponden de \002%i\002 elementos buscados." },
+{ RPL_CHANOPSLISTEND, "-=[ Fin de lista de ops ]=-" },
+{ RPL_CHANAKLISTHEAD1, "-=[ Lista de akicks para \002%s\002 ]=-" },
+{ RPL_CHANAKLISTHEAD2, "(Indice) (Mask)" },
+{ RPL_CHANAKLISTHEAD3, "(Hora [GMT]) (Razón)" },
+{ RPL_CHANAKLISTDATA1, "(%-3i) (%-s)" },
+{ RPL_CHANAKLISTDATA2, "(%s) (%s)" },
+/* 140 - 159 */
+{ RPL_CHANAKLISTEND, "-=[ Fin de lista de Akicks ]=-" },
+{ RPL_CHANDROP, "El registro de canal para \002%s\002 ha sido descontinuado." },
+{ ERR_NICKNOTINCHAN, "Lo siento, \002%s\002 no está en \002%s\002." },
+{ RPL_NOWCHANOPERATOR, "Tu eres ahora un operador de canal en \002%s\002." },
+{ RPL_NOTCHANOPERATOR, "Ya no eres un operador de canal en \002%s\002." },
+{ ERR_NOSUCHCHAN, "Lo siento, \002%s\002 no existe." },
+{ RPL_NUMUSERSINCHAN, "\002%d\002 usuarios en \002%s\002." },
+{ RPL_CHANCLISTDATA, ":%s -> %s%s" },
+{ ERR_MISSINGKEY, "Debes especificar una clave para que un canal tenga modelock +k." },
+{ ERR_MISSINGLIMIT, "Debes especificar un lÃmite para que un canal tenga modelock +l." },
+{ RPL_MLOCKSETTO, "Modo para \002%s\002 está ahora aseguraro a \002%s\002." },
+{ RPL_RESTRICTSETTO, "\002%s\002 está ahora restricto a \002%i+\002 nivel de usuarios." },
+{ RPL_TOPICLOCKSETTO, "La rectricción de topic para \002%s\002 ha sido cambiada a niveles \002%i+\002." },
+{ RPL_CHANSETSTATUS, "\002%s\002 para \002%s\002 es \002%s\002." },
+{ RPL_CHANSETDESC, "La descripción para \002%s\002 es: %s" },
+{ RPL_CHANSETDESCCLEAR, "Descripción de \002%s\002 limpiada." },
+{ RPL_REMCHANBANS, "Ban removido: %s" },
+{ RPL_CHANLIST, "%s (%s) [%i/%i]" },
+{ RPL_CHANMASSDEOP, "Deop: %s" },
+{ RPL_CHANMASSDEVOICE, "DeVoice: %s" },
+/* 160 - 179 */
+{ RPL_CHANMASSKICK, "Masskick completo, \002%i\002 gente pateada, \002%s\002 limpiado." },
+{ RPL_CHANMODECLEAR, "Modeclear para \002%s\002 exitoso." },
+{ ERR_BADMASK, "Lo siento, \002%s\002 no es una forma correcta de Mask."},
+{ RPL_AKILLADDED, "Agregado %s para \002%s\002 para \002%s\002 [%s]" },
+{ ERR_MASKEXISTS, "La Mask \002%s\002 ya existe en la lista %s." },
+{ ERR_INVALIDMODES, "Lo siento, %s es una lista de modes inválida." },
+{ ERR_NOSUCHSERVER, "Lo siento, no existe ese servidor \002%s\002." },
+{ ERR_ALREADYSVSNOOP, "Lo siento, \002%s\002 ya está en el modo SVSNOOP." },
+{ ERR_NOTSVNOOP, "Lo siento, \002%s\002 no está en modo SVSNOOP." },
+{ RPL_EKILLEMPTY, "La lista de Dynamic EKILL esta vacÃa." },
+{ RPL_EKILLHEAD, "-=[ Lista de Dynamic EKILL ]=-" },
+{ RPL_EKILLDATA, "%-25s (puesto por %s) %s %s" },
+{ RPL_EKILLEND, "-=[ Fin de la lista ]=-" },
+{ ERR_NOSUCHEKILL, "Lo siento, No existe el EKILL: \002%s\002." },
+{ RPL_EKILLDELED, "EKILL removido para \002%s\002" },
+{ ERR_EKILLEXISTS, "Ese EKILL ya existe: \002%s\002" },
+{ RPL_EKILLADDED, "EKILL agregado para \002%s\002." },
+{ RPL_RESTARTING, "Reiniciando." },
+{ RPL_SHUTTINGDOWN, "Apagando." },
+{ RPL_PERMCLONEIGNHEAD, "-=[ Lista de ignores a clones permanente ]=-" },
+/* 180 - 199 */
+{ ERR_ACCMASKNOTADDED, "Lo siento - Pero la Mask \002%s\002 no ha sigo agregada, está mal hecha o ya existe." },
+{ RPL_ACCMASKADDED, "La Mask \002%s\002 ha sido agregada a tu lista de access-mask." },
+{ RPL_ACCLISTCLEARED, "Tu lista de access-list ha sido limpiada." },
+{ RPL_ACCMASKREMOVED, "La Mask \002%s\002 ha sido removida de tu lista de access-mask." },
+{ ERR_ACCENTRYNOTFOUND, "Lo siento, La búsqueda #%s no fue encontrada en tu lista de access-mask." },
+{ ERR_ACCMASKNOTFOUND, "Lo siento, La mask \002%s\002 no fue encontrada en tu lista de access-mask." },
+{ RPL_NLIST1, "%4i: %s %s" },
+{ RPL_NLIST2, "%4i: %s!%s@%s%s" },
+{ RPL_NLIST3, "%4i: %s!%s@%s" },
+{ ERR_PROPERHOST1, "Lo siento, pero tienes que usar una hostmask en la forma nick!usuario@host." },
+{ ERR_WIDEHOST, "Lo siento, pero el rango es muy grande, por favor hazlo mas pequeño." },
+{ RPL_NLISTHEADER, "-=[ Inicio de la lista (\002%s\002) ]=-" },
+{ RPL_NLISTFOOTER, "-=[ Fin de la lista \002%i\002 de \002%i\002 correspondieron a la condición \002%s\002) ]=-" },
+{ ERR_NLISTEMPTY, "Lo siento, pero tu búsqueda no tuvo resultados." },
+{ RPL_NICKRELEASED, "El nick \002%s\002 ha sido soltado, y está disponible para uso otra vez." },
+{ ERR_NICKNOTHELD, "Lo siento, pero el nick %s no está siendo detenido por servicios." },
+{ ERR_BADFLAG, "Lo siento, pero \002%c\002 es una bandera(flag) desconocida para mi." },
+{ RPL_CHANGEDFLAGS, "Haz cambiado las banderas(flags) para \002%s\002 a \002%s%s%s%s\002." },
+{ RPL_BANNEDNICK, "Haz baneado permanente el nick \002%s\002 para su uso." },
+{ RPL_GETPASS, "El password para el nick \002%s\002 ha sido enviado al email \002%s\002." },
+/* 200 - 219 */
+/* Ax0n: 200 - 219 */
+{ RPL_PERMCLONEIGNDATA, "%i) %s" },
+{ RPL_PERMCLONEIGNEND, "-=[ Fin de lista de ignores permanentes ]=-" },
+{ RPL_UPTIME1, "Los servicios han estado en lÃnea por:" },
+{ RPL_UPTIME2, "%i Dias, %i horas, %i minitos, and %i segundos." },
+{ RPL_ALLOCSTAT1, "smalloc() info: Usada %i veces" },
+{ RPL_ALLOCSTAT2, "sfree() info: Usada %i Veces" },
+{ RPL_CLONESTATUS1, "%s@%s tiene %i/%i clones (total/trigger)" },
+{ RPL_CLONESTATUS2, "%s tiene %i/%i clones (total/trigger)" },
+{ ERR_INVALIDTRIGLEVEL, "Por favor especifia un nivel válido de trigger." },
+{ ERR_NOSUCHTRIGGER, "No usuario usuario@host (%s@%s)." },
+{ RPL_NOCLONEFLAGS, "%s no tiene configuración de cloneflags." },
+{ RPL_HASCLONEFLAGS, "%s tiene banderas(flags): %s%s%s" },
+{ ERR_PERMIGNEXISTS, "%s ya está en perm ignore." },
+{ ERR_NOSUCHPERMIGN, "%s no está en perm ignore." },
+{ ERR_UNKNOWNFLAG, "Bandera(flag) desconocida %s." },
+{ ERR_UNKNOWHOST, "Host desconocido %s." },
+{ ERR_NOMATCH, "No hay resultados para %s@%s" },
+{ RPL_MAPHEAD, "-=[ Lista de servidores conectados ]=-" },
+{ RPL_MAPDATA, "%s (%s)" },
+{ ERR_PROPERHOST2, "Lo siento, pero tienes que usar una hostmask en la forma usuario@host." },
+/* 220 - 239 */
+{ RPL_GETKEY, "El número de activación para \002%s\002 es \002%s\002." },
+{ RPL_GETREALPASS, "El password para el nick \002%s\002 es \002%s\002." },
+{ RPL_DELETE, "El nick \002%s\002 ha sido removido de la base de datos." },
+{ RPL_SAVE, "La base de datos de NickServ ha sido sincronizada al disco." },
+{ ERR_ALREADYLINKID, "Tu te has identificado remotamente para el nick \002%s\002." },
+{ ERR_MAXLINKID, "No puedes estar remotamente identificado para mas de \002%i\002 nicks." },
+{ RPL_NICKWARN1, "El nick está registrado. Si este es tu nick, por favor identifÃcate a NickServ ahora." },
+{ RPL_NICKWARN2, "Si no te identificas, tu nick será cambiado en 30 segundos." },
+{ RPL_NICKWARN3, "Para identificarte, usa el comando \002IDENTIFY\002 : \002/ns IDENTIFY <tu password>\002" },
+{ RPL_NICKWARN4, "Te quedan 15 segundos para identificarte, antes de que tu nick sea cambiado." },
+{ RPL_NICKWARN5, "Tu nick ha sido cambiado. Por favor usa un nick que no esté registrado aún." },
+{ RPL_HELP, "%s" },
+{ RPL_YOUHAVEMEMOS, "Tienes \002%i\002 memo(s) nuevo(s) esperando. (\002%i\002 total)" },
+{ RPL_MEMO1, "\002%2i\002. Recibido en %-30s [%s]" },
+{ RPL_MEMO2, " \002%s\002: %s" },
+{ ERR_NOSUCHMEMO, "Lo siento, pero no hay memo \002%i\002." },
+{ RPL_MLISTHEADER, "-=[ Lista de memos para \002%s\002 ]=-" },
+{ RPL_MLIST1, "\002%2i\002. Recibido en %-30s de \002%s\002 [%s]" },
+{ RPL_MLISTFOOTER, "-=[ Fin de la lista de memos ]=-" },
+{ ERR_MLISTEMPTY, "Lo siento, pero tu lista de memos está vacÃa." },
+/* 240 - 259 */
+{ ERR_MEMOTOOLONG, "Lo siento, pero tu memo es muy largo, Por favor, mantenlo en menos de \002%i\002 caracteres." },
+{ ERR_ISNOMEMO, "Lo siento, pero \002%s\002 no te permite enviarle memos." },
+{ ERR_MEMOBOXFULL, "Lo siento, pero la caja de memos de \002%s\002 está llena. " },
+{ ERR_TOOMANYMEMOS, "Lo siento, pero has enviado demasiados memos. " },
+{ RPL_GOTNEWMEMO, "\002%s\002 te acaba de enviar un memo, para leerlo: \002/msg MemoServ READ %i\002" },
+{ RPL_SENTMEMO, "Tu memo ha sido exitosamente enviado a \002%s\002" },
+{ ERR_ISNOFORWARD, "Lo siento, pero \002%s\002 no te permite que le envÃes memos en forward a el." },
+{ RPL_MEMOFORWARDED, "Has hecho forward exitosamente de \002%i\002 memo%s a \002%s\002", },
+{ ERR_NOFWDTOSELF, "Lo siento, pero hacer forward a ti mismo me parece extraño. " },
+{ RPL_DELMEMO, "Haz borrado \002%s\002 memos." },
+{ RPL_DELMEMONR, "Haz borrado el memo \002%i\002." },
+{ RPL_MAPEND, "-=[ Fin de a lista de servidores ]=-" },
+{ RPL_MMAX, "\002%s\002 está puesto en \002%i\002 para este nick." },
+{ ERR_MMAXSET, "Lo siento, pero tienes que escoger un número entre \002 1\002 y \002%i\002" },
+{ RPL_MMAXNOW, "\002%s\002 ha sido ahora puesto en \002%i\002 para ete nick." },
+{ RPL_MFORWARD, "Tus memos están actualmente siendo mandados a \002%s\002." },
+{ RPL_MFORWARDNOW, "Tus memos están ahora siendo mandados a \002%s\002." },
+{ ERR_NOFWDMEMOS, "Lo siento, pero \002%s\002 no te permite que le redirigas memos a el." },
+{ RPL_MEMOSRETRIEVED, "Todos tus memos han sido mandados al email \002%s\002." },
+{ ERR_MNEEDLEVEL, "Lo siento, pero necesitas especificar un nivel de chanop." },
+/* 260 - 279 */
+{ RPL_SENTMEMOCHAN, "Tu memo ha sido entregado a \002%i\002 de \002%i\002 destinos." },
+{ ERR_JINXEXIST, "Lo siento, pero ese \002%s\002 para \002%s\002 ya existe." },
+{ ERR_NOSUCHNICK, "Lo siento, pero \002%s\002 no parece estar en lÃnea." },
+{ ERR_CANTJINXSRA, "Lo siento, pero no puedes poner jinx a un Service Root." },
+{ ERR_NOSUCHJINX, "Lo siento, pero no parece haber un \002%s\002 para \002%s\002." },
+{ RPL_JINXLISTEMPTY, "Lo siento, pero no hay \002%s\002 puestos." },
+{ RPL_JINXLISTHEADER, "-=[ Listado de todos los \002%s\002 ]=-" },
+{ RPL_JINXLISTFOOTER, "-=[ Fin de la lista de \002%s\002 ]=-" },
+{ RPL_JINXLIST1, "%-25s [set by %s] (%s) %s" },
+{ RPL_JINXADDED, "Haz agregado exitosamente un \002%s\002 para el nick \002%s\002." },
+{ RPL_JINXREMOVED, "Haz removido exitosamente \002%s\002 para el nick \002%s\002." },
+{ ERR_NEEDUSERHOST, "Lo siento, pero tienes que proporcionar una mask en la forma usuario@host." },
+{ ERR_THISISNONICKDUMMY,"Este es un \002nick enforcer\002 registrado con NickServ, y no un usuario real." },
+{ ERR_NOHELPONTHAT, "Lo siento, pero no hay ayuda disponible para \002%s\002. Porfavor, entra a " NETCHAN " para asistencia." },
+{ ERR_BADCHANNELNAME, "Lo siento, pero \002%s\002 no es un nombre de canla válido." },
+{ RPL_CHANCLOSED, "El canal \002%s\002 ha sido \002CERRADO\002." },
+{ ERR_CHANNOTCLOSED, "El canal \002%s\002 no ha sido \002CERRADO\002." },
+{ RPL_CHANUNCLOSED, "El canal \002%s\002 ha sido \002RE-ABIERTO\002." },
+{ RPL_GLOBALNOTICE, "\002Bienvenidos a Serenity-IRC\002" },
+{ ERR_NOTAVALIDNUMBER, "\002%s\002 is not a valid number." },
+/* 280 - 299 */
+{ ERR_INCORRECTUSAGE, "You used the %s command incorrectly."},
+{ RPL_INFOREMARK, "\002Remark #%i\002 by %s on %s: %s"},
+{ RPL_DELREMARK, "The specified remark for \002%s\002 has been removed."},
+{ RPL_ADDREMARK, "Remark for \002%s\002 added."},
+{ -1, "" }
+};
+
+#endif
--- /dev/null
+#ifndef __MEMOSERV_H
+#define __MEMOSERV_H
+
+/* various MS flags */
+#define MNOMEMO 0x0001
+#define MSECURE 0x0002
+#define MSELFCLEAN 0x0004
+#define MFORWARDED 0x0008
+#define MNOFORWARD 0x0010
+
+/* memo flags */
+#define MEMO_UNREAD 0x0001
+#define MEMO_DELETE 0x0002
+#define MEMO_SAVE 0x0004
+#define MEMO_FWD 0x0008
+#define MEMO_REPLY 0x0010
+
+typedef struct memolist MemoList;
+struct memolist {
+ int flags, index;
+ time_t sent;
+ char from[NICKLEN + CHANLEN + 1];
+ char memo[MEMOLEN];
+ MemoList *next, *previous;
+};
+
+typedef struct memobox MemoBox;
+struct memobox {
+ int memos, sent, flags, max;
+ time_t lastsent;
+ char redirect[NICKLEN];
+ MemoList *firstMemo, *lastMemo;
+};
+
+void MreadCmd(UserList *, char **, int);
+void MlistCmd(UserList *, char **, int);
+void MsendCmd(UserList *, char **, int);
+void MforwardCmd(UserList *, char **, int);
+void McsendCmd(UserList *, char **, int);
+void MdeleteCmd(UserList *, char **, int);
+void McleanCmd(UserList *, char **, int);
+void MsetCmd(UserList *, char **, int);
+void MretrieveCmd(UserList *, char **, int);
+void initMemoBox(MemoBox *);
+void addMemo(MemoBox *, MemoList *);
+void delMemo(MemoBox *, MemoList *);
+void checkMemos(UserList *);
+void cleanMemos(UserList *);
+void syncMemoData(time_t);
+
+/*
+ * functions
+ */
+void sendToMemoServ(UserList *, char **, int);
+
+#endif /* __MEMOSERV_H */
--- /dev/null
+#ifndef __MSGTAB
+#define __MSGTAB
+
+#define NEEDREGNICK 0x00000001
+#define NEEDACTNICK 0x00000002
+#define NEEDOPER 0x00000004
+#define NEEDSERVOP 0x00000008
+#define NEEDROOT 0x00000010
+#define NEEDID 0x00000020
+
+struct Message {
+ char *cmd;
+ void (* func)();
+ unsigned int flag;
+ long count;
+ unsigned long totaltime;
+ int params;
+};
+
+void msgtabCheck(char *, UserList *, char **, int);
+
+#ifdef ANALYSE_FUNCTIONS
+void NSdebug(UserList *, char **, int);
+void MSdebug(UserList *, char **, int);
+void CSdebug(UserList *, char **, int);
+void OSdebug(UserList *, char **, int);
+long GetClock(void);
+struct timeval fcountt;
+struct timezone fcountz;
+#endif
+int DoFloodCheck(UserList *);
+
+#endif
--- /dev/null
+#include <stdlib.h>
+
+void *smalloc(size_t);
+void sfree(void *);
--- /dev/null
+#ifndef __NICKSERV_H
+#define __NICKSERV_H
+
+/* online flags: */
+#define NISOPER 0x0001
+#define NISAWAY 0x0002
+#define NISHELPOP 0x0004
+#define NISONLINE 0x0008
+#define NISADMIN 0x0010
+#define NISPLUSX 0x0020
+#define NISINVIS 0x0040
+#define NISIDENT 0x0080
+
+/* NICKNAME FLAGS -- FIRST SLOT FILLED */
+#define NKILL 0x00000001
+#define NVACATION 0x00000002
+#define NHOLD 0x00000004
+#define NACTIVE 0x00000008
+#define NREG 0x00000010
+#define NSERVOP 0x00000020
+#define NROOT 0x00000040
+#define NEMAIL 0x00000080
+#define NBANISH 0x00000100
+#define NDEACC 0x00000200
+#define NOPER 0x00000400 /* This one wasn't used anymore, we'll use it to determine who
+ can view logs using the web interface. -- Remmy 20020214 */
+#define NNETFND 0x00000800 /* Unused -- Remmy 20031115 */
+#define NBOT 0x00001000 /* Unused -- Remmy 20020214 */
+#define NREGBOT 0x00002000 /* Unused -- Remmy 20020214 */
+#define NNETADM 0x00004000
+#define NMARKED 0x00008000
+#define NNOOP 0x00010000
+#define NHIDE 0x00020000
+
+/* NICKNAME FLAGS -- SECOND SLOT */
+//#define NROLEPLAY 0x00000001 -- Not used anymore
+#define NSTICKYOP 0x00000002
+#define NNOPWWARN 0x00000004
+#define NMSGMODE 0x00000008
+#define NREGWEBTV 0x00000010
+#define NSIDENTIFY 0x00000020
+
+/*
+ * access list for a nick
+ */
+typedef struct naccesslist_struct nAccessList;
+
+struct naccesslist_struct {
+ int index;
+ char mask[71]; /* their mask */
+ nAccessList *next; /* The next mask. */
+ nAccessList *previous;
+};
+
+/*
+ * Linked list for notes regarding nicks
+ */
+typedef struct nmarklist_struct nMarkList;
+
+struct nmarklist_struct {
+ char markedby[NICKLEN+1];
+ time_t timestamp;
+ char remark[128];
+ nMarkList *next;
+};
+
+/*
+ * Linked nicks for remote-ID (for now, more is likely to follow) -GZ
+ */
+typedef struct nlinkednicks_struct nLinkList;
+
+struct nlinkednicks_struct {
+ char nick[NICKLEN+1];
+ nLinkList *next;
+ nLinkList *previous;
+};
+
+/*
+ * ===DOC===
+ * This is 'better' docs of whats in the nicklist_struct structure:
+ * nick: the persons nick
+ * user: the persons username
+ * host: the persons host.
+ * timestamp: the time they signed on, also saved as their last seen time.
+ * timereg: when their nick was registered, NULL if not registered.
+ * amasks: how many access masks do we have, -1 if not registered.
+ * flags set on this nick, i.e. REGISTERED, HELD, KILL etc.
+ * *AccessList: a pointer to a linked list of access list info for this
+ * person
+ * *ChanList: a pointer to a linked list of the channels this person is on
+ * (this makes life somuch easier, trust me, :>)
+ * next: the next (online) nickname.
+ */
+
+struct regnicklist_struct {
+ char nick[NICKLEN];
+ char user[USERLEN];
+ char host[HOSTLEN];
+ char realname[51];
+ char password[16];
+ char password2[12];
+ char url[128];
+ char email[EMAILLEN];
+ int language;
+ time_t timestamp; /* Signon time (again) (Doubles as last seen) */
+ time_t timereg; /* when this was registered. */
+ time_t lastpwchange;
+ int amasks; /* number of masks in access list */
+ unsigned int flags; /* nick flags */
+ unsigned int flags2; /* additional flags */
+ unsigned int chans;
+ char info[200]; /* users info, neat feature */
+ nAccessList *firstAcc, *lastAcc;
+ nMarkList *firstMark;
+ MemoBox *memos;
+ RegNickList *next, *previous, *hashnext, *hashprev;
+};
+
+struct userlist_struct
+{
+ char nick[NICKLEN];
+ char user[USERLEN], host[HOSTLEN];
+ char server[51];
+ char realname[51];
+ unsigned int oflags, floodlevel, caccess;
+ unsigned int floodbytes;
+ int linked; /* Number of linked nicks */
+ int flooder;
+ int floodwarn;
+ int failid;
+ int remotefailid;
+ int resynch;
+ int webbie; /* Keeps track of WebTV users online */
+ time_t lastmsg;
+ RegNickList *reg;
+ nLinkList *firstLink, *lastLink;
+ UserList *next, *previous, *hashnext, *hashprev;
+};
+
+/*
+ * functions.
+ */
+
+void addNewUser(char **, int);
+void addNewUserSN(char **, int);
+void remUser(char *);
+void sendToNickServ(UserList *, char **, int);
+void setMode(char *, char *);
+void changeNick(char *, char *, char *);
+UserList *getNickData(char *);
+RegNickList *getRegNickData(char *);
+void setFlags(char *, int, char);
+void cleanNickList(void);
+int isOper(UserList *);
+int isRoot(UserList *);
+int isServop(UserList *);
+int checkAccess(char *, char *, RegNickList *);
+void addAccessMask(char *, UserList *);
+void delAccessMask(char *, UserList *);
+int isGhost(char *);
+void delGhost(char *);
+int addFlood(UserList *, int);
+void nDesynch(char *, char *);
+void add_mark(time_t, char *, RegNickList *, char *);
+void del_mark(RegNickList *, int);
+void addNick(UserList *);
+void addRegNick(RegNickList *);
+void delNick(UserList *);
+void delRegNick(RegNickList *);
+void initNickData(RegNickList *);
+int addAccItem(RegNickList *, char *);
+int delAccItem(RegNickList *, char *, char *);
+void syncNickData(time_t);
+void NidentifyCmd(UserList *, char **, int);
+void NsetCmd(UserList *, char **, int);
+void NregisterCmd(UserList *, char **, int);
+void NactivateCmd(UserList *, char **, int);
+void NinfoCmd(UserList *, char **, int);
+void NdropCmd(UserList *, char **, int);
+void NaddMaskCmd(UserList *, char **, int);
+void NaccessCmd(UserList *, char **, int);
+void NsetflagsCmd(UserList *, char **, int);
+void NbanishCmd(UserList *, char **, int);
+void NgetpassCmd(UserList *, char **, int);
+void NgetkeyCmd(UserList *, char **, int);
+void NgetrealpassCmd(UserList *, char **, int);
+void NdeleteCmd(UserList *, char **, int);
+void NlistCmd(UserList *, char **, int);
+void NwebtvcountCmd(UserList *, char **, int);
+void NhardDeleteCmd(UserList *, char **, int);
+void NghostCmd(UserList *, char **args, int);
+void NsaveCmd(UserList *, char **args, int);
+void NlistopsCmd(UserList *, char **, int);
+void NresendCmd(UserList *, char **, int);
+void NmarkCmd(UserList *, char **, int);
+#endif /* __NICKSERV_H */
--- /dev/null
+/* This file contains all possible replies Services will send to users
+ * do not modify unless you know *EXACTLY* how this works.
+ *
+ */
+
+#ifndef NUMERIC__H
+#define NUMERIC__H
+
+char retlanguage[16];
+
+struct LangTable {
+ char language[20];
+ int numerics;
+ struct FormatTable *numtable;
+};
+
+struct FormatTable {
+ int numeric;
+ char *format;
+};
+
+
+char *GetLanguage(UserList *);
+char *GetReply(int, UserList *);
+int LoadTables();
+struct LangTable *GetLanguageTab(void);
+
+
+#define RPL_CUSTOM 0
+#define ERR_NEEDREGNICK 1
+#define ERR_NEEDACTNICK 2
+#define ERR_NEEDSRA 3
+#define ERR_NEEDSERVOP 4
+#define ERR_NEEDOPER 5
+#define ERR_UNKNOWNCOMMAND 6
+#define RPL_MOREHELP 7
+#define RPL_DEBUGHEADER 8
+#define RPL_DEBUGFOOTER 9
+#define RPL_DEBUGLINE1 10
+#define RPL_DEBUGLINE2 11
+#define ERR_BADPARAMS 12
+#define RPL_PASSOKAY 13
+#define RPL_YOUAREROOT 14
+#define RPL_YOUARESERVOP 15
+#define RPL_NOCHANGEPASS 16
+#define RPL_MOREHELPCMD 17
+#define RPL_PASSNOTOKAY 18
+#define RPL_EMAILHACK1 19
+#define RPL_EMAILHACK2 20
+#define RPL_EMAILHACK3 21
+#define RPL_EMAILHACK4 22
+#define RPL_EMAILHACK5 23
+#define RPL_EMAILHACK6 24
+#define ERR_NICKNOTREGGED 25
+#define RPL_INFOHEADER 26
+#define RPL_INFOFOOTER 27
+#define RPL_INFOBANISHED 28
+#define RPL_INFONOWON 29
+#define RPL_INFODEREG 30
+#define RPL_INFOLASTSEEN1 31
+#define RPL_INFOLASTSEEN2 32
+#define RPL_INFOREGGEDON 33
+#define RPL_INFOEMAIL 34
+#define RPL_INFOACCESS 35
+#define RPL_INFOOPTIONS 36
+#define RPL_INFOMEMO 37
+#define RPL_INFOLINKID 38
+#define RPL_INFOCURRENTACC 39
+#define RPL_INFODATA 40
+#define RPL_INFOSTATUS 41
+#define RPL_INFOREGBY 42
+#define RPL_INFOTIMENOW 43
+#define ERR_NEEDID 44
+#define RPL_NSETIS 45
+#define RPL_NSETNOW 46
+#define ERR_BADSETTING 47
+#define ERR_BADPASSWORD 48
+#define RPL_PASSWORDNOW 49
+#define ERR_VALIDEMAIL 50
+#define ERR_NICKLIMIT 51
+#define ERR_NOWEBMAIL 52
+#define RPL_TEMPDEAC1 53
+#define RPL_TEMPDEAC2 54
+#define RPL_TEMPDEAC3 55
+#define RPL_TEMPDEAC4 56
+#define ERR_NOMAILSENT 57
+#define ERR_ALREADYREG 58
+#define ERR_NEEDTOACT 59
+#define ERR_CANNOTREGTHIS 60
+#define ERR_BANNEDEMAIL 61
+#define ERR_CANNOTGHOSTSELF 62
+#define ERR_NOTONLINE 63
+#define ERR_ACCESSDENIED 64
+#define RPL_NICKGHOSTED 65
+#define RPL_TOCHANOPS 66
+#define RPL_AUTOSET_S 67
+#define RPL_NOOPSFROZEN 68
+#define RPL_CHANDESC 69
+#define RPL_NOOPS 70
+#define RPL_PING1 71
+#define RPL_PING2 72
+#define ERR_CHANNOTREGGED 73
+#define RPL_NEXTDBSYNC 74
+#define RPL_CHANINFO1 75
+#define RPL_ACTIVATE1 76
+#define RPL_ACTIVATE2 77
+#define RPL_ACTIVATE3 78
+#define RPL_ACTIVATE4 79
+#define RPL_ACTIVATE5 80
+#define RPL_ACTIVATE6 81
+#define RPL_REACTIVATE 82
+#define RPL_ALREADYACT 83
+#define RPL_NICKDROPPED 84
+#define RPL_YOURACCESSIS 85
+#define RPL_CHANINFO2 86
+#define RPL_CHANINFO3 87
+#define RPL_CHANINFO4 88
+#define RPL_CHANINFO5 89
+#define RPL_CHANINFO6 90
+#define RPL_CHANINFO7 91
+#define RPL_CHANINFO8 92
+#define RPL_CHANINFO9 93
+#define RPL_CHANINFO10 94
+#define RPL_CHANACCESS1 95
+#define RPL_CHANACCESS2 96
+#define ERR_NOTOPEDINCHAN 97
+#define ERR_CHANALREADYREG 98
+#define ERR_TOMANYREGCHAN1 99
+#define ERR_TOMANYREGCHAN2 100
+#define RPL_CHANNOWREG 101
+#define RPL_CHANREGNOTE 102
+#define ERR_CHANFROZEN 103
+#define ERR_NOOPON 104
+#define RPL_CHANTRANS 105
+#define RPL_ACCESSHEADER 106
+#define RPL_ACCESSLIST1 107
+#define RPL_ACCESSFOOTER 108
+#define ERR_NOREMOTEACC 109
+#define RPL_CURRENTACC 110
+#define RPL_LISTOPHEADER 111
+#define RPL_LISTOP1 112
+#define RPL_LISTOPFOOTER 113
+#define ERR_BADACCMASK 114
+#define ERR_TOOMANYACCMASKS 115
+#define ERR_CHANAXTOOLOW 116
+#define ERR_CHANNOMOREOPS 117
+#define ERR_UNKAXLEVEL 118
+#define ERR_NOAXCGFOUNDER 119
+#define RPL_CHANAXCHANGE 120
+#define RPL_CHANOPADDED 121
+#define ERR_CHANNOMOREAKICK 122
+#define ERR_THISEXISTS 123
+#define ERR_INVALIDAKICK 124
+#define RPL_CHANAKICKADDED 125
+#define ERR_NOTINOPSLIST 126
+#define RPL_CHANOPDELED 127
+#define ERR_AKICKNOTEXIST 128
+#define RPL_CHANAKICKDELED 129
+#define RPL_CHANOPSLISTHEAD1 130
+#define RPL_CHANOPSLISTHEAD2 131
+#define RPL_CHANOPSLISTDATA 132
+#define RPL_LISTSEARCHNUM 133
+#define RPL_CHANOPSLISTEND 134
+#define RPL_CHANAKLISTHEAD1 135
+#define RPL_CHANAKLISTHEAD2 136
+#define RPL_CHANAKLISTHEAD3 137
+#define RPL_CHANAKLISTDATA1 138
+#define RPL_CHANAKLISTDATA2 139
+#define RPL_CHANAKLISTEND 140
+#define RPL_CHANDROP 141
+#define ERR_NICKNOTINCHAN 142
+#define RPL_NOWCHANOPERATOR 143
+#define RPL_NOTCHANOPERATOR 144
+#define ERR_NOSUCHCHAN 145
+#define RPL_NUMUSERSINCHAN 146
+#define RPL_CHANCLISTDATA 147
+#define ERR_MISSINGKEY 148
+#define ERR_MISSINGLIMIT 149
+#define RPL_MLOCKSETTO 150
+#define RPL_RESTRICTSETTO 151
+#define RPL_TOPICLOCKSETTO 152
+#define RPL_CHANSETSTATUS 153
+#define RPL_CHANSETDESC 154
+#define RPL_CHANSETDESCCLEAR 155
+#define RPL_REMCHANBANS 156
+#define RPL_CHANLIST 157
+#define RPL_CHANMASSDEOP 158
+#define RPL_CHANMASSDEVOICE 159
+#define RPL_CHANMASSKICK 160
+#define RPL_CHANMODECLEAR 161
+#define ERR_BADMASK 162
+#define RPL_AKILLADDED 163
+#define ERR_MASKEXISTS 164
+#define ERR_INVALIDMODES 165
+#define ERR_NOSUCHSERVER 166
+#define ERR_ALREADYSVSNOOP 167
+#define ERR_NOTSVNOOP 168
+#define RPL_EKILLEMPTY 169
+#define RPL_EKILLHEAD 170
+#define RPL_EKILLDATA 171
+#define RPL_EKILLEND 172
+#define ERR_NOSUCHEKILL 173
+#define RPL_EKILLDELED 174
+#define ERR_EKILLEXISTS 175
+#define RPL_EKILLADDED 176
+#define RPL_RESTARTING 177
+#define RPL_SHUTTINGDOWN 178
+#define RPL_PERMCLONEIGNHEAD 179
+#define ERR_ACCMASKNOTADDED 180
+#define RPL_ACCMASKADDED 181
+#define RPL_ACCLISTCLEARED 182
+#define RPL_ACCMASKREMOVED 183
+#define ERR_ACCENTRYNOTFOUND 184
+#define ERR_ACCMASKNOTFOUND 185
+#define RPL_NLIST1 186
+#define RPL_NLIST2 187
+#define RPL_NLIST3 188
+#define ERR_PROPERHOST1 189
+#define ERR_WIDEHOST 190
+#define RPL_NLISTHEADER 191
+#define RPL_NLISTFOOTER 192
+#define ERR_NLISTEMPTY 193
+#define RPL_NICKRELEASED 194
+#define ERR_NICKNOTHELD 195
+#define ERR_BADFLAG 196
+#define RPL_CHANGEDFLAGS 197
+#define RPL_BANNEDNICK 198
+#define RPL_GETPASS 199
+#define RPL_PERMCLONEIGNDATA 200
+#define RPL_PERMCLONEIGNEND 201
+#define RPL_UPTIME1 202
+#define RPL_UPTIME2 203
+#define RPL_ALLOCSTAT1 204
+#define RPL_ALLOCSTAT2 205
+#define RPL_CLONESTATUS1 206
+#define RPL_CLONESTATUS2 207
+#define ERR_INVALIDTRIGLEVEL 208
+#define ERR_NOSUCHTRIGGER 209
+#define RPL_NOCLONEFLAGS 210
+#define RPL_HASCLONEFLAGS 211
+#define ERR_PERMIGNEXISTS 212
+#define ERR_NOSUCHPERMIGN 213
+#define ERR_UNKNOWNFLAG 214
+#define ERR_UNKNOWHOST 215
+#define ERR_NOMATCH 216
+#define RPL_MAPHEAD 217
+#define RPL_MAPDATA 218
+#define ERR_PROPERHOST2 219
+#define RPL_GETKEY 220
+#define RPL_GETREALPASS 221
+#define RPL_DELETE 222
+#define RPL_SAVE 223
+#define ERR_ALREADYLINKID 224
+#define ERR_MAXLINKID 225
+#define RPL_NICKWARN1 226
+#define RPL_NICKWARN2 227
+#define RPL_NICKWARN3 228
+#define RPL_NICKWARN4 229
+#define RPL_NICKWARN5 230
+#define RPL_HELP 231
+#define RPL_YOUHAVEMEMOS 232
+#define RPL_MEMO1 233
+#define RPL_MEMO2 234
+#define ERR_NOSUCHMEMO 235
+#define RPL_MLISTHEADER 236
+#define RPL_MLIST1 237
+#define RPL_MLISTFOOTER 238
+#define ERR_MLISTEMPTY 239
+#define ERR_MEMOTOOLONG 240
+#define ERR_ISNOMEMO 241
+#define ERR_MEMOBOXFULL 242
+#define ERR_TOOMANYMEMOS 243
+#define RPL_GOTNEWMEMO 244
+#define RPL_SENTMEMO 245
+#define ERR_ISNOFORWARD 246
+#define RPL_MEMOFORWARDED 247
+#define ERR_NOFWDTOSELF 248
+#define RPL_DELMEMO 249
+#define RPL_DELMEMONR 250
+#define RPL_MAPEND 251
+#define RPL_MMAX 252
+#define ERR_MMAXSET 253
+#define RPL_MMAXNOW 254
+#define RPL_MFORWARD 255
+#define RPL_MFORWARDNOW 256
+#define ERR_NOFWDMEMOS 257
+#define RPL_MEMOSRETRIEVED 258
+#define ERR_MNEEDLEVEL 259
+#define RPL_SENTMEMOCHAN 260
+#define ERR_JINXEXIST 261
+#define ERR_NOSUCHNICK 262
+#define ERR_CANTJINXSRA 263
+#define ERR_NOSUCHJINX 264
+#define RPL_JINXLISTEMPTY 265
+#define RPL_JINXLISTHEADER 266
+#define RPL_JINXLISTFOOTER 267
+#define RPL_JINXLIST1 268
+#define RPL_JINXADDED 269
+#define RPL_JINXREMOVED 270
+#define ERR_NEEDUSERHOST 271
+#define ERR_THISISNONICKDUMMY 272
+#define ERR_NOHELPONTHAT 273
+#define ERR_BADCHANNELNAME 274
+#define RPL_CHANCLOSED 275
+#define ERR_CHANNOTCLOSED 276
+#define RPL_CHANUNCLOSED 277
+#define RPL_GLOBALNOTICE 278
+#define ERR_NOTAVALIDNUMBER 279
+#define ERR_INCORRECTUSAGE 280
+#define RPL_INFOREMARK 281
+#define RPL_DELREMARK 282
+#define RPL_ADDREMARK 283
+
+#endif
--- /dev/null
+#ifndef __OPERSERV_H
+#define __OPERSERV_H
+
+#include "nickserv.h"
+
+/*
+ * ===DOC===
+ * Straightforward I hope...simple AKill structure
+ * nick!user@host + reason (for akill)
+ */
+
+struct access_mod {
+ struct access_mod *next, *prev;
+ char nick[NICKLEN];
+ char user[USERLEN];
+ char host[HOSTLEN];
+ time_t set;
+ time_t unset;
+ char setby[NICKLEN];
+ char reason[80];
+ char type;
+ unsigned int tid;
+ unsigned int id;
+};
+
+/*
+#define OAKILL 0x0001
+#define OIGNORE 0x0002
+#define OTRIGGER 0x0004
+*/
+void sendToOperServ(UserList *, char **, int);
+struct access_mod *isAKilled(char *, char *, char *);
+struct access_mod *isExempted(char *, char*, char*);
+struct access_mod *isHJinxed(char *, char*, char*);
+struct access_mod *isIgnored(char *, char *, char *);
+void send_matching_exempts(char *nick, char *user, char *host);
+void addTempHost(long, char *, char *, int);
+void loadAKills(void);
+void saveAKills(void);
+char *expand_time(long);
+
+void OaccessmodCmd(UserList *, char **, int);
+void OmodeCmd(UserList *, char **, int);
+void OrawCmd(UserList *, char **, int);
+void OinjectCmd(UserList *, char **, int);
+void OshutdownCmd(UserList *, char **, int);
+void OrestartCmd(UserList *, char **, int);
+void OjupeCmd(UserList *, char **, int);
+void OsyncCmd(UserList *, char **, int);
+void OuptimeCmd(UserList *, char **, int);
+void OmkillCmd(UserList *,char **, int);
+void OjinxCmd(UserList *, char **, int);
+void OpermjinxCmd(UserList *, char **, int);
+void OhostjinxCmd(UserList *, char **, int);
+void ObroadcastCmd(UserList *, char **, int);
+void OmapCmd(UserList *, char **, int);
+void OekillCmd(UserList *, char **, int);
+void OlistCmd(UserList *, char **, int);
+void OsvsnoopCmd(UserList *, char **, int);
+void OenforceCmd(UserList *, char **, int);
+void OlogaccessCmd(UserList *, char **, int);
+void OallocstatCmd(UserList *, char **, int);
+void OtriggerCmd(UserList *, char **, int);
+void OclonesetCmd(UserList *, char **, int);
+void OrootOpsCmd (UserList *,char **,int);
+void OlistOpsCmd (UserList *,char **,int);
+void OantispamCmd (UserList *,char **,int);
+void OsvsjoinCmd(UserList *, char **, int);
+void OsvspartCmd(UserList *, char **, int);
+void OsvsbeamCmd(UserList *, char **, int);
+void OrollupCmd(UserList *, char **, int);
+
+#endif /* __OPERSERV_H */
--- /dev/null
+/*
+ * New Services Options. Just put in options that are likely to change here. (-GZ)
+ *
+ */
+
+#ifndef __OPTIONS_H
+#define __OPTIONS_H
+
+#include "config.h"
+
+/* Location and path defines */
+
+/* The path to the databases */
+#define DBDIR "db"
+/* The default path for services data */
+#define CFGFILE "services.conf"
+/* Location of the .pid file */
+#define PIDFILE "services.pid"
+/* Here we keep our core-archive */
+#define COREDIR "cores"
+/* This is the actual name of your corefile */
+#define COREFILE "core"
+/* Directory to put logfiles */
+#define LOGDIR "logs"
+
+/* Debugging and coding related defines */
+
+#undef NOFORK /* With this defined services wont fork */
+#define FORCE_CORE /* Force services to spit out a core file */
+#undef DEBUG /* Specify DEBUG-LEVEL (#define DEBUG <level>) */
+/* #define DEBUG 5 */
+#undef DBDEBUG /* Debug database calls */
+#undef CDEBUG /* Channel debug */
+#undef HASHDEBUG /* Hash table debug */
+#ifdef DEBUG
+ void _debug(int level, char *msg, ...);
+ #define Debug(x) _debug x
+#else
+ #define Debug(x) ;
+#endif
+#define DEBUG_ERROR 1 /* Errors are reported */
+#define DEBUG_WARN 2 /* Debug warnings */
+#define DEBUG_NOTICE 3 /* Debug notices */
+#define DEBUG_INFO 4 /* Debug information */
+#define DEBUG_TCP 5 /* Connection, Sent, Received, etc */
+#undef TELNET /* Enable telnet port for debugging */
+#undef ANALYSE_FUNCTIONS /* Allows advanced command debugging */
+
+/* Network defines */
+
+#define NETWORK "Serenity-IRC" /* Define your network name */
+#define NETHOST "Serenity-IRC.Net"
+#define NETCHAN "#help"
+#define SERVERMLINE "Serenity-IRC Network User Services" /* Define your server MLINE */
+#define AKILLMSG "This user has been autokilled, Please mail kline@serenity-irc.net for more information"
+#define AKILLMAILTO "kline@serenity-irc.net" /* This is where akill mail goes to */
+#define BACKUPDATABASE /* Define if you want to backup databases or not */
+#define MAXSQ 500000 /* Max amount of bytes allowed in your send queue */
+#define MAXRQ 500000 /* Max amount of bytes alloed in your receive queue */
+
+#endif
--- /dev/null
+/* replies.h:
+ * Here you can edit the replies services gives..
+ * a few notes:
+ * 1> DO NOT EVER REMOVE ANYTHING STARTING WITH A %
+ * If you do, services will probably coredump and I'll smack you, alot.
+ * 2> Some replies carry across commands...such as:
+ * NO_ACCESS "Access denied."
+ * Such things will be marked :)
+ */
+
+
+/* Nick not registered/not active */
+#define ERROR_NOTREG ":%s NOTICE %s :Your nickname is not registered."
+#define ERROR_NOTACTIVE ":%s NOTICE %s :Your nickname is not activated."
+/* Unknown command reply */
+#define ERROR_BADCMD ":%s NOTICE %s :Unknown command %s\r:%s NOTICE %s :Please try \002/MSG %s HELP\002 for assistance"
+/* Incorrect usage reply */
+#define ERROR_BADUSE ":%s NOTICE %s :Incorrect syntax."
+/* Incorrect usage reply for Webbies */
+#define ERROR_BADUSE_WEBTV ":%s PRIVMSG %s :Incorrect syntax."
+/* No access error */
+#define ERROR_ACCESSDENIED ":%s NOTICE %s :Access denied."
+
+/* Database synch thingy */
+#define REPLY_DBSYNCH ":%s NOTICE %s :Next database synch(save) in %d minutes."
+
+/* NickServ ID replies */
+#define NSID_ACCEPT ":%s NOTICE %s :Password accepted. Good to have you back %s!"
+#define NSID_DENY ":%s NOTICE %s :Password incorrect, identification failed."
+/* NickServ SET replies */
+#define NSSET_UNKNOWNFL ":%s NOTICE %s :Unknown setting"
+#define NSSET_NEEDPARAM ":%s NOTICE %s :You must specify a parameter"
+
+#define NSSET_KILLIS ":%s NOTICE %s :Your nick kill is currently %s"
+#define NSSET_KILLON ":%s NOTICE %s :Your nick kill enforcement is now ON"
+#define NSSET_KILLOFF ":%s NOTICE %s :Your nick kill enforcement is now OFF"
+
+#define NSSET_ELONGPASS ":%s NOTICE %s :Please specify a password of 15 or less characters"
+#define NSSET_CHGPASS ":%s NOTICE %s :Your password is now \002%s\002, do not forget it! We are not responsible for lost passwords"
+
+#define NSSET_URLGONE ":%s NOTICE %s :Your URL has been cleared"
+#define NSSET_URLIS ":%s NOTICE %s :Your URL is now: \002%s\002"
+
+#define NSSET_EMAILIS ":%s NOTICE %s :Your email address is currently \002%s\002"
+#define NSSET_EMAILPUB ":%s NOTICE %s :Your email address is now \002public\002"
+#define NSSET_EMAILPRIV ":%s NOTICE %s :Your email address is now \002private\002"
+
+#define NSBANISHMSG "Banished nickname. Please choose another."
+
--- /dev/null
+/* This is where the more crucial defines are done. Don't start messing with
+ * these unless you are sure about what you are doing. Also don't add things
+ * here that are likely to change, such as paths or debug-settings.
+ *
+ * - GZ
+ */
+
+#ifndef __SERVICES_H
+#define __SERVICES_H
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <time.h>
+#include "options.h" /* Include the rest of our settings */
+
+/* Define some standard lengths */
+#define NICKLEN 32
+#define USERLEN 15
+#define HOSTLEN 64
+#define EMAILLEN 80
+#define CHANLEN 33
+#define MEMOLEN 350
+
+/* Hash table defines */
+#define NICKHASHSIZE 6007 /* How many nicks in the hash array */
+#define CHANHASHSIZE 2003 /* How many channels in the hash array */
+#define CHANUSERHASHSIZE 547 /* How many users in a channel */
+#define OPHASHSIZE 547 /* How many ops in a hash entry */
+#define VARHASHSIZE NICKHASHSIZE /* Just leave this the same as nick */
+#define NICKCHANHASHSIZE 10
+#define CLONEHASHSIZE 2003
+
+/* Define structures etc here */
+#define A_AKILL 0x01
+#define A_IGNORE 0x02
+#define A_EXEMPT 0x04
+#define A_HOSTJINX 0x08
+#define CLONE_KILLFLAG 0x01
+#define CLONE_IGNOREFLAG 0x02
+#define CLONE_PERMIGNORE 0x04
+
+typedef struct userlist_struct UserList;
+
+typedef struct service_struct {
+ char name[21];
+ char uname[11];
+ char host[67];
+ char rname[51];
+ char mode[10];
+} Service;
+
+typedef struct database_struct {
+ FILE *ns;
+ FILE *cs;
+ FILE *os;
+ FILE *nsreg;
+ FILE *ms;
+ FILE *w;
+} database;
+
+/* Global function prototypes */
+
+void flushLogs(char *);
+void expireChans(char *);
+void expireNicks(char *);
+void sshutdown(int);
+void srestart(void);
+void disk_synch(void);
+void addUser(char *, char *, char *, char *, char *);
+int listenOnPort(int);
+int ConnectToServer(char *, int);
+struct hostent *resolve(char *);
+struct hostent *lookupHost(char *);
+struct hostent *lookupIP(char *);
+void sSend(char *,...);
+void uSend(char *, UserList *, char *, ...);
+void sockSend(int, char *,...);
+void killUser(Service, UserList *, char *);
+void userMode(UserList *, char *);
+void logDump(FILE *, char *,...);
+int sendMail(char *, char *, char *, char *,...);
+void breakLine(char *);
+void parseLine(char *);
+void segvdie(int);
+int cancel_timer(unsigned int);
+unsigned int timer(long, void (*func) (char *), char *, char *);
+void checktimers(void);
+int breakString(int, char *, char **, char *);
+int match(char *, char *);
+void strtolower(char *);
+char *sfgets(char *, int, FILE *);
+int check_match(char *);
+int exp_match(char *, char *);
+void *smalloc(size_t);
+void sfree(void *);
+char *sstrdup(const char *);
+void list_access_mod(char *from, char type, char *mask);
+void add_access_mod(long length, char *mask, char *by, char type, char *reason);
+void remove_access_mod(char *from, char type, char *mask);
+int find_access_mod(char type, char *mask);
+void save_access_mod();
+void load_access_mod();
+int FreeJinxedHost(char *hostmask, char *from);
+int JinxJinxedHost(char *hostmask, char *by, char *reason);
+int JinxHostMatch(char *nick, char *user, char *host, char *mask);
+int check_mask (char *, int);
+
+/* Global variables */
+
+int antiloop;
+char datadir[512];
+char timerbuff[512];
+char debugbuff[512];
+time_t debugtime;
+time_t timertime;
+char myname[64];
+char mypass[33];
+char hostname[10][64];
+char hostservername[64];
+int port[10];
+int server, synched;
+Service services[20];
+database db;
+FILE *operlog, *nicklog, *chanlog, *corelog, /**servout,*/ *rootlog;
+long totalusers, mostusers, mostnicks, mostchans, mostmemos, ac_mod_counter, startup;
+unsigned int AllocCalled, FreeCalled;
+char *OperServ, *NickServ, *ChanServ, *MemoServ, coreBuffer[512];
+int AccessLimit, OpLimit, AkickLimit, ChanLimit, NickLimit;
+time_t CTime; /* current time, keep this in mind... */
+typedef struct regnicklist_struct RegNickList;
+struct regnicklist_struct *firstRegNick, *lastRegNick;
+struct userlist_struct *firstUser, *lastUser;
+struct nreglist_struct *firstReg, *lastReg;
+struct chanlist_struct *firstChan, *lastChan;
+struct regchanlist_struct *firstRegChan, *lastRegChan;
+typedef struct chanlist_struct ChanList;
+
+#include "stuff.h"
+#include "memoserv.h"
+#include "nickserv.h"
+#include "chanserv.h"
+#include "operserv.h"
+#include "help.h"
+#include "db.h"
+#include "ban.h"
+#include "replies.h"
+#include "webtv.h"
+#include "jinx.h"
+#include "msgtab.h"
+#include "hash.h"
+#include "numeric.h"
+
+UserHashEnt UserHash[NICKHASHSIZE];
+RegNickHashEnt RegNickHash[NICKHASHSIZE];
+ChanHashEnt ChanHash[CHANHASHSIZE];
+RegChanHashEnt RegChanHash[CHANHASHSIZE];
+CloneHashEnt CloneHash[CLONEHASHSIZE];
+
+#ifdef TELNET
+#include "telnet.h"
+ int telnetsock;
+#endif
+
+time_t nextNsync, nextCsync;
+time_t nextMsync;
+
+int cslock,mslock,nslock, pidlock;
+
+char *WebServ;
+char *Serenity;
+
+/*
+ * other MemoServ things you'll need:
+ * MS_DEF_RCV_MAX = The *default* number of memos a max recieved field
+ * will be set to
+ * MS_RCV_MAX_HIGHEST = The highest a USER can set his max received field to
+ * MS_SENT_MAX = The most memos a person can send out per hour.
+ * IRCops are exempt, and forward groups and CSENDS count as 1.
+ */
+
+#define MS_DEF_RCV_MAX 50
+#define MS_RCV_MAX_HIGHEST 200
+#define MS_SENT_MAX 6
+
+#define MAXFLOODLEVEL 100
+#define NICKDROPTIME (30*24*3600)
+#define CHANDROPTIME (30*24*3600)
+#define PASSWARNTIME (60*24*3600)
+#define MEMODROPTIME (10*24*3600)
+#define SYNCTIME (15*60) /* Define time between synchs to disk */
+
+/* SHOWSYNCH - globops each time databases are saves */
+/* SHOWSYNCHALL - notice to users showing how long until next save*/
+
+#undef SHOWSYNCH
+#ifdef SHOWSYNCH
+ #undef SHOWSYNCHALL
+#endif
+
+/*
+ * default clone flags:
+ * 0 for none
+ * CLONE_KILLFLAG to autokill for every host
+ * CLONE_IGNOREFLAG to autoignore for every host
+ * CLONE_PERMTRIGGER to make ALL triggers permanet (including unchaged)
+ *
+ * DEFHOSTCLONETRIGGER = Warning level for clones from *@host
+ * DEFUSERCLONETRIGGER = Warning level for clones from user@host
+ * DEFHOSTILEHOSTCLONES = Akill level for clones from *@host
+ * DEFHOSTILEUSERCLONES = Akill level for clones from user@host
+ */
+
+#define DEFCLONEFLAGS 0
+#define DEFHOSTCLONETRIGGER 5
+#define DEFUSERCLONETRIGGER 3
+#define DEFHOSTILEHOSTCLONES 7
+#define DEFHOSTILEUSERCLONES 5
+
+char retnum[2048];
+
+int ToRecvQ(char *);
+int FromRecvQ(void);
+int ToSendQ(char *);
+int FromSendQ(void);
+
+struct ArecvQ { /* Incoming traffic. */
+ int messages;
+ int length;
+ char buffer[MAXRQ];
+} recvQ;
+
+struct AsendQ { /* Outgoing traffic. */
+ int messages;
+ int length;
+ char buffer[MAXSQ];
+} sendQ;
+
+#define MAXREMOTEID 5 /* Define the maximum remote ID's per nick */
+
+char ftrack[512]; /* To store a function name here */
+
+typedef struct ftrackstruct aftrackstruct;
+
+struct ftrackstruct {
+ unsigned long starttime;
+ char function[512];
+ aftrackstruct *next, *prev;
+};
+
+aftrackstruct ftracklist;
+
+#endif /* __SERVICES_H */
--- /dev/null
+#ifndef __CLONE_H
+#define __CLONE_H
+
+typedef struct userclonestruct UserClone;
+struct userclonestruct {
+ char user[USERLEN];
+ int clones, trigger;
+ UserClone *next, *previous;
+};
+
+typedef struct hostclonestruct HostClone;
+struct hostclonestruct {
+ char host[HOSTLEN];
+ UserClone *firstUser, *lastUser;
+ int trigger;
+ int clones;
+ int flags;
+ HostClone *next, *previous, *hashnext, *hashprev;
+};
+
+typedef struct hostcloneliststruct HostCloneList;
+struct hostcloneliststruct {
+ char host[HOSTLEN];
+ char setby[NICKLEN];
+ time_t setwhen;
+ HostCloneList *next, *prev;
+};
+HostCloneList *firstPermClone;
+
+int addClone(char *, char *, char *);
+void delClone(char *, char *);
+HostClone *getCloneData(char *);
+int addUserClone(HostClone *, char *);
+void delUserClone(HostClone *, UserClone *);
+UserClone *getUserCloneData(HostClone *, char *);
+void initCloneData(HostClone *);
+int killMassClones(char *, char *);
+void loadpermignores();
+void savepermignores();
+
+char *maskchecksum(char *);
+int str2array(char **, char *, char *);
+char *return_user_mask(char *);
+char *maskuser(UserList *);
+char *maskreguser(RegNickList *);
+
+/*
+ * In this structure is where we keep track of all servers that have been linked to us.
+ */
+
+typedef struct Server aServer;
+struct Server {
+ char name[HOSTLEN];
+ char version[NICKLEN*2];
+ int svsnoop;
+ aServer *next, *prev;
+};
+aServer *ServerList;
+
+void AddServer(char *, char *);
+int CheckServer(char *);
+aServer *GetServer(char *);
+void DeleteServer(char *);
+void free_server(aServer *);
+aServer *make_server();
+
+typedef struct Jupe aJupe;
+struct Jupe {
+ char server[HOSTLEN];
+ char juper[NICKLEN];
+ time_t date;
+ char reason[80];
+ int synced;
+ aJupe *next, *prev;
+};
+aJupe *JupeList;
+
+void AddJupe(char *, char *, time_t, char *, int now);
+void DeleteJupe(char *);
+int CheckJupe(char *);
+void sync_jupes(char *doot);
+aJupe *make_jupe();
+void free_jupe(aJupe *);
+
+/*
+ *
+ * In this structure is where we keep all email addresses we dont like.
+ *
+ */
+
+typedef struct Email anEmail;
+struct Email {
+ char email[EMAILLEN];
+ char by[NICKLEN];
+ time_t time;
+ char reason[512];
+ anEmail *next, *prev;
+};
+anEmail *EmailList;
+
+void AddEmail(char *, char *, char *);
+int CheckEmail(char *);
+int VerifyEmail(char *);
+void DeleteEmail(char *);
+void free_email(anEmail *);
+anEmail *make_email();
+void loaddynamicekills();
+void savedynamicekills();
+
+/* New masking stuff */
+extern char *crypt();
+#endif
--- /dev/null
+#ifndef __TELNET_H
+#define __TELNET_H
+
+typedef struct tn_sock_struct {
+ int socket;
+ char readbuf[1024];
+ struct sockaddr_in sa;
+ int lensa;
+ char address[64];
+ time_t connect;
+ time_t lastrcv;
+ time_t loggedin;
+ RegNickList *user;
+} tn_sock;
+
+void checkTelnet(void);
+void initTelnet(void);
+#endif
--- /dev/null
+#ifndef __WEBSERV_H
+# define __WEBSERV_H
+
+/* #define WEBTVCHAN "#WebTV" */
+
+typedef struct badnick_struct BadNickList;
+
+struct badnick_struct {
+ char nickmask[NICKLEN + 2]; /* Allow for '*' in front and end of nick */
+ BadNickList *next, *prev;
+};
+
+void addBadNick(char *nickmask);
+int isBadNick(char *nickmask);
+void sendToWebServ(UserList *, char **, int);
+
+
+#endif /* __WEBSERV_H */
--- /dev/null
+########################################
+# Services Configuration File #
+########################################
+
+MyName Services.Serenity-IRC.Net
+
+# P:port (what port are they *connecting* to)
+Port 0 7827
+
+# W:password (C/N password doohickey)
+LinkPass ServerPass
+
+# C:server (where are we connecting to.)
+ConnectHost 0 127.0.0.1
+
+##############################################################################
+# limits:
+# CL = Registered channel limit
+# NL = Registered nick limit
+# OL = Op Limit (includes founders too!)
+# BL = Akick Limit
+# LL = Access List item limit
+##############################################################################
+
+OpLimit 251
+BanLimit 100
+AccessItemLimit 10
+ChanLimit 5
+NickLimit 5
+
+##############################################################################
+# Services info stuff.
+# O:OperServ N:NickServ C:ChanServ M:MemoServ
+# ?N: Service's name
+# ?U: Service's username
+# ?H: Service's host
+# ?R: Service's realname
+# ?M: Service's mode
+##############################################################################
+### OperServ ###
+OSNick OperServ
+OSUserName Services
+OSHostName Serenity-IRC.Net
+OSRealName Operator Services
+OSUserMode +on
+### NickServ ###
+NSNick NickServ
+NSUserName Services
+NSHostName Serenity-IRC.Net
+NSRealName Nickname Services
+NSUserMode +n
+### ChanServ ###
+CSNick ChanServ
+CSUserName Services
+CSHostName Serenity-IRC.Net
+CSRealName Channel Services
+CSUserMode +n
+### MemoServ ###
+MSNick MemoServ
+MSUserName Services
+MSHostName Serenity-IRC.Net
+MSRealName Memo Services
+MSUserMode +n
+### WebServ ###
+WSNick WebServ
+WSUserName Services
+WSHostName Serenity-IRC.Net
+WSRealname WebTV Services
+WSUserMode +n
+### Global Messenger ###
+GMNick Serenity-IRC
+GMUserName Services
+GMHostName Serenity-IRC.Net
+GMRealname Serenity-IRC Global Messenger
+GMUserMode +on
+
+#############################################################################
+# Network Administrator:
+# Nick MUST be registered, or this has no effect
+# Includes all capabilities of root, naming as root is redundant
+#############################################################################
+NetAdmin Remmy
+#############################################################################
+# Services Root:
+# These nicks MUST be registered, or SRA has NO affect on them
+#############################################################################
+RootAdmin darkk-desires
+RootAdmin NiteHawk
+##############################################################################
+# Channel masks to force +s:
+##############################################################################
+ForceMask #*xxx*
+ForceMask #*sex*
+ForceMask #*w?r?z*
+ForceMask #*p?rn*
+ForceMask #*f?ck*
+ForceMask #*sh?t*
+ForceMask #*cum*
+ForceMask #*fag*
+ForceMask #*cunt*
+ForceMask #*cock*
+ForceMask #*penis*
+ForceMask #*pr?ck*
+ForceMask #*p?x*
+ForceMask #*kabrones*
+#########################################################################
+#Channels to be prohibited entirely
+#########################################################################
+BanChannel #*child*sex*
+BanChannel #*kid*sex*
+BanChannel #*teen*sex*
+BanChannel #*warez*
+BanChannel #*pedo*
--- /dev/null
+0
+0
+0
+0
+22
--- /dev/null
+#include "services.h"
+/*************************************************************************
+ * This file contains functions for enhancing or limiting once access to *
+ * the network. Though it contained specific AKILL only functions before *
+ * they have been rewritten to now support: AKILL, Services Ignore, *
+ * AKILL Exemption and timed jinxes. These functions are all covered by *
+ * the generic term of 'access modifiers'. -- Remmy 06/03/2002 *
+ *************************************************************************/
+static struct access_mod *first_access_mod = NULL;
+
+void auto_remove_access_mod(char *mask_and_type);
+int remove_covered_exempts(char *nick, char *user, char *host);
+
+void list_access_mod(char *from, char type, char *masker)
+{
+ struct access_mod *ac;
+ char mask[NICKLEN + USERLEN + HOSTLEN + 2];
+ char length[16];
+ struct tm *t;
+ char date[20];
+ int found = 0;
+ int phobia = 0; /* Phobia counter */
+
+ if (first_access_mod) {
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (ac->type == type) {
+ if (!found)
+ sSend(":%s NOTICE %s :%-14s %-8s %-20s %-10s %s",
+ OperServ, from, "SetTime", "Length", "Mask",
+ "Set By", "Reason");
+ found++;
+ strcpy(mask, ac->nick);
+ strcat(mask, "!");
+ strcat(mask, ac->user);
+ strcat(mask, "@");
+ strcat(mask, ac->host);
+ t = localtime(&(ac->set));
+ strftime(date, 20, "%m/%d/%y-%I:%M%p", t);
+
+ if (ac->unset)
+ sprintf(length, "%luh",
+ (long) (ac->unset - ac->set) / 3600);
+ else
+ strcpy(length, "forever");
+
+ if (masker) {
+ if (!match(masker, mask))
+ sSend(":%s NOTICE %s :%s %-8s %-20s %-10s %s",
+ OperServ, from, date, length, mask,
+ ac->setby, ac->reason);
+ } else
+ if (match("Phobia bot", ac->reason)) {
+ sSend(":%s NOTICE %s :%s %-8s %-20s %-10s %s",
+ OperServ, from, date, length, mask, ac->setby,
+ ac->reason);
+ } else {
+ phobia++;
+ }
+ }
+ }
+ }
+
+ if (found)
+ if (phobia)
+ sSend(":%s NOTICE %s :End of list. (%d total and %d unlisted phobia bots)",
+ OperServ, from, found, phobia);
+ else
+ sSend(":%s NOTICE %s :End of list. (%d total)", OperServ, from,
+ found);
+ else
+ sSend(":%s NOTICE %s :There are no matching access modifiers.", OperServ, from);
+
+}
+
+struct access_mod *isAKilled(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_AKILL)) {
+ if (!isExempted(nick, user, host))
+ return ac;
+ else
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+struct access_mod *isExempted(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_EXEMPT))
+ return ac;
+ }
+ return NULL;
+}
+
+struct access_mod *isHJinxed(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_HOSTJINX))
+ return ac;
+ }
+ return NULL;
+}
+
+struct access_mod *isIgnored(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_IGNORE))
+ return ac;
+ }
+ return NULL;
+}
+
+void add_access_mod(long length, char *mask, char *by, char type, char *reason)
+{
+ UserList *from;
+ struct access_mod *ac;
+ char *acmask;
+ char *temp1;
+ char *user1 = NULL, *host1 = NULL;
+ char type_and_mask[NICKLEN + USERLEN + HOSTLEN + 3];
+ char sendfrom[256];
+ char subject[256];
+ char temp[12];
+
+ if (strlen(mask) < 5)
+ return;
+
+ if (!check_mask( mask, 1))
+ return;
+
+ ac = smalloc(sizeof(struct access_mod));
+
+ acmask = strdup(mask);
+
+ for (temp1 = acmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user1 = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host1 = temp1 + 1;
+ }
+ }
+
+ if ((!user1) || (!host1)) {
+ sfree(acmask);
+ return;
+ }
+
+ strcpy(ac->nick, acmask);
+ strcpy(ac->user, user1);
+ strcpy(ac->host, host1);
+
+ if (strlen(ac->user) == 1 && strlen(ac->host) == 1) {
+ from = getNickData(by);
+ }
+
+ if (first_access_mod)
+ first_access_mod->prev = ac;
+
+ ac->next = first_access_mod;
+ ac->prev = NULL;
+ first_access_mod = ac;
+
+ strcpy(ac->setby, by);
+
+ ac->set = time(NULL);
+
+ if (length == 0)
+ ac->unset = 0;
+ else
+ ac->unset = ac->set + length;
+
+ ac->type = type;
+ strcpy(ac->reason, reason);
+
+ sprintf(sendfrom, "Operator Services - Kline <%s@%s>", OperServ,
+ NETHOST);
+
+ switch (type) {
+ case A_AKILL:
+ if (match("Phobia bot", reason))
+ sSend(":%s GLOBOPS :%s set akill for %s for %s [%s]", OperServ, by,
+ mask, expand_time(length), reason);
+ sprintf(subject, "AKILL for %s", mask);
+ strcpy(temp, "autokilled");
+ break;
+ case A_EXEMPT:
+ sSend(":%s GLOBOPS :%s set akill exemption for %s for %s [%s]", OperServ, by,
+ mask, expand_time(length), reason);
+ sprintf(subject, "EXEMPT for %s", mask);
+ strcpy(temp, "exempted");
+ break;
+ case A_HOSTJINX:
+ sSend(":%s GLOBOPS :%s set hostjinx for %s for %s [%s]", OperServ, by,
+ mask, expand_time(length), reason);
+ JinxJinxedHost( mask, by, reason);
+ sprintf(subject, "HOSTJINX for %s", mask);
+ strcpy(temp, "hostjinxed");
+ break;
+ case A_IGNORE:
+ sSend(":%s GLOBOPS :%s set ignore for %s for %s [%s]", OperServ,
+ by, mask, expand_time(length), reason);
+ sprintf(subject, "IGNORE for %s", mask);
+ strcpy(temp, "ignored");
+ break;
+ }
+
+ if (type == A_AKILL && !strcmp(ac->nick, "*"))
+ sSend(":%s AKILL %s %s :K-lined for %s [%s]", myname, ac->host,
+ ac->user, expand_time(length), ac->reason);
+ else if (type == A_EXEMPT && !strcmp(ac->nick, "*"))
+ sSend(":%s AKILLEX %s %s :Exempted for %s [%s]", myname, ac->host,
+ ac->user, expand_time(length), ac->reason);
+ else if (type == A_HOSTJINX)
+ AddJinx(ac->nick, "OperServ", ac->reason);
+
+ if (ac->unset) {
+ type_and_mask[0] = type;
+ strcpy(&type_and_mask[1], mask);
+ ac->tid = timer(length, auto_remove_access_mod, "auto_remove_access_mod", type_and_mask);
+ }
+ else
+ ac->tid = 0;
+
+ if (type != A_HOSTJINX)
+ sendMail(AKILLMAILTO, sendfrom, subject,
+ "%s was %s by %s for %s\nReason: %s\nSet at %s", mask, temp,
+ ac->setby, expand_time(length), reason, ctime(&(ac->set)));
+
+ sfree(acmask);
+}
+
+void remove_access_mod(char *from, char type, char *mask)
+{
+ char *temp1;
+ struct access_mod *ac;
+ char *nick, *user = NULL, *host = NULL, *oldmask;
+ char sendfrom[256], subject[256];
+ time_t temp;
+ int removed;
+
+ if (strlen(mask) < 5)
+ return;
+
+ if (!check_mask( mask, 1))
+ return;
+
+ oldmask = strdup(mask);
+
+ nick = oldmask;
+
+ for (temp1 = oldmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host = temp1 + 1;
+ }
+ }
+
+ if ((!user) || (!host))
+ return;
+
+ sprintf(sendfrom, "Operator Services <%s@%s>", OperServ,
+ NETHOST);
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+
+ if (!strcmp(host, ac->host) && !strcmp(user, ac->user)
+ && !strcmp(nick, ac->nick) && ac->type == type) {
+
+ if (ac->type == A_AKILL) {
+ sprintf(subject, "Removal of AKILL for %s", mask);
+ if (match("Phobia bot", ac->reason))
+ sSend(":%s GLOBOPS :%s is removing akill %s.", OperServ,
+ from, mask);
+ logDump(operlog, "%s removed akill %s", from, mask);
+ } else if (ac->type == A_EXEMPT) {
+ sprintf(subject, "Removal of AKILL EXEMPT for %s", mask);
+ sSend(":%s GLOBOPS :%s is removing exemption %s.", OperServ,
+ from, mask);
+ logDump(operlog, "%s removed exemption %s", from, mask);
+ } else if (ac->type == A_HOSTJINX) {
+ sprintf(subject, "Removal of HOSTJINX for %s", mask);
+ sSend(":%s GLOBOPS :%s is removing hostjinx %s.", OperServ,
+ from, mask);
+ logDump(operlog, "%s removed hostjinx %s", from, mask);
+ } else {
+ sprintf(subject, "Removal of IGNORE for %s", mask);
+ sSend(":%s GLOBOPS :%s is removing ignore %s.", OperServ,
+ from, mask);
+ logDump(operlog, "%s removed ignore %s", from, mask);
+ }
+
+ temp = time(NULL);
+
+ if (ac->type != A_HOSTJINX)
+ sendMail(AKILLMAILTO, sendfrom, subject,
+ "%s removed access modifier %s at %s", from, mask,
+ ctime(&temp));
+
+ if (ac->prev)
+ ac->prev->next = ac->next;
+ if (ac->next)
+ ac->next->prev = ac->prev;
+ if (ac == first_access_mod)
+ first_access_mod = ac->next;
+
+ if (ac->type == A_AKILL && !strcmp(nick, "*"))
+ sSend(":%s RAKILL %s %s", myname, ac->host, ac->user);
+ else if (ac->type == A_EXEMPT && !strcmp(nick, "*"))
+ sSend(":%s RAKILLEX %s %s", myname, ac->host, ac->user);
+/*
+ * Fun fact: If OperServ is removing the autokill, the timer is up, and
+ * it shouldn't be canceled, or two timers will be cancelled...
+ */
+ if (strcmp(from, OperServ)) {
+ if (ac->type == A_AKILL)
+ sSend(":%s NOTICE %s :AutoKill %s removed", OperServ, from, mask);
+ else if (ac->type == A_EXEMPT)
+ sSend(":%s NOTICE %s :Exempt %s removed", OperServ, from, mask);
+ else if (ac->type == A_HOSTJINX)
+ sSend(":%s NOTICE %s :Hostjinx %s removed", OperServ, from, mask);
+ else
+ sSend(":%s NOTICE %s :Ignore %s removed", OperServ, from, mask);
+ cancel_timer(ac->tid);
+ }
+
+ if (ac->type == A_AKILL) {
+ removed = remove_covered_exempts(ac->nick, ac->user, ac->host);
+ if (removed > 0) {
+ sSend(":%s GLOBOPS :Auto removed %d matching exempt(s).",
+ OperServ, removed);
+ }
+ }
+
+ /* A place to check for jinxed users from a HOSTJINX */
+ if (ac->type == A_HOSTJINX)
+ FreeJinxedHost(mask, from);
+
+ sfree(ac);
+ sfree(oldmask);
+ return;
+ }
+ }
+
+ if (strcmp(from, OperServ))
+ sSend(":%s NOTICE %s :Access modifier %s not found", OperServ,
+ from, mask);
+
+ sfree(oldmask);
+}
+
+/* This function removes exempts when an akill is removed. Its purpose is
+ * to keep the access modifier list clean from exempts that serve no longer
+ * any purpose. The number of exempts removed is returned to the calling
+ * function. -- Remmy 20020619 */
+int remove_covered_exempts(char *nick, char *user, char *host)
+{
+ struct access_mod *ac, *ac_tmp;
+ int counter = 0;
+
+ ac = first_access_mod;
+ while (ac) {
+ if (!match(ac->host, host) && !match(ac->user, user)
+ && !match(ac->nick, nick) && ac->type == A_EXEMPT) {
+ if (ac->prev)
+ ac->prev->next = ac->next;
+ if (ac->next)
+ ac->next->prev = ac->prev;
+ if (ac == first_access_mod)
+ first_access_mod = ac->next;
+
+ ac_tmp = ac;
+ ac = ac->next;
+
+ sfree(ac_tmp);
+ counter++;
+ } else {
+ ac = ac->next;
+ }
+ }
+
+ return counter;
+}
+
+void send_matching_exempts(char *nick, char *user, char *host) {
+
+ struct access_mod *ex;
+
+ for (ex = first_access_mod; ex; ex = ex->next)
+ if (!match(ex->host, host) && !match(ex->user, user)
+ && !match(ex->nick, nick) && ex->type == A_EXEMPT)
+ sSend(":%s AKILLEX %s %s :Exempted for %s [%s]", myname,
+ ex->host, ex->user, expand_time(ex->unset), ex->reason);
+
+ return;
+}
+
+int find_access_mod(char type, char *mask)
+{
+ char *temp1;
+ struct access_mod *ac;
+ char *nick, *user = NULL, *host = NULL, *oldmask;
+
+ oldmask = strdup(mask);
+
+ nick = oldmask;
+
+ for (temp1 = oldmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host = temp1 + 1;
+ }
+ }
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!strcmp(host, ac->host) && !strcmp(user, ac->user)
+ && !strcmp(nick, ac->nick) && (type == ac->type)) {
+ sfree(oldmask);
+ return 1;
+ }
+ }
+ sfree(oldmask);
+ return 0;
+}
+
+/* This function only gets called by the timer function when an access mode
+ * is to expire. As the timer can only be set with a single argument to the
+ * function it is to call I had to put both the access mode type and the
+ * mask to apply it to into a single string to pass as argument. I know it
+ * is not pretty, but it will have to do for now. -- Remmy 17/03/2002 */
+void auto_remove_access_mod(char *mask_and_type)
+{
+ char *mask;
+ char type;
+
+ /* Extract access mode type and mask to apply it to */
+ type = mask_and_type[0];
+ mask = mask_and_type + 1;
+
+ remove_access_mod(OperServ, type, mask);
+}
+
+void save_access_mod()
+{
+ FILE *acsave;
+ struct access_mod *ac;
+
+ acsave = fopen(DBDIR "/access_mod.db", "w");
+ if (acsave == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open acces_mod db"));
+ return;
+ }
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ fputs("-\n", acsave);
+ fputs(ac->nick, acsave);
+ fputs("\n", acsave);
+ fputs(ac->user, acsave);
+ fputs("\n", acsave);
+ fputs(ac->host, acsave);
+ fputs("\n", acsave);
+ fprintf(acsave, "%lu %lu\n", (long) ac->set, (long) ac->unset);
+ fputs(ac->setby, acsave);
+ fputs("\n", acsave);
+ fputs(ac->reason, acsave);
+ fputs("\n", acsave);
+ fprintf(acsave, "%d\n", ac->type);
+ }
+ fclose(acsave);
+}
+
+void load_access_mod()
+{
+ FILE *acload;
+ struct access_mod *ac;
+ char buffer[256], mask[NICKLEN + USERLEN + HOSTLEN + 2];
+ int i = 1, t, expired = 0, count = 0;
+ long length;
+ time_t start;
+
+ first_access_mod = NULL;
+
+ start = time(NULL);
+
+ acload = fopen(DBDIR "/access_mod.db", "r");
+
+ if (!acload) {
+ return;
+ }
+
+ while (sfgets(buffer, 256, acload)) {
+/*
+ * Check for sync
+ */
+ if (strcmp(buffer, "-") != 0) {
+ sSend(":%s GLOBOPS :Sync error in access_mod.db near line %d",
+ OperServ, i);
+ fprintf(corelog, "Sync error in access_mod.db near line %d\n", i);
+ fclose(acload);
+ return;
+ }
+
+ ac = smalloc(sizeof(struct access_mod));
+
+ fscanf(acload, "%s\n", ac->nick);
+ fscanf(acload, "%s\n", ac->user);
+ fscanf(acload, "%s\n", ac->host);
+/*
+ sfgets(ac->nick, NICKLEN, acload);
+ sfgets(ac->user, USERLEN, acload);
+ sfgets(ac->host, HOSTLEN, acload);
+*/
+ fscanf(acload, "%lu %lu\n", (long *) &(ac->set),
+ (long *) &(ac->unset));
+ sfgets(ac->setby, NICKLEN, acload);
+ sfgets(ac->reason, 80, acload);
+ fscanf(acload, "%d\n", &t);
+ ac->type = t;
+ ac->tid = 0;
+
+ strcpy(mask, ac->nick);
+ strcat(mask, "!");
+ strcat(mask, ac->user);
+ strcat(mask, "@");
+ strcat(mask, ac->host);
+
+ count++;
+ length = 0;
+
+ if (ac->unset)
+ length = ac->unset - ac->set;
+
+ if ((start < ac->unset) || (ac->unset == 0)) {
+ if (ac->unset)
+ ac->tid =
+ timer((ac->unset - start), auto_remove_access_mod,
+ "auto_remove_access_mod", mask);
+
+ if ((ac->type == A_AKILL) && (!strcmp(ac->nick, "*")))
+ sSend(":%s AKILL %s %s :K-lined for %s [%s]", myname,
+ ac->host, ac->user, expand_time(length), ac->reason);
+
+ ac->next = first_access_mod;
+ ac->prev = NULL;
+ if (ac->next)
+ ac->next->prev = ac;
+ first_access_mod = ac;
+ } else { /* IT'S EXPIRED, REALLY! */
+ if (ac->type == A_AKILL)
+ sSend(":%s RAKILL %s %s", myname, ac->host, ac->user);
+ expired++;
+ sfree(ac);
+ }
+ }
+ fclose(acload);
+}
--- /dev/null
+
+# Which compiler
+CC=gcc
+
+# Include files
+INCLUDE=../include
+
+# Install location
+INSTDIR=../services
+
+# Compiler flags
+CFLAGS=-O -Wall
+
+all: services
+
+services: akill.o ban.o chanserv.o db.o hash.o help.o jinx.o main.o msgtab.o \
+ memoserv.o numeric.o newmalloc.o nickserv.o operserv.o server.o \
+ stuff.o timer.o webtv.o
+ $(CC) $(LDFLAGS) -o services akill.o ban.o chanserv.o db.o hash.o help.o jinx.o \
+ main.o msgtab.o memoserv.o numeric.o newmalloc.o nickserv.o operserv.o server.o \
+ stuff.o timer.o webtv.o
+
+akill.o: akill.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c akill.c
+ban.o: ban.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c ban.c
+chanserv.o: chanserv.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c chanserv.c
+db.o: db.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c db.c
+hash.o: hash.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c hash.c
+help.o: help.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c help.c
+jinx.o: jinx.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c jinx.c
+main.o: main.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
+msgtab.o: msgtab.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c msgtab.c
+memoserv.o: memoserv.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c memoserv.c
+numeric.o: numeric.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c numeric.c
+newmalloc.o: newmalloc.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c newmalloc.c
+nickserv.o: nickserv.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c nickserv.c
+operserv.o: operserv.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c operserv.c
+server.o: server.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c server.c
+stuff.o: stuff.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c stuff.c
+timer.o: timer.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c timer.c
+webtv.o: webtv.c
+ $(CC) -I$(INCLUDE) $(CFLAGS) -c webtv.c
+
+clean:
+ $(RM) -f *.o *~ *.sav *.save services
--- /dev/null
+#include "services.h"
+/*************************************************************************
+ * This file contains functions for enhancing or limiting ones access to *
+ * the network. Though it contained specific AKILL only functions before *
+ * they have been rewritten to now support: AKILL, Services Ignore, *
+ * AKILL Exemption and timed jinxes. These functions are all covered by *
+ * the generic term of 'access modifiers'. -- Remmy 06/03/2002 *
+ *************************************************************************/
+static struct access_mod *first_access_mod = NULL;
+
+void auto_remove_access_mod(char *mask_and_type);
+int remove_covered_exempts(char *nick, char *user, char *host);
+
+void list_access_mod(char *from, char type, char *masker)
+{
+ struct access_mod *ac;
+ char mask[NICKLEN + USERLEN + HOSTLEN + 2];
+ char length[16];
+ struct tm *t;
+ char date[20];
+ int found = 0;
+
+ if (first_access_mod) {
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (ac->type == type) {
+ if (!found)
+ sSend(":%s NOTICE %s :%-10s %-14s %-8s %-20s %-10s %s",
+ OperServ, from, "ID", "SetTime", "Length", "Mask",
+ "Set By", "Reason");
+ found++;
+ strcpy(mask, ac->nick);
+ strcat(mask, "!");
+ strcat(mask, ac->user);
+ strcat(mask, "@");
+ strcat(mask, ac->host);
+ t = localtime(&(ac->set));
+ strftime(date, 20, "%m/%d/%y-%I:%M%p", t);
+
+ if (ac->unset)
+ sprintf(length, "%luh",
+ (long) (ac->unset - ac->set) / 3600);
+ else
+ strcpy(length, "forever");
+
+ if (masker) {
+ if (!match(masker, mask) || atoi(&masker[1]) == ac->id)
+ sSend(":%s NOTICE %s :#%-9d %s %-8s %-20s %-10s %s",
+ OperServ, from, ac->id, date, length, mask,
+ ac->setby, ac->reason);
+ } else
+ sSend(":%s NOTICE %s :#%-9d %s %-8s %-20s %-10s %s",
+ OperServ, from, ac->id, date, length, mask,
+ ac->setby, ac->reason);
+ }
+ }
+ }
+
+ if (found)
+ sSend(":%s NOTICE %s :End of list. (%d total)", OperServ, from, found);
+}
+
+struct access_mod *isAKilled(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_AKILL)) {
+ if (!isExempted(nick, user, host))
+ return ac;
+ else
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+struct access_mod *isExempted(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_EXEMPT))
+ return ac;
+ }
+ return NULL;
+}
+
+struct access_mod *isHJinxed(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_HOSTJINX))
+ return ac;
+ }
+ return NULL;
+}
+
+struct access_mod *isIgnored(char *nick, char *user, char *host)
+{
+ struct access_mod *ac;
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!match(nick, ac->nick) && !match(user, ac->user)
+ && !match(host, ac->host) && (ac->type == A_IGNORE))
+ return ac;
+ }
+ return NULL;
+}
+
+void add_access_mod(long length, char *mask, char *by, char type, char *reason)
+{
+ UserList *from;
+ struct access_mod *ac;
+ char *acmask;
+ char *temp1;
+ char *user1 = NULL, *host1 = NULL;
+ char type_and_mask[NICKLEN + USERLEN + HOSTLEN + 4];
+
+ if (strlen(mask) < 5)
+ return;
+
+ if (!check_mask( mask, 1))
+ return;
+
+ ac = smalloc(sizeof(struct access_mod));
+
+ acmask = strdup(mask);
+
+ for (temp1 = acmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user1 = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host1 = temp1 + 1;
+ }
+ }
+
+ if ((!user1) || (!host1)) {
+ sfree(acmask);
+ return;
+ }
+
+ strcpy(ac->nick, acmask);
+ strcpy(ac->user, user1);
+ strcpy(ac->host, host1);
+ ac->id = ++ac_mod_counter;
+
+ if (strlen(ac->user) == 1 && strlen(ac->host) == 1) {
+ from = getNickData(by);
+ }
+
+ if (first_access_mod)
+ first_access_mod->prev = ac;
+
+ ac->next = first_access_mod;
+ ac->prev = NULL;
+ first_access_mod = ac;
+
+ strcpy(ac->setby, by);
+
+ ac->set = time(NULL);
+
+ if (length == 0)
+ ac->unset = 0;
+ else
+ ac->unset = ac->set + length;
+
+ ac->type = type;
+ strcpy(ac->reason, reason);
+
+ switch (type) {
+ case A_AKILL:
+ sSend(":%s GLOBOPS :%s set akill for %s for %s [#%ld: %s]", OperServ,
+ by, mask, expand_time(length), ac->id, reason);
+ break;
+ case A_EXEMPT:
+ sSend(":%s GLOBOPS :%s set akill exemption for %s for %s [#%d: %s]",
+ OperServ, by, mask, expand_time(length), ac->id, reason);
+ break;
+ case A_HOSTJINX:
+ sSend(":%s GLOBOPS :%s set hostjinx for %s for %s [%s]", OperServ, by,
+ mask, expand_time(length), reason);
+ JinxJinxedHost( mask, by, reason);
+ break;
+ case A_IGNORE:
+ sSend(":%s GLOBOPS :%s set ignore for %s for %s [%s]", OperServ,
+ by, mask, expand_time(length), reason);
+ break;
+ }
+
+ if (type == A_AKILL && !strcmp(ac->nick, "*"))
+ sSend(":%s AKILL %s %s :K-lined for %s [#%d: %s]", myname, ac->host,
+ ac->user, expand_time(length), ac_mod_counter, ac->reason);
+ else if (type == A_EXEMPT && !strcmp(ac->nick, "*"))
+ sSend(":%s AKILLEX %s %s :Exempted for %s [%s]", myname, ac->host,
+ ac->user, expand_time(length), ac->reason);
+ else if (type == A_HOSTJINX && match(ac->nick, "*"))
+ AddJinx(ac->nick, by, ac->reason);
+
+ if (ac->unset) {
+ type_and_mask[0] = type;
+ strcpy(&type_and_mask[1], mask);
+ ac->tid = timer(length, auto_remove_access_mod, "auto_remove_access_mod", type_and_mask);
+ }
+ else
+ ac->tid = 0;
+
+ sfree(acmask);
+}
+
+void remove_access_mod(char *from, char type, char *mask)
+{
+ char *temp1;
+ struct access_mod *ac;
+ char *nick = NULL, *user = NULL, *host = NULL, *oldmask = NULL;
+ char tempmask[NICKLEN + USERLEN + HOSTLEN + 2];
+ time_t temp;
+ int removed, id = 0;
+
+ if (mask[0] == '#') {
+ id = atoi(&mask[1]);
+ nick = mask;
+ user = mask;
+ host = mask;
+ } else {
+ if (strlen(mask) < 5)
+ return;
+
+ if (!check_mask( mask, 1))
+ return;
+
+ oldmask = strdup(mask);
+
+ nick = oldmask;
+
+
+ for (temp1 = oldmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host = temp1 + 1;
+ }
+ }
+
+ if ((!user) || (!host))
+ return;
+ }
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+
+ if ((!strcmp(host, ac->host) && !strcmp(user, ac->user)
+ && !strcmp(nick, ac->nick) && ac->type == type) ||
+ (ac->id == id && ac->type == type)) {
+
+ if (id > 0) {
+ strcpy(tempmask, ac->nick);
+ strcat(tempmask, "!");
+ strcat(tempmask, ac->user);
+ strcat(tempmask, "@");
+ strcat(tempmask, ac->host);
+
+ mask = tempmask;
+ }
+
+ if (ac->type == A_AKILL) {
+ sSend(":%s GLOBOPS :%s is removing akill #%d %s.", OperServ,
+ from, ac->id, mask);
+ logDump(operlog, "%s removed akill #%d %s", from, ac->id, mask);
+ } else if (ac->type == A_EXEMPT) {
+ sSend(":%s GLOBOPS :%s is removing exemption #%d %s.",
+ OperServ, from, ac->id, mask);
+ logDump(operlog, "%s removed exemption #%d %s", from, ac->id,
+ mask);
+ } else if (ac->type == A_HOSTJINX) {
+ sSend(":%s GLOBOPS :%s is removing hostjinx #%d %s.", OperServ,
+ from, ac->id, mask);
+ logDump(operlog, "%s removed hostjinx #%d for %s", from,
+ ac->id, mask);
+ } else {
+ sSend(":%s GLOBOPS :%s is removing ignore #%d %s.",
+ OperServ, from, ac->id, mask);
+ logDump(operlog, "%s removed ignore #%d %s", from, ac->id,
+ mask);
+ }
+
+ temp = time(NULL);
+
+ if (ac->prev)
+ ac->prev->next = ac->next;
+ if (ac->next)
+ ac->next->prev = ac->prev;
+ if (ac == first_access_mod)
+ first_access_mod = ac->next;
+
+ if (ac->type == A_AKILL && !strcmp(ac->nick, "*"))
+ sSend(":%s RAKILL %s %s", myname, ac->host, ac->user);
+ else if (ac->type == A_EXEMPT && !strcmp(ac->nick, "*"))
+ sSend(":%s RAKILLEX %s %s", myname, ac->host, ac->user);
+/*
+ * Fun fact: If OperServ is removing the autokill, the timer is up, and
+ * it shouldn't be canceled, or two timers will be cancelled...
+ */
+ if (strcmp(from, OperServ)) {
+ if (ac->type == A_AKILL)
+ sSend(":%s NOTICE %s :AutoKill %s removed", OperServ, from, mask);
+ else if (ac->type == A_EXEMPT)
+ sSend(":%s NOTICE %s :Exempt %s removed", OperServ, from, mask);
+ else if (ac->type == A_HOSTJINX)
+ sSend(":%s NOTICE %s :Hostjinx %s removed", OperServ, from, mask);
+ else
+ sSend(":%s NOTICE %s :Ignore %s removed", OperServ, from, mask);
+ cancel_timer(ac->tid);
+ }
+
+ if (ac->type == A_AKILL) {
+ removed = remove_covered_exempts(ac->nick, ac->user, ac->host);
+ if (removed > 0) {
+ sSend(":%s GLOBOPS :Auto removed %d matching exempt(s).",
+ OperServ, removed);
+ }
+ }
+
+ /* A place to check for jinxed users from a HOSTJINX */
+ if (ac->type == A_HOSTJINX)
+ FreeJinxedHost(mask, from);
+
+ sfree(ac);
+ sfree(oldmask);
+ return;
+ }
+ }
+
+ if (strcmp(from, OperServ))
+ sSend(":%s NOTICE %s :Access modifier %s not found", OperServ,
+ from, mask);
+
+ sfree(oldmask);
+}
+
+/* This function removes exempts when an akill is removed. Its purpose is
+ * to keep the access modifier list clean from exempts that serve no longer
+ * any purpose. The number of exempts removed is returned to the calling
+ * function. -- Remmy 20020619 */
+int remove_covered_exempts(char *nick, char *user, char *host)
+{
+ struct access_mod *ac, *ac_tmp;
+ int counter = 0;
+
+ ac = first_access_mod;
+ while (ac) {
+ if (!match(ac->host, host) && !match(ac->user, user)
+ && !match(ac->nick, nick) && ac->type == A_EXEMPT) {
+ if (ac->prev)
+ ac->prev->next = ac->next;
+ if (ac->next)
+ ac->next->prev = ac->prev;
+ if (ac == first_access_mod)
+ first_access_mod = ac->next;
+
+ ac_tmp = ac;
+ ac = ac->next;
+
+ sfree(ac_tmp);
+ counter++;
+ } else {
+ ac = ac->next;
+ }
+ }
+
+ return counter;
+}
+
+void send_matching_exempts(char *nick, char *user, char *host) {
+
+ struct access_mod *ex;
+
+ for (ex = first_access_mod; ex; ex = ex->next)
+ if (!match(ex->host, host) && !match(ex->user, user)
+ && !match(ex->nick, nick) && ex->type == A_EXEMPT)
+ sSend(":%s AKILLEX %s %s :Exempted for %s [%s]", myname,
+ ex->host, ex->user, expand_time(ex->unset), ex->reason);
+
+ return;
+}
+
+int find_access_mod(char type, char *mask)
+{
+ char *temp1;
+ struct access_mod *ac;
+ char *nick, *user = NULL, *host = NULL, *oldmask;
+
+ oldmask = strdup(mask);
+
+ nick = oldmask;
+
+ for (temp1 = oldmask; *temp1; temp1++) {
+ if (*temp1 == '!') {
+ *temp1 = 0;
+ user = temp1 + 1;
+ }
+ if (*temp1 == '@') {
+ *temp1 = 0;
+ host = temp1 + 1;
+ }
+ }
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ if (!strcmp(host, ac->host) && !strcmp(user, ac->user)
+ && !strcmp(nick, ac->nick) && (type == ac->type)) {
+ sfree(oldmask);
+ return 1;
+ }
+ }
+ sfree(oldmask);
+ return 0;
+}
+
+/* This function only gets called by the timer function when an access mode
+ * is to expire. As the timer can only be set with a single argument to the
+ * function it is to call I had to put both the access mode type and the
+ * mask to apply it to into a single string to pass as argument. I know it
+ * is not pretty, but it will have to do for now. -- Remmy 17/03/2002 */
+void auto_remove_access_mod(char *mask_and_type)
+{
+ char *mask;
+ char type;
+
+ /* Extract access mode type and mask to apply it to */
+ type = mask_and_type[0];
+ mask = mask_and_type + 1;
+
+ remove_access_mod(OperServ, type, mask);
+}
+
+void save_access_mod()
+{
+ FILE *acsave;
+ struct access_mod *ac;
+
+ acsave = fopen(DBDIR "/access_mod.db", "w");
+ if (acsave == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open acces_mod db"));
+ return;
+ }
+
+ for (ac = first_access_mod; ac; ac = ac->next) {
+ fputs("-\n", acsave);
+ fputs(ac->nick, acsave);
+ fputs("\n", acsave);
+ fputs(ac->user, acsave);
+ fputs("\n", acsave);
+ fputs(ac->host, acsave);
+ fputs("\n", acsave);
+ fprintf(acsave, "%lu %lu\n", (long) ac->set, (long) ac->unset);
+ fputs(ac->setby, acsave);
+ fputs("\n", acsave);
+ fputs(ac->reason, acsave);
+ fputs("\n", acsave);
+ fprintf(acsave, "%d\n", ac->type);
+ fputs("\n", acsave);
+ fprintf(acsave, "%d\n", ac->id);
+ }
+ fclose(acsave);
+}
+
+void load_access_mod()
+{
+ FILE *acload;
+ struct access_mod *ac;
+ char buffer[256], mask[NICKLEN + USERLEN + HOSTLEN + 3];
+ char type_and_mask[NICKLEN + USERLEN + HOSTLEN + 4];
+ int i = 1, t, expired = 0, count = 0;
+ long length;
+ time_t start;
+
+ first_access_mod = NULL;
+
+ start = time(NULL);
+
+ acload = fopen(DBDIR "/access_mod.db", "r");
+
+ if (!acload) {
+ return;
+ }
+
+ while (sfgets(buffer, 256, acload)) {
+/*
+ * Check for sync
+ */
+ if (strcmp(buffer, "-") != 0) {
+ sSend(":%s GLOBOPS :Sync error in access_mod.db near line %d",
+ OperServ, i);
+ fprintf(corelog, "Sync error in access_mod.db near line %d\n", i);
+ fclose(acload);
+ return;
+ }
+
+ ac = smalloc(sizeof(struct access_mod));
+
+ fscanf(acload, "%s\n", ac->nick);
+ fscanf(acload, "%s\n", ac->user);
+ fscanf(acload, "%s\n", ac->host);
+ fscanf(acload, "%lu %lu\n", (long *) &(ac->set),
+ (long *) &(ac->unset));
+ sfgets(ac->setby, NICKLEN, acload);
+ sfgets(ac->reason, 80, acload);
+ fscanf(acload, "%d\n", &t);
+ ac->type = (char) t;
+ fscanf(acload, "%d\n", &t);
+ ac->id = t;
+ if (ac->id > ac_mod_counter)
+ ac_mod_counter = ac->id;
+ ac->tid = 0;
+
+ strcpy(mask, ac->nick);
+ strcat(mask, "!");
+ strcat(mask, ac->user);
+ strcat(mask, "@");
+ strcat(mask, ac->host);
+
+ count++;
+ length = 0;
+
+ if (ac->unset)
+ length = ac->unset - start;
+
+ if ((start < ac->unset) || (ac->unset == 0)) {
+ if (ac->unset) {
+ type_and_mask[0] = ac->type;
+ strcpy(&type_and_mask[1], mask);
+ ac->tid = timer(length, auto_remove_access_mod,
+ "auto_remove_access_mod", type_and_mask);
+ }
+
+ if ((ac->type == A_AKILL) && (!strcmp(ac->nick, "*")))
+ sSend(":%s AKILL %s %s :K-lined for %s [%s]", myname,
+ ac->host, ac->user, expand_time(length), ac->reason);
+
+ ac->next = first_access_mod;
+ ac->prev = NULL;
+ if (ac->next)
+ ac->next->prev = ac;
+ first_access_mod = ac;
+ } else { /* IT'S EXPIRED, REALLY! */
+ if (ac->type == A_AKILL)
+ sSend(":%s RAKILL %s %s", myname, ac->host, ac->user);
+ expired++;
+ sfree(ac);
+ }
+ }
+ fclose(acload);
+}
--- /dev/null
+#include "services.h"
+
+void mask(char *user, char *host, int type, char *where)
+{
+ char *blah2 = NULL;
+
+ blah2 = index(host, '.');
+
+ /*
+ * make sure there's more than one '.' in the name
+ */
+ if (blah2) {
+ if (strlen(blah2) > 4) {
+ if ((is_ip_address(host)) == 1) {
+ blah2 = host;
+ blah2 = rindex(blah2, '.');
+ blah2[1] = '*';
+ blah2[2] = '\0';
+ } else {
+ host = index(host, '.');
+ host -= 1;
+ host[0] = '*';
+ }
+ }
+ }
+ if (!type)
+ sprintf(where, "%s@%s", user, host);
+ else
+ sprintf(where, "*%s@%s", user, host);
+}
+
+int is_ip_address(char *host)
+{
+ char *blah = NULL;
+
+ blah = host;
+ blah = rindex(blah, '.');
+ blah += 1;
+ if (blah[0] == '0' || blah[0] == '1' || blah[0] == '2'
+ || blah[0] == '3' || blah[0] == '4' || blah[0] == '5'
+ || blah[0] == '6' || blah[0] == '7' || blah[0] == '8'
+ || blah[0] == '9') {
+ return 1;
+ } else {
+ return 0;
+ }
+}
--- /dev/null
+/* 2481 */
+
+#include "services.h"
+
+/* Some small macro to check if a channel name is valid. -GZ */
+#define IsChannelName(name) ((name) && ((*(name) == '#')))
+
+void indexAkickItems (RegChanList *);
+void indexOpItems (RegChanList *);
+
+/* all these are ONLY for channel linked list funcs */
+int isFounder (RegChanList *, UserList *);
+void makeModeLockStr (RegChanList *, char *);
+void banKick (ChanList *, UserList *, char *, ...);
+int countRegChans (char *);
+void remfromallchanops (char *);
+char *showchanoplevel (int);
+
+void createGhostChannel (char *);
+void deleteGhostChannel (char *);
+
+void doRegChanMode (RegChanList *);
+
+int locmp (const void *, const void *);
+int locmpl (const void *, const void *);
+
+
+/* This one will massdeop a channel, no questions asked */
+void CSmassdeop (char *);
+
+int check_wildcard (char *);
+
+/* THIS FUNCTION MAKES SURE A HOSTMASK CONTAINS MORE THAN JUST WILDCARDS */
+/* RETURNS 1 IF IT DOES, 0 IF IT DOES NOT */
+/* INPUT STRING MUST BE NULL TERMINATED */
+
+int
+check_wildcard (char *mask)
+{
+ char *temp1;
+ int foundflag = 0;
+
+ for (temp1 = mask; *temp1; temp1++)
+ {
+ if ((*temp1 != '.') && (*temp1 != '*') && (*temp1 != '?'))
+ {
+ foundflag = 1;
+ break;
+ }
+ }
+ return (foundflag);
+}
+
+/* THIS FUNCTION CHECKS A HOSTMASK FOR VALIDITY */
+/* *!*@* IS NOT ALLOWED */
+/* RETURNS 1 IF GOOD, 0 IF FAULT */
+
+int
+check_mask (char *maskin, int allow_wild)
+{
+ char *nick;
+ char *user = NULL;
+ char *host = NULL;
+ char *tmp;
+ char mask[NICKLEN + USERLEN + HOSTLEN + 2];
+ int valid;
+
+ if ((!maskin) || (!(*maskin))
+ || (strlen (maskin) > NICKLEN + USERLEN + HOSTLEN + 2))
+ return 0;
+
+ strcpy (mask, maskin);
+
+ if (!strchr (mask, '!') || !strchr (mask, '@'))
+ return 0;
+
+ /* a mask of the format *@*!* will core services at this point so this */
+ /* is to check for that format of mask */
+ if (strchr (mask, '!') > strchr (mask, '@'))
+ return 0;
+
+ nick = mask;
+
+ for (tmp = mask; *tmp; tmp++)
+ {
+ if (*tmp == '!')
+ {
+ if ((!user) && (!host))
+ {
+ *tmp = 0;
+ user = tmp + 1;
+ }
+ }
+ if (*tmp == '@')
+ {
+ if ((!host) && (user))
+ {
+ *tmp = 0;
+ host = tmp + 1;
+ }
+ }
+ }
+
+ if (!strlen (nick) || (!strlen (user)) || (!strlen (host)))
+ return 0;
+
+ if (strchr (user, '!') || strchr (user, '@') || strchr (host, '!')
+ || strchr (host, '@'))
+ return 0;
+
+ if (allow_wild)
+ return 1;
+ else
+ {
+ valid =
+ check_wildcard (nick) + check_wildcard (user) + check_wildcard (host);
+
+ if (!valid)
+ return 0;
+ else
+ return 1;
+ }
+}
+
+/* The following bunch of functions all deal with channels and registered
+ * ones, ignore them unless you need to fiddle with the linked lists for
+ * channels. */
+void
+addChan (ChanList * newchan)
+{
+ long hashEnt = getHashKey (newchan->name) % CHANHASHSIZE;
+
+ if (getChanData (newchan->name))
+ {
+ sfree (newchan);
+ return;
+ }
+
+ if (!firstChan)
+ {
+ firstChan = newchan;
+ newchan->previous = NULL;
+ }
+ else
+ {
+ lastChan->next = newchan;
+ newchan->previous = lastChan;
+ }
+ lastChan = newchan;
+ newchan->next = NULL;
+
+ if (!ChanHash[hashEnt].chan)
+ {
+ ChanHash[hashEnt].chan = newchan;
+ newchan->hashprev = NULL;
+ }
+ else
+ {
+ ChanHash[hashEnt].lastchan->hashnext = newchan;
+ newchan->hashprev = ChanHash[hashEnt].lastchan;
+ }
+
+ ChanHash[hashEnt].lastchan = newchan;
+ newchan->hashnext = NULL;
+}
+
+void
+addRegChan (RegChanList * newchan)
+{
+ long hashEnt = getHashKey (newchan->name) % CHANHASHSIZE;
+
+ if (getRegChanData (newchan->name))
+ {
+ sfree (newchan);
+ return;
+ }
+
+ if (!firstRegChan)
+ {
+ firstRegChan = newchan;
+ newchan->previous = NULL;
+ }
+ else
+ {
+ lastRegChan->next = newchan;
+ newchan->previous = lastRegChan;
+ }
+ lastRegChan = newchan;
+ newchan->next = NULL;
+
+ if (!RegChanHash[hashEnt].chan)
+ {
+ RegChanHash[hashEnt].chan = newchan;
+ newchan->hashprev = NULL;
+ }
+ else
+ {
+ RegChanHash[hashEnt].lastchan->hashnext = newchan;
+ newchan->hashprev = RegChanHash[hashEnt].lastchan;
+ }
+
+ RegChanHash[hashEnt].lastchan = newchan;
+ newchan->hashnext = NULL;
+}
+
+void
+addChanUser (ChanList * channel, cNickList * newnick)
+{
+ if (!channel->firstUser)
+ {
+ channel->firstUser = newnick;
+ newnick->previous = NULL;
+ }
+ else
+ {
+ channel->lastUser->next = newnick;
+ newnick->previous = channel->lastUser;
+ }
+
+ channel->lastUser = newnick;
+ newnick->next = NULL;
+
+}
+
+/* add someone to the channel ban list */
+void
+addChanBan (ChanList * channel, cBanList * item)
+{
+ if (!channel->firstBan)
+ {
+ channel->firstBan = item;
+ item->previous = NULL;
+ }
+ else
+ {
+ channel->lastBan->next = item;
+ item->previous = channel->lastBan;
+ }
+
+ channel->lastBan = item;
+ item->next = NULL;
+}
+
+/* add someone to the channel exempt list */
+void
+addChanExempt (ChanList * channel, cBanList * item)
+{
+ if (!channel->firstExempt)
+ {
+ channel->firstExempt = item;
+ item->previous = NULL;
+ }
+ else
+ {
+ channel->lastExempt->next = item;
+ item->previous = channel->lastExempt;
+ }
+
+ channel->lastExempt = item;
+ item->next = NULL;
+}
+
+
+/* add someone to the channel akick list */
+void
+addChanAkick (RegChanList * channel, cAkickList * item)
+{
+ if (!channel->firstAkick)
+ {
+ channel->firstAkick = item;
+ item->previous = NULL;
+ }
+ else
+ {
+ channel->lastAkick->next = item;
+ item->previous = channel->lastAkick;
+ }
+
+ channel->lastAkick = item;
+ item->next = NULL;
+ channel->akicks++;
+ indexAkickItems (channel);
+}
+
+/* add someone to the channel 'access list' */
+void
+addChanOp (RegChanList * channel, cAccessList * item)
+{
+ if (!channel->firstOp)
+ {
+ channel->firstOp = item;
+ item->previous = NULL;
+ }
+ else
+ {
+ channel->lastOp->next = item;
+ item->previous = channel->lastOp;
+ }
+ channel->lastOp = item;
+ item->next = NULL;
+ channel->ops++;
+ indexOpItems (channel);
+}
+
+/* remove a channel from the channel list, and close it up where necessary */
+void
+delChan (ChanList * killme)
+{
+ long hashEnt;
+ ChanList *tmpchan;
+
+ if (killme->previous)
+ killme->previous->next = killme->next;
+ else
+ firstChan = killme->next;
+ if (killme->next)
+ killme->next->previous = killme->previous;
+ else
+ lastChan = killme->previous;
+
+ hashEnt = getHashKey (killme->name) % CHANHASHSIZE;
+ for (tmpchan = ChanHash[hashEnt].chan; tmpchan; tmpchan = tmpchan->hashnext)
+ {
+ if (tmpchan == killme)
+ {
+ if (killme->hashprev)
+ killme->hashprev->hashnext = killme->hashnext;
+ else
+ ChanHash[hashEnt].chan = killme->hashnext;
+ if (killme->hashnext)
+ killme->hashnext->hashprev = killme->hashprev;
+ else
+ ChanHash[hashEnt].lastchan = killme->hashprev;
+ }
+ }
+
+ while (killme->firstUser)
+ delChanUser (killme, killme->lastUser);
+ while (killme->firstBan)
+ delChanBan (killme, killme->lastBan);
+
+ sfree (killme);
+}
+
+void
+delRegChan (RegChanList * killme)
+{
+ long hashEnt;
+ RegChanList *tmpchan;
+
+ if (killme->previous)
+ killme->previous->next = killme->next;
+ else
+ firstRegChan = killme->next;
+ if (killme->next)
+ killme->next->previous = killme->previous;
+ else
+ lastRegChan = killme->previous;
+
+ hashEnt = getHashKey (killme->name) % CHANHASHSIZE;
+ for (tmpchan = RegChanHash[hashEnt].chan; tmpchan;
+ tmpchan = tmpchan->hashnext)
+ {
+ if (tmpchan == killme)
+ {
+ if (killme->hashprev)
+ killme->hashprev->hashnext = killme->hashnext;
+ else
+ RegChanHash[hashEnt].chan = killme->hashnext;
+ if (killme->hashnext)
+ killme->hashnext->hashprev = killme->hashprev; /* AAAAAHHHHAAAA!!! */
+ else
+ RegChanHash[hashEnt].lastchan = killme->hashprev;
+ }
+ }
+ while (killme->firstOp)
+ delChanOp (killme, killme->lastOp);
+ while (killme->firstAkick)
+ delChanAkick (killme, killme->lastAkick);
+
+ sfree (killme);
+}
+
+/* now delete the user from the channel, gee is this easy or what? no. :> */
+void
+delChanUser (ChanList * channel, cNickList * nick)
+{
+ if (!nick)
+ return;
+ if (nick->previous)
+ nick->previous->next = nick->next;
+ else
+ channel->firstUser = nick->next;
+ if (nick->next)
+ nick->next->previous = nick->previous;
+ else
+ channel->lastUser = nick->previous;
+
+ sfree (nick);
+}
+
+/* remove channel ban */
+void
+delChanBan (ChanList * channel, cBanList * item)
+{
+ if (item->previous)
+ item->previous->next = item->next;
+ else
+ channel->firstBan = item->next;
+ if (item->next)
+ item->next->previous = item->previous;
+ else
+ channel->lastBan = item->previous;
+
+ sfree (item);
+}
+
+/* remove channel exempt */
+void
+delChanExempt (ChanList * channel, cBanList * item)
+{
+ if (item->previous)
+ item->previous->next = item->next;
+ else
+ channel->firstExempt = item->next;
+ if (item->next)
+ item->next->previous = item->previous;
+ else
+ channel->lastExempt = item->previous;
+
+ sfree (item);
+}
+
+
+/* remove channel akick */
+void
+delChanAkick (RegChanList * channel, cAkickList * item)
+{
+ if (item->previous)
+ item->previous->next = item->next;
+ else
+ channel->firstAkick = item->next;
+ if (item->next)
+ item->next->previous = item->previous;
+ else
+ channel->lastAkick = item->previous;
+
+ sfree (item);
+ channel->akicks--;
+ indexAkickItems (channel);
+}
+
+/* remove channel ban */
+void
+delChanOp (RegChanList * channel, cAccessList * item)
+{
+ if (item->previous)
+ item->previous->next = item->next;
+ else
+ channel->firstOp = item->next;
+ if (item->next)
+ item->next->previous = item->previous;
+ else
+ channel->lastOp = item->previous;
+
+ sfree (item);
+ channel->ops--;
+ indexOpItems (channel);
+}
+
+/* find a channel in the list, return NULL if its not found */
+ChanList *getChanData(char *name)
+{
+ long hashEnt;
+ ChanList *tmpchan;
+ char *tmpname;
+
+ if (!name)
+ return NULL;
+
+ /* if a '#' or '&' are not present assume '#' */
+ if (*name != '#' && *name != '&') {
+ tmpname = (char *) smalloc(strlen(name) + 2);
+ sprintf(tmpname, "#%s", name);
+ } else {
+ tmpname = (char *) smalloc(strlen(name) + 1);
+ sprintf(tmpname, "%s", name);
+ }
+
+ hashEnt = getHashKey(tmpname) % CHANHASHSIZE;
+
+
+ if (ChanHash[hashEnt].chan) {
+ for (tmpchan = ChanHash[hashEnt].chan; tmpchan;
+ tmpchan = tmpchan->hashnext) {
+ if (!strcasecmp(tmpchan->name, tmpname)) {
+ sfree(tmpname);
+ return tmpchan;
+ }
+ }
+ }
+ sfree(tmpname);
+ return NULL;
+}
+
+RegChanList *getRegChanData(char *name)
+{
+ long hashEnt;
+ RegChanList *tmpchan;
+ char *tmpname;
+
+ if (!name)
+ return NULL;
+
+ /* if a '#' or '&' are not present assume '#' */
+ if (*name != '#' && *name != '&') {
+ tmpname = (char *) smalloc(strlen(name) + 2);
+ sprintf(tmpname, "#%s", name);
+ } else {
+ tmpname = (char *) smalloc(strlen(name) + 1);
+ sprintf(tmpname, "%s", name);
+ }
+
+ hashEnt = getHashKey(tmpname) % CHANHASHSIZE;
+
+ if (RegChanHash[hashEnt].chan) {
+ for (tmpchan = RegChanHash[hashEnt].chan; tmpchan;
+ tmpchan = tmpchan->hashnext) {
+ if (!strcasecmp(tmpchan->name, tmpname)) {
+ sfree(tmpname);
+ return tmpchan;
+ }
+ }
+ }
+
+ sfree(tmpname);
+ return NULL;
+}
+
+cNickList *
+getChanUserData (ChanList * chan, UserList * data)
+{
+ if (!data || !chan)
+ return NULL;
+ else
+ {
+ cNickList *tmpnick;
+ for (tmpnick = chan->firstUser; tmpnick; tmpnick = tmpnick->next)
+ {
+ if (tmpnick->person == data)
+ return tmpnick;
+ }
+ return NULL;
+ }
+}
+
+int
+getChanOp (RegChanList * chan, char *nick)
+{
+ int highest;
+ UserList *tmp;
+ cAccessList *tmpnick;
+ nLinkList *tmp2;
+
+ if (!nick || !chan)
+ return 0;
+
+ tmp = getNickData (nick);
+
+ if (tmp == NULL)
+ return 0;
+
+ highest = 0;
+
+ if (chan->flags & CIDENT)
+ {
+ UserList *check = getNickData (nick);
+ if (check && check->reg)
+ {
+ if (check->caccess == 3)
+ {
+ tmpnick = getChanOpData (chan, nick);
+ if (tmpnick)
+ highest = tmpnick->uflags;
+ }
+ }
+ }
+ else
+ {
+ if (tmp->caccess > 1 && (tmpnick = getChanOpData (chan, nick)))
+ highest = tmpnick->uflags;
+ else
+ {
+ for (tmpnick = chan->firstOp; tmpnick; tmpnick = tmpnick->next)
+ {
+ if (checkAccess
+ (tmp->user, tmp->host, getRegNickData (tmpnick->nick)) == 1)
+ {
+ if (highest < tmpnick->uflags)
+ highest = tmpnick->uflags;
+ }
+ }
+ }
+ }
+
+ /* And now for the remote ID's -GZ */
+
+ if (tmp->linked)
+ {
+ for (tmp2 = tmp->firstLink; tmp2; tmp2 = tmp2->next)
+ {
+ tmpnick = getChanOpData (chan, tmp2->nick);
+ if (tmpnick)
+ if (tmpnick->uflags > highest)
+ highest = tmpnick->uflags;
+ }
+ }
+
+ if (!highest)
+ {
+ cAkickList *tmpak;
+ char hostmask[HOSTLEN + USERLEN + NICKLEN];
+ sprintf (hostmask, "%s!%s@%s", tmp->nick, tmp->user, tmp->host);
+ for (tmpak = chan->firstAkick; tmpak; tmpak = tmpak->next)
+ {
+ if (!match (hostmask, tmpak->mask))
+ {
+ highest = -1;
+ break;
+ }
+ }
+ }
+ return highest;
+}
+
+cAccessList *
+getChanOpData (RegChanList * chan, char *nick)
+{
+ if (!nick || !chan)
+ return NULL;
+
+ else
+ {
+ cAccessList *tmpnick;
+ for (tmpnick = chan->firstOp; tmpnick; tmpnick = tmpnick->next)
+ {
+ if (!strcasecmp (tmpnick->nick, nick))
+ {
+ return tmpnick;
+ }
+ }
+ return NULL;
+ }
+}
+
+cBanList *
+getChanBan (ChanList * chan, char *ban)
+{
+ cBanList *tmp;
+
+ if (!chan || !ban)
+ return NULL;
+
+ for (tmp = chan->firstBan; tmp; tmp = tmp->next)
+ {
+ if (!strcasecmp (ban, tmp->ban))
+ return tmp;
+ }
+ return NULL;
+}
+
+cBanList *
+getChanExempt (ChanList * chan, char *ban)
+{
+ cBanList *tmp;
+
+ if (!chan || !ban)
+ return NULL;
+
+ for (tmp = chan->firstExempt; tmp; tmp = tmp->next)
+ {
+ if (!strcasecmp (ban, tmp->ban))
+ return tmp;
+ }
+ return NULL;
+}
+
+cAkickList *
+getChanAkick (RegChanList * chan, char *akick)
+{
+ cAkickList *tmp;
+
+ if (!chan || !akick)
+ return NULL;
+ for (tmp = chan->firstAkick; tmp; tmp = tmp->next)
+ {
+ if (!strcasecmp (akick, tmp->mask))
+ return tmp;
+ }
+ return NULL;
+}
+
+void
+indexAkickItems (RegChanList * chan)
+{
+ cAkickList *tmp;
+ int i = 1;
+ for (tmp = chan->firstAkick; tmp; tmp = tmp->next)
+ {
+ tmp->index = i;
+ i++;
+ }
+}
+
+void
+indexOpItems (RegChanList * chan)
+{
+ cAccessList *tmp;
+ int i = 1;
+ for (tmp = chan->firstOp; tmp; tmp = tmp->next)
+ {
+ tmp->index = i;
+ i++;
+ }
+}
+
+int
+isFounder (RegChanList * chan, UserList * nick)
+{
+ char *from = nick->nick;
+
+/* RETURNS 0 ON FAIL, 1 FOR TRUE FOUNDER MATCH, 2 FOR SERVICES OVERRIDE */
+
+ if (nick->caccess < 3)
+ return 0;
+
+ if ((!strcasecmp (chan->founder, from)) && (nick->caccess > 2))
+ return 1;
+ else if (isRoot (nick))
+ return 2;
+ else
+ return 0;
+}
+
+int
+countRegChans (char *nick)
+{
+/* THIS FUNCTION COUNTS THE TOTAL CHANNELS REGISTERED TO <NICK> */
+/* USES LITTLE MORE CPU, BUT IT'S WORTH THE EXPENSE */
+
+ RegChanList *tmp;
+ int total_count = 0;
+
+ for (tmp = firstRegChan; tmp; tmp = tmp->next)
+ {
+ if (!strcasecmp (tmp->founder, nick))
+ total_count++;
+ }
+ return total_count;
+}
+
+void
+remfromallchanops (char *nick)
+{
+/* THIS FUNCTION WILL REMOVED A SPECIFIED NICK FROM ALL CHANNEL ACCESS LISTS */
+/* IF NICK IS CHANNEL FOUNDER, CHANNEL WILL BE EXPIRED */
+
+ RegChanList *tmpchan, *nextchan;
+ cAccessList *tmpop, *nextop;
+ int need_new_founder;
+ RegNickList *new_founder;
+
+ for (tmpchan = firstRegChan; tmpchan; tmpchan = nextchan)
+ {
+ nextchan = tmpchan->next;
+
+ need_new_founder = 0;
+
+ if (!strcasecmp (tmpchan->founder, nick)) /* LOST THE FOUNDER, FIND ANOTHER OR EXPIRE */
+ need_new_founder = 1;
+
+ for (tmpop = tmpchan->firstOp; tmpop; tmpop = nextop)
+ {
+ nextop = tmpop->next;
+ if (!strcasecmp (tmpop->nick, nick)) /* FOUND HIM */
+ delChanOp (tmpchan, tmpop);
+ else
+ {
+ if ((need_new_founder) && (tmpop->uflags == FOUNDER))
+ {
+ new_founder = getRegNickData (tmpop->nick);
+ if ((new_founder) && (new_founder->flags & NACTIVE)
+ && (new_founder->chans < (unsigned int) ChanLimit))
+ {
+ need_new_founder = 0;
+ strcpy (tmpchan->founder, tmpop->nick);
+ tmpop->uflags = FOUNDER;
+ new_founder->chans++;
+ logDump (chanlog, "%s FOUNDER LOST, TRANSFERRED TO %s.",
+ tmpchan->name, tmpop->nick);
+ }
+ }
+ }
+ }
+
+ if ((!tmpchan->ops) || (need_new_founder))
+ {
+ if (tmpchan->flags & CCLOSED)
+ {
+ cAccessList *newone;
+
+ newone = getChanOpData (tmpchan, "Serenity");
+ if (!newone)
+ {
+ newone = smalloc (sizeof (cAccessList));
+ strcpy (newone->nick, "Serenity");
+ addChanOp (tmpchan, newone);
+ }
+
+ newone->uflags = FOUNDER;
+
+ strcpy (tmpchan->founder, "Serenity");
+
+ logDump (chanlog,
+ "%s HAS FOUNDER EXPIRED OR DELETED WHILE BEING IN A CLOSED STATE",
+ tmpchan->name);
+ }
+ else
+ {
+ ChanList *ick;
+ ick = getChanData (tmpchan->name);
+ if (ick)
+ ick->reg = NULL;
+ logDump (chanlog, "%s EXPIRE (FOUNDER EXPIRED OR DELETED)",
+ tmpchan->name);
+ delRegChan (tmpchan);
+ mostchans--;
+ }
+ }
+ }
+}
+
+char *
+showchanoplevel (int level)
+{
+/* SHOWS A FRIENDLY TEXT VERSION OF THE INTERNAL CHANOP LEVELS */
+/* RETURNS POINTER TO TEMP STRING - DESTROYED ON CONSECUTIVE CALLS */
+
+ static char retstr[20];
+ char tempstr[6];
+
+ strcpy (retstr, "AKICK");
+ if (level >= OPNONE)
+ strcpy (retstr, "NORMAL");
+ if (level >= MAOP)
+ strcpy (retstr, "VOICE");
+ if (level >= AOP)
+ strcpy (retstr, "AOP");
+ if (level >= MSOP)
+ strcpy (retstr, "MSOP");
+ if (level >= SOP)
+ strcpy (retstr, "SOP");
+ if (level >= MFOUNDER)
+ strcpy (retstr, "COFOUNDER");
+ if (level == FOUNDER)
+ strcpy (retstr, "FOUNDER");
+
+ sprintf (tempstr, " (%i)", level);
+ strcat (retstr, tempstr);
+
+ return ((char *) retstr);
+}
+
+void
+initChanData (ChanList * chan)
+{
+ bzero (chan->name, CHANLEN);
+ chan->firstBan = chan->lastBan = NULL;
+ chan->firstUser = chan->lastUser = NULL;
+ chan->modes = 0;
+ chan->reg = NULL;
+ chan->next = chan->previous = NULL;
+}
+
+void
+initRegChanData (RegChanList * chan)
+{
+ bzero (chan->name, CHANLEN);
+ bzero (chan->founder, NICKLEN);
+ chan->facc = 0;
+ bzero (chan->desc, 101);
+ bzero (chan->topic, 307);
+ bzero (chan->tsetby, NICKLEN);
+ bzero (chan->url, 128);
+ bzero (chan->password, 16);
+ chan->ttimestamp = 0;
+ chan->mlock = 0;
+ chan->flags = 0;
+ chan->timereg = 0;
+ chan->timestamp = 0;
+ bzero (chan->key, 23);
+ chan->limit = 0;
+ chan->ops = 0;
+ chan->akicks = 0;
+ chan->tlocklevel = 0;
+ chan->restrictlevel = 0;
+ chan->firstOp = chan->lastOp = NULL;
+ chan->firstAkick = chan->lastAkick = NULL;
+}
+
+void
+sendToChanOps (ChanList * chan, char *format, ...)
+{
+ char buffer[512];
+ va_list stuff;
+ cNickList *tmp;
+
+ if (!chan || (chan->reg && chan->reg->flags & CQUIET))
+ return;
+
+ va_start (stuff, format);
+ vsprintf (buffer, format, stuff);
+
+ for (tmp = chan->firstUser; tmp; tmp = tmp->next)
+ {
+ if (tmp->op)
+ {
+ uSend (ChanServ, tmp->person,
+ GetReply (RPL_TOCHANOPS, tmp->person), chan->name, buffer);
+ }
+ }
+}
+
+void
+banKick (ChanList * chan, UserList * nick, char *format, ...)
+{
+ char user[USERLEN], host[HOSTLEN], theirmask[USERLEN + HOSTLEN + 3];
+ char buffer[256];
+ va_list stuff;
+ cBanList *tmpban;
+
+ strcpy (user, nick->user);
+ strcpy (host, nick->host);
+
+ mask (user, host, 1, theirmask);
+
+ sSend (":%s MODE %s +b %s", ChanServ, chan->name, theirmask);
+ tmpban = smalloc (sizeof (cBanList));
+ strcpy (tmpban->ban, theirmask);
+ addChanBan (chan, tmpban);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Added ban %s on %s", myname, theirmask, chan->name);
+#endif
+ va_start (stuff, format);
+ vsprintf (buffer, format, stuff);
+
+ sSend (":%s KICK %s %s :%s", ChanServ, chan->name, nick->nick, buffer);
+ remUserFromChan (nick, chan->name);
+}
+
+
+void
+createGhostChannel (char *chan)
+{
+ sSend (":%s JOIN %s", ChanServ, chan);
+ sSend (":%s MODE %s +o %s", ChanServ, chan, ChanServ);
+ sSend (":%s MODE %s +sil 1", ChanServ, chan);
+}
+
+void
+deleteGhostChannel (char *chan)
+{
+ sSend (":%s MODE %s -sil", ChanServ, chan);
+ sSend (":%s PART %s", ChanServ, chan);
+}
+
+void
+makeModeLockStr (RegChanList * chan, char *modelock)
+{
+ char *p = modelock;
+ memset (modelock, ' ', 20);
+
+ if (chan->
+ mlock & (PM_I | PM_L | PM_K | PM_M | PM_N | PM_P | PM_S | PM_T |
+ PM_C | PM_R))
+ {
+ *p++ = '+';
+ if (chan->mlock & PM_I)
+ *p++ = 'i';
+ if (chan->mlock & PM_L)
+ *p++ = 'l';
+ if (chan->mlock & PM_K)
+ *p++ = 'k';
+ if (chan->mlock & PM_M)
+ *p++ = 'm';
+ if (chan->mlock & PM_N)
+ *p++ = 'n';
+ if ((chan->mlock & PM_P)
+ &&
+ (!((isForced
+ (chan->name) || (chan->flags & CFORCES))
+ && !(chan->flags & CFEXEMPT))))
+ *p++ = 'p';
+ if (chan->mlock & PM_S)
+ *p++ = 's';
+ if (chan->mlock & PM_T)
+ *p++ = 't';
+ if (chan->mlock & PM_C)
+ *p++ = 'c';
+ if (chan->mlock & PM_R)
+ *p++ = 'R';
+ }
+ if (chan->
+ mlock & (MM_I | MM_L | MM_K | MM_M | MM_N | MM_P | MM_S | MM_T |
+ MM_C | MM_R))
+ {
+ *p++ = '-';
+ if (chan->mlock & MM_I)
+ *p++ = 'i';
+ if (chan->mlock & MM_L)
+ *p++ = 'l';
+ if (chan->mlock & MM_K)
+ *p++ = 'k';
+ if (chan->mlock & MM_M)
+ *p++ = 'm';
+ if (chan->mlock & MM_N)
+ *p++ = 'n';
+ if (chan->mlock & MM_P)
+ *p++ = 'p';
+ if ((chan->mlock & MM_S)
+ &&
+ (!((isForced
+ (chan->name) || (chan->flags & CFORCES))
+ && !(chan->flags & CFEXEMPT))))
+ *p++ = 's';
+ if (chan->mlock & MM_T)
+ *p++ = 't';
+ if (chan->mlock & MM_C)
+ *p++ = 'c';
+ if (chan->mlock & MM_R)
+ *p++ = 'R';
+ }
+
+ *p++ = 0;
+}
+
+/* add a user to a channel, fun...really */
+void
+addUserToChan (UserList * nick, char *channel)
+{
+ char chan[CHANLEN];
+ int a = 0, exempt = 0;
+ ChanList *tmp;
+ cNickList *person;
+
+ if (*channel == ':')
+ channel++;
+
+ while (*channel)
+ {
+ bzero (chan, CHANLEN);
+ a = 0;
+ while ((*channel) && (*channel != ','))
+ {
+ chan[a] = *channel;
+ a++;
+ channel++;
+ }
+ chan[a] = 0;
+ if (*channel)
+ channel++;
+
+ if (chan[0] == '0')
+ remFromAllChans (nick);
+ else if (chan[0] != '+')
+ {
+ tmp = getChanData (chan);
+
+ if ((!tmp) || (!tmp->firstUser))
+ {
+ /* FIRST USER IN CHANNEL */
+
+ /* INSERT NEW CHANNEL INTO INTERNAL LIST */
+ if (!tmp)
+ {
+ tmp = smalloc (sizeof (ChanList));
+ initChanData (tmp);
+ strncpy (tmp->name, chan, CHANLEN);
+ addChan (tmp);
+ }
+
+ person = smalloc (sizeof (cNickList));
+ person->person = nick;
+ person->op = 0;
+
+ addChanUser (tmp, person);
+
+ if (isBanChannel (tmp->name))
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :Channel is not permitted on this network.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Created channel %s, added %s to it",
+ myname, chan, nick->nick);
+#endif
+
+ tmp->reg = getRegChanData (chan);
+
+ /* new closed channels check -GZ */
+
+ if (tmp->reg && tmp->reg->flags & CCLOSED)
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :This channel has been \002CLOSED\002 by the Serenity-IRC administration.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ if ((isForced (tmp->name)
+ || (tmp->reg && tmp->reg->flags & CFORCES))
+ && !(tmp->reg && tmp->reg->flags & CFEXEMPT))
+ {
+ sSend (":%s MODE %s +s", ChanServ, tmp->name);
+ uSend (ChanServ, nick, GetReply (RPL_AUTOSET_S, nick));
+ if (tmp->reg)
+ tmp->reg->flags |= CPRIVATE;
+ }
+ /* IF THE CHANNEL IS REGISTERED -- CHECK OUT THE REGISTRATION DATA */
+ if (tmp->reg)
+ {
+ char mode[20];
+
+ /* OPS/BANS LIST */
+ a = getChanOp (tmp->reg, nick->nick);
+
+ /* Thou shall not akick servops */
+ if (!isServop (nick))
+ {
+ char reason[500];
+ if (a == -1)
+ { /* IS AKICKED? */
+ cAkickList *blah;
+ char userhost[NICKLEN + USERLEN + HOSTLEN];
+
+ sprintf (userhost, "%s!%s@%s", nick->nick,
+ nick->user, nick->host);
+ for (blah = tmp->reg->firstAkick; blah;
+ blah = blah->next)
+ {
+ if (!match (userhost, blah->mask))
+ {
+ cBanList *newban;
+ newban = smalloc (sizeof (cBanList));
+ sSend (":%s MODE %s +b %s", ChanServ,
+ chan, blah->mask);
+ strcpy (newban->ban, blah->mask);
+ sprintf (reason,
+ "You have been permanently banned by ");
+ strcat (reason, blah->reason);
+ addChanBan (tmp, newban);
+ break;
+ }
+ }
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel,
+ "deleteGhostChannel", tmp->name);
+ sSend (":%s KICK %s %s :%s.", ChanServ, chan,
+ nick->nick, reason);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ if ((tmp->reg->restrictlevel != 0)
+ && ((a < tmp->reg->restrictlevel)
+ || (!a
+ && ((tmp->reg->mlock & PM_K)
+ || (tmp->reg->mlock & PM_I)))))
+ {
+ /* IS BELOW RESTRICT LEVEL */
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ if (!isServop (nick))
+ {
+// banKick(tmp, nick, "This channel is restricted to level %i and above", tmp->reg->restrictlevel);
+ banKick (tmp, nick,
+ "Sorry. This is a restricted access channel.");
+ }
+ return;
+ }
+
+ if (a && a < AOP && !(tmp->reg->flags & CCLASSIC)
+ && !(tmp->reg->flags & CFREEZE))
+ {
+ /* IS A VOICED OP +v */
+ if (synched)
+ {
+ sSend (":%s MODE %s +v %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+ person->op |= CHANVOICE;
+ tmp->reg->timestamp = CTime;
+ }
+ else if (a && a >= AOP
+ && !(tmp->reg->flags & CCLASSIC)
+ && !(tmp->reg->flags & CFREEZE))
+ {
+ /* IS AUTO-OPPED */
+ if (synched)
+ {
+ sSend (":%s MODE %s +o %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+ person->op |= CHANOP;
+ tmp->reg->timestamp = CTime;
+ /* This will let Webbies know they are getting ops */
+ if (nick->webbie && synched)
+ sSend
+ (":%s PRIVMSG %s :You are now a channel operator in %s.",
+ NickServ, nick->nick, tmp->name);
+
+ }
+
+ if ((tmp->reg->flags & CKTOPIC) && (tmp->reg->topic[0])
+ && !(tmp->reg->flags & CFREEZE))
+ /* IF KEEPTOPIC - RESTORE SAVED TOPIC */
+ sSend (":%s TOPIC %s %s %lu :%s", ChanServ,
+ tmp->name, tmp->reg->tsetby,
+ tmp->reg->ttimestamp, tmp->reg->topic);
+
+ /* ChanServ will now enforce that absolutely nobody but SO's get ops */
+
+ if ((tmp->reg->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick,
+ GetReply (RPL_NOOPSFROZEN, nick));
+ sSend (":%s MODE %s -o %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+
+ makeModeLockStr (tmp->reg, mode);
+ doRegChanMode (tmp->reg);
+
+ if ((tmp->reg->flags & CNOTICE) && (tmp->reg->desc[0]))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANDESC, nick),
+ tmp->name, tmp->reg->desc);
+ }
+ }
+ else
+ /* Unregistered channel... limit the users that can join... */
+ sSend (":%s MODE %s +l 5", ChanServ, tmp->name);
+ }
+ else
+ {
+ /* NOT FIRST USER IN CHANNEL */
+
+ person = getChanUserData (tmp, nick);
+
+ tmp->reg = getRegChanData (chan);
+
+ if (person)
+ delChanUser (tmp, person);
+
+ person = smalloc (sizeof (cNickList));
+ person->person = nick;
+ person->op = 0;
+ addChanUser (tmp, person);
+
+ /* new closed channels check -GZ */
+
+ if (tmp->reg && tmp->reg->flags & CCLOSED)
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :This channel has been \002CLOSED\002 by the Serenity-IRC administration.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ if (tmp->reg)
+ {
+ a = getChanOp (tmp->reg, nick->nick);
+ /* IS AKICKED?? */
+ /* Thou shall not akick servops */
+ if (!isServop (nick))
+ {
+ if (a == -1)
+ {
+ cAkickList *blah;
+ char userhost[NICKLEN + USERLEN + HOSTLEN + 3];
+ char reason[500];
+
+ sprintf (userhost, "%s!%s@%s", nick->nick,
+ nick->user, nick->host);
+ for (blah = tmp->reg->firstAkick; blah;
+ blah = blah->next)
+ {
+ if (!match (userhost, blah->mask))
+ {
+ /* See if we have an exempt in place */
+ cBanList *newban;
+ cBanList *tmpex;
+
+ for (tmpex = tmp->firstExempt; tmpex;
+ tmpex = tmpex->next) {
+ if (!match (userhost, tmpex->ban)) {
+ exempt = 1;
+ break; /* User is exempted */
+ }
+ }
+
+ if (!exempt) {
+ newban = smalloc (sizeof (cBanList));
+ sSend (":%s MODE %s +b %s", ChanServ,
+ chan, blah->mask);
+ strcpy (newban->ban, blah->mask);
+ strcpy (reason, blah->reason);
+ addChanBan (tmp, newban);
+ break;
+ }
+ }
+ }
+ if (!exempt) {
+ sSend (":%s KICK %s %s :%s", ChanServ, chan,
+ nick->nick, reason);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+ }
+
+ if (a < tmp->reg->restrictlevel
+ && tmp->reg->restrictlevel != 0)
+ {
+ /* BELOW RESTRICT LEVEL */
+ if (!isServop (nick))
+ {
+// banKick(tmp, nick, "This channel is restricted to level %i+", tmp->reg->restrictlevel);
+ banKick (tmp, nick,
+ "Sorry. This is a restricted access channel.");
+
+ }
+ return;
+ }
+ if (a && a < AOP && !(tmp->reg->flags & CCLASSIC)
+ && !(tmp->reg->flags & CFREEZE))
+ {
+ /* AUTO VOICE woo */
+ if (synched)
+ sSend (":%s MODE %s +v %s", ChanServ, tmp->name,
+ nick->nick);
+ person->op |= CHANVOICE;
+ tmp->reg->timestamp = CTime;
+ }
+ else if (a && a >= AOP
+ && !(tmp->reg->flags & CCLASSIC)
+ && !(tmp->reg->flags & CFREEZE))
+ {
+ /* AUTO OP woo */
+ if (synched)
+ sSend (":%s MODE %s +o %s", ChanServ, tmp->name,
+ nick->nick);
+ person->op |= CHANOP;
+ tmp->reg->timestamp = CTime;
+
+ /* This will let Webbies know they are getting ops */
+ if (nick->webbie)
+ sSend
+ (":%s PRIVMSG %s :You are now a channel operator in %s.",
+ WebServ, nick->nick, tmp->name);
+ }
+
+ /* Make sure nobody gets ops */
+
+ if ((tmp->reg->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick,
+ GetReply (RPL_NOOPSFROZEN, nick));
+ sSend (":%s MODE %s -o %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+
+ if ((tmp->reg->flags & CNOTICE) && (tmp->reg->desc[0]))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANDESC, nick),
+ tmp->name, tmp->reg->desc);
+ }
+ }
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Added %s to channel %s", myname,
+ nick->nick, chan);
+#endif
+ }
+ }
+ }
+}
+
+void
+remUserFromChan (UserList * nick, char *channel)
+{
+ char chan[CHANLEN];
+ int a = 0;
+ ChanList *tmp;
+ cNickList *person;
+
+ if (*channel == ':')
+ channel++;
+ while (*channel)
+ {
+ bzero (chan, CHANLEN);
+ a = 0;
+ while (*channel != ',' && *channel != 0)
+ {
+ chan[a] = *channel;
+ a++;
+ channel++;
+ }
+ chan[a] = 0;
+ a = 0;
+
+ if (*channel)
+ channel++;
+
+ if (chan[0] != '+')
+ {
+ tmp = getChanData (chan);
+ if (!tmp)
+ return;
+ person = getChanUserData (tmp, nick);
+ if (!person)
+ return;
+
+ delChanUser (tmp, person);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Removed %s from %s", myname, nick->nick, chan);
+#endif
+
+ if (!tmp->firstUser)
+ {
+ if (tmp->reg && (tmp->reg->flags & CCLOSED))
+ sSend (":%s PART %s", ChanServ, tmp->name);
+ delChan (tmp);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Removed channel %s", myname, chan);
+#endif
+ }
+ }
+ }
+}
+
+
+void
+doKick (UserList * from, UserList * to, char *channel)
+{
+ ChanList *chan;
+
+ if ((!from) || (!to) || (!channel) || (channel[0] != '#'))
+ return;
+
+ chan = getChanData (channel);
+
+ if (!chan)
+ return;
+
+ if (chan->reg)
+ {
+ if (chan->reg->flags & CPROTOP)
+ {
+ int fromop = 0, toop = 0;
+
+ fromop = getChanOp (chan->reg, from->nick);
+ toop = getChanOp (chan->reg, to->nick);
+
+ if ((toop > fromop) && (!isOper (from)))
+ sSend
+ (":%s KICK %s %s :It's bad manners to kick people with higher access than you.",
+ ChanServ, channel, from->nick);
+ }
+ }
+ remUserFromChan (to, channel);
+}
+
+void
+remFromAllChans (UserList * nick)
+{
+ ChanList *tmp = NULL;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Clearing %s from ALL channels", myname, nick->nick);
+#endif
+ for (tmp = firstChan; tmp; tmp = tmp->next)
+ {
+ if (tmp)
+ {
+ delChanUser (tmp, getChanUserData (tmp, nick));
+ if (!tmp->firstUser)
+ delChan (tmp);
+ }
+ }
+}
+
+void
+changeNickOnAllChans (UserList * oldnick, UserList * newnick)
+{
+ ChanList *tmp;
+ cNickList *oldent, *newent;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Changing nick for %s->%s", myname, oldnick->nick,
+ newnick->nick);
+#endif
+ for (tmp = firstChan; tmp; tmp = tmp->next)
+ {
+ if ((oldent = getChanUserData (tmp, oldnick)))
+ {
+ newent = smalloc (sizeof (cNickList));
+ newent->op = oldent->op;
+ newent->person = newnick;
+ delChanUser (tmp, oldent);
+ addChanUser (tmp, newent);
+ }
+ }
+}
+
+
+/* set chan modes, called on /os mode, when a user sets a mode, etc etc */
+
+void
+setChanMode (char **args, int numargs)
+{
+ int on = 1, onarg = 4, i = 0;
+ ChanList *tmp = getChanData (args[2]);
+ cBanList *tmpban;
+ cNickList *tmpnick;
+ char mode[20];
+
+/* This is for the webbies, so they'll know if they get (de)opped -GZ */
+ UserList *webbie;
+
+ int minusS = 0;
+
+ if (!tmp)
+ return;
+
+ if (*args[0] == ':')
+ args[0]++;
+
+ for (i = 0; args[3][i]; i++)
+ {
+ switch (args[3][i])
+ {
+ case '+':
+ on = 1;
+ break;
+ case '-':
+ on = 0;
+ break;
+
+ case 'b':
+ if (onarg == numargs)
+ break;
+ if (on)
+ {
+ tmpban = smalloc (sizeof (cBanList));
+ strcpy (tmpban->ban, args[onarg]);
+ addChanBan (tmp, tmpban);
+ }
+ else
+ {
+ tmpban = getChanBan (tmp, args[onarg]);
+ if (tmpban)
+ {
+ delChanBan (tmp, tmpban);
+ }
+ }
+ onarg++;
+ break;
+
+ case 'e':
+ if (onarg == numargs)
+ break;
+ if (on)
+ {
+ tmpban = smalloc (sizeof (cBanList));
+ strcpy (tmpban->ban, args[onarg]);
+ addChanExempt (tmp, tmpban);
+ }
+ else
+ {
+ tmpban = getChanExempt (tmp, args[onarg]);
+ if (tmpban)
+ {
+ delChanExempt (tmp, tmpban);
+ }
+ }
+ onarg++;
+ break;
+
+ case 'c':
+ if (on)
+ tmp->modes |= PM_C;
+ else
+ tmp->modes -= PM_C;
+ break;
+
+ case 'i':
+ if (on)
+ tmp->modes |= PM_I;
+ else
+ tmp->modes -= PM_I;
+ break;
+
+ case 'l':
+ if (on)
+ {
+ if (onarg == numargs)
+ break;
+ tmp->modes |= PM_L;
+ if (tmp->reg && !(tmp->reg->mlock & PM_L))
+ tmp->reg->limit = atol (args[onarg]);
+ onarg++;
+ }
+ else
+ {
+ tmp->modes -= PM_L;
+ if (tmp->reg)
+ tmp->reg->limit = 0;
+ }
+ if (!tmp->reg) { /* Unregistered channels get +l 5 */
+ sSend (":%s MODE %s +l 5", ChanServ, tmp->name);
+ tmp->modes |= PM_L;
+ }
+ break;
+ case 'k':
+ if (onarg == numargs)
+ break;
+ if (on)
+ {
+ tmp->modes |= PM_K;
+ if (tmp->reg && !(tmp->reg->mlock & PM_K))
+ strcpy (tmp->reg->key, args[onarg]);
+ }
+ else
+ {
+ tmp->modes -= PM_K;
+ if (tmp->reg)
+ tmp->reg->key[0] = 0;
+ }
+ onarg++;
+ break;
+
+ case 'm':
+ if (on)
+ tmp->modes |= PM_M;
+ else
+ tmp->modes -= PM_M;
+ break;
+
+ case 'n':
+ if (on)
+ tmp->modes |= PM_N;
+ else
+ tmp->modes -= PM_N;
+ break;
+
+ case 'o':
+
+ /* Create data for WebTV users so they get notified when the receive ops
+ * this will be used to notify Webbies if they get ops (see below) -GZ
+ */
+
+ webbie = getNickData (args[onarg]);
+
+ if (on)
+ {
+ tmpnick = getChanUserData (tmp, getNickData (args[onarg]));
+ if (tmpnick)
+ {
+ if (tmp->reg)
+ {
+ int newoplevel = getChanOp (tmp->reg, args[onarg]);
+ if (((newoplevel < AOP)
+ && (tmp->reg->flags & COPGUARD
+ || tmp->firstUser == tmp->lastUser))
+ && !isOper (getNickData (args[onarg])))
+ {
+ uSend (ChanServ, webbie,
+ GetReply (RPL_NOOPS, webbie));
+ sSend (":%s MODE %s -o %s", ChanServ, tmp->name,
+ args[onarg]);
+ }
+ else
+ {
+ tmpnick->op |= CHANOP;
+
+ if (webbie->webbie)
+ sSend
+ (":%s PRIVMSG %s :You are now a channel operator in %s.",
+ WebServ, webbie->nick, tmp->name);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Oped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ else
+ {
+ tmpnick->op |= CHANOP;
+ if (webbie->webbie)
+ sSend
+ (":%s PRIVMSG %s :You are now a channel operator in %s.",
+ WebServ, webbie->nick, tmp->name);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Oped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ }
+ else
+ {
+ tmpnick = getChanUserData (tmp, getNickData (args[onarg]));
+ if (tmpnick)
+ {
+ if (tmp->reg)
+ {
+ if ((getChanOp (tmp->reg, args[onarg]) >
+ getChanOp (tmp->reg, args[0]))
+ && tmp->reg->flags & CPROTOP)
+ sSend (":%s MODE %s +o %s", ChanServ, tmp->name,
+ args[onarg]);
+ else
+ {
+ tmpnick->op &= ~CHANOP;
+ if (webbie->webbie)
+ sSend
+ (":%s PRIVMSG %s :You are no longer a channel operator in %s",
+ WebServ, webbie->nick, tmp->name);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :DeOped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ else
+ {
+ tmpnick->op &= ~CHANOP;
+ if (webbie->webbie)
+ sSend
+ (":%s PRIVMSG %s :You are no longer a channel operator in %s",
+ WebServ, webbie->nick, tmp->name);
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :DeOped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ }
+ onarg++;
+ break;
+
+ case 's':
+ if (on)
+ {
+ tmp->modes |= PM_S;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Set %s +s", myname, tmp->name);
+#endif
+ }
+ else
+ {
+ tmp->modes -= PM_S;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Set %s -s", myname, tmp->name);
+#endif
+ minusS = 1;
+ }
+ break;
+
+ case 't':
+ if (on)
+ {
+ tmp->modes |= PM_T;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Set %s +t", myname, tmp->name);
+#endif
+ }
+ else
+ {
+ tmp->modes -= PM_T;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Set %s -t", myname, tmp->name);
+#endif
+ }
+ break;
+
+ case 'v':
+ if (on)
+ {
+ tmpnick = getChanUserData (tmp, getNickData (args[onarg]));
+ if (tmpnick)
+ {
+ tmpnick->op |= CHANVOICE;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Oped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ else
+ {
+ tmpnick = getChanUserData (tmp, getNickData (args[onarg]));
+ if (tmpnick)
+ {
+ tmpnick->op &= ~CHANVOICE;
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :DeOped %s in %s", myname,
+ args[onarg], tmp->name);
+#endif
+ }
+ }
+ onarg++;
+ break;
+ }
+ }
+
+ if (tmp->reg)
+ {
+ makeModeLockStr (tmp->reg, mode);
+ doRegChanMode (tmp->reg);
+ }
+ if (minusS)
+ {
+ if ((isForced (tmp->name)
+ || (tmp->reg && tmp->reg->flags & CFORCES)) && !(tmp->reg
+ && tmp->reg->
+ flags & CFEXEMPT))
+ {
+ sSend (":%s MODE %s +s", ChanServ, tmp->name);
+ sSend
+ (":%s NOTICE %s :This channel is auto set to mode +s as a precaution for our younger users. This will not affect the channel in any way, other than to make it invisible on a channel list.",
+ ChanServ, tmp->name);
+ }
+ }
+}
+
+void
+setChanTopic (char **args, int numargs)
+{
+ RegChanList *tmp;
+ UserList *changeuser;
+ int i = 6;
+ tmp = getRegChanData (args[2]);
+
+ if (!tmp)
+ return;
+
+ changeuser = getNickData (args[3]);
+
+ if ((getChanOp (tmp, args[3]) < tmp->tlocklevel) && (!isOper (changeuser)))
+ {
+ if (tmp->topic[0])
+ sSend (":%s TOPIC %s %s %lu :%s", ChanServ, tmp->name,
+ tmp->tsetby, tmp->ttimestamp, tmp->topic);
+ }
+
+ else
+ {
+ strcpy (tmp->tsetby, args[3]);
+ tmp->ttimestamp = atol (args[4]);
+
+ args[5]++;
+ strcpy (tmp->topic, args[5]);
+
+ while (i < numargs)
+ {
+ strcat (tmp->topic, " ");
+ strcat (tmp->topic, args[i]);
+ i++;
+ }
+ }
+}
+
+void
+sendToChanServ (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ /* small "hack" to make services work in either /cs #channel cmd
+ * or /cs cmd #channel way */
+ char crud[40];
+
+ if (index (args[0], '#') && args[1])
+ {
+ strcpy (crud, args[0]);
+ strcpy (args[0], args[1]);
+ strcpy (args[1], crud);
+ }
+
+ if (!strcmp (args[0], "\001PING"))
+ {
+ if (numargs < 3)
+ uSend (ChanServ, nick, GetReply (RPL_PING1, nick), args[1]);
+ else
+ uSend (ChanServ, nick, GetReply (RPL_PING2, nick), args[1], args[2]);
+ return;
+ }
+
+ else if (!strcasecmp (args[0], "HELP") && numargs == 1)
+ {
+ sendHelp (from, ChanServ, NULL, 0);
+ }
+
+ else if (!strcasecmp (args[0], "HELP"))
+ {
+ sendHelp (from, ChanServ, args, numargs);
+ }
+
+ /* Parse and adjust some commands before sending it to the message tables */
+
+ else if (!strcasecmp (args[0], "CHANOP"))
+ {
+ int i = 3;
+ if (args[1] && args[2])
+ {
+ if (!strcasecmp (args[2], "add"))
+ strcpy (args[0], "addop");
+ else if (!match (args[2], "del*"))
+ strcpy (args[0], "delop");
+ else if (!strcasecmp (args[2], "list"))
+ strcpy (args[0], "listop");
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKNOWNCOMMAND, nick),
+ args[2]);
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELPCMD, nick),
+ ChanServ, "ChanOp");
+ return;
+ }
+ }
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELPCMD, nick),
+ ChanServ, "ChanOp");
+ return;
+ }
+ while (i < numargs)
+ {
+ strcpy (args[i - 1], args[i]);
+ i++;
+ }
+ numargs--;
+ sendToChanServ (nick, args, numargs);
+ return;
+ }
+ else if (!strcasecmp (args[0], "AKICK"))
+ {
+ int i = 3;
+ if (args[1] && args[2])
+ {
+ if (!strcasecmp (args[2], "add"))
+ strcpy (args[0], "addak");
+ else if (!match (args[2], "del*"))
+ strcpy (args[0], "delak");
+ else if (!strcasecmp (args[2], "list"))
+ strcpy (args[0], "listak");
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKNOWNCOMMAND, nick),
+ args[2]);
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELPCMD, nick),
+ ChanServ, "Akick");
+ return;
+ }
+ }
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELPCMD, nick),
+ ChanServ, "Akick");
+ return;
+ }
+ while (i < numargs)
+ {
+ strcpy (args[i - 1], args[i]);
+ i++;
+ }
+ numargs--;
+ sendToChanServ (nick, args, numargs);
+ return;
+ }
+
+ else
+ msgtabCheck (ChanServ, nick, args, numargs); /* New messagetables to replace old code -GZ */
+
+#ifdef SHOWSYNCHALL
+ uSend (ChanServ, nick, GetReply (RPL_NEXTDBSYNC, nick),
+ ((nextCsync - CTime) / 60));
+#endif
+}
+
+void
+CinfoCmd (UserList * nick, char **args, int numargs)
+{
+ RegChanList *chan;
+ char timejunk[80];
+ char modestring[20];
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO1, nick), chan->name);
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO2, nick), chan->founder);
+ if (chan->desc[0])
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO3, nick), chan->desc);
+ if (chan->topic[0])
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO4, nick), chan->topic,
+ chan->tsetby);
+ if (chan->flags & CIDENT || chan->flags & CPROTOP
+ || chan->flags & CKTOPIC || chan->flags & COPGUARD
+ || chan->flags & CQUIET || chan->flags & CCLASSIC
+ || chan->flags & CNOTICE || chan->flags & CFORUM)
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO5, nick),
+ chan->flags & CIDENT ? "Ident. " : "",
+ chan->flags & CPROTOP ? "Protected Ops. " : "",
+ chan->flags & CKTOPIC ? "Preserve Topic. " : "",
+ chan->flags & COPGUARD ? "Op Guard. " : "",
+ chan->flags & CQUIET ? "Quiet Changes. " : "",
+ chan->flags & CCLASSIC ? "No AutoOping." : "",
+ chan->flags & CNOTICE ? "Join Notice." : "",
+ chan->flags & CFORUM ? "Channel Forum." : "");
+
+ strftime (timejunk, 80, "%a %d/%m/%Y %T", gmtime (&chan->timestamp));
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO8, nick), timejunk);
+ strftime (timejunk, 80, "%a %d/%m/%Y %T", gmtime (&chan->timereg));
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO7, nick), timejunk);
+ if (isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO9, nick),
+ chan->flags & CCLOSED ? "Closed. " : "",
+ chan->flags & CFORCES ? "Forces. " : "",
+ chan->flags & CHOLD ? "Held. " : "",
+ chan->flags & CFREEZE ? "Frozen. " : "",
+ chan->ops, chan->akicks);
+ }
+ makeModeLockStr (chan, modestring);
+ if (modestring[0] == 0)
+ strcpy (modestring, "(none)");
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO6, nick), chan->tlocklevel,
+ chan->restrictlevel, modestring);
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANINFO10, nick));
+}
+
+
+void
+CaccessCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *tmp;
+ int test_level;
+
+ tmp = getRegChanData (args[1]);
+
+ if (!tmp)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (numargs > 2)
+ {
+ test_level = getChanOp (tmp, args[2]);
+ uSend (ChanServ, nick, GetReply (RPL_CHANACCESS1, nick), args[2],
+ showchanoplevel (test_level), tmp->name);
+ }
+ else
+ {
+ test_level = getChanOp (tmp, from);
+ uSend (ChanServ, nick, GetReply (RPL_CHANACCESS2, nick),
+ showchanoplevel (test_level), tmp->name);
+ }
+ return;
+}
+
+void
+CregisterCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cNickList *tmp;
+ cAccessList *founder;
+ ChanList *chan;
+ RegChanList *reg;
+ int i;
+ unsigned int flags;
+
+ if (!(nick->reg) || !(nick->reg->flags & NACTIVE))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NEEDREGNICK, nick));
+ return;
+ }
+
+ flags = 0;
+ if (nick->reg)
+ flags = nick->reg->flags;
+
+ if (!(nick->caccess > 2))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NEEDID, nick));
+ return;
+ }
+
+ chan = getChanData (args[1]);
+ tmp = getChanUserData (chan, nick);
+
+ if (!chan || !tmp || !tmp->op)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOTOPEDINCHAN, nick));
+ return;
+ }
+
+ reg = getRegChanData (args[1]);
+
+ if (reg)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANALREADYREG, nick));
+ return;
+ }
+
+ /* PROPER FIX - THIS VERIFIES ACTUAL CHANNELS REGISTERED TO NICK */
+ nick->reg->chans = countRegChans (from);
+
+ if ((nick->reg->chans >= (unsigned int) ChanLimit && !isServop (nick))
+ && (!isOper (nick)) && strcasecmp (from, "Serenity"))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_TOMANYREGCHAN1, nick));
+ sSend (":%s GLOBOPS :%s is trying to register too many channels",
+ ChanServ, from);
+ return;
+ }
+
+ nick->reg->chans++;
+ reg = smalloc (sizeof (RegChanList));
+ initRegChanData (reg);
+ chan->reg = reg;
+ strcpy (reg->name, chan->name);
+ strcpy (reg->founder, nick->reg->nick);
+ strcpy (reg->key, "0");
+ for (i = 0; i < 8; i++)
+ reg->password[i] = (((u_short) rand ()) % 26) + 97;
+ reg->timereg = CTime;
+ reg->timestamp = CTime;
+ sendToChanOps (chan, "%s just registered %s", from, reg->name);
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANNOWREG, nick), args[1], from);
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANREGNOTE, nick));
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELP, nick), ChanServ);
+
+ if (isForced (reg->name))
+ {
+ sSend (":%s MODE %s +rs-l", ChanServ, reg->name);
+ uSend (ChanServ, nick, GetReply (RPL_AUTOSET_S, nick));
+ reg->flags |= CPRIVATE;
+ if (!(flags & (NROOT)))
+ sSend (":%s GLOBOPS :%s registered %s (forced +s)", ChanServ, from,
+ reg->name);
+ }
+ else
+ {
+ if (!(flags & (NROOT)))
+ sSend (":%s GLOBOPS :%s registered %s", ChanServ, from, reg->name);
+ sSend (":%s MODE %s +r-l", ChanServ, reg->name);
+ }
+
+ founder = smalloc (sizeof (cAccessList));
+ strcpy (founder->nick, nick->reg->nick);
+ founder->uflags = FOUNDER;
+
+ addChanOp (reg, founder);
+ reg->flags |= CKTOPIC | CIDENT;
+ reg->mlock |= PM_N;
+ reg->mlock |= PM_T;
+ reg->mlock |= MM_K;
+ addRegChan (reg);
+ mostchans++;
+ logDump (chanlog, "%s!%s@%s REGISTER (%s)", nick->nick, nick->user,
+ nick->host, reg->name);
+}
+
+void
+CfounderCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cAccessList *newitem;
+ RegChanList *chan;
+ RegNickList *add;
+ int founder_control;
+
+ if (numargs < 4)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ return;
+ }
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ founder_control = isFounder (chan, nick);
+
+ if (!founder_control)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ add = getRegNickData (args[3]);
+ if (!add || !(add->flags & NACTIVE))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NICKNOTREGGED, nick), args[3]);
+ return;
+ }
+
+ if ((add->flags & NNOOP) && !isRoot (nick))
+ {
+
+ uSend (ChanServ, nick, GetReply (ERR_NOOPON, nick), add->nick);
+ return;
+ }
+
+ add->chans = countRegChans (add->nick);
+
+ if ((add->chans >= (unsigned int) ChanLimit) && (founder_control != 2)
+ && strcasecmp (add->nick, "Serenity"))
+ {
+
+ uSend (ChanServ, nick, GetReply (ERR_TOMANYREGCHAN2, nick), add->nick);
+ return;
+ }
+
+ newitem = getChanOpData (chan, add->nick);
+
+ if (!newitem)
+ {
+ newitem = smalloc (sizeof (cAccessList));
+ strcpy (newitem->nick, add->nick);
+ addChanOp (chan, newitem);
+ }
+
+ newitem->uflags = FOUNDER;
+
+ strcpy (chan->founder, newitem->nick);
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANTRANS, nick), chan->name,
+ newitem->nick);
+ sendToChanOps (getChanData (chan->name),
+ "%s transferred founder status to %s.", from, newitem->nick);
+ logDump (chanlog, "%s!%s@%s TRANSFER (%s) TO %s", nick->nick,
+ nick->user, nick->host, chan->name, newitem->nick);
+ add->chans++;
+
+ if (founder_control != 2)
+ nick->reg->chans--;
+}
+
+void
+CaddopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cAccessList *olditem, *newitem;
+ RegChanList *chan;
+ RegNickList *add;
+ int access_level, a;
+ int host_access_level;
+
+ chan = getRegChanData (args[1]);
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ host_access_level = getChanOp (chan, from);
+
+ if ((SOP > host_access_level) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANAXTOOLOW, nick));
+ return;
+ }
+
+ if (chan->ops >= OpLimit)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOMOREOPS, nick), chan->name);
+ return;
+ }
+
+ add = getRegNickData (args[2]);
+ if (!add || !(add->flags & NACTIVE))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NICKNOTREGGED, nick), args[2]);
+ return;
+ }
+
+ olditem = getChanOpData (chan, args[2]);
+ if (olditem)
+ {
+
+ access_level = OPNONE;
+
+ if (numargs < 4)
+ access_level = AOP;
+
+ else if (isalpha (args[3][0]))
+ {
+ if (!strcasecmp (args[3], "founder"))
+ access_level = FOUNDER;
+ else if (!strcasecmp (args[3], "cofounder"))
+ access_level = MFOUNDER;
+ else if (!strcasecmp (args[3], "sop"))
+ access_level = SOP;
+ else if (!strcasecmp (args[3], "msop"))
+ access_level = MSOP;
+ else if (!strcasecmp (args[3], "aop"))
+ access_level = AOP;
+ else if (!strcasecmp (args[3], "voice"))
+ access_level = MAOP;
+ }
+ else
+ access_level = atoi (args[3]);
+
+ if ((MAOP > access_level) || (FOUNDER < access_level))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKAXLEVEL, nick), args[4]);
+ return;
+ }
+
+ if (((access_level >= MFOUNDER && FOUNDER > host_access_level)
+ || (access_level >= MSOP && MFOUNDER > host_access_level)
+ || host_access_level < SOP) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (!strcasecmp (chan->founder, args[2]))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOAXCGFOUNDER, nick),
+ args[2], chan->name);
+ return;
+ }
+
+ a = getChanOp (chan, from);
+
+ if ((olditem->uflags >= MFOUNDER && FOUNDER > a) ||
+ (olditem->uflags >= MSOP && MFOUNDER > a) ||
+ ((a < SOP) && !isRoot (nick) && strcasecmp (from, args[2])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ delChanOp (chan, olditem);
+
+ newitem = smalloc (sizeof (cAccessList));
+
+ newitem->uflags = access_level;
+ strcpy (newitem->nick, add->nick);
+ newitem->uflags = access_level;
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANAXCHANGE, nick),
+ newitem->nick, showchanoplevel (newitem->uflags));
+ sendToChanOps (getChanData (chan->name),
+ "%s changed access for op %s to %s", from,
+ newitem->nick, showchanoplevel (newitem->uflags));
+ addChanOp (chan, newitem);
+ return;
+ }
+
+ access_level = OPNONE;
+
+ if (numargs < 4)
+ access_level = AOP;
+ else
+ {
+ if (isalpha (args[3][0]))
+ {
+ if (!strcasecmp (args[3], "founder"))
+ access_level = FOUNDER;
+ else if (!strcasecmp (args[3], "cofounder"))
+ access_level = MFOUNDER;
+ else if (!strcasecmp (args[3], "sop"))
+ access_level = SOP;
+ else if (!strcasecmp (args[3], "msop"))
+ access_level = MSOP;
+ else if (!strcasecmp (args[3], "aop"))
+ access_level = AOP;
+ else if (!strcasecmp (args[3], "voice"))
+ access_level = MAOP;
+ }
+ else
+ access_level = atoi (args[3]);
+ }
+
+ if ((MAOP > access_level) || (FOUNDER < access_level))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKAXLEVEL, nick), args[4]);
+ return;
+ }
+
+ if (((access_level >= MFOUNDER && FOUNDER > host_access_level)
+ || (access_level >= MSOP && MFOUNDER > host_access_level)
+ || host_access_level < SOP) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (add->flags & NNOOP && !isRoot (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOOPON, nick), add->nick);
+ return;
+ }
+
+ newitem = smalloc (sizeof (cAccessList));
+
+ newitem->uflags = access_level;
+ strcpy (newitem->nick, add->nick);
+
+ addChanOp (chan, newitem);
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPADDED, nick), chan->ops,
+ newitem->nick, showchanoplevel (newitem->uflags));
+ sendToChanOps (getChanData (chan->name), "%s added op %s as %s", from,
+ newitem->nick, showchanoplevel (newitem->uflags));
+}
+
+void
+CaddakCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cAkickList *newitem;
+ RegChanList *chan;
+ int i;
+
+ chan = getRegChanData (args[1]);
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((MSOP > getChanOp (chan, from)) && (!isServop (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANAXTOOLOW, nick));
+ return;
+ }
+
+/* if (chan->ops >= AkickLimit) {
+ uSend(ChanServ, nick, GetReply(ERR_CHANNOMOREAKICK, nick),
+ chan->name);
+ return;
+ }*/
+
+ newitem = getChanAkick (chan, args[2]);
+ if (newitem)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_THISEXISTS, nick), args[2],
+ "Akick");
+ return;
+ }
+
+ if (!check_mask (args[2], isServop (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_INVALIDAKICK, nick), args[2]);
+ return;
+ }
+
+ newitem = smalloc (sizeof (cAkickList));
+ strcpy (newitem->mask, args[2]);
+ sprintf (newitem->reason, "%s:", from);
+ for (i = 3;
+ i < numargs
+ && (strlen (newitem->reason) + strlen (args[i]) <= NICKLEN + 51); i++)
+ {
+ strcat (newitem->reason, " ");
+ strcat (newitem->reason, args[i]);
+ }
+ newitem->added = CTime;
+ addChanAkick (chan, newitem);
+ sendToChanOps (getChanData (chan->name), "%s added akick %s (%s)", from,
+ newitem->mask, newitem->reason);
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKICKADDED, nick),
+ newitem->mask, chan->name);
+}
+
+void
+CdelopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+ cAccessList *delop;
+ int a, x;
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((x = atoi (args[2])))
+ {
+ for (delop = chan->firstOp; delop; delop = delop->next)
+ {
+ if (delop->index == x)
+ break;
+ }
+ }
+ else
+ delop = getChanOpData (chan, args[2]);
+
+ if (!delop)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOTINOPSLIST, nick), args[2],
+ chan->name);
+ return;
+ }
+
+ if (!strcasecmp (chan->founder, delop->nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOAXCGFOUNDER, nick),
+ chan->founder, chan->name);
+ return;
+ }
+
+ a = getChanOp (chan, from);
+
+ if (!strcasecmp (from, delop->nick) && !(nick->caccess > 2))
+ {
+ sSend
+ (":%s GLOBOPS :Unidentified nick %s tried to delop itself from %s",
+ ChanServ, from, args[1]);
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (((delop->uflags >= MFOUNDER && FOUNDER > a)
+ || (delop->uflags >= MSOP && MFOUNDER > a) || a < SOP)
+ && (!isRoot (nick)) && strcasecmp (from, delop->nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ sendToChanOps (getChanData (chan->name), "%s deleted op %s [%s]", from,
+ delop->nick, showchanoplevel (delop->uflags));
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPDELED, nick), delop->nick,
+ chan->name);
+ delChanOp (chan, delop);
+}
+
+void
+CdelakCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+ cAkickList *delak;
+ int x;
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((x = atoi (args[2])))
+ {
+ for (delak = chan->firstAkick; delak; delak = delak->next)
+ {
+ if (delak->index == x)
+ break;
+ }
+ }
+ else
+ delak = getChanAkick (chan, args[2]);
+
+ if (!delak)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_AKICKNOTEXIST, nick), args[2],
+ chan->name);
+ return;
+ }
+
+ if ((MSOP > getChanOp (chan, from)) && (!isServop (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ sendToChanOps (getChanData (chan->name), "%s deleted akick %s", from,
+ delak->mask);
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKICKDELED, nick), delak->mask,
+ chan->name);
+ delChanAkick (chan, delak);
+}
+
+void
+ClistopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ RegChanList *tmpchan;
+ int levelsearch = 0, i = 0, x = 0;
+ char namesearch[NICKLEN] = "\0";
+ cAccessList *tmp;
+
+ if (numargs == 2)
+ {
+ levelsearch = 0;
+ namesearch[0] = 0;
+ }
+ if (numargs == 3)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ return;
+ }
+ if (numargs == 4)
+ {
+ if (!strcasecmp (args[2], "-l"))
+ levelsearch = atoi (args[3]);
+ else if (!strcasecmp (args[2], "-n"))
+ strcpy (namesearch, args[3]);
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKNOWNCOMMAND, nick),
+ args[2]);
+ return;
+ }
+ }
+
+ tmpchan = getRegChanData (args[1]);
+
+ if ((tmpchan == NULL))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!(getChanOp (tmpchan, from) > 0) && !isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTHEAD1, nick),
+ tmpchan->name);
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTHEAD2, nick));
+
+ for (tmp = tmpchan->firstOp; tmp; tmp = tmp->next, i++)
+ {
+ if (levelsearch)
+ {
+ if (tmp->uflags == levelsearch)
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTDATA, nick),
+ tmp->index, tmp->nick, showchanoplevel (tmp->uflags));
+ x++;
+ }
+ }
+ else if (namesearch[0])
+ {
+ if (!match (tmp->nick, namesearch))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTDATA, nick),
+ tmp->index, tmp->nick, showchanoplevel (tmp->uflags));
+ x++;
+ }
+ }
+ else
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTDATA, nick),
+ tmp->index, tmp->nick, showchanoplevel (tmp->uflags));
+ x++;
+ }
+ }
+
+ if (namesearch[0] || levelsearch)
+ uSend (ChanServ, nick, GetReply (RPL_LISTSEARCHNUM, nick), x, i);
+ uSend (ChanServ, nick, GetReply (RPL_CHANOPSLISTEND, nick));
+}
+
+void
+ClistakCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char aktime[30];
+ RegChanList *tmpchan;
+ int i = 0, x = 0;
+ char namesearch[NICKLEN + USERLEN + HOSTLEN] = "\0";
+ cAkickList *tmp;
+
+ if (numargs == 2)
+ {
+ namesearch[0] = 0;
+ }
+
+ if (numargs == 3)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ return;
+ }
+
+ if (numargs == 4)
+ {
+ if (!strcasecmp (args[2], "-n"))
+ strcpy (namesearch, args[3]);
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_UNKNOWNCOMMAND, nick),
+ args[2]);
+ return;
+ }
+ }
+
+ tmpchan = getRegChanData (args[1]);
+
+ if (!tmpchan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!getChanOp (tmpchan, from) && !isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTHEAD1, nick), args[1]);
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTHEAD2, nick));
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTHEAD3, nick));
+
+ for (tmp = tmpchan->firstAkick; tmp; tmp = tmp->next, i++)
+ {
+ if (namesearch[0])
+ {
+ if (!match (tmp->mask, namesearch))
+ {
+ strftime (aktime, 15, "%a %d/%m/%Y", gmtime (&tmp->added));
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTDATA1, nick),
+ tmp->index, tmp->mask);
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTDATA2, nick),
+ aktime, tmp->reason);
+ x++;
+ }
+ uSend (ChanServ, nick, GetReply (RPL_LISTSEARCHNUM, nick), x, i);
+ }
+ else
+ {
+ strftime (aktime, 15, "%a %d/%m/%Y", gmtime (&tmp->added));
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTDATA1, nick),
+ tmp->index, tmp->mask);
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTDATA2, nick),
+ aktime, tmp->reason);
+ x++;
+ }
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANAKLISTEND, nick));
+}
+
+void
+CdropCmd (UserList * nick, char **args, int numargs)
+{
+ RegChanList *tmp;
+ ChanList *chan;
+ char *from = nick->nick;
+ int oper_drop;
+
+ tmp = getRegChanData (args[1]);
+
+ if (!tmp)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ /* Stop users from getting rid of this stuff so easily */
+
+ if (((tmp->flags & CFORCES) || (tmp->flags & CCLOSED)) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (!isFounder (tmp, nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ /* DON'T DECREMENT OPERS CHAN COUNT */
+ oper_drop = 0;
+ if (!match (tmp->founder, from))
+ oper_drop = 1;
+
+ sendToChanOps (getChanData (tmp->name), "%s just dropped %s", from,
+ args[1]);
+ uSend (ChanServ, nick, GetReply (RPL_CHANDROP, nick), args[1]);
+
+ chan = getChanData (args[1]);
+ if (chan)
+ chan->reg = NULL;
+ logDump (chanlog, "%s!%s@%s DROP (%s)", nick->nick, nick->user,
+ nick->host, tmp->name);
+ delRegChan (tmp);
+
+ if (!oper_drop)
+ {
+ /* DON'T LET NICKSERV GO NEGATIVE */
+ if (nick->reg->chans > 0)
+ nick->reg->chans--;
+ }
+ return;
+}
+
+void
+CopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+ cNickList *tmpnick;
+ UserList *webbie;
+
+ tmp = getRegChanData (args[1]);
+ chan = getChanData (args[1]);
+
+ if (!tmp)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if (numargs > 2)
+ tmpnick = getChanUserData (chan, getNickData (args[2]));
+ else
+ tmpnick = getChanUserData (chan, nick);
+
+ if (!tmpnick)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NICKNOTINCHAN, nick),
+ (numargs == 3) ? args[2] : from, args[1]);
+ return;
+ }
+
+ a = getChanOp (tmp, (numargs > 2) ? args[2] : from);
+
+ if ((!a || !getChanOp (tmp, from) || a < 3) && !isRoot (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ sendToChanOps (getChanData (tmp->name), "%s used \002OP\002 on %s", from,
+ (numargs > 2) ? args[2] : from);
+ tmp->timestamp = CTime; /* Update channel timestamp */
+ if (a < AOP && !isRoot (nick))
+ {
+ sSend (":%s MODE %s +v %s", ChanServ, chan->name,
+ (numargs > 2) ? args[2] : from);
+ tmpnick->op |= CHANVOICE;
+ return;
+ }
+ else
+ {
+ sSend (":%s MODE %s +o %s", ChanServ, chan->name,
+ (numargs > 2) ? args[2] : from);
+ tmpnick->op |= CHANOP;
+
+ /* Inform webbies they are opped now */
+ if (numargs > 2)
+ webbie = getNickData (args[2]);
+ else
+ webbie = getNickData (from);
+
+ if (webbie->webbie)
+ uSend (ChanServ, nick, GetReply (RPL_NOWCHANOPERATOR, nick),
+ chan->name);
+ return;
+ }
+}
+
+void
+CdeopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+ cNickList *tmpnick;
+ UserList *webbie;
+
+ chan = getChanData (args[1]);
+ tmp = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if (!tmp)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if (numargs > 2)
+ tmpnick = getChanUserData (chan, getNickData (args[2]));
+ else
+ tmpnick = getChanUserData (chan, nick);
+
+ if (!tmpnick)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NICKNOTINCHAN, nick),
+ (numargs == 3) ? args[2] : from, chan->name);
+ return;
+ }
+
+ a = getChanOp (tmp, from);
+
+ if (!a || !getChanOp (tmp, from) || a < 3)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ sendToChanOps (getChanData (tmp->name), "%s used \002DEOP\002 on %s",
+ from, (numargs > 2) ? args[2] : from);
+ sSend (":%s MODE %s -ov %s %s", ChanServ, chan->name,
+ (numargs == 3) ? args[2] : from, (numargs > 2) ? args[2] : from);
+ tmpnick->op &= ~CHANOP;
+
+ /* Inform webbies they are de-opped now */
+ if (numargs > 2)
+ webbie = getNickData (args[2]);
+ else
+ webbie = getNickData (from);
+
+ if (webbie->webbie)
+ uSend (ChanServ, nick, GetReply (RPL_NOTCHANOPERATOR, nick),
+ (numargs == 3) ? args[2] : from, chan->name);
+ return;
+
+}
+
+void
+CclistCmd (UserList * nick, char **args, int numargs)
+{
+ ChanList *chan;
+
+ if (!isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ chan = getChanData (args[1]);
+
+ if (chan)
+ {
+ cNickList *tmp;
+ int totusers = 0;
+
+ for (tmp = chan->firstUser; tmp; tmp = tmp->next)
+ {
+ totusers++;
+ uSend (ChanServ, nick, GetReply (RPL_CHANCLISTDATA, nick),
+ chan->name, tmp->person->nick, (tmp->op) ? " [OP]" : "");
+ }
+ uSend (ChanServ, nick, GetReply (RPL_NUMUSERSINCHAN, nick), totusers,
+ chan->name);
+ }
+ else
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+}
+
+
+void
+CmodelockCmd (UserList * nick, char **args, int numargs)
+{
+ int onargs = 3;
+ int on = 1;
+ RegChanList *chan;
+ ChanList *tmp;
+ char *from = nick->nick;
+ int i;
+ char mode[20];
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((MFOUNDER > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+ chan->mlock = 0;
+ for (i = 0; (unsigned int) i < strlen (args[2]); i++)
+ {
+ switch (args[2][i])
+ {
+ case '+':
+ on = 1;
+ break;
+ case '-':
+ on = 0;
+ break;
+ case 'R':
+ if (on)
+ {
+ chan->mlock |= PM_R;
+ chan->mlock &= ~MM_R;
+ }
+ else
+ {
+ chan->mlock |= MM_R;
+ chan->mlock &= ~PM_R;
+ }
+ break;
+ case 'c':
+ if (on)
+ {
+ chan->mlock |= PM_C;
+ chan->mlock &= ~MM_C;
+ }
+ else
+ {
+ chan->mlock |= MM_C;
+ chan->mlock &= ~PM_C;
+ }
+ break;
+ case 'i':
+ if (on)
+ {
+ chan->mlock |= PM_I;
+ chan->mlock &= ~MM_I;
+ }
+ else
+ {
+ chan->mlock |= MM_I;
+ chan->mlock &= ~PM_I;
+ }
+ break;
+ case 'k':
+ if (on)
+ {
+ if (numargs < (onargs + 1))
+ uSend (ChanServ, nick, GetReply (ERR_MISSINGKEY, nick));
+ else
+ {
+ strcpy (chan->key, args[onargs]);
+ onargs++;
+ chan->mlock |= PM_K;
+ chan->mlock &= ~MM_K;
+ }
+ }
+ else
+ {
+ chan->mlock |= MM_K;
+ chan->mlock &= ~PM_K;
+ }
+ break;
+ case 'l':
+ if (on)
+ {
+ if (numargs < (onargs + 1))
+ uSend (ChanServ, nick, GetReply (ERR_MISSINGLIMIT, nick));
+ else
+ {
+ chan->limit = atoi (args[onargs]);
+ onargs++;
+ chan->mlock |= PM_L;
+ chan->mlock &= ~MM_L;
+ }
+ }
+ else
+ {
+ chan->mlock |= MM_L;
+ chan->mlock &= ~PM_L;
+ }
+ break;
+ case 'm':
+ if (on)
+ {
+ chan->mlock |= PM_M;
+ chan->mlock &= ~MM_M;
+ }
+ else
+ {
+ chan->mlock |= MM_M;
+ chan->mlock &= ~PM_M;
+ }
+ break;
+ case 'n':
+ if (on)
+ {
+ chan->mlock |= PM_N;
+ chan->mlock &= ~MM_N;
+ }
+ else
+ {
+ chan->mlock |= MM_N;
+ chan->mlock &= ~PM_N;
+ }
+ break;
+ case 'p':
+ if (on)
+ {
+ chan->mlock |= PM_P;
+ chan->mlock &= ~MM_P;
+ }
+ else
+ {
+ chan->mlock |= MM_P;
+ chan->mlock &= ~PM_P;
+ }
+ break;
+ case 's':
+ if (on)
+ {
+ chan->mlock |= PM_S;
+ chan->mlock &= ~MM_S;
+ }
+
+ else
+ {
+
+ tmp = getChanData (args[1]);
+
+ if ((tmp && isForced (tmp->name)) ||
+ ((tmp && tmp->reg && tmp->reg->flags & CFORCES)
+ && !(tmp->reg && tmp->reg->flags & CFEXEMPT)))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_AUTOSET_S, nick));
+ return;
+ }
+
+ else
+ {
+ chan->mlock |= MM_S;
+ chan->mlock &= ~PM_S;
+ }
+ }
+ break;
+ case 't':
+ if (on)
+ {
+ chan->mlock |= PM_T;
+ chan->mlock &= ~MM_T;
+ }
+ else
+ {
+ chan->mlock |= MM_T;
+ chan->mlock &= ~PM_T;
+ }
+ break;
+ }
+ }
+
+ makeModeLockStr (chan, mode);
+ sendToChanOps (getChanData (chan->name), "%s set modelock (%s)", from,
+ mode);
+ doRegChanMode (chan);
+ uSend (ChanServ, nick, GetReply (RPL_MLOCKSETTO, nick), chan->name, mode);
+}
+
+
+void
+CrestrictCmd (UserList * nick, char **args, int numargs)
+{
+ RegChanList *chan;
+ char *from = nick->nick;
+ int reslevel;
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((MFOUNDER > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ reslevel = atoi (args[2]);
+ if ((reslevel > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ chan->restrictlevel = reslevel;
+
+ sendToChanOps (getChanData (chan->name),
+ "%s has set restriction to %i+ levels", from, reslevel);
+ uSend (ChanServ, nick, GetReply (RPL_RESTRICTSETTO, nick), chan->name,
+ reslevel);
+}
+
+void
+CtopiclockCmd (UserList * nick, char **args, int numargs)
+{
+ RegChanList *chan;
+ char *from = nick->nick;
+ int reslevel;
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((MFOUNDER > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if ((chan->tlocklevel > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ reslevel = atoi (args[2]);
+ if ((reslevel > getChanOp (chan, from)) && (!isRoot (nick)))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ chan->tlocklevel = reslevel;
+
+ sendToChanOps (getChanData (chan->name),
+ "%s has set topic restriction to %i+ levels", from,
+ reslevel);
+ uSend (ChanServ, nick, GetReply (RPL_TOPICLOCKSETTO, nick), chan->name,
+ reslevel);
+}
+
+void
+CsetCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+ ChanList *tmp;
+
+ chan = getRegChanData (args[1]);
+ tmp = getChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if (MFOUNDER > getChanOp (chan, from) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (!strcasecmp (args[2], "NFPRIV") && isServop (nick))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CFEXEMPT;
+ chan->flags &= ~CFORCES;
+ sSend (":%s GLOBOPS :%s made %s exempt from +s forcing",
+ ChanServ, from, chan->name);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CFEXEMPT;
+ sSend (":%s GLOBOPS :%s removed %s from +s force exemption",
+ ChanServ, from, chan->name);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NFPRIV", chan->name, (chan->flags & CFEXEMPT) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "HOLD") && isServop (nick))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CHOLD;
+ sSend (":%s GLOBOPS :%s made %s held.", ChanServ, from,
+ chan->name);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CHOLD;
+ sSend (":%s GLOBOPS :%s removed hold from %s.", ChanServ,
+ from, chan->name);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "HELD", chan->name, (chan->flags & CHOLD) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "FORCES") && isServop (nick))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CFORCES;
+ chan->flags &= ~CFEXEMPT;
+ sSend (":%s MODE %s +s", ChanServ, chan->name);
+ sSend (":%s GLOBOPS :%s forces %s as +s", ChanServ, from,
+ chan->name);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CFORCES;
+ sSend (":%s GLOBOPS :%s removed +s force from %s", ChanServ,
+ from, chan->name);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "FORCES", chan->name, (chan->flags & CFORCES) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "FREEZE") && isServop (nick))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CFREEZE;
+ CSmassdeop (chan->name);
+ sSend (":%s GLOBOPS :%s freezes %s", ChanServ, from,
+ chan->name);
+ logDump (chanlog, "%s FREEZES %s", from, chan->name);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CFREEZE;
+ sSend (":%s GLOBOPS :%s defrosted %s", ChanServ, from,
+ chan->name);
+ logDump (chanlog, "%s UNFREEZES %s", from, chan->name);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ chan->name, (chan->flags & CFREEZE) ? "FROZEN" : "UNFROZEN");
+ }
+
+ else if (!strcasecmp (args[2], "PRIVATE"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CPRIVATE;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PRIVATE", chan->name, "ON");
+ sendToChanOps (tmp, "%s set private mode on", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CPRIVATE;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PRIVATE", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set private mode off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PRIVATE", chan->name,
+ (chan->flags & CPRIVATE) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "OPGUARD"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= COPGUARD;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "OPGUARD", chan->name, "ON");
+ sendToChanOps (tmp, "%s set op guard on", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~COPGUARD;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "OPGUARD", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set op guard off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "OPGUARD", chan->name,
+ (chan->flags & COPGUARD) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "KEEPTOPIC"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CKTOPIC;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "KEEPTOPIC", chan->name, "ON");
+ sendToChanOps (tmp, "%s set topic holding on", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CKTOPIC;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "KEEPTOPIC", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set topic holding off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "KEEPTOPIC", chan->name,
+ (chan->flags & CKTOPIC) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "NAOP"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CCLASSIC;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NAOP", chan->name, "ON");
+ sendToChanOps (tmp, "%s set CS AutoOp OFF", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CCLASSIC;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NAOP", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set CS AutoOp ON", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NAOP", chan->name, (chan->flags & CCLASSIC) ? "OFF" : "ON");
+ }
+ else if (!strcasecmp (args[2], "IDENT"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CIDENT;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "IDENT", chan->name, "ON");
+ sendToChanOps (tmp, "%s set ID requirement on", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CIDENT;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "IDENT", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set ID requirement off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "IDENT", chan->name, (chan->flags & CIDENT) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "PROTOP"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ chan->flags |= CPROTOP;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PROTOP", chan->name, "ON");
+ sendToChanOps (tmp, "%s set Op protection on", from);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CPROTOP;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PROTOP", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set op protection off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "PROTOP", chan->name, (chan->flags & CPROTOP) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "QUIET"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "QUIET", chan->name, "ON");
+ sendToChanOps (tmp,
+ "%s set Quiet changes mode on, this is the last you'll hear from me",
+ from);
+ chan->flags |= CQUIET;
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CQUIET;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "QUIET", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set quiet changes mode off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "QUIET", chan->name, (chan->flags & CQUIET) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "FORUM"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "FORUM", chan->name, "ON");
+ sendToChanOps (tmp,
+ "%s requested the channel forum to be created. See /cs help set forum for further information",
+ from);
+ chan->flags |= CFORUM;
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CFORUM;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "QUIET", chan->name, "OFF");
+ sendToChanOps (tmp, "%s requested the channel forum to be closed. Any posts will be deleted", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "FORUM", chan->name, (chan->flags & CFORUM) ? "ON" : "OFF");
+ }
+ else if (!strcasecmp (args[2], "FOUNDER"))
+ CfounderCmd (nick, args, numargs);
+ else if (!match (args[2], "desc*"))
+ {
+ int i;
+ chan->desc[0] = '\0';
+ if (numargs >= 4)
+ {
+ if (strlen (args[3]) <= 99)
+ {
+ strcpy (chan->desc, args[3]);
+ for (i = 4;
+ i < numargs
+ && strlen (chan->desc) + strlen (args[i]) <= 99; i++)
+ {
+ strcat (chan->desc, " ");
+ strcat (chan->desc, args[i]);
+ }
+ }
+ }
+ if (chan->desc[0])
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETDESC, nick),
+ chan->name, chan->desc);
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETDESCCLEAR, nick),
+ chan->name);
+ }
+ else if (!strcasecmp (args[2], "NOTICE"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NOTICE", chan->name, "ON");
+ sendToChanOps (tmp, "%s set Notice On Join mode ON", from);
+ chan->flags |= CNOTICE;
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CNOTICE;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NOTICE", chan->name, "OFF");
+ sendToChanOps (tmp, "%s set Notice On Join mode off", from);
+ }
+ }
+ else
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "NOTICE", chan->name, (chan->flags & CQUIET) ? "ON" : "OFF");
+
+ }
+ else if (!strcasecmp (args[2], "ANTISPAM"))
+ {
+ if (numargs > 3)
+ {
+ if (!strcasecmp (args[3], "ON"))
+ {
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "ANTISPAM", chan->name, "ON");
+ sendToChanOps (tmp, "%s set AntiSpam mode ON", from);
+ sSend (":ChanServ PRIVMSG AntiSpam :join %s", args[1]);
+ }
+ else if (!strcasecmp (args[3], "OFF"))
+ {
+ chan->flags &= ~CNOTICE;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "ANTISPAM", chan->name, "OFF");
+ sSend (":ChanServ PRIVMSG AntiSpam :part %s", args[1]);
+ }
+ }
+ else
+ uSend (ChanServ, nick,
+ "Sorry, it is impossible to check status of this mode");
+ }
+ else
+ uSend (ChanServ, nick, GetReply (ERR_UNKNOWNCOMMAND, nick), args[2]);
+}
+
+void
+expireChans (char *placeholder)
+{
+ time_t timestart, timeend;
+ RegChanList *tmp, *next;
+#ifdef BACKUPDATABASE
+ char backup[30];
+ char cmd[500];
+#endif
+ int i = 0;
+
+ mostchans = 0;
+ timestart = time (NULL);
+#ifdef BACKUPDATABASE
+ strftime (backup, 30, "chanserv.db%d%m%Y", localtime (×tart));
+ sprintf (cmd, "cp %s/chanserv.db %s/%s", DBDIR, DBDIR, backup);
+ system (cmd);
+#endif
+ for (tmp = firstRegChan; tmp; tmp = next)
+ {
+ next = tmp->next;
+
+ if (tmp->timestamp > timestart) /* NEGATIVE TIME? */
+ tmp->timestamp = timestart; /* FIX THIS NOW */
+
+ if (((timestart - tmp->timestamp) >= CHANDROPTIME)
+ && !(tmp->flags & CHOLD))
+ {
+ ChanList *ick;
+ ick = getChanData (tmp->name);
+ if (ick)
+ ick->reg = NULL;
+ logDump (chanlog, "%s EXPIRE (AGE)", tmp->name);
+ delRegChan (tmp);
+ i++;
+ }
+ mostchans++;
+ }
+ timeend = time (NULL);
+#ifdef SHOWSYNCH
+ sSend (":%s GLOBOPS :ChanServ EXPIRE(%i/%lu) %lu seconds", ChanServ, i,
+ mostchans, (timeend - timestart));
+#endif
+ timer (9000, expireChans, "expireChans", "void");
+}
+
+void
+CsaveCmd (UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+
+ sSend
+ (":%s GLOBOPS :Synchronising \002ChanServ database\002 to disk at the request of \002%s\002.",
+ ChanServ, from);
+ saveChanData (firstRegChan);
+}
+
+void
+CinviteCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+
+ chan = getRegChanData (args[1]);
+
+ if (!chan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ if ((1 > getChanOp (chan, from)) && (!isOper (nick)))
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ else
+ sSend (":%s INVITE %s :%s", ChanServ, from, chan->name);
+}
+
+void
+CunbanCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+ ChanList *tmp;
+ cBanList *tmpban;
+ int a, domodes = 0;
+ char mode[512] = "";
+ char userhost[NICKLEN + USERLEN + HOSTLEN];
+ char cloakedhost[NICKLEN + USERLEN + HOSTLEN];
+
+ if (!(chan = getRegChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!(tmp = getChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ a = getChanOp (chan, from);
+
+ if (0 >= a)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ if (!strcasecmp (args[2], "me"))
+ {
+ sprintf (userhost, "%s!%s@%s", nick->nick, nick->user, nick->host);
+ sprintf (cloakedhost, "%s!%s@%s", nick->nick, nick->user,
+ return_user_mask(nick->host));
+ for (tmpban = tmp->firstBan; tmpban; tmpban = tmpban->next)
+ {
+ if ((!match (userhost, tmpban->ban))
+ || (!match (cloakedhost, tmpban->ban)))
+ {
+ strcat (mode, tmpban->ban);
+ strcat (mode, " ");
+ domodes++;
+ delChanBan (tmp, tmpban);
+ if (domodes == 6 || !tmpban->next)
+ {
+ uSend (ChanServ, nick, GetReply (RPL_REMCHANBANS, nick),
+ mode);
+ sSend (":%s MODE %s -bbbbbb %s", ChanServ, tmp->name, mode);
+ domodes = 0;
+ mode[0] = 0;
+ }
+ }
+ }
+ }
+ else if (!strcasecmp (args[2], "all"))
+ {
+ if (a < MSOP && !isOper (nick))
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ else
+ {
+ for (tmpban = tmp->firstBan; tmpban; tmpban = tmpban->next)
+ {
+ strcat (mode, tmpban->ban);
+ strcat (mode, " ");
+ domodes++;
+ delChanBan (tmp, tmpban);
+ if (domodes == 6 || !tmpban->next)
+ {
+ uSend (ChanServ, nick, GetReply (RPL_REMCHANBANS, nick),
+ mode);
+ sSend (":%s MODE %s -bbbbbb %s", ChanServ, tmp->name, mode);
+ domodes = 0;
+ mode[0] = 0;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (a < MSOP && !isOper (nick))
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ else
+ {
+ for (tmpban = tmp->firstBan; tmpban; tmpban = tmpban->next)
+ {
+ if (!match (tmpban->ban, args[2]))
+ {
+ strcat (mode, tmpban->ban);
+ strcat (mode, " ");
+ domodes++;
+ delChanBan (tmp, tmpban);
+ if (domodes == 6 || !tmpban->next)
+ {
+ uSend (ChanServ, nick,
+ GetReply (RPL_REMCHANBANS, nick), mode);
+ sSend (":%s MODE %s -bbbbbb %s", ChanServ, tmp->name,
+ mode);
+ domodes = 0;
+ mode[0] = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* defines for flags, not really important but I like them */
+#define CLF_FOUNDER 0x1
+#define CLF_CHNAME 0x2
+#define CLF_NUMOPG 0x4
+#define CLF_NUMOPL 0x8
+#define CLF_NUMAKG 0x10
+#define CLF_NUMAKL 0x20
+
+void
+ClistCmd (UserList * tmp, char **args, int numargs)
+{
+/* unused
+ char *from = tmp->nick; */
+ char mask[CHANLEN];
+ char fmask[NICKLEN];
+ int sno, sna;
+ int i, x, m;
+ int cf = 0;
+ char *s;
+ int onargs = 2;
+ RegChanList *reg;
+ sno = sna = 0;
+ i = x = 0;
+
+ s = args[1];
+ while (*s && args[onargs])
+ {
+ switch (*s)
+ {
+ case 'm':
+ cf |= CLF_CHNAME;
+ strncpy (mask, args[onargs], CHANLEN);
+ onargs++;
+ break;
+ case 'f':
+ cf |= CLF_FOUNDER;
+ strncpy (fmask, args[onargs], NICKLEN);
+ onargs++;
+ break;
+ case 'o':
+ s++;
+ if (*s == '<')
+ cf |= CLF_NUMOPL;
+ else if (*s == '>')
+ cf |= CLF_NUMOPG;
+ else
+ s--;
+ sno = atoi (args[onargs]);
+ onargs++;
+ break;
+ case 'a':
+ s++;
+ if (*s == '<')
+ cf |= CLF_NUMAKL;
+ else if (*s == '>')
+ cf |= CLF_NUMAKG;
+ else
+ s--;
+ sna = atoi (args[onargs]);
+ onargs++;
+ break;
+ }
+ s++;
+ }
+ for (reg = firstRegChan; reg; reg = reg->next)
+ {
+ m = 0;
+ if (cf & CLF_FOUNDER)
+ {
+ if (!match (reg->founder, fmask))
+ m = 1;
+ else
+ m = 0;
+ }
+ if (cf & CLF_CHNAME)
+ {
+ if (!match (reg->name, mask))
+ m = 1;
+ else
+ m = 0;
+ }
+ if (cf & CLF_NUMOPG)
+ {
+ if (reg->ops > sno)
+ m = 1;
+ else
+ m = 0;
+ }
+ if (cf & CLF_NUMOPL)
+ {
+ if (reg->ops < sno)
+ m = 1;
+ else
+ m = 0;
+ }
+ if (cf & CLF_NUMAKG)
+ {
+ if (reg->akicks > sna)
+ m = 1;
+ else
+ m = 0;
+ }
+ if (cf & CLF_NUMAKL)
+ {
+ if (reg->akicks < sna)
+ m = 1;
+ else
+ m = 0;
+ }
+ if (m)
+ {
+ i++;
+ if (!(reg->flags & CPRIVATE) || isOper (tmp))
+ uSend (ChanServ, tmp, GetReply (RPL_CHANLIST, tmp),
+ reg->name, reg->founder, reg->ops, reg->akicks);
+ }
+ x++;
+ }
+ uSend (ChanServ, tmp, GetReply (RPL_LISTSEARCHNUM, tmp), i, x);
+}
+
+void
+CdeleteCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ ChanList *unf;
+ RegChanList *moo;
+
+ moo = getRegChanData (args[1]);
+ if (!moo)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+ nick->reg->chans--;
+ unf = getChanData (args[1]);
+ if (unf)
+ unf->reg = NULL;
+ uSend (ChanServ, nick, GetReply (RPL_CHANSETSTATUS, nick),
+ "REGISTRATION", moo->name, "DROPPED");
+ delRegChan (moo);
+ mostchans--;
+ logDump (chanlog, "%s!%s@%s deleted channel %s", from, nick->user,
+ nick->host, args[1]);
+
+ sSend (":%s GLOBOPS :%s deleted channel %s", ChanServ, from, args[1]);
+}
+
+
+
+void
+syncChanData (time_t next)
+{
+ nextCsync = next;
+ saveChanData (firstRegChan);
+}
+
+void
+doRegChanMode (RegChanList * chan)
+{
+ char mode[80];
+ char fmt[80];
+ strcpy (fmt, ":%s MODE %s r%s");
+ if (chan->mlock & PM_L)
+ sprintf (&fmt[strlen (fmt)], " %lu", chan->limit);
+ strcat (fmt, " %s");
+
+ makeModeLockStr (chan, mode);
+ sSend (fmt, ChanServ, chan->name, mode,
+ ((chan->mlock & PM_K) || (chan->mlock & MM_K)) ? chan->key : "");
+}
+
+void
+CmassdeopCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cNickList *x;
+ ChanList *c;
+ RegChanList *rc;
+ int l, ml, w;
+
+ char deoplist[512];
+ char devclist[512];
+ int dop, dvc;
+
+ if (!(rc = getRegChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!(c = getChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if ((rc->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ return;
+ }
+
+ l = getChanOp (rc, from);
+
+ w = ml = 0;
+ for (x = c->firstUser; x; x = x->next)
+ {
+ w = getChanOp (rc, x->person->nick);
+ if (w > ml)
+ {
+ ml = w;
+ }
+ }
+ if ((ml > l || !l) && !isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ sSend (":%s NOTICE %s :%s tried to massdeop, but failed.", ChanServ,
+ c->name, from);
+ return;
+ }
+ else
+ {
+ bzero (deoplist, 512);
+ bzero (devclist, 512);
+ dop = dvc = 0;
+ for (x = c->firstUser; x; x = x->next)
+ {
+ if (dop == 6)
+ {
+ sSend (":%s MODE %s -oooooo %s", ChanServ, c->name, deoplist);
+ uSend (ChanServ, nick, GetReply (RPL_CHANMASSDEOP, nick),
+ deoplist);
+ dop = 0;
+ bzero (deoplist, 512);
+ }
+ if (dvc == 6)
+ {
+ sSend (":%s MODE %s -vvvvvv %s", ChanServ, c->name, devclist);
+ uSend (ChanServ, nick, GetReply (RPL_CHANMASSDEVOICE, nick),
+ devclist);
+ dvc = 0;
+ bzero (devclist, 512);
+ }
+ if (x->op & CHANOP)
+ {
+ dop++;
+ strcat (deoplist, " ");
+ strcat (deoplist, x->person->nick);
+ x->op &= ~CHANOP;
+ }
+ else if (x->op & CHANVOICE)
+ {
+ dvc++;
+ strcat (devclist, " ");
+ strcat (devclist, x->person->nick);
+ x->op &= ~CHANVOICE;
+ }
+ }
+ if (dop)
+ {
+ sSend (":%s MODE %s -oooooo %s", ChanServ, c->name, deoplist);
+ uSend (ChanServ, nick, GetReply (RPL_CHANMASSDEOP, nick), deoplist);
+ dop = 0;
+ bzero (deoplist, 512);
+ }
+ if (dvc)
+ {
+ sSend (":%s MODE %s -vvvvvv %s", ChanServ, c->name, devclist);
+ uSend (ChanServ, nick, GetReply (RPL_CHANMASSDEVOICE, nick),
+ devclist);
+ dvc = 0;
+ bzero (devclist, 512);
+ }
+ }
+}
+
+
+void
+CmasskickCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cNickList *x, *nextnick = NULL;
+ ChanList *c;
+ RegChanList *rc;
+ int kicked;
+ int founder_control;
+
+ if (!(rc = getRegChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!(c = getChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if ((rc->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ founder_control = isFounder (rc, nick);
+
+ if (!founder_control && !isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ sendToChanOps (c, "%s tried to masskick, but failed.", from);
+ return;
+ }
+ else
+ {
+ kicked = 0;
+
+ createGhostChannel (c->name);
+ timer (10, deleteGhostChannel, "deleteGhostChannel", c->name);
+ for (x = c->firstUser; x; x = nextnick)
+ {
+
+ nextnick = x->next;
+
+ if (x->person != nick && !isRoot (x->person))
+ {
+ kicked++;
+ sSend (":%s KICK %s %s :Masskick from \002%s\002", ChanServ,
+ c->name, x->person->nick, from);
+ remUserFromChan (x->person, c->name);
+ }
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANMASSKICK, nick), kicked,
+ args[1]);
+ }
+}
+
+void
+CmodeclearCmd (UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ cNickList *x;
+ ChanList *c;
+ RegChanList *rc;
+ int ml, l, w;
+
+ if (!(rc = getRegChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!(c = getChanData (args[1])))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if ((rc->flags & CFREEZE) && !isServop (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANFROZEN, nick));
+ return;
+ }
+
+ l = getChanOp (rc, from);
+
+ w = ml = 0;
+ for (x = c->firstUser; x; x = x->next)
+ {
+ w = getChanOp (rc, x->person->nick);
+ if (w > ml)
+ {
+ ml = w;
+ }
+ }
+
+ if ((ml > l || !l) && !isOper (nick))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_ACCESSDENIED, nick));
+ sSend (":%s NOTICE %s :%s tried to modeclear, but failed.",
+ ChanServ, c->name, from);
+ return;
+ }
+ else
+ {
+ sSend (((rc->flags & CFORCES)
+ && !isServop (nick)) ? ":%s MODE %s -iklmnptcR cowsRleet" :
+ ":%s MODE %s -iklmnpstcR cowsRleet", ChanServ, c->name);
+ uSend (ChanServ, nick, GetReply (RPL_CHANMODECLEAR, nick), c->name);
+ }
+}
+
+
+ForceList *firstForce = NULL;
+ForceList *lastForce = NULL;
+
+void
+addForce (char *mask)
+{
+ ForceList *nf;
+ if (!mask)
+ return;
+
+ nf = smalloc (sizeof (ForceList));
+ strncpy (nf->mask, mask, CHANLEN);
+
+ if (!firstForce)
+ {
+ firstForce = nf;
+ nf->prev = NULL;
+ }
+ else
+ {
+ nf->prev = lastForce;
+ lastForce->next = nf;
+ }
+ nf->next = NULL;
+ lastForce = nf;
+}
+
+int
+isForced (char *mask)
+{
+ ForceList *f;
+
+ for (f = firstForce; f; f = f->next)
+ {
+ if (!match (mask, f->mask))
+ return 1;
+ }
+ return 0;
+}
+
+BanChannelList *firstBanChannel = NULL;
+BanChannelList *lastBanChannel = NULL;
+
+void
+addBanChannel (char *mask)
+{
+ BanChannelList *newban;
+ if (!mask)
+ return;
+
+ newban = smalloc (sizeof (BanChannelList));
+ strncpy (newban->mask, mask, CHANLEN);
+
+ if (!firstBanChannel)
+ {
+ firstBanChannel = newban;
+ newban->prev = NULL;
+ }
+ else
+ {
+ newban->prev = lastBanChannel;
+ lastBanChannel->next = newban;
+ }
+ newban->next = NULL;
+ lastBanChannel = newban;
+}
+
+int
+isBanChannel (char *mask)
+{
+ BanChannelList *tmp;
+
+ for (tmp = firstBanChannel; tmp; tmp = tmp->next)
+ {
+ if (!match (mask, tmp->mask))
+ return 1;
+ }
+ return 0;
+}
+
+void
+CSmassdeop (char *channame)
+{
+ cNickList *x;
+ ChanList *c;
+ RegChanList *rc;
+ int ml, w;
+
+ char deoplist[512];
+ char devclist[512];
+ int dop, dvc;
+
+ if (!(c = getChanData (channame)))
+ {
+ return;
+ }
+
+ rc = getRegChanData (channame);
+
+ w = ml = 0;
+ for (x = c->firstUser; x; x = x->next)
+ {
+ w = getChanOp (rc, x->person->nick);
+ if (w > ml)
+ {
+ ml = w;
+ }
+ }
+ {
+ bzero (deoplist, 512);
+ bzero (devclist, 512);
+ dop = dvc = 0;
+ for (x = c->firstUser; x; x = x->next)
+ {
+ if (dop == 6)
+ {
+ sSend (":%s MODE %s -oooooo %s", ChanServ, c->name, deoplist);
+ dop = 0;
+ bzero (deoplist, 512);
+ }
+ if (dvc == 6)
+ {
+ sSend (":%s MODE %s -vvvvvv %s", ChanServ, c->name, devclist);
+ dvc = 0;
+ bzero (devclist, 512);
+ }
+ if (x->op & CHANOP)
+ {
+ dop++;
+ strcat (deoplist, " ");
+ strcat (deoplist, x->person->nick);
+ x->op &= ~CHANOP;
+ }
+ else if (x->op & CHANVOICE)
+ {
+ dvc++;
+ strcat (devclist, " ");
+ strcat (devclist, x->person->nick);
+ x->op &= ~CHANVOICE;
+ }
+ }
+ if (dop)
+ {
+ sSend (":%s MODE %s -oooooo %s", ChanServ, c->name, deoplist);
+ dop = 0;
+ bzero (deoplist, 512);
+ }
+ if (dvc)
+ {
+ sSend (":%s MODE %s -vvvvvv %s", ChanServ, c->name, devclist);
+ dvc = 0;
+ bzero (devclist, 512);
+ }
+ }
+}
+
+/* This will parse SJOINS and convert them to regular joins */
+
+void
+ParseSJOIN (char *channel, char *string)
+{
+
+ int i, c;
+ char *nick[256];
+ char stringlist[256][NICKLEN * 2];
+ char buffer[1024];
+ UserList *tmp;
+
+ for (i = 0; i < 256; i++)
+ nick[i] = stringlist[i];
+
+ c = breakString (255, string, nick, " ");
+
+ for (i = 0; i < c; i++)
+ {
+ if (nick[i][0] == ':')
+ nick[i]++;
+ if (nick[i][0] == '@')
+ {
+ nick[i]++;
+ if (nick[i][0] == '+')
+ nick[i]++;
+ tmp = getNickData (nick[i]);
+ if (!tmp)
+ {
+ sSend (":%s KILL %s :%s!%s (Desynch, type: [%s])", NickServ,
+ nick[i], services[1].host, NickServ, "SJOIN");
+ continue;
+ }
+ addUserToChanSJ (tmp, channel, 2);
+ if (synched)
+ {
+ bzero (buffer, 1024);
+ printf (buffer, ":%s MODE %s +o %s", myname, channel, nick[i]);
+ parseLine (buffer);
+ }
+ }
+ else if (nick[i][0] == '+')
+ {
+ nick[i]++;
+ tmp = getNickData (nick[i]); // This should be the correct line here
+ if (!tmp) // Value of tmp unknown - this is a bug!!!
+ {
+ sSend (":%s KILL %s :%s!%s (Desynch, type: [%s])", NickServ,
+ nick[i], services[1].host, NickServ, "SJOIN");
+ continue;
+ }
+ tmp = getNickData (nick[i]);
+ addUserToChanSJ (tmp, channel, 1);
+ if (synched)
+ {
+ bzero (buffer, 1024);
+ sprintf (buffer, ":%s MODE %s +v %s", myname, channel, nick[i]);
+ parseLine (buffer);
+ }
+ }
+ else
+ {
+ tmp = getNickData (nick[i]);
+ if (!tmp)
+ {
+ sSend (":%s KILL %s :%s!%s (Desynch, type: [%s])", NickServ,
+ nick[i], services[1].host, NickServ, "SJOIN");
+ continue;
+ }
+ addUserToChanSJ (tmp, channel, 0);
+ }
+ }
+ return;
+}
+
+/* add a user to a channel, fun...really */
+void
+addUserToChanSJ (UserList * nick, char *channel, int status)
+{
+ char chan[CHANLEN];
+ int a = 0;
+ ChanList *tmp;
+ cNickList *person;
+
+ if (nick == NULL || channel == NULL)
+ {
+ sSend
+ ("GLOBOPS :addUserToChanSJ() called with null arguments! [%p %p %d]",
+ nick, channel, status);
+ return;
+ }
+
+ if (*channel == ':')
+ channel++;
+
+ while (*channel)
+ {
+ bzero (chan, CHANLEN);
+ a = 0;
+ while ((*channel) && (*channel != ','))
+ {
+ chan[a] = *channel;
+ a++;
+ channel++;
+ }
+ chan[a] = 0;
+ if (*channel)
+ channel++;
+
+ if (chan[0] == '0')
+ remFromAllChans (nick);
+ else if (chan[0] != '+')
+ {
+ tmp = getChanData (chan);
+
+ if ((!tmp) || (!tmp->firstUser))
+ {
+ /* FIRST USER IN CHANNEL */
+
+ /* INSERT NEW CHANNEL INTO INTERNAL LIST */
+ if (!tmp)
+ {
+ tmp = smalloc (sizeof (ChanList));
+ initChanData (tmp);
+ strncpy (tmp->name, chan, CHANLEN);
+ addChan (tmp);
+ }
+
+ person = smalloc (sizeof (cNickList));
+ person->person = nick;
+ person->op = 0;
+
+ addChanUser (tmp, person);
+
+ if (isBanChannel (tmp->name))
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :Channel is not permitted on this network.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Created channel %s, added %s to it",
+ myname, chan, nick->nick);
+#endif
+
+ tmp->reg = getRegChanData (chan);
+
+ /* new closed channels check -GZ */
+
+ if (tmp->reg && tmp->reg->flags & CCLOSED)
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :This channel has been \002CLOSED\002 by the Serenity-IRC administration.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ if ((isForced (tmp->name)
+ || (tmp->reg && tmp->reg->flags & CFORCES))
+ && !(tmp->reg && tmp->reg->flags & CFEXEMPT))
+ {
+ sSend (":%s MODE %s +s", ChanServ, tmp->name);
+ if (tmp->reg)
+ tmp->reg->flags |= CPRIVATE;
+ }
+ /* IF THE CHANNEL IS REGISTERED -- CHECK OUT THE REGISTRATION DATA */
+
+ if (tmp->reg)
+ {
+ char mode[20];
+
+ /* OPS/BANS LIST */
+ a = getChanOp (tmp->reg, nick->nick);
+
+ /* Thou shall not akick servops */
+
+ if (!isServop (nick))
+ {
+ if (a == -1)
+ { /* IS AKICKED? */
+ cAkickList *blah;
+ char userhost[NICKLEN + USERLEN + HOSTLEN];
+
+ sprintf (userhost, "%s!%s@%s", nick->nick,
+ nick->user, nick->host);
+ for (blah = tmp->reg->firstAkick; blah;
+ blah = blah->next)
+ {
+ if (!match (userhost, blah->mask))
+ {
+ cBanList *newban =
+ smalloc (sizeof (cBanList));
+ sSend (":%s MODE %s +b %s", ChanServ,
+ chan, blah->mask);
+ strcpy (newban->ban, blah->mask);
+ addChanBan (tmp, newban);
+ break;
+ }
+ }
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel,
+ "deleteGhostChannel", tmp->name);
+ sSend
+ (":%s KICK %s %s :You have been permanently banned from this channel.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ /* Scanbot protection -GZ */
+ if ((tmp->reg->restrictlevel != 0)
+ && ((a < tmp->reg->restrictlevel)
+ || (!a
+ && ((tmp->reg->mlock & PM_K)
+ || (tmp->reg->mlock & PM_I)))))
+ {
+ /* IS BELOW RESTRICT LEVEL */
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ if (!isServop (nick))
+ {
+// banKick(tmp, nick, "This channel is restricted to level %i and above", tmp->reg->restrictlevel);
+ banKick (tmp, nick,
+ "Sorry. This is a restricted access channel.");
+
+ }
+ return;
+ }
+
+ if ((tmp->reg->flags & CKTOPIC) && (tmp->reg->topic[0])
+ && !(tmp->reg->flags & CFREEZE))
+ /* IF KEEPTOPIC - RESTORE SAVED TOPIC */
+ sSend (":%s TOPIC %s %s %lu :%s", ChanServ,
+ tmp->name, tmp->reg->tsetby,
+ tmp->reg->ttimestamp, tmp->reg->topic);
+
+ /* ChanServ will now enforce that absolutely nobody but SO's get ops */
+ if ((tmp->reg->flags & CFREEZE) && !isServop (nick)
+ && status == 2)
+ {
+ sSend (":%s MODE %s -o %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+
+ makeModeLockStr (tmp->reg, mode);
+ doRegChanMode (tmp->reg);
+ }
+ }
+ else
+ {
+ /* NOT FIRST USER IN CHANNEL */
+
+ tmp->reg = getRegChanData (chan);
+
+ person = getChanUserData (tmp, nick);
+ if (person)
+ delChanUser (tmp, person);
+
+ person = smalloc (sizeof (cNickList));
+ person->person = nick;
+ person->op = 0;
+ addChanUser (tmp, person);
+
+ /* New CLOSED channel check. -GZ */
+
+ if (tmp->reg && tmp->reg->flags & CCLOSED)
+ {
+ if (!isServop (nick))
+ {
+ createGhostChannel (tmp->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel",
+ tmp->name);
+ sSend (":%s MODE %s +b *!*@*", ChanServ, chan);
+ sSend
+ (":%s KICK %s %s :This channel has been \002CLOSED\002 by the Serenity-IRC administration.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+ if (tmp->reg)
+ {
+ a = getChanOp (tmp->reg, nick->nick);
+ /* IS AKICKED?? */
+ /* Thou shall not akick servops */
+ if (!isServop (nick))
+ {
+ if (a == -1)
+ {
+ cAkickList *blah;
+ char userhost[NICKLEN + USERLEN + HOSTLEN];
+
+ sprintf (userhost, "%s!%s@%s", nick->nick,
+ nick->user, nick->host);
+ for (blah = tmp->reg->firstAkick; blah;
+ blah = blah->next)
+ {
+ if (!match (userhost, blah->mask))
+ {
+ cBanList *newban =
+ smalloc (sizeof (cBanList));
+ sSend (":%s MODE %s +b %s", ChanServ,
+ chan, blah->mask);
+ strcpy (newban->ban, blah->mask);
+ addChanBan (tmp, newban);
+ break;
+ }
+ }
+ sSend
+ (":%s KICK %s %s :You have been permanently banned from this channel.",
+ ChanServ, chan, nick->nick);
+ remUserFromChan (nick, chan);
+ return;
+ }
+ }
+
+
+ if (a < tmp->reg->restrictlevel
+ && tmp->reg->restrictlevel != 0)
+ {
+ /* BELOW RESTRICT LEVEL */
+ if (!isServop (nick))
+ {
+// banKick(tmp, nick, "This channel is restricted to level %i+", tmp->reg->restrictlevel);
+ banKick (tmp, nick,
+ "Sorry. This is a restricted access channel.");
+ }
+ return;
+ }
+
+ /* Make sure nobody gets ops */
+ if ((tmp->reg->flags & CFREEZE) && !isServop (nick)
+ && status == 2)
+ {
+ uSend (ChanServ, nick,
+ GetReply (RPL_NOOPSFROZEN, nick));
+ sSend (":%s MODE %s -o %s", ChanServ, tmp->name,
+ nick->nick);
+ }
+
+ }
+#ifdef CDEBUG
+ sSend (":%s GNOTICE :Added %s to channel %s", myname,
+ nick->nick, chan);
+#endif
+ }
+ }
+ }
+}
+
+void
+CcloseCmd (UserList * nick, char **args, int numargs)
+{
+ ChanList *channel;
+ RegChanList *regchan;
+ int i;
+ cAccessList *founder;
+ cNickList *x, *nextnick = NULL;
+ char reason[512];
+ if (!strcasecmp (args[1], "add"))
+ {
+
+ if (!IsChannelName (args[2]))
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADCHANNELNAME, nick),
+ args[2]);
+ return;
+ }
+
+ channel = getChanData (args[2]);
+ regchan = getRegChanData (args[2]);
+ *reason = '\0';
+ for (i = 3; i < numargs; i++)
+ {
+ if ((strlen (reason) + strlen (args[i])) > 510)
+ break;
+ strcat (reason, args[i]);
+ if ((i + 1) != numargs)
+ strcat (reason, " ");
+ }
+
+ if (!*reason)
+ {
+ sSend
+ (":%s NOTICE %s :Syntax error: \2/CS CLOSE ADD #Channel <reason>\2",
+ ChanServ, nick->nick);
+ return;
+ }
+ if (!regchan)
+ {
+ regchan = smalloc (sizeof (RegChanList));
+ initRegChanData (regchan);
+
+ if (channel)
+ channel->reg = regchan;
+
+ strcpy (regchan->name, args[2]);
+ strcpy (regchan->founder, "Serenity");
+
+ for (i = 0; i < 8; i++)
+ regchan->password[i] = (((u_short) rand ()) % 26) + 97;
+
+ regchan->timereg = CTime;
+ regchan->timestamp = CTime;
+
+ strcpy (regchan->key, "0");
+
+ founder = smalloc (sizeof (cAccessList));
+ strcpy (founder->nick, "Serenity");
+ founder->uflags = FOUNDER;
+ addChanOp (regchan, founder);
+ regchan->mlock |= PM_N;
+ regchan->mlock |= PM_T;
+ regchan->mlock |= PM_I;
+ regchan->mlock |= PM_S;
+ addRegChan (regchan);
+ mostchans++;
+ }
+
+ regchan->flags |= CCLOSED;
+ regchan->flags |= CKTOPIC;
+ strcpy (regchan->topic,
+ "This channel has been \002CLOSED\002 by the Serenity-IRC administration.");
+ strcpy (regchan->tsetby, ChanServ);
+ regchan->ttimestamp = CTime;
+
+ if (channel)
+ {
+ createGhostChannel (channel->name);
+ timer (30, deleteGhostChannel, "deleteGhostChannel", channel->name);
+ for (x = channel->firstUser; x; x = nextnick)
+ {
+ nextnick = x->next;
+
+ if (!isOper (x->person))
+ {
+ sSend
+ (":%s KICK %s %s :This channel has been \002CLOSED\002 by the Serenity-IRC administration.",
+ ChanServ, channel->name, x->person->nick);
+ remUserFromChan (x->person, channel->name);
+ }
+ }
+ sSend (":%s TOPIC %s :%s", ChanServ, channel->name, regchan->topic);
+ }
+
+ uSend (ChanServ, nick, GetReply (RPL_CHANCLOSED, nick), regchan->name);
+ sSend
+ (":%s GLOBOPS :%s has CLOSED the channel \002%s\002 (%s) - founder: %s.",
+ ChanServ, nick->nick, regchan->name, reason, regchan->founder);
+/* sSend
+ (":%s NOTICE @#closed :(Ops/#Closed) %s has CLOSED the channel \002%s\002 (%s) - founder: %s",
+ ChanServ, nick->nick, regchan->name, reason,
+ regchan->founder);*/
+ logDump (chanlog,
+ "%s has CLOSED the channel %s (%s) - founder: %s.",
+ nick->nick, regchan->name, reason, regchan->founder);
+ /* int sendMail(char *to, char *from, char *subject, char *format, ...) */
+ sendMail ("close@serenity-irc.net", "Services@Serenity-IRC.Net",
+ "Closure of channel",
+ "%s has closed channel %s - founder is %s and reason is \"%s\"",
+ nick->nick, regchan->name, regchan->founder, reason);
+ }
+
+ else if (!strcasecmp (args[1], "del"))
+ {
+ regchan = getRegChanData (args[2]);
+
+ if (nick->reg)
+ {
+ if (!(nick->reg->flags & (NROOT)))
+ {
+ sSend (":%s NOTICE %s :You must be SRA to reopen a channel.",
+ ChanServ, nick->nick);
+ return;
+ }
+ }
+
+ if (!regchan)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTREGGED, nick), args[2]);
+ return;
+ }
+
+ if (!regchan->flags & CCLOSED)
+ {
+ uSend (ChanServ, nick, GetReply (ERR_CHANNOTCLOSED, nick),
+ regchan->name);
+ return;
+ }
+
+ regchan->flags &= ~CCLOSED;
+ uSend (ChanServ, nick, GetReply (RPL_CHANUNCLOSED, nick),
+ regchan->name);
+ sSend
+ (":%s GLOBOPS :%s has REOPENED the channel \002%s\002 (founder: %s).",
+ ChanServ, nick->nick, regchan->name, regchan->founder);
+ logDump (chanlog, "%s has REOPENED the channel %s (founder: %s).",
+ nick->nick, regchan->name, regchan->founder);
+/* sSend
+ (":%s NOTICE @#closed :(Ops/#Closed) %s has REOPENED the channel \002%s\002 - founder: %s",
+ ChanServ, nick->nick, regchan->name, regchan->founder);*/
+
+ sendMail ("close@serenity-irc.net", "Services@Serenity-IRC.Net",
+ "Reopening of channel",
+ "%s has reopened channel %s - founder: %s", nick->nick,
+ regchan->name, regchan->founder);
+
+ if (!strcmp (regchan->founder, "Serenity"))
+ {
+ delRegChan (regchan);
+ mostchans--;
+ }
+ }
+
+ else
+ {
+ uSend (ChanServ, nick, GetReply (ERR_BADPARAMS, nick));
+ uSend (ChanServ, nick, GetReply (RPL_MOREHELPCMD, nick), ChanServ,
+ "CLOSE");
+ return;
+ }
+
+ return;
+}
--- /dev/null
+/* 188 */
+
+#include "services.h"
+
+/* NickServ -- Nicknames. save/read/delete */
+
+void saveNickData(RegNickList * first)
+{
+ RegNickList *nl = first;
+ nAccessList *accitem;
+ nMarkList *markitem;
+ int i, x = 0;
+ db.ns = fopen(DBDIR "/nickserv.db", "w");
+ if (db.ns == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open nickserv db"));
+ return;
+ }
+ while (nl != NULL) {
+ i = 0;
+ /* new nick insertion point */
+ fprintf(db.ns, "nick ");
+ fprintf(db.ns, "%s %s %s ", nl->nick, nl->user, nl->host);
+ fprintf(db.ns, "%s %s ", nl->password, nl->password2);
+ fprintf(db.ns, "%s ", nl->email);
+ fprintf(db.ns, "%lu ", (unsigned long) nl->timestamp);
+ fprintf(db.ns, "%lu ", (unsigned long) nl->timereg);
+ fprintf(db.ns, "%i %i :%s\n", nl->flags, nl->chans, nl->realname);
+ if (nl->lastpwchange > nl->timereg)
+ fprintf(db.ns, "expire %s %lu\n", nl->nick,
+ (unsigned long) nl->lastpwchange);
+ if (nl->url[0])
+ fprintf(db.ns, "url %s %s\n", nl->nick, nl->url);
+ for (accitem = nl->firstAcc; accitem; accitem = accitem->next) {
+ fprintf(db.ns, "access %s %s\n", nl->nick, accitem->mask);
+ }
+ if (nl->info[0])
+ fprintf(db.ns, "info %s x x x x x x x x x :%s\n", nl->nick,
+ nl->info);
+ if (nl->flags2)
+ fprintf(db.ns, "flags %s %i\n", nl->nick, nl->flags2);
+ x++;
+ fprintf(db.ns, "language %s %i\n", nl->nick, nl->language);
+ for (markitem = nl->firstMark; markitem; markitem = markitem->next) {
+ fprintf(db.ns, "mark %s %s %lu x x x x x x x :%s\n",
+ nl->nick, markitem->markedby, markitem->timestamp,
+ markitem->remark);
+ }
+ fflush(db.ns);
+#ifdef DBDEBUG
+ sSend("GNOTICE :Saved nick data (%s)", nl->nick);
+#endif
+ nl = nl->next;
+ }
+ fprintf(db.ns, "done\n");
+ fflush(db.ns);
+ fclose(db.ns);
+#ifdef SHOWSYNCH
+ sSend(":%s GLOBOPS :Completed save(%i)", NickServ, x);
+#endif
+}
+
+
+void readNickData()
+{
+ RegNickList *read;
+ char line[1024];
+ char *tmp = line;
+ char args[13][129];
+ int done = 0;
+ int a, x, teller = 0;
+
+ db.ns = fopen(DBDIR "/nickserv.db", "r");
+ if (!db.ns) {
+ Debug((DEBUG_ERROR, "Failed to open nickserv db"));
+ return;
+ }
+ while (!done) {
+ memset(args, 0, 13 * 129);
+ if (!(sfgets(line, 1024, db.ns))) {
+ done = 1;
+ fclose(db.ns);
+ return;
+ }
+ tmp = line;
+ x = a = 0;
+ while (*tmp && x < 12) {
+ if (x == 11) {
+ tmp++;
+ while (*tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ } else {
+ while (*tmp != ' ' && *tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ }
+
+ args[x][a] = 0;
+ x++;
+ while (*tmp == ' ')
+ tmp++;
+ a = 0;
+ }
+ teller++;
+ if (!strcmp(args[0], "nick")) {
+ read = smalloc(sizeof(RegNickList));
+ memset(read, 0, sizeof(RegNickList));
+ strcpy(read->nick, args[1]);
+ strcpy(read->user, args[2]);
+ strcpy(read->host, args[3]);
+ strcpy(read->password, args[4]);
+ strcpy(read->password2, args[5]);
+ strcpy(read->email, args[6]);
+ read->timestamp = (time_t) atol(args[7]);
+ read->timereg = (time_t) atol(args[8]);
+ read->lastpwchange = read->timereg; /* THIS WAY TO SAVE STORAGE */
+ read->amasks = 0; /* atoi(args[9]); <--- not needed... */
+ read->flags = atoi(args[9]);
+ read->chans = atoi(args[10]);
+ strcpy(read->realname, args[11]);
+ read->flags &= ~NNETADM;
+ read->flags &= ~NROOT;
+ addRegNick(read);
+ } else if (!strcmp(args[0], "expire")) {
+ read = getRegNickData(args[1]);
+ read->lastpwchange = (time_t) atol(args[2]);
+ } else if (!strcmp(args[0], "url")) {
+ read = getRegNickData(args[1]);
+ strcpy(read->url, args[2]);
+ } else if (!strcmp(args[0], "info")) {
+ read = getRegNickData(args[1]);
+ strcpy(read->info, args[11]);
+ } else if (!strcmp(args[0], "flags")) {
+ read = getRegNickData(args[1]);
+ read->flags2 = atoi(args[2]);
+ } else if (!strcmp(args[0], "access")) {
+ read = getRegNickData(args[1]);
+ addAccItem(read, args[2]);
+ } else if (!strcmp(args[0], "language")) {
+ read = getRegNickData(args[1]);
+ read->language = atoi(args[2]);
+ } else if (!strcmp(args[0], "mark")) {
+ read = getRegNickData(args[1]);
+ add_mark((time_t) atol(args[3]), args[2], read, args[11]);
+ } else if (!strcmp(args[0], "done"))
+ done = 1;
+ else {
+ printf("failed.\n");
+ printf("Error reading: line: %s (%i)\n", line, teller);
+ sshutdown(-1);
+ }
+#ifdef DBDEBUG
+ sSend("GNOTICE :Read nick data (%s)", line);
+#endif
+ }
+ fclose(db.ns);
+ readMemoData();
+}
+
+/* ChanServ, all things ChanServ, and the like.... */
+
+void saveChanData(RegChanList * first)
+{
+ RegChanList *cl = first;
+ cAccessList *accitem;
+ cAkickList *akitem;
+ int x = 0;
+ db.cs = fopen(DBDIR "/chanserv.db", "w");
+ if (db.cs == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open chanserv db"));
+ return;
+ }
+ while (cl) {
+ /* new chan insertion point */
+ fprintf(db.cs, "channel ");
+ fprintf(db.cs, "%s %s ", cl->name, cl->founder);
+ fprintf(db.cs, "%lu %lu %s ", cl->mlock, cl->flags, cl->password);
+ fprintf(db.cs, "%lu ", (unsigned long) cl->timereg);
+ fprintf(db.cs, "%lu ", (unsigned long) cl->timestamp);
+ fprintf(db.cs, "%s %lu ", cl->key, cl->limit);
+ fprintf(db.cs, "%i %i :%s\n", cl->tlocklevel, cl->restrictlevel,
+ cl->desc);
+ if (cl->topic[0])
+ fprintf(db.cs, "topic %s %s %lu :%s\n", cl->name, cl->tsetby,
+ cl->ttimestamp, cl->topic);
+ if (cl->firstOp) {
+ for (accitem = cl->firstOp; accitem; accitem = accitem->next) {
+ fprintf(db.cs, "op %s %s ", cl->name, accitem->nick);
+ fprintf(db.cs, "%i\n", accitem->uflags);
+ }
+ }
+
+ if (cl->firstAkick)
+ {
+ char *p1,*p2;
+
+ for (akitem = cl->firstAkick; akitem; akitem = akitem->next)
+ {
+ p1=akitem->reason;
+ if (!p1) continue;
+ if (*p1)
+ {
+ p2=p1+strlen (p1)-1;
+ while (p2>p1)
+ {
+ if (*p2<32) p2--;
+ else break;
+ }
+ p2[1]=0;
+ }
+ fprintf(db.cs, "akick %s %s ", cl->name, akitem->mask);
+ fprintf(db.cs, "%lu :%s\n", (unsigned long) akitem->added, p1);
+ }
+ }
+ x++;
+ fflush(db.cs);
+#ifdef DBDEBUG
+ sSend("GNOTICE :Saved chan data (%s)", cl->name);
+#endif
+ cl = cl->next;
+ }
+ fprintf(db.cs, "done\n");
+ fflush(db.cs);
+ fclose(db.cs);
+#ifdef SHOWSYNCH
+ sSend(":%s GLOBOPS :Completed save(%i)", ChanServ, x);
+#endif
+}
+
+void readChanData()
+{
+ RegChanList *read;
+ char line[2048];
+ char *tmp = line;
+ char args[15][512];
+ int done = 0;
+ int x, a, teller = 0;
+ db.cs = fopen(DBDIR "/chanserv.db", "r");
+ if (!db.cs) {
+ Debug((DEBUG_ERROR,
+ "Failed to open \"" DBDIR "/chanserv.db\"!"));
+ return;
+ }
+ while (!done) {
+ read = NULL;
+ bzero(line, 2048);
+ tmp = line;
+ memset(args, 0, 15 * 512);
+
+ if (!(sfgets(line, 2048, db.cs))) {
+ done = 1;
+ fclose(db.cs);
+ }
+
+ strtok(line,"\r");
+
+ tmp = line;
+ x = a = 0;
+ while (*tmp && x < 13) {
+ if ((x == 4 || x == 12) && (*tmp == ':')) {
+ tmp++;
+ while (*tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ } else {
+ while (*tmp != ' ' && *tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ }
+
+ args[x][a] = 0;
+ x++;
+ while (*tmp == ' ')
+ tmp++;
+ a = 0;
+ }
+ teller++;
+ if (!strcmp(args[0], "channel")) {
+ read = smalloc(sizeof(RegChanList));
+ initRegChanData(read);
+ strcpy(read->name, args[1]);
+ strcpy(read->founder, args[2]);
+ read->mlock = atol(args[3]);
+ read->flags = atol(args[4]);
+ strcpy(read->password, args[5]);
+ read->timereg = (time_t) atol(args[6]);
+ read->timestamp = (time_t) atol(args[7]);
+ strcpy(read->key, args[8]);
+ read->limit = atol(args[9]);
+ read->tlocklevel = atoi(args[10]);
+ read->restrictlevel = atoi(args[11]);
+ strcpy(read->desc, args[12]);
+ addRegChan(read);
+ mostchans++;
+ } else if (!strcmp(args[0], "topic")) {
+ char *s1;
+ s1 = args[4];
+ while (*s1 == ' ')
+ s1++;
+ if (*s1) {
+ read = getRegChanData(args[1]);
+ strcpy(read->tsetby, args[2]);
+ read->ttimestamp = (time_t) atol(args[3]);
+ strcpy(read->topic, s1);
+ }
+ } else if (!strcmp(args[0], "op")) {
+ cAccessList *lame;
+ lame = smalloc(sizeof(cAccessList));
+ read = getRegChanData(args[1]);
+ strcpy(lame->nick, args[2]);
+ lame->uflags = atoi(args[3]);
+ if (getRegNickData(args[2]))
+ addChanOp(read, lame);
+ else
+ free(lame);
+ } else if (!strcmp(args[0], "akick")) {
+ cAkickList *lame;
+ lame = smalloc(sizeof(cAkickList));
+ read = getRegChanData(args[1]);
+ strcpy(lame->mask, args[2]);
+ lame->added = (time_t) atol(args[3]);
+ strcpy(lame->reason, args[4]);
+ addChanAkick(read, lame);
+ } else if (!strcmp(args[0], "done"))
+ done = 1;
+ else {
+/* printf("failed.\n");
+ printf("Error reading: line: %s (%i)\n", args[0], teller);
+ sshutdown(-1);*/
+ printf("Skipping unknown line %d:\n'%s'\n", teller, args[0]);
+ }
+
+#ifdef DBDEBUG
+ sSend("GNOTICE :Read chan data (%s)", line);
+#endif
+ }
+ fclose(db.cs);
+}
+
+
+void saveMemoData(RegNickList * first)
+{
+ RegNickList *nl = first;
+ MemoBox *tmp;
+ MemoList *memo;
+ int x = 0;
+ db.ms = fopen(DBDIR "/memoserv.db", "w");
+ if (db.ms == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open memoserv db"));
+ return;
+ }
+
+ while (nl != NULL) {
+ sprintf(debugbuff, "Memo save %s", nl->nick);
+ tmp = nl->memos;
+ if (tmp) {
+ fprintf(db.ms, "data %s %i %i %i %i %lu\n", nl->nick,
+ tmp->memos, tmp->sent, tmp->flags, tmp->max,
+ (long) tmp->lastsent);
+ if ((tmp->flags & MFORWARDED) && (tmp->redirect[0]))
+ fprintf(db.ms, "redirect %s %s\n", nl->nick,
+ tmp->redirect);
+ for (memo = tmp->firstMemo; memo; memo = memo->next)
+ fprintf(db.ms, "memo %s %i %i %lu %s :%s\n", nl->nick,
+ memo->index, memo->flags, (long) memo->sent,
+ memo->from, memo->memo);
+ x++;
+#ifdef DBDEBUG
+ sSend("GNOTICE :Saved memo data (%s)", nl->nick);
+#endif
+ } else {
+ fprintf(db.ms, "data %s 0 0 0 %i\n", nl->nick, MS_DEF_RCV_MAX);
+ x++;
+ }
+ fflush(db.ms);
+ strcat(debugbuff, " (success)");
+ nl = nl->next;
+ }
+ fprintf(db.ms, "done\n");
+ fflush(db.ms);
+ fclose(db.ms);
+#ifdef SHOWSYNCH
+ sSend(":%s GLOBOPS :Completed save(%i)", MemoServ, mostmemos);
+#endif
+}
+
+void readMemoData()
+{
+ RegNickList *nick;
+ MemoBox *newbox;
+ MemoList *newmemo;
+ char line[2048];
+ char *tmp = line;
+ char args[15][MEMOLEN];
+ int done = 0;
+ int x, a;
+
+ mostmemos = 0;
+ db.ms = fopen(DBDIR "/memoserv.db", "r");
+ if (!db.ms) {
+ Debug((DEBUG_ERROR, "Failed to open memoserv db"));
+ return;
+ }
+ while (!done) {
+ if (!(sfgets(line, 2048, db.ms))) {
+ done = 1;
+ fclose(db.ms);
+ return;
+ }
+ for (x = 0; x < 7; x++)
+ args[x][0] = 0;
+
+ tmp = line;
+ x = a = 0;
+ while (*tmp && x < 7) {
+ if ((x == 4 || x == 6) && *tmp == ':') {
+ tmp++;
+ while (*tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ } else {
+ while (*tmp != ' ' && *tmp) {
+ args[x][a] = *tmp;
+ a++;
+ tmp++;
+ }
+ }
+
+ args[x][a] = 0;
+ x++;
+ while (*tmp == ' ')
+ tmp++;
+ a = 0;
+ }
+
+ if (!strcmp(args[0], "data")) {
+ newbox = smalloc(sizeof(MemoBox));
+ nick = getRegNickData(args[1]);
+ if (nick) {
+ nick->memos = newbox;
+ newbox->memos = atoi(args[2]);
+ newbox->sent = atoi(args[3]);
+ newbox->flags = atoi(args[4]);
+ newbox->max = atoi(args[5]);
+ newbox->lastsent = (time_t) atol(args[6]);
+ } else {
+ free(newbox);
+ }
+ } else if (!strcmp(args[0], "redirect")) {
+ RegNickList *fwd_nick;
+ nick = getRegNickData(args[1]);
+ fwd_nick = getRegNickData(args[2]);
+ if (!fwd_nick)
+ nick->memos->flags &= ~MFORWARDED;
+ else
+ strcpy(nick->memos->redirect, args[2]);
+ } else if (!strcmp(args[0], "memo")) {
+ newmemo = smalloc(sizeof(MemoList));
+ nick = getRegNickData(args[1]);
+ if (nick) {
+ newmemo->index = atoi(args[2]);
+ newmemo->flags = atoi(args[3]);
+ newmemo->sent = (time_t) atol(args[4]);
+ strcpy(newmemo->from, args[5]);
+ strcpy(newmemo->memo, args[6]);
+ addMemo(nick->memos, newmemo);
+ } else
+ sfree(newmemo);
+ } else if (!strcmp(args[0], "done"))
+ done = 1;
+ else {
+ printf("failed.\n");
+ printf("Error reading: line: %s\n", line);
+ sshutdown(-1);
+ }
+
+#ifdef DBDEBUG
+ sSend("GNOTICE :Read memo data (%s)", line);
+#endif
+ }
+ fclose(db.ms);
+}
+
+void sync_cfg(char *type)
+{
+
+ if (!type) {
+ Debug((DEBUG_ERROR, "Call to sync_cfg with no arguments!"));
+ return;
+ }
+
+ Debug((DEBUG_ERROR, "Call to sync_cfg with argument '%c'", *type));
+
+ switch (*type) {
+ case '1':
+ syncNickData((time_t) (CTime + (SYNCTIME * 3)));
+ nextCsync = (CTime + SYNCTIME);
+ nextMsync = (CTime + (SYNCTIME * 2));
+ nextNsync = (CTime + (SYNCTIME * 3));
+ timer(SYNCTIME, sync_cfg, "syncChanData", "2");
+ break;
+ case '2':
+ syncChanData((time_t) (CTime + (SYNCTIME * 2)));
+ nextMsync = (CTime + SYNCTIME);
+ nextNsync = (CTime + (SYNCTIME * 2));
+ nextCsync = (CTime + (SYNCTIME * 2));
+ timer(SYNCTIME, sync_cfg, "syncMemoData", "3");
+ break;
+ case '3':
+ syncMemoData((time_t) (CTime + SYNCTIME));
+ nextNsync = nextCsync = nextMsync = (CTime + SYNCTIME);
+ timer(SYNCTIME, sync_cfg, "syncNickData+syncChanData+syncMemoData", "4");
+ break;
+ case '4':
+ syncNickData((time_t) (CTime + SYNCTIME));
+ syncChanData((time_t) (CTime + (SYNCTIME * 2)));
+ syncMemoData((time_t) (CTime + (SYNCTIME * 3)));
+ nextNsync = (CTime + SYNCTIME);
+ nextCsync = (CTime + SYNCTIME * 2);
+ nextMsync = (CTime + SYNCTIME * 3);
+ timer(SYNCTIME, sync_cfg, "syncNickData", "1");
+ break;
+ default:
+ Debug((DEBUG_ERROR, "Call to sync_cfg(%s), there is no such thing!", type));
+ break;
+ }
+}
+
+void disk_synch()
+{
+ saveChanData(firstRegChan);
+ saveNickData(firstRegNick);
+ saveMemoData(firstRegNick);
+}
+
+void do_remaining_backup(char *placeholder)
+{
+
+ char backup[50];
+ char cmd[512];
+ time_t timestart;
+
+ timestart = time(NULL);
+
+ strftime(backup, 30, "access_mod.db%d%m%Y", localtime(×tart));
+ sprintf(cmd, "cp %s/access_mod.db %s/%s", DBDIR, DBDIR, backup);
+ system(cmd);
+
+ strftime(backup, 30, "dekill.db%d%m%Y", localtime(×tart));
+ sprintf(cmd, "cp %s/dekill.db %s/%s",
+ DBDIR, DBDIR, backup);
+ system(cmd);
+
+ strftime(backup, 30, "memoserv.db%d%m%Y", localtime(×tart));
+ sprintf(cmd, "cp %s/memoserv.db %s/%s",
+ DBDIR, DBDIR, backup);
+ system(cmd);
+
+ timer(2 * 3600, do_remaining_backup, "do_remaining_backup", "void");
+}
--- /dev/null
+#include "services.h"
+
+
+/*
+ * this func borrowed from DALnet ircd, and such
+ */
+long getHashKey(char *hname)
+{
+ unsigned char *name = (unsigned char *) hname;
+ long hash = 0x00005555;
+
+ for (; *name; name++)
+ hash = (hash << 2) ^ tolower(*name);
+
+ if (hash < 0)
+ hash = -hash;
+ return (hash);
+}
+
+/*
+ * clean hash tables, one for each table
+ */
+
+void cleanNickHash(void)
+{
+ long i;
+
+ for (i = 0; i < NICKHASHSIZE; i++) {
+ RegNickHash[i].nick = RegNickHash[i].lastnick = NULL;
+ UserHash[i].nick = UserHash[i].lastnick = NULL;
+ }
+ for (i = 0; i < CLONEHASHSIZE; i++) {
+ CloneHash[i].clone = CloneHash[i].lastclone = NULL;
+ }
+ return;
+}
+
+void cleanChanHash(void)
+{
+ long i;
+
+ for (i = 0; i < CHANHASHSIZE; i++) {
+ RegChanHash[i].chan = RegChanHash[i].lastchan = NULL;
+ ChanHash[i].chan = ChanHash[i].lastchan = NULL;
+ }
+ return;
+}
--- /dev/null
+#include "services.h"
+
+/*
+ * For lack of better place to put this stuff....
+ * * MOTD/help stuff, :>
+ */
+
+void showMotd(char *to)
+{
+ sSend(":%s 375 %s :- %s Message of the Day - ", myname, to, myname);
+
+ sSend(":%s 372 %s :-", myname, to);
+ sSend(":%s 372 %s :- Serenity-IRC Network Services %s.",
+ myname, to, PACKAGE " v" VERSION);
+ sSend(":%s 372 %s :- Copyright (c) 1997-2003 StarChat, Serenity-IRC",
+ myname, to);
+ sSend(":%s 372 %s :-", myname, to);
+ sSend
+ (":%s 372 %s :- There are currently \002%lu\002 nicknames and \002%lu\002 channels registered.",
+ myname, to, mostnicks, mostchans);
+ sSend(":%s 372 %s :- Our current user-record is \002%lu\002 users.",
+ myname, to, mostusers);
+ sSend(":%s 372 %s :-", myname, to);
+ sSend(":%s 372 %s :- If you require IRC Operator assistance, please join #help",
+ myname, to);
+ sSend(":%s 372 %s :-", myname, to);
+ sSend(":%s 372 %s :End of /MOTD command", myname, to);
+}
+
+/* Used for parsing of the helpdata */
+char tmpstr[81];
+
+char *parsestr(char *str)
+{
+ char *s1, *s2;
+
+ s2 = tmpstr;
+ bzero(tmpstr, 81);
+
+ for (s1 = str; *s1; s1++) {
+ if (*s1 == '%')
+ *s2 = '\002';
+ else if (*s1 == '&')
+ *s2 = '\x1f';
+ else
+ *s2 = *s1;
+ s2++;
+ }
+
+ return (char *) tmpstr;
+}
+
+char *fixnullstr(char *str)
+{
+ char *s1, *s2;
+ int allspace = 1;
+
+ for (s1 = str; *s1; s1++) {
+ if (*s1 != ' ') {
+ allspace = 0;
+ break;
+ }
+ }
+ if (allspace) {
+ strcpy(str, " ");
+ return str;
+ } else {
+ s2 = parsestr(str);
+ return s2;
+ }
+}
+void sendHelp(char *to, char *service, char *args[511], int numargs)
+{
+ int i;
+ char data[81];
+ char filename[512];
+ char searchargs[512];
+ FILE *fp;
+
+ UserList *tmp;
+
+ if (service == NULL) /* YIPE -- NO SERVICE ASKED FOR THIS */
+ return;
+
+ tmp = getNickData(to);
+
+ strcpy(filename, GetLanguage(tmp));
+ strcat(filename, "/");
+ strcat(filename, service);
+ strcat(filename, "/");
+
+
+
+ if (numargs == 0) { /* DEFAULT -- INDEX.HELP */
+ strcat(filename, "index.help\0");
+ strcpy(searchargs, service);
+ } else {
+ strcat(filename, args[1]);
+ strcpy(searchargs, args[1]);
+ i = 2;
+
+ while (i < numargs) {
+ strcat(filename, "-");
+ strcat(filename, args[i]);
+ strcat(searchargs, " ");
+ strcat(searchargs, args[i]);
+ i++;
+ }
+ strcat(filename, ".help\0");
+ }
+ strtolower(filename);
+
+#ifdef DEBUG
+ printf("Attempting to open helpfile '%s'...\n", filename);
+#endif
+
+ i = 0;
+
+ if ((fp = fopen(filename, "r")) != NULL) {
+ if (tmp) {
+ while (sfgets(data, 81, fp)) {
+ if (!strncmp(data, "<oper>", 6)) {
+ while (sfgets(data, 81, fp) && strncmp(data, "</oper>", 7)) {
+ if (isOper(tmp)) {
+ uSend(service, tmp, GetReply(RPL_HELP, tmp), fixnullstr(data));
+ i++;
+ }
+ }
+ } else if (!strncmp(data, "<servop>", 8)) {
+ while (sfgets(data, 81, fp) && strncmp(data, "</servop>", 9)) {
+ if (isServop(tmp)) {
+ uSend(service, tmp, GetReply(RPL_HELP, tmp), fixnullstr(data));
+ i++;
+ }
+ }
+ } else if (!strncmp(data, "<root>", 6)) {
+ while (sfgets(data, 81, fp) && strncmp(data, "</root>", 7)) {
+ if (isRoot(tmp)) {
+ uSend(service, tmp, GetReply(RPL_HELP, tmp), fixnullstr(data));
+ i++;
+ }
+ }
+ } else {
+ uSend(service, tmp, GetReply(RPL_HELP, tmp),
+ fixnullstr(data));
+ i++;
+ }
+ }
+ }
+ fclose(fp);
+ }
+
+ if (!i) {
+ uSend(service, tmp, GetReply(ERR_NOHELPONTHAT, tmp), searchargs);
+ }
+}
--- /dev/null
+#include "services.h"
+
+
+void AddJinx(char *nick, char *by, char *reason)
+{
+
+ aJinx *Jinxptr;
+
+ Jinxptr = make_jinx();
+ strncpy(Jinxptr->nick, nick, sizeof(Jinxptr->nick));
+ strncpy(Jinxptr->by, by, sizeof(Jinxptr->by));
+ Jinxptr->time = CTime;
+ strncpy(Jinxptr->reason, reason, sizeof(Jinxptr->reason));
+
+ if (JinxList == NULL)
+ JinxList = Jinxptr;
+ else {
+ JinxList->prev = Jinxptr;
+ Jinxptr->next = JinxList;
+ JinxList = Jinxptr;
+ }
+
+ return;
+}
+
+aJinx *make_jinx()
+{
+ aJinx *Jinxptr;
+
+ Jinxptr = (aJinx *) smalloc(sizeof(aJinx));
+
+ Jinxptr->nick[0] = '\0';
+ Jinxptr->by[0] = '\0';
+ Jinxptr->time = 0;
+ Jinxptr->reason[0] = '\0';
+ Jinxptr->prev = Jinxptr->next = NULL;
+
+ return Jinxptr;
+}
+
+void free_jinx(jinxptr)
+aJinx *jinxptr;
+{
+ free((char *) jinxptr);
+}
+
+void DeleteJinx(char *nick)
+{
+
+ aJinx *jinxptr;
+ aJinx *jinxptr2;
+
+ if (JinxList == NULL)
+ return;
+
+ for (jinxptr = JinxList; jinxptr; jinxptr = jinxptr2) {
+ jinxptr2 = jinxptr->next;
+ if (!strcasecmp(jinxptr->nick, nick)) {
+ if (jinxptr->prev)
+ jinxptr->prev->next = jinxptr->next;
+ else
+ JinxList = jinxptr->next;
+ if (jinxptr->next)
+ jinxptr->next->prev = jinxptr->prev;
+ free_jinx(jinxptr);
+ return;
+ }
+ }
+
+ return;
+}
+
+int CheckJinx(char *jinx)
+{
+
+ aJinx *jinxptr;
+ aJinx *jinxptr2;
+
+ if (JinxList == NULL)
+ return 0;
+
+ for (jinxptr = JinxList; jinxptr; jinxptr = jinxptr2) {
+ jinxptr2 = jinxptr->next;
+ if (!strcasecmp(jinxptr->nick, jinx)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int FreeJinxedHost(char *hostmask, char *from)
+{
+ UserList *tmp;
+
+ int i = 0;
+
+ for (tmp = firstUser; tmp; tmp = tmp->next) {
+ if (JinxHostMatch(tmp->nick, tmp->user, tmp->host, hostmask)) {
+ if (CheckJinx(tmp->nick)){
+ i++;
+ DeleteJinx(tmp->nick);
+ sSend(":%s UNJINX %s", myname, tmp->nick);
+ }
+ }
+ }
+ sSend(":%s GLOBOPS :\002%d\002 active JINX's removed", OperServ, i);
+ return i;
+}
+
+int JinxJinxedHost(char *hostmask, char *by, char* reason)
+{
+ UserList *tmp;
+
+ int i = 0;
+
+ for (tmp = firstUser; tmp; tmp = tmp->next) {
+ if (JinxHostMatch(tmp->nick, tmp->user, tmp->host, hostmask)) {
+ if(!CheckJinx(tmp->nick)){
+ i++;
+ AddJinx(tmp->nick, by, reason);
+ sSend(":%s JINX %s", myname, tmp->nick);
+ }
+ }
+ }
+ sSend(":%s GLOBOPS :\002%d\002 JINX's activated", OperServ, i);
+ return i;
+}
+
+int JinxHostMatch(char *nick, char *user, char *host, char *mask)
+{
+ /* isHJinxed is totaly messed up as far as FreeJinxedHost is concerned */
+ /* so something else needs to compare the mask.... */
+
+ int nick_match;
+ int user_match;
+ int host_match;
+
+ char *temp_mask;
+ char *string_ptr;
+ char *string_end;
+
+ temp_mask = (char *)smalloc( (sizeof( char) * strlen(mask)) + sizeof(char));
+ sprintf( temp_mask, "%s", mask);
+
+ string_end = index( temp_mask, '!');
+ *string_end = (char) NULL;
+ nick_match = match( nick, temp_mask);
+ *string_end = '!';
+
+ string_ptr = string_end + 1;
+ string_end = index( temp_mask, '@');
+ *string_end = (char) NULL;
+ user_match = match( user, string_ptr);
+ *string_end = '@';
+
+ string_ptr = string_end + 1;
+
+ host_match = match( host, string_ptr);
+
+ sfree( temp_mask);
+
+ if (!nick_match && !user_match && !host_match)
+ return 1;
+ else
+ return 0;
+
+}
--- /dev/null
+#include "services.h"
+#include <getopt.h>
+#include <dirent.h>
+#include <sys/types.h>
+
+char buffer[4096];
+int pdr, pds, brcv, bsnd;
+
+void checkTusers(void);
+void readConf(void);
+
+struct option long_opts[] = {
+ {"datadir", 1, 0, 'd'},
+ {"help", 0, 0, 'h'},
+ {"version", 0, 0, 'V'},
+ {0, 0, 0, 0}
+};
+
+void usage(void)
+{
+ printf(PACKAGE " v" VERSION " \n");
+ printf("Usage: services [options]\n");
+ printf("\t-d, --datadir\t\tDirectory with our data\n");
+ printf("\t-h, --help\t\tPrint this usage message\n");
+ printf("\t-V, --version\t\tPrint the release version\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ fd_set readme;
+ FILE *fp;
+ struct timeval tv;
+ int i;
+ int o;
+ time_t timestart;
+ char backup[124];
+ int languages;
+
+
+#ifdef FORCE_CORE
+ struct rlimit corelim;
+#endif
+ int pid = 0;
+
+ antiloop = 0;
+ timerbuff[0] = '\0';
+ debugbuff[0] = '\0';
+
+ startup = time(NULL);
+
+ /* use some very neato FreeBSD malloc() stuff... */
+ // setenv("MALLOC_OPTIONS", "AR", 1);
+
+#ifdef FORCE_CORE
+ corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_CORE, &corelim);
+#endif
+
+ while ((o = getopt_long(argc, argv, "d:hV", &long_opts[0], NULL)) != EOF) {
+ switch (o) {
+ case 'd':
+ strncpy(datadir, optarg, 512);
+ printf("Data directory is `%s`\n", datadir);
+ break;
+ case 'V':
+ printf(PACKAGE " v" VERSION "\n");
+ return 0;
+ case 'h':
+ usage();
+ return 0;
+ default:
+ case '?':
+ printf("Try `services --help` for more information.\n");
+ return 1;
+ }
+ }
+
+ if (getuid() == 0 || geteuid() == 0) {
+ fprintf(stderr, "Please do not run services as root!\n");
+ exit(1);
+ }
+
+ if (strcmp(datadir, ".") == 0) {
+ fprintf(stderr, "Please specify a full pathname to the data directory.\n");
+ exit(1);
+ }
+
+ if (strcmp(datadir, "") == 0) {
+ strcpy(datadir, getenv("HOME"));
+ strcat(datadir, "/services");
+ }
+
+ if (chdir(datadir) == -1) {
+ fprintf(stderr, "Invalid data directory. [%s]\n", datadir);
+ exit(1);
+ }
+
+ fp = fopen(PIDFILE, "r");
+ if (fp != NULL) {
+ fgets(buffer, 512, fp);
+ pid = atoi(buffer);
+ if (pid != 0) {
+ if(kill(pid, 0) == 0)
+ exit(1);
+ }
+
+ fclose(fp);
+ }
+
+// Make this smarker about missing directories
+// if (opendir(datadir))
+//
+ cslock = open(DBDIR "/chanserv.db", O_RDONLY);
+ i = flock(cslock, LOCK_EX | LOCK_NB);
+ if (!i)
+ nslock = open(DBDIR "/nickserv.db", O_RDONLY);
+ i = flock(nslock, LOCK_EX | LOCK_NB);
+ if (!i)
+ mslock = open(DBDIR "/memoserv.db", O_RDONLY);
+ i = flock(mslock, LOCK_EX | LOCK_NB);
+ if (i) {
+ sshutdown(-1);
+ } else
+ printf("Database files locked\n");
+
+ timestart = time(NULL);
+ strftime(backup, 120, COREDIR "/core.%d%b.%H%M",
+ localtime(×tart));
+ if (rename(COREFILE, backup) == 0) {
+ printf("Saving core file '%s' -> '%s'\n", COREFILE, backup);
+ }
+
+ firstRegNick = lastRegNick = NULL;
+ firstUser = lastUser = NULL;
+ firstReg = lastReg = NULL;
+ firstChan = lastChan = NULL;
+ firstRegChan = lastRegChan = NULL;
+#ifdef SERVICESOPER
+ firstOper = lastOper = NULL;
+#endif
+ pdr = pds = 0;
+ brcv = bsnd = 0;
+
+ printf("Loading Serenity-IRC " NETWORK " Services...\n");
+
+ /* logging files */
+ rootlog = fopen(LOGDIR "/root.log", "a");
+ if (rootlog == NULL) {
+ return 201;
+ }
+ operlog = fopen(LOGDIR "/operserv.log", "a");
+ if (operlog == NULL) {
+ printf("Failed to open operserv log\n");
+ return 201;
+ }
+ nicklog = fopen(LOGDIR "/nickserv.log", "a");
+ if (nicklog == NULL) {
+ printf("Failed to open nickserv log\n");
+ return 201;
+ }
+ chanlog = fopen(LOGDIR "/chanserv.log", "a");
+ if (chanlog == NULL) {
+ printf("Failed to open chanserv log\n");
+ return 201;
+ }
+ corelog = fopen(LOGDIR "/core.log", "a");
+ if (corelog == NULL) {
+ printf("Failed to open core log\n");
+ return 201;
+ }
+ printf("Logfiles opened\n");
+
+ /*
+ * clear out our hash lists
+ */
+ cleanNickHash();
+ cleanChanHash();
+ printf("Hashes cleaned\n");
+
+ AllocCalled = FreeCalled = 0;
+ printf("Reading Databases/configuration...\n");
+ printf("NickServ...");
+ readNickData();
+ printf("done.\n");
+ printf("ChanServ...");
+ readChanData();
+ printf("done.\n");
+ printf("MemoServ...");
+ readConf();
+ printf("done.\n");
+ printf("Complete...\n");
+ printf("My name : %s\n", myname);
+ printf("Primary host/port: %s %i\n", hostname[0], port[0]);
+ printf("Op/Akick Limits : %i/%i\n", OpLimit, AkickLimit);
+ printf("Nick/Chan Limits : %i/%i\n", NickLimit, ChanLimit);
+ printf("Access Item Limit: %i\n", AccessLimit);
+
+ fp = fopen("services.totals", "r");
+
+ if (fp) {
+ sfgets(buffer, 256, fp);
+ mostusers = atoi(buffer);
+ sfgets(buffer, 256, fp);
+ mostnicks = atoi(buffer);
+ sfgets(buffer, 256, fp);
+ mostchans = atoi(buffer);
+ sfgets(buffer, 256, fp);
+ mostmemos = atoi(buffer);
+ sfgets(buffer, 256, fp);
+ ac_mod_counter = atoi(buffer);
+ fclose(fp);
+ }
+ printf("Saved Totals: Users: %lu Nicks: %lu Chans: %lu Memos: %lu\n",
+ mostusers, mostnicks, mostchans, mostmemos);
+ totalusers = 3;
+
+#ifndef WIN32
+ signal(SIGPIPE, segvdie);
+ signal(SIGSEGV, segvdie);
+ signal(SIGHUP, SIG_IGN);
+#ifdef DEBUG
+ signal(SIGINT, segvdie);
+#else
+ signal(SIGINT, SIG_IGN);
+#endif
+ signal(SIGBUS, segvdie);
+ signal(SIGTERM, segvdie);
+
+ printf("Added signal handlers\n");
+#endif
+ OperServ = services[0].name;
+ NickServ = services[1].name;
+ ChanServ = services[2].name;
+ MemoServ = services[3].name;
+ WebServ = services[4].name;
+ Serenity = services[5].name;
+
+ /* Load the language-tables here */
+
+ languages = LoadTables();
+
+ server = -1;
+ for (i = 0; i < 10 && hostname[i][0]; i++) {
+ server = ConnectToServer(hostname[i], port[i]);
+ if (server >= 1)
+ break;
+ }
+
+ if (server < 0) {
+ printf("Could not connect to server!, exiting now.\n");
+ exit(0);
+ }
+
+ synched = 0;
+ sSend("PASS %s", mypass);
+ sSend("SERVER %s 1 Star5._cap1 :%s", myname, SERVERMLINE);
+
+ /* This could be done with SJOIN or SNICK */
+
+ addUser(services[0].name, services[0].uname, services[0].host, services[0].rname, services[0].mode);
+ addUser(services[1].name, services[1].uname, services[1].host, services[1].rname, services[1].mode);
+ addUser(services[2].name, services[2].uname, services[2].host, services[2].rname, services[2].mode);
+ addUser(services[3].name, services[3].uname, services[3].host, services[3].rname, services[3].mode);
+ addUser(services[4].name, services[4].uname, services[4].host, services[4].rname, services[4].mode);
+ addUser(services[5].name, services[5].uname, services[5].host, services[5].rname, services[5].mode);
+
+ printf("Connected to server %s/%i\n", hostname[i], port[i]);
+ flushLogs("void");
+ expireChans("void");
+ expireNicks("void");
+ sync_cfg("4");
+ load_access_mod();
+ loadpermignores();
+ loaddynamicekills();
+#ifdef BACKUPDATABASE
+ do_remaining_backup(NULL);
+#endif
+ printf("Initialized in %lu seconds\n\n", time(NULL) - startup);
+#if !defined(DEBUG) && !defined(NOFORK)
+ pid = fork();
+ if (pid) {
+ printf("Forking to background. PID: %i\n", pid);
+
+ flock(pidlock, LOCK_UN);
+ fp = fopen(PIDFILE, "w");
+ if (fp == NULL) {
+ printf("Warning: Failed to create pid file!");
+ return(0);
+ }
+ fprintf(fp, "%i", pid);
+ fclose(fp);
+ pidlock = open(PIDFILE, O_RDONLY);
+ return 0;
+ }
+#endif
+ sSend(":Serenity GLOBOPS :Serenity-IRC Network Services (%s) are now online.", PACKAGE " v" VERSION);
+
+ /* Add our jupes AFTER we sync, so that existing servers don't prevent us from connecting if they are in our JupeList */
+ timer(2, sync_jupes, "sync_jupes", "void");
+// sync_jupes();
+
+ while (1) { /* loop forever...supposedly... */
+ tv.tv_sec = 0;
+ tv.tv_usec = 500;
+ FD_ZERO(&readme);
+ FD_SET(server, &readme);
+ bzero(buffer, 4096);
+/* fflush(servout);*/
+#ifdef TELNET
+ checkTelnet();
+#endif
+
+ FromSendQ(); /* And here goes the sendQ */
+
+ if (select(server + 1, &readme, NULL, NULL, &tv)) {
+ recv(server, buffer, 4096, 0);
+
+ ToRecvQ(buffer); /* All data read goes right into the recvQ */
+ }
+
+ FromRecvQ(); /* And here it comes out again, looks so stupid without threads :) */
+
+ checktimers();
+ }
+ return(0);
+}
+
+void flushLogs(char *placeholder)
+{
+ fflush(nicklog);
+ fflush(chanlog);
+ fflush(operlog);
+ fflush(rootlog);
+ timer(60, flushLogs, "flushLogs", "void");
+}
+
+void srestart()
+{
+ FILE *fp = fopen("services.totals", "w");
+
+ if (fp) {
+ fprintf(fp, "%lu\n%lu\n%lu\n%lu\n%lu\n", mostusers, mostnicks,
+ mostchans, mostmemos, ac_mod_counter);
+ fflush(fp);
+ fclose(fp);
+ }
+
+ unlink(PIDFILE);
+ save_access_mod();
+ savepermignores();
+ savedynamicekills();
+ saveChanData(firstRegChan);
+ saveNickData(firstRegNick);
+ saveMemoData(firstRegNick);
+
+ flock(cslock, LOCK_UN);
+ flock(nslock, LOCK_UN);
+ flock(mslock, LOCK_UN);
+ flock(pidlock, LOCK_UN);
+ sSend(":%s SQUIT %s :Services %s restarted.", myname, hostservername, VERSION);
+ FromSendQ(); /* Let's empty our SendQ before splitting */
+/* fflush(servout);
+ fclose(servout);*/
+ close(server);
+ (void) execv("services", NULL);
+ exit(0);
+}
+
+void sshutdown(int type)
+{
+ FILE *fp = fopen("services.totals", "w");
+
+ if (fp) {
+ fprintf(fp, "%lu\n%lu\n%lu\n%lu\n%lu\n", mostusers, mostnicks, mostchans, mostmemos, ac_mod_counter);
+ fflush(fp);
+ fclose(fp);
+ }
+
+ if (type != (-1) && antiloop < 2) {
+ antiloop = 1;
+ save_access_mod();
+ savepermignores();
+ savedynamicekills();
+ saveChanData(firstRegChan);
+ saveNickData(firstRegNick);
+ saveMemoData(firstRegNick);
+ }
+
+ unlink(PIDFILE);
+
+ if (type == 1) {
+ sSend(":%s SQUIT %s :Services %s fall down go BOOM!", myname, hostservername, VERSION);
+ FromSendQ(); /* Let's empty our SendQ before splitting */
+/* fflush(servout);
+ fclose(servout);*/
+ close(server);
+ fclose(corelog);
+ kill(getpid(), 3);
+ kill(getpid(), 9);
+ exit(1);
+ } else if (type != -1) {
+ sSend(":%s SQUIT %s :Services %s shutdown.", myname, hostservername, VERSION);
+ FromSendQ(); /* Let's empty our SendQ before splitting */
+/* fflush(servout);
+ fclose(servout);*/
+ fclose(corelog);
+ close(server);
+ }
+ exit(0);
+}
+
+void WriteCoreLog(void)
+{
+ char temp[512];
+
+ strftime(temp, 80, "%a %d/%m/%Y %T %Z", localtime(&timertime));
+ logDump(corelog,
+ "<- Core Info ->");
+ if (coreBuffer[0])
+ logDump(corelog, "Last parsed command: %s", coreBuffer);
+ else
+ logDump(corelog, "Last parsed command: No commands parsed.");
+ if (timerbuff[0])
+ logDump(corelog, "Last used timer : %s at %s", timerbuff, temp);
+ else
+ logDump(corelog, "Last used timer : No timers called.");
+}
+
+#ifndef WIN32
+void segvdie(int doot)
+{
+ FILE *fp; /* File Pointer for the totals. -GZ */
+
+ switch (doot) {
+ case SIGPIPE:
+ case SIGINT:
+ case SIGTERM:
+ sshutdown(0);
+ break;
+ case SIGSEGV:
+ case SIGBUS:
+ if (!antiloop) {
+ antiloop++;
+
+ fp = fopen("services.totals", "w");
+
+ if (fp) {
+ fprintf(fp, "%lu\n%lu\n%lu\n%lu\n%lu\n", mostusers, mostnicks, mostchans, mostmemos, ac_mod_counter);
+ fflush(fp);
+ fclose(fp);
+ }
+
+ sSend(":%s GLOBOPS :\002PANICK!\002 Services has detected a fatal error and will shut itself down.", Serenity);
+ WriteCoreLog();
+ sshutdown(1);
+ } else {
+
+ fclose(corelog);
+ close(server);
+ kill(getpid(), 3);
+ kill(getpid(), 9);
+ }
+ break;
+ default:
+ sSend(":%s GLOBOPS :Received unidentified signal %i, ignoring.",
+ myname, doot);
+ break;
+ }
+ return;
+}
+#endif
+
+void readConf(void)
+{
+ /*
+ * read services.conf
+ */
+
+ FILE *fp;
+ char buffer[256];
+ char *args[256];
+ char realargs[256][128];
+ int i, x;
+
+ for (i = 0; i < 256; i++)
+ args[i] = realargs[i];
+
+ fp = fopen(CFGFILE, "r");
+ if (fp == NULL) {
+ printf("Failed to open config file '%s': %s\n", CFGFILE, strerror(errno));
+ exit(-1);
+ }
+
+ while (sfgets(buffer, 256, fp) != NULL) {
+ if (*buffer == '#' || !*buffer) {
+ } else {
+ bzero(args[0], 128);
+ bzero(args[1], 128);
+ bzero(args[2], 128);
+
+ i = breakString(255, buffer, args, " \t");
+
+ if (!strcasecmp(args[0], "MyName"))
+ strcpy(myname, args[1]);
+ else if (!strcasecmp(args[0], "Port"))
+ port[atoi(args[1])] = atoi(args[2]);
+ else if (!strcasecmp(args[0], "LinkPass"))
+ strcpy(mypass, args[1]);
+ else if (!strcasecmp(args[0], "ConnectHost")) {
+ strcpy(hostname[atoi(args[1])], args[2]);
+ hostname[atoi(args[1]) + 1][0] = 0;
+ } else if (!strcasecmp(args[0], "OSNick"))
+ strcpy(services[0].name, args[1]);
+ else if (!strcasecmp(args[0], "OSUserName"))
+ strcpy(services[0].uname, args[1]);
+ else if (!strcasecmp(args[0], "OSHostName"))
+ strcpy(services[0].host, args[1]);
+ else if (!strcasecmp(args[0], "OSRealName")) {
+ x = 2;
+ strcpy(services[0].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[0].rname, " ");
+ strcat(services[0].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "OSUserMode"))
+ strcpy(services[0].mode, args[1]);
+ else if (!strcasecmp(args[0], "NSNick"))
+ strcpy(services[1].name, args[1]);
+ else if (!strcasecmp(args[0], "NSUserName"))
+ strcpy(services[1].uname, args[1]);
+ else if (!strcasecmp(args[0], "NSHostName"))
+ strcpy(services[1].host, args[1]);
+ else if (!strcasecmp(args[0], "NSRealName")) {
+ x = 2;
+ strcpy(services[1].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[1].rname, " ");
+ strcat(services[1].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "NSUserMode"))
+ strcpy(services[1].mode, args[1]);
+ else if (!strcasecmp(args[0], "CSNick"))
+ strcpy(services[2].name, args[1]);
+ else if (!strcasecmp(args[0], "CSUserName"))
+ strcpy(services[2].uname, args[1]);
+ else if (!strcasecmp(args[0], "CSHostName"))
+ strcpy(services[2].host, args[1]);
+ else if (!strcasecmp(args[0], "CSRealName")) {
+ x = 2;
+ strcpy(services[2].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[2].rname, " ");
+ strcat(services[2].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "CSUserMode"))
+ strcpy(services[2].mode, args[1]);
+ else if (!strcasecmp(args[0], "MSNick"))
+ strcpy(services[3].name, args[1]);
+ else if (!strcasecmp(args[0], "MSUserName"))
+ strcpy(services[3].uname, args[1]);
+ else if (!strcasecmp(args[0], "MSHostName"))
+ strcpy(services[3].host, args[1]);
+ else if (!strcasecmp(args[0], "MSRealName")) {
+ x = 2;
+ strcpy(services[3].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[3].rname, " ");
+ strcat(services[3].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "MSUserMode"))
+ strcpy(services[3].mode, args[1]);
+ else if (!strcasecmp(args[0], "WSNick"))
+ strcpy(services[4].name, args[1]);
+ else if (!strcasecmp(args[0], "WSUserName"))
+ strcpy(services[4].uname, args[1]);
+ else if (!strcasecmp(args[0], "WSHostName"))
+ strcpy(services[4].host, args[1]);
+ else if (!strcasecmp(args[0], "WSRealName")) {
+ x = 2;
+ strcpy(services[4].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[4].rname, " ");
+ strcat(services[4].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "WSUserMode"))
+ strcpy(services[4].mode, args[1]);
+ else if (!strcasecmp(args[0], "GMNick"))
+ strcpy(services[5].name, args[1]);
+ else if (!strcasecmp(args[0], "GMUserName"))
+ strcpy(services[5].uname, args[1]);
+ else if (!strcasecmp(args[0], "GMHostName"))
+ strcpy(services[5].host, args[1]);
+ else if (!strcasecmp(args[0], "GMRealName")) {
+ x = 2;
+ strcpy(services[5].rname, args[1]);
+
+ while (x < i) {
+ strcat(services[5].rname, " ");
+ strcat(services[5].rname, args[x]);
+ x++;
+ }
+ } else if (!strcasecmp(args[0], "GMUserMode"))
+ strcpy(services[5].mode, args[1]);
+ else if (!strcasecmp(args[0], "OpLimit"))
+ OpLimit = atoi(args[1]);
+ else if (!strcasecmp(args[0], "BanLimit"))
+ AkickLimit = atoi(args[1]);
+ else if (!strcasecmp(args[0], "AccessItemLimit"))
+ AccessLimit = atoi(args[1]);
+ else if (!strcasecmp(args[0], "ChanLimit"))
+ ChanLimit = atoi(args[1]);
+ else if (!strcasecmp(args[0], "NickLimit"))
+ NickLimit = atoi(args[1]);
+ else if (!strcasecmp(args[0], "RootAdmin")) {
+ RegNickList *root;
+ root = getRegNickData(args[1]);
+
+ if (root) {
+ root->flags |= NHOLD;
+ root->flags |= NROOT;
+ }
+ } else if (!strcasecmp(args[0], "NetAdmin")) {
+ RegNickList *root;
+ root = getRegNickData(args[1]);
+
+ if (root) {
+ root->flags |= NHOLD;
+ root->flags |= NROOT;
+ root->flags |= NNETADM;
+ }
+ } else if (!strcasecmp(args[0], "NetFounder")) {
+ RegNickList *root;
+ root = getRegNickData(args[1]);
+
+ if (root) {
+ root->flags |= NHOLD;
+ root->flags |= NROOT;
+ }
+ } else if (!strcasecmp(args[0], "ForceMask"))
+ addForce(args[1]);
+ else if (!strcasecmp(args[0], "BanChannel"))
+ addBanChannel(args[1]);
+ else if (!strcasecmp(args[0], "BadNick"))
+ addBadNick(args[1]);
+ }
+ }
+ fclose(fp);
+}
+
+#ifdef DEBUG
+/* Don't call this function directly, use the macro Debug
+ * as follows:
+ * Debug((LOGLEVEL,"Mesg %s",param))
+ * Don't forget the (( ))
+ */
+#ifdef DEBUGFILE
+static int debugfd = -1;
+#endif
+
+void _debug(int level, char *msg, ...)
+{
+ va_list vl;
+ static char debugbuf[2049];
+ int len;
+
+ if (level > DEBUG)
+ return;
+
+ va_start(vl, msg);
+ vsprintf(debugbuf, msg, vl);
+ va_end(vl);
+
+ len = strlen(debugbuf);
+ if (len == 0)
+ return;
+ if (debugbuf[len - 1] != '\n') {
+ debugbuf[len++] = '\n';
+ debugbuf[len] = 0;
+ }
+
+#ifdef DEBUGFILE
+ if (debugfd == -1) {
+ /* Open the debugging file */
+ debugfd = open(DEBUGFILE, O_CREAT | O_WRONLY);
+ if (debugfd == -1) {
+ fprintf(stderr,
+ "Panic! Can't open debugfile \"%s\"! Aborting!\n",
+ DEBUGFILE);
+ exit(200);
+ }
+ }
+ write(debugfd, debugbuf, len);
+#endif
+ fputs(debugbuf, stderr);
+
+ return;
+}
+
+#endif /* DEBUG */
--- /dev/null
+#include "services.h"
+
+void indexMemoList(MemoBox *);
+
+void initMemoBox(MemoBox * memobox)
+{
+ memobox->memos = memobox->flags = memobox->sent = 0;
+ memobox->lastsent = 0;
+ memobox->max = MS_DEF_RCV_MAX;
+ memobox->redirect[0] = 0;
+ memobox->firstMemo = memobox->lastMemo = NULL;
+}
+
+void checkMemos(UserList * nick)
+{
+ int unread, save, fwd, reply, i;
+ MemoList *tmp;
+ i = unread = save = fwd = reply = 0;
+
+ if (!nick->reg || !nick->reg->memos) return;
+
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next)
+ {
+ i++;
+ if (tmp->flags & MEMO_UNREAD) unread++;
+ if (tmp->flags & MEMO_SAVE) save++;
+ if (tmp->flags & MEMO_FWD) fwd++;
+ if (tmp->flags & MEMO_REPLY) reply++;
+ }
+
+ if (unread) uSend(MemoServ, nick, GetReply(RPL_YOUHAVEMEMOS, nick), unread, i);
+}
+
+void cleanMemos(UserList * nick)
+{
+ MemoList *tmp;
+ if (!nick->reg->memos) return;
+ if (nick->reg->memos->flags & MSELFCLEAN)
+ {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next)
+ {
+ if (tmp->flags & MEMO_DELETE) delMemo(nick->reg->memos, tmp);
+ }
+ }
+}
+
+void addMemo(MemoBox * mbox, MemoList * memo)
+{
+ mostmemos++;
+ if (!mbox->firstMemo)
+ {
+ mbox->firstMemo = memo;
+ memo->previous = NULL;
+ }
+ else
+ {
+ mbox->lastMemo->next = memo;
+ memo->previous = mbox->lastMemo;
+ }
+ mbox->lastMemo = memo;
+ memo->next = NULL;
+ indexMemoList(mbox);
+}
+
+void delMemo(MemoBox * mbox, MemoList * memo)
+{
+ mostmemos--;
+ if (memo->previous) memo->previous->next = memo->next;
+ else mbox->firstMemo = memo->next;
+ if (memo->next) memo->next->previous = memo->previous;
+ else mbox->lastMemo = memo->previous;
+ sfree(memo);
+ indexMemoList(mbox);
+}
+
+void indexMemoList(MemoBox * mbox)
+{
+ MemoList *tmp;
+ int i = 1;
+ for (tmp = mbox->firstMemo; tmp; tmp = tmp->next)
+ {
+ tmp->index = i;
+ i++;
+ }
+ mbox->memos = (i - 1);
+}
+
+/* yeah yeah, global variable, feh. */
+char memos[20][NICKLEN];
+
+void sendToMemoServ(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ if (!strcmp(args[0], "\001PING"))
+ {
+ if (numargs < 3) uSend(MemoServ, nick, GetReply(RPL_PING1, nick), args[1]);
+ else uSend(MemoServ, nick, GetReply(RPL_PING2, nick), args[1], args[2]);
+ return;
+ }
+
+ if (!strcasecmp(args[0], "HELP") && numargs == 1)
+ {
+ sendHelp(from, MemoServ, NULL, 0);
+ return;
+ }
+ else if (!strcasecmp(args[0], "HELP"))
+ {
+ sendHelp(from, MemoServ, args, numargs);
+ return;
+ }
+ if (((nick->reg && nick->reg->memos) && (nick->reg->memos->flags & MSECURE) && nick->caccess < 3))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_ACCESSDENIED, nick));
+ return;
+ }
+ else if (nick->reg && !nick->reg->flags & NACTIVE)
+ {
+ uSend(MemoServ, nick, GetReply(ERR_NEEDACTNICK, nick));
+ return;
+ }
+ else if (nick->caccess < 2)
+ {
+ uSend(MemoServ, nick, GetReply(ERR_ACCESSDENIED, nick));
+ return;
+ }
+ else
+ {
+ char *blech = args[1];
+ int i = 0, x = 0;
+
+ if (!nick->reg->memos)
+ {
+ MemoBox *odd;
+ odd = smalloc(sizeof(MemoBox));
+ initMemoBox(odd);
+ nick->reg->memos = odd;
+ }
+
+ if (blech)
+ {
+ bzero(memos, 20 * NICKLEN);
+ while ((*blech) && (x < 20))
+ {
+ if (*blech == ',')
+ {
+ memos[x][i] = 0;
+ x++;
+ i = 0;
+ blech++;
+ } else if (!*blech) {
+ memos[x][i] = 0;
+ x++;
+ memos[x][0] = 0;
+ break;
+ } else {
+ memos[x][i] = *blech;
+ i++;
+ blech++;
+ }
+ }
+ }
+
+ msgtabCheck(MemoServ, nick, args, numargs); /* New messagetables to replace old code -GZ */
+
+ }
+}
+
+void MreadCmd(UserList * nick, char **args, int numargs)
+{
+ int i;
+ MemoList *tmp;
+ struct tm *time;
+ char temp[30];
+
+ if (!strcasecmp(args[1], "all")) {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ time = localtime(&tmp->sent);
+ strftime(temp, 30, "%a %d/%m/%Y %T %Z", time);
+ uSend(MemoServ, nick, GetReply(RPL_MEMO1, nick), tmp->index,
+ temp,
+ tmp->flags & MEMO_DELETE ? "Deleted" : tmp->
+ flags & MEMO_UNREAD ? "New" : "Read");
+ uSend(MemoServ, nick, GetReply(RPL_MEMO2, nick), tmp->from,
+ tmp->memo);
+ tmp->flags &= ~MEMO_UNREAD;
+ }
+ }
+
+ else {
+ int y;
+ for (y = 0; memos[y][0]; y++) {
+ i = atoi(memos[y]);
+ if (i > nick->reg->memos->memos || i <= 0) {
+ uSend(MemoServ, nick, GetReply(ERR_NOSUCHMEMO, nick), i);
+ return;
+ }
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ if (tmp->index == i)
+ break;
+ }
+
+ time = localtime(&tmp->sent);
+ strftime(temp, 30, "%a %d/%m/%Y %T %Z", time);
+ uSend(MemoServ, nick, GetReply(RPL_MEMO1, nick), tmp->index,
+ temp,
+ tmp->flags & MEMO_DELETE ? "Deleted" : tmp->
+ flags & MEMO_UNREAD ? "New" : "Read");
+ uSend(MemoServ, nick, GetReply(RPL_MEMO2, nick), tmp->from,
+ tmp->memo);
+ tmp->flags &= ~MEMO_UNREAD;
+ }
+ }
+}
+
+void MlistCmd(UserList * nick, char **args, int numargs)
+{
+ MemoList *tmp;
+ struct tm *time;
+ char temp[30];
+ char search[NICKLEN + 2];
+ if (numargs < 2)
+ bzero(search, NICKLEN + 2);
+ else
+ strcpy(search, args[1]);
+
+ uSend(MemoServ, nick, GetReply(RPL_MLISTHEADER, nick), nick->nick);
+
+ if (nick->reg->memos->firstMemo) {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ if (search[0]) {
+ if (!match(tmp->from, search)) {
+ time = localtime(&tmp->sent);
+ strftime(temp, 30, "%a %d/%m/%Y %T %Z", time);
+ uSend(MemoServ, nick, GetReply(RPL_MLIST1, nick),
+ tmp->index, temp, tmp->from,
+ tmp->flags & MEMO_DELETE ? "Deleted" : tmp->
+ flags & MEMO_UNREAD ? "New" : "Read");
+ }
+ } else {
+ time = localtime(&tmp->sent);
+ strftime(temp, 30, "%a %d/%m/%Y %T %Z", time);
+ uSend(MemoServ, nick, GetReply(RPL_MLIST1, nick),
+ tmp->index, temp, tmp->from,
+ tmp->flags & MEMO_DELETE ? "Deleted" : tmp->
+ flags & MEMO_UNREAD ? "New" : "Read");
+ }
+ }
+ } else
+ uSend(MemoServ, nick, GetReply(ERR_MLISTEMPTY, nick));
+
+ uSend(MemoServ, nick, GetReply(RPL_MLISTFOOTER, nick));
+
+}
+
+void MsendCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegNickList *sendto;
+ MemoList *send;
+ UserList *unf;
+ char memo[512]; /* sanity */
+ int i;
+ unsigned int rnflg;
+ char sendnick[NICKLEN];
+
+ sendto = getRegNickData(args[1]);
+ rnflg=0;
+ if (nick->reg) rnflg=nick->reg->flags;
+
+ if (!sendto || !sendto->flags & NACTIVE) {
+ uSend(MemoServ, nick, GetReply(ERR_NICKNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ if (!sendto->memos) {
+ sendto->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(sendto->memos);
+ }
+
+ send = smalloc(sizeof(MemoList));
+ strcpy(send->from, from);
+ send->memo[0] = 0;
+ send->sent = CTime;
+ send->flags |= MEMO_UNREAD;
+ strcpy(memo, args[2]);
+ for (i = 3; i < numargs; i++) {
+ strcat(memo, " ");
+ strcat(memo, args[i]);
+ }
+
+ if (strlen(memo) >= MEMOLEN) {
+ uSend(MemoServ, nick, GetReply(ERR_MEMOTOOLONG, nick),
+ MEMOLEN - 1);
+ sfree(send);
+ return;
+ }
+
+ strcpy(send->memo, memo);
+
+ strcpy(sendnick, sendto->nick);
+
+ if (sendto->memos->flags & MFORWARDED) {
+ RegNickList *fwd_nick = getRegNickData(sendto->memos->redirect);
+ if (!fwd_nick) {
+ sendto->memos->flags &= ~MFORWARDED;
+ sendto->memos->redirect[0] = 0;
+ } else {
+ if (!fwd_nick->memos) {
+ fwd_nick->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(fwd_nick->memos);
+ }
+
+ if ((!(fwd_nick->memos->flags & MNOFORWARD))
+ && (!(fwd_nick->memos->flags & MNOMEMO))) {
+ sendto = fwd_nick;
+ send->flags |= MEMO_FWD;
+ }
+ }
+
+ }
+
+ if ((sendto->memos->flags & MNOMEMO) && (!(rnflg&(NROOT))))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_ISNOMEMO, nick), sendnick);
+ sfree(send);
+ return;
+ }
+
+ if ((sendto->memos->memos >= sendto->memos->max) && (!(rnflg&(NROOT))))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_MEMOBOXFULL, nick), sendnick);
+ sfree(send);
+ return;
+ }
+ if ((CTime - nick->reg->memos->lastsent) > 3600L)
+ {
+ nick->reg->memos->lastsent = CTime;
+ nick->reg->memos->sent = 0;
+ }
+
+ if ((nick->reg->memos->sent >= MS_SENT_MAX) && !isOper(nick))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_TOOMANYMEMOS, nick));
+ sfree(send);
+ return;
+ }
+
+ addMemo(sendto->memos, send);
+ unf = getNickData(sendto->nick);
+ if (unf && unf->caccess >= 2)
+ uSend(MemoServ, unf, GetReply(RPL_GOTNEWMEMO, unf), from,
+ send->index);
+ nick->reg->memos->sent++;
+ uSend(MemoServ, nick, GetReply(RPL_SENTMEMO, nick), sendnick);
+}
+
+void MforwardCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ MemoList *memo, *send = NULL;
+ RegNickList *sendto;
+ UserList *unf;
+ char sendnick[NICKLEN];
+ char tempmemo[MEMOLEN];
+ int sent_cnt = 0;
+
+ if (!strcasecmp(args[2], from)) {
+ uSend(MemoServ, nick, GetReply(ERR_NOFWDTOSELF, nick));
+ return;
+ }
+
+ if (!nick->reg->memos->firstMemo) {
+ uSend(MemoServ, nick, GetReply(ERR_MLISTEMPTY, nick));
+ return;
+ }
+
+ sendto = getRegNickData(args[2]);
+
+ if (!sendto || !sendto->flags & NACTIVE) {
+ uSend(MemoServ, nick, GetReply(ERR_NICKNOTREGGED, nick), args[2]);
+ return;
+ }
+
+ if (!sendto->memos) {
+ sendto->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(sendto->memos);
+ }
+
+ strcpy(sendnick, sendto->nick);
+
+ if (sendto->memos->flags & MFORWARDED) {
+ RegNickList *fwd_nick = getRegNickData(sendto->memos->redirect);
+ if (!fwd_nick) {
+ sendto->memos->flags &= ~MFORWARDED;
+ sendto->memos->redirect[0] = 0;
+ } else {
+ if (!fwd_nick->memos) {
+ fwd_nick->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(fwd_nick->memos);
+ }
+
+ if ((!(fwd_nick->memos->flags & MNOFORWARD))
+ && (!(fwd_nick->memos->flags & MNOMEMO))) {
+ sendto = fwd_nick;
+ }
+ }
+
+ }
+
+ if ((sendto->memos->flags & MNOFORWARD)
+ || (sendto->memos->flags & MNOMEMO)) {
+ uSend(MemoServ, nick, GetReply(ERR_ISNOFORWARD, nick), sendnick);
+ return;
+ }
+
+ if ((CTime - nick->reg->memos->lastsent) > 3600L) {
+ nick->reg->memos->lastsent = CTime;
+ nick->reg->memos->sent = 0;
+ }
+
+ if ((nick->reg->memos->sent >= MS_SENT_MAX) && !isOper(nick)) {
+ uSend(MemoServ, nick, GetReply(ERR_TOOMANYMEMOS, nick));
+ return;
+ }
+
+ if (!strcasecmp(args[1], "all")) {
+ for (memo = nick->reg->memos->firstMemo; memo; memo = memo->next) {
+
+ if (sendto->memos->memos >= sendto->memos->max) {
+ uSend(MemoServ, nick, GetReply(ERR_MEMOBOXFULL, nick),
+ sendnick);
+ break;
+ }
+
+ send = smalloc(sizeof(MemoList));
+ strcpy(send->from, memo->from);
+ send->sent = CTime;
+ send->flags |= MEMO_UNREAD | MEMO_FWD;
+ strcpy(tempmemo, memo->memo);
+ tempmemo[MEMOLEN - NICKLEN - 7] = 0;
+ sprintf(send->memo, "FWD:%s > %s", from, tempmemo);
+ addMemo(sendto->memos, send);
+ sent_cnt++;
+ }
+ } else {
+ int i, y;
+ for (y = 0; memos[y][0]; y++) {
+ i = atoi(memos[y]);
+ if (i > nick->reg->memos->memos || i <= 0) {
+ uSend(MemoServ, nick, GetReply(ERR_NOSUCHMEMO, nick), i);
+ return;
+ }
+ for (memo = nick->reg->memos->firstMemo; memo;
+ memo = memo->next) {
+ if (memo->index == i)
+ break;
+ }
+
+ if (sendto->memos->memos >= sendto->memos->max) {
+ uSend(MemoServ, nick, GetReply(ERR_MEMOBOXFULL, nick),
+ sendnick);
+ break;
+ }
+
+ send = smalloc(sizeof(MemoList));
+ strcpy(send->from, memo->from);
+ send->sent = CTime;
+ send->flags |= MEMO_UNREAD | MEMO_FWD;
+ strcpy(tempmemo, memo->memo);
+ tempmemo[MEMOLEN - NICKLEN - 7] = 0;
+ sprintf(send->memo, "FWD:%s > %s", from, tempmemo);
+ addMemo(sendto->memos, send);
+ sent_cnt++;
+ }
+ }
+ if (sent_cnt) {
+ nick->reg->memos->sent++;
+ unf = getNickData(sendto->nick);
+ if (unf && unf->caccess >= 2)
+ uSend(MemoServ, unf, GetReply(RPL_GOTNEWMEMO, unf), from,
+ send->index);
+ uSend(MemoServ, nick, GetReply(RPL_MEMOFORWARDED, nick), sent_cnt,
+ sent_cnt == 1 ? "" : "s", sendnick);
+ }
+}
+
+void MdeleteCmd(UserList * nick, char **args, int numargs)
+{
+ MemoList *tmp;
+
+ if (!strcasecmp(args[1], "all")) {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ tmp->flags |= MEMO_DELETE;
+ }
+ uSend(MemoServ, nick, GetReply(RPL_DELMEMO, nick), "ALL");
+ } else if (!strcasecmp(args[1], "new")) {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ if (tmp->flags & MEMO_UNREAD) {
+ tmp->flags |= MEMO_DELETE;
+ }
+ }
+ uSend(MemoServ, nick, GetReply(RPL_DELMEMO, nick), "ALL UNREAD");
+ } else if (!strcasecmp(args[1], "old") || !strcasecmp(args[1], "read")) {
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ if (!(tmp->flags & MEMO_UNREAD))
+ tmp->flags |= MEMO_DELETE;
+ }
+ uSend(MemoServ, nick, GetReply(RPL_DELMEMO, nick), "ALL READ");
+ } else {
+ int y, i;
+ for (y = 0; memos[y][0]; y++) {
+ i = atoi(memos[y]);
+ if (i <= 0 || i > nick->reg->memos->memos)
+ uSend(MemoServ, nick, GetReply(ERR_NOSUCHMEMO, nick), i);
+ else {
+ for (tmp = nick->reg->memos->firstMemo; tmp;
+ tmp = tmp->next) {
+ if (tmp->index == i) {
+ tmp->flags |= MEMO_DELETE;
+ break;
+ }
+ }
+ uSend(MemoServ, nick, GetReply(RPL_DELMEMONR, nick), i);
+ }
+ }
+ }
+
+ McleanCmd(nick, args, numargs);
+}
+
+void McleanCmd(UserList * nick, char **args, int numargs)
+{
+ MemoList *tmp;
+ int i, x;
+
+ i = x = 0;
+
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next, x++) {
+ if (tmp->flags & MEMO_DELETE) {
+ delMemo(nick->reg->memos, tmp);
+ i++;
+ }
+ }
+}
+
+
+void MsetCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ if (!strcasecmp(args[1], "secure")) {
+ if (numargs < 3)
+ uSend(MemoServ, nick, GetReply(RPL_NSETIS, nick),
+ "Secure Memos",
+ nick->reg->memos->flags & MSECURE ? "ON" : "OFF");
+ else if (!strcasecmp(args[2], "on")) {
+ nick->reg->memos->flags |= MSECURE;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Secure Memos", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ nick->reg->memos->flags &= ~MSECURE;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Secure Memos", "OFF");
+ } else {
+ uSend(MemoServ, nick, GetReply(ERR_BADSETTING, nick), args[2]);
+ uSend(MemoServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ MemoServ, "SET SECURE");
+ }
+ } else if (!strcasecmp(args[1], "nomemo")) {
+ if (numargs < 3)
+ uSend(MemoServ, nick, GetReply(RPL_NSETIS, nick),
+ "Memo Reception Blocking",
+ nick->reg->memos->flags & MNOMEMO ? "ON" : "OFF");
+ else if (!strcasecmp(args[2], "on")) {
+ nick->reg->memos->flags |= MNOMEMO;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Memo Reception Blocking", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ nick->reg->memos->flags &= ~MNOMEMO;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Memo Reception Blocking", "OFF");
+ } else {
+ uSend(MemoServ, nick, GetReply(ERR_BADSETTING, nick), args[2]);
+ uSend(MemoServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ MemoServ, "SET NOMEMO");
+ }
+ } else if (!strcasecmp(args[1], "max")) {
+ if (numargs < 3)
+ uSend(MemoServ, nick, GetReply(RPL_MMAX, nick),
+ "Maximum Memos", nick->reg->memos->max);
+ else {
+ int i = atoi(args[2]);
+ if (i <= 0 || i > MS_RCV_MAX_HIGHEST)
+ uSend(MemoServ, nick, GetReply(ERR_MMAXSET, nick),
+ MS_RCV_MAX_HIGHEST);
+ else {
+ nick->reg->memos->max = i;
+ uSend(MemoServ, nick, GetReply(RPL_MMAXNOW, nick),
+ "Maximum Memos", nick->reg->memos->max);
+ }
+ }
+ } else if (!strcasecmp(args[1], "forward")) {
+ if (numargs < 3) {
+ if ((nick->reg->memos->flags & MFORWARDED)
+ && (getRegNickData(nick->reg->memos->redirect)))
+ uSend(MemoServ, nick, GetReply(RPL_MFORWARD, nick),
+ nick->reg->memos->redirect);
+ else
+ uSend(MemoServ, nick, GetReply(RPL_MFORWARD, nick),
+ "NOBODY");
+ } else {
+ if (!strcasecmp(args[2], from)) {
+ nick->reg->memos->flags &= ~MFORWARDED;
+ nick->reg->memos->redirect[0] = 0;
+ uSend(MemoServ, nick, GetReply(RPL_MFORWARDNOW, nick),
+ "NOBODY");
+ } else {
+ RegNickList *fwd_nick = getRegNickData(args[2]);
+ if ((!fwd_nick) || (!(fwd_nick->flags & NACTIVE)))
+ uSend(MemoServ, nick,
+ GetReply(ERR_NICKNOTREGGED, nick), args[2]);
+ else {
+ if (!fwd_nick->memos) {
+ fwd_nick->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(fwd_nick->memos);
+ }
+ if ((fwd_nick->memos->flags & MNOFORWARD)
+ || (fwd_nick->memos->flags & MNOMEMO))
+ uSend(MemoServ, nick,
+ GetReply(ERR_NOFWDMEMOS, nick),
+ fwd_nick->nick);
+ else {
+ nick->reg->memos->flags |= MFORWARDED;
+ strcpy(nick->reg->memos->redirect, fwd_nick->nick);
+ uSend(MemoServ, nick,
+ GetReply(RPL_MFORWARDNOW, nick),
+ nick->reg->memos->redirect);
+ }
+ }
+ }
+ }
+ } else if (!strcasecmp(args[1], "nofwd")) {
+ if (numargs < 3)
+ uSend(MemoServ, nick, GetReply(RPL_NSETIS, nick),
+ "Accept No Forwards",
+ nick->reg->memos->flags & MNOFORWARD ? "ON" : "OFF");
+
+ else if (!strcasecmp(args[2], "on")) {
+ nick->reg->memos->flags |= MNOFORWARD;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Accept No Forwards", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ nick->reg->memos->flags &= ~MNOFORWARD;
+ uSend(MemoServ, nick, GetReply(RPL_NSETNOW, nick),
+ "Accept No Forwards", "OFF");
+ } else {
+ uSend(MemoServ, nick, GetReply(ERR_BADSETTING, nick), args[2]);
+ uSend(MemoServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ MemoServ, "SET NOFWD");
+ }
+ } else {
+ uSend(MemoServ, nick, GetReply(ERR_BADSETTING, nick), args[1]);
+ uSend(MemoServ, nick, GetReply(RPL_MOREHELPCMD, nick), MemoServ,
+ "SET");
+ }
+}
+
+void MretrieveCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char memobuffer[60000]; /* fill this up? not likely */
+ char buffer[512], temp[31]; /* temporary, don't ask... */
+ char sendfrom[USERLEN + HOSTLEN];
+ MemoList *tmp;
+ struct tm *time;
+ int type = 0, x;
+
+ bzero(memobuffer, 60000);
+ sprintf(sendfrom, "%s@%s", MemoServ, NETHOST);
+
+ if (numargs < 2)
+ type = 0;
+ else {
+ if (!strcasecmp(args[1], "all"))
+ type = 0;
+ if (!strcasecmp(args[1], "read"))
+ type = 1;
+ else if (!strcasecmp(args[1], "save"))
+ type = 2;
+ else if (!strcasecmp(args[1], "unread"))
+ type = 3;
+ }
+
+ sprintf(memobuffer, "\nMemos for %s:\n", from);
+ for (tmp = nick->reg->memos->firstMemo; tmp; tmp = tmp->next) {
+ x = 0;
+ if (type) {
+ switch (type) {
+ case 1:
+ if (!(tmp->flags & MEMO_UNREAD))
+ x = 1;
+ break;
+ case 2:
+ if (tmp->flags & MEMO_SAVE)
+ x = 1;
+ break;
+ case 3:
+ if (tmp->flags & MEMO_UNREAD)
+ x = 1;
+ break;
+ }
+ } else
+ x = 1;
+
+ sprintf(buffer, "Memo (%3i) from: %s\n", tmp->index, tmp->from);
+ strcat(memobuffer, buffer);
+ time = localtime(&tmp->sent);
+ strftime(temp, 30, "%a %d/%m/%Y %T %Z", time);
+ sprintf(buffer, "Sent at: %-30s Flagged %c%c%c%c%c\n", temp,
+ tmp->flags & MEMO_UNREAD ? '*' : '-',
+ tmp->flags & MEMO_DELETE ? 'D' : ' ',
+ tmp->flags & MEMO_SAVE ? 'S' : ' ',
+ tmp->flags & MEMO_FWD ? 'f' : ' ',
+ tmp->flags & MEMO_REPLY ? 'r' : ' ');
+ strcat(memobuffer, buffer);
+ sprintf(buffer, "%s\n\n", tmp->memo);
+ strcat(memobuffer, buffer);
+ }
+
+ sendMail(nick->reg->email, sendfrom, "Retreived memos:", memobuffer);
+ uSend(MemoServ, nick, GetReply(RPL_MEMOSRETRIEVED, nick),
+ nick->reg->email);
+}
+
+void McsendCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int i = 0, x = 0, lev = 0;
+ int mfirstword = 2;
+ unsigned int rnflg;
+ RegChanList *chan;
+ cAccessList *tmp;
+ MemoList *send;
+ UserList *unf;
+ RegNickList *snick;
+ char memo[512];
+ char sfrom[NICKLEN + CHANLEN];
+ int fwd_flag;
+
+ chan = getRegChanData(args[1]);
+
+ if (!chan)
+ {
+ uSend(MemoServ, nick, GetReply(ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+ rnflg=0;
+ snick=nick->reg;
+ if (snick) rnflg=snick->flags;
+ if ((1 > getChanOp(chan, from))&&(!(rnflg&(NROOT))))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_ACCESSDENIED, nick));
+ return;
+ }
+ if ((args[2][0] >= '0') && (args[2][0] <= '9'))
+ {
+ lev = atoi(args[2]);
+ if ((lev < 0) || (lev > FOUNDER))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_MNEEDLEVEL, nick));
+ return;
+ }
+ mfirstword = 3;
+ }
+
+ sprintf(sfrom, "%s/%s", chan->name, from);
+ sprintf(memo, "%i+ >> %s", lev, args[mfirstword]);
+ for (i = mfirstword + 1; i < numargs; i++)
+ {
+ strcat(memo, " ");
+ strcat(memo, args[i]);
+ }
+
+ if (strlen(memo) >= (MEMOLEN - CHANLEN + 2))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_MEMOTOOLONG, nick),
+ MEMOLEN - CHANLEN - 3);
+ return;
+ }
+
+ if ((CTime - nick->reg->memos->lastsent) > 3600L)
+ {
+ nick->reg->memos->sent = 0;
+ nick->reg->memos->lastsent = CTime;
+ }
+
+ if ((nick->reg->memos->sent >= MS_SENT_MAX) && !isOper(nick))
+ {
+ uSend(MemoServ, nick, GetReply(ERR_TOOMANYMEMOS, nick));
+ return;
+ }
+
+ i = 0;
+ for (tmp = chan->firstOp; tmp; tmp = tmp->next)
+ {
+ if (tmp->uflags >= lev && match(tmp->nick, from))
+ {
+ i++;
+
+ snick = getRegNickData(tmp->nick);
+ if (!snick)
+ continue;
+
+ if (!snick->memos)
+ {
+ snick->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(snick->memos);
+ }
+
+ fwd_flag = 0;
+ if (snick->memos->flags & MFORWARDED)
+ {
+ RegNickList *fwd_nick = getRegNickData(snick->memos->redirect);
+ if (!fwd_nick)
+ {
+ snick->memos->flags &= ~MFORWARDED;
+ snick->memos->redirect[0] = 0;
+ }
+ else
+ {
+ if (!fwd_nick->memos)
+ {
+ fwd_nick->memos = smalloc(sizeof(MemoBox));
+ initMemoBox(fwd_nick->memos);
+ }
+ if (!fwd_nick->memos->flags & (MNOFORWARD | MNOMEMO))
+ {
+ snick = fwd_nick;
+ fwd_flag = 1;
+ }
+ }
+ }
+
+ if ((snick->memos->memos >= snick->memos->max) || (snick->memos->flags & MNOMEMO))
+ continue;
+
+ x++;
+ send = smalloc(sizeof(MemoList));
+ strcpy(send->memo, memo);
+ strcpy(send->from, sfrom);
+ send->flags |= MEMO_UNREAD;
+ if (fwd_flag)
+ send->flags |= MEMO_FWD;
+ send->sent = CTime;
+ addMemo(snick->memos, send);
+ unf = getNickData(snick->nick);
+ if (unf && unf->caccess >= 2)
+ uSend(MemoServ, unf, GetReply(RPL_GOTNEWMEMO, unf), from, send->index);
+ }
+ }
+
+ if (x)
+ {
+ nick->reg->memos->sent++;
+ uSend(MemoServ, nick, GetReply(RPL_SENTMEMO, nick), chan->name);
+ }
+
+ uSend(MemoServ, nick, GetReply(RPL_SENTMEMOCHAN, nick), x, i);
+}
--- /dev/null
+/*
+ * New Services Message Tables by GZ (April 2000)
+ * +New Kinky FloodProtection
+ *
+ */
+
+#include "services.h"
+
+struct Message NSmsgtab[] = {
+ {"id", NidentifyCmd, NEEDACTNICK, 0, 0, 2},
+ {"identify", NidentifyCmd, NEEDACTNICK, 0, 0, 2},
+ {"info", NinfoCmd, 0, 0, 0, 1},
+ {"sidentify", NidentifyCmd, NEEDACTNICK, 0, 0, 2},
+ {"register", NregisterCmd, 0, 0, 0, 3},
+ {"set", NsetCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+ {"ghost", NghostCmd, 0, 0, 0, 3},
+ {"activate", NactivateCmd, NEEDREGNICK, 0, 0, 2},
+ {"listops", NlistopsCmd, 0, 0, 0, 1},
+ {"addmask", NaddMaskCmd, NEEDACTNICK | NEEDID, 0, 0, 1},
+ {"drop", NdropCmd, NEEDREGNICK | NEEDID, 0, 0, 2},
+ {"list", NlistCmd, NEEDACTNICK | NEEDOPER, 0, 0, 2},
+ {"access", NaccessCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+ {"setflags", NsetflagsCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 3},
+ {"webtvcount", NwebtvcountCmd, NEEDOPER, 0, 0, 1},
+ {"banish", NbanishCmd, NEEDACTNICK | NEEDROOT, 0, 0, 2},
+ {"getpass", NgetpassCmd, NEEDACTNICK | NEEDOPER, 0, 0, 2},
+ {"getkey", NgetkeyCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 2},
+ {"getrealpass", NgetrealpassCmd, NEEDACTNICK | NEEDROOT, 0, 0, 2},
+ {"delete", NdeleteCmd, NEEDACTNICK | NEEDOPER, 0, 0, 2},
+ {"save", NsaveCmd, NEEDACTNICK | NEEDROOT, 0, 0, 1},
+ {"resend", NresendCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 2},
+ {"mark", NmarkCmd, NEEDOPER, 0, 0, 4},
+#ifdef ANALYSE_FUNCTIONS
+ {"debug", NSdebug, NEEDROOT, 0, 0, 0},
+#endif
+ {NULL, NULL, 0, 0, 0, 0}
+};
+
+struct Message CSmsgtab[] = {
+ {"acc", CaccessCmd, 0, 0, 0, 2},
+ {"access", CaccessCmd, 0, 0, 0, 2},
+ {"info", CinfoCmd, 0, 0, 0, 2},
+ {"register", CregisterCmd, NEEDACTNICK, 0, 0, 2},
+ {"addop", CaddopCmd, NEEDACTNICK, 0, 0, 3},
+ {"addak", CaddakCmd, NEEDACTNICK, 0, 0, 3},
+ {"delop", CdelopCmd, NEEDACTNICK, 0, 0, 3},
+ {"delak", CdelakCmd, NEEDACTNICK, 0, 0, 3},
+ {"listop", ClistopCmd, NEEDACTNICK, 0, 0, 2},
+ {"listak", ClistakCmd, NEEDACTNICK, 0, 0, 2},
+ {"drop", CdropCmd, NEEDACTNICK, 0, 0, 2},
+ {"op", CopCmd, NEEDACTNICK, 0, 0, 2},
+ {"deop", CdeopCmd, NEEDACTNICK, 0, 0, 2},
+ {"clist", CclistCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 2},
+ {"mlock", CmodelockCmd, NEEDACTNICK, 0, 0, 3},
+ {"modelock", CmodelockCmd, NEEDACTNICK, 0, 0, 3},
+ {"restrict", CrestrictCmd, NEEDACTNICK, 0, 0, 3},
+ {"topiclock", CtopiclockCmd, NEEDACTNICK, 0, 0, 3},
+ {"set", CsetCmd, NEEDACTNICK, 0, 0, 3},
+ {"save", CsaveCmd, NEEDACTNICK | NEEDROOT, 0, 0, 1},
+ {"unban", CunbanCmd, NEEDACTNICK, 0, 0, 3},
+ {"invite", CinviteCmd, NEEDACTNICK, 0, 0, 2},
+ {"list", ClistCmd, NEEDACTNICK | NEEDOPER, 0, 0, 3},
+ {"delete", CdeleteCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 2},
+ {"massdeop", CmassdeopCmd, NEEDACTNICK, 0, 0, 2},
+ {"masskick", CmasskickCmd, NEEDACTNICK, 0, 0, 2},
+ {"modeclear", CmodeclearCmd, NEEDACTNICK, 0, 0, 2},
+ {"close", CcloseCmd, NEEDACTNICK | NEEDSERVOP, 0, 0, 3},
+
+#ifdef ANALYSE_FUNCTIONS
+ {"debug", CSdebug, NEEDROOT, 0, 0, 0},
+#endif
+ {NULL, NULL, 0, 0, 0, 0}
+};
+
+struct Message OSmsgtab[] = {
+ {"jinx", OjinxCmd, NEEDOPER, 0, 0, 2},
+ {"hostjinx", OaccessmodCmd, NEEDSERVOP, 0, 0, 2},
+ {"broadcast", ObroadcastCmd, NEEDSERVOP, 0, 0, 2},
+ {"ekill", OekillCmd, NEEDSERVOP, 0, 0, 2},
+ {"list", OlistCmd, NEEDOPER, 0, 0, 2},
+ {"map", OmapCmd, NEEDOPER, 0, 0, 1},
+ {"trigger", OtriggerCmd, NEEDOPER, 0, 0, 2},
+ {"cloneset", OclonesetCmd, NEEDOPER, 0, 0, 2},
+ {"masskill", OmkillCmd, NEEDSERVOP, 0, 0, 2},
+ {"mkill", OmkillCmd, NEEDSERVOP, 0, 0, 2},
+ {"mode", OmodeCmd, NEEDOPER, 0, 0, 3},
+ {"raw", OrawCmd, NEEDOPER | NEEDROOT, 0, 0, 2},
+ {"inject", OinjectCmd, NEEDOPER | NEEDROOT, 0, 0, 2},
+ {"enforce", OenforceCmd, NEEDROOT, 0, 0, 1},
+ {"shutdown", OshutdownCmd, NEEDROOT, 0, 0, 1},
+ {"svsnoop", OsvsnoopCmd, NEEDROOT, 0, 0, 3},
+ {"allocstat", OallocstatCmd, NEEDROOT, 0, 0, 1},
+ {"restart", OrestartCmd, NEEDOPER | NEEDROOT, 0, 0, 1},
+ {"jupe", OjupeCmd, NEEDOPER, 0, 0, 2},
+ {"jupiter", OjupeCmd, NEEDOPER, 0, 0, 2},
+ {"sync", OsyncCmd, NEEDOPER | NEEDROOT, 0, 0, 1},
+ {"uptime", OuptimeCmd, NEEDOPER, 0, 0, 1},
+ {"rootops", OrootOpsCmd, NEEDOPER | NEEDROOT, 0, 0, 1},
+ {"listops", OlistOpsCmd, NEEDOPER, 0, 0, 1},
+ {"push", OsvsjoinCmd, NEEDSERVOP, 0, 0, 3},
+ {"part", OsvspartCmd, NEEDSERVOP, 0, 0, 3},
+ {"pull", OsvspartCmd, NEEDSERVOP, 0, 0, 3},
+ {"beam", OsvsbeamCmd, NEEDSERVOP, 0, 0, 4},
+ {"akill", OaccessmodCmd, NEEDOPER, 0, 0, 2},
+ {"autokill", OaccessmodCmd, NEEDOPER, 0, 0, 2},
+ {"exempt", OaccessmodCmd, NEEDOPER, 0, 0, 2},
+ {"rollup", OrollupCmd, NEEDROOT, 0, 0, 2},
+#ifdef ANALYSE_FUNCTIONS
+ {"debug", OSdebug, NEEDROOT, 0, 0, 0},
+#endif
+ {NULL, NULL, 0, 0, 0, 0}
+};
+
+struct Message MSmsgtab[] = {
+ {"del", MdeleteCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+ {"delete", MdeleteCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+ {"set", MsetCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+ {"retrieve", MretrieveCmd, NEEDACTNICK | NEEDID, 0, 0, 1},
+ {"forward", MforwardCmd, NEEDACTNICK | NEEDID, 0, 0, 3},
+ {"list", MlistCmd, NEEDACTNICK | NEEDID, 0, 0, 1},
+ {"send", MsendCmd, NEEDACTNICK | NEEDID, 0, 0, 3},
+ {"csend", McsendCmd, NEEDACTNICK | NEEDID, 0, 0, 3},
+ {"read", MreadCmd, NEEDACTNICK | NEEDID, 0, 0, 2},
+#ifdef ANALYSE_FUNCTIONS
+ {"debug", MSdebug, NEEDROOT, 0, 0, 0},
+#endif
+ {NULL, NULL, 0, 0, 0, 0}
+};
+
+void msgtabCheck(char *Service, UserList * tmp, char **args, int numargs)
+{
+
+ int i, registered, activated;
+ int oper, servop, root, id;
+ long timenow;
+#ifdef ANALYSE_FUNCTIONS
+ long before, ticks;
+#endif
+ struct Message *tabpointer = NULL;
+ i = registered = activated = 0;
+ oper = servop = root = id = 0;
+ timenow = time(NULL);
+
+ if (DoFloodCheck(tmp)) {
+ tmp->lastmsg = timenow;
+ return;
+ } else
+ tmp->lastmsg = timenow;
+
+ if (tmp->reg) {
+ registered = 1;
+ if (tmp->reg->flags & NACTIVE) {
+ activated = 1;
+ if (isServop(tmp))
+ servop = 1;
+ if (isRoot(tmp))
+ root = 1;
+ }
+ }
+
+ if (isOper(tmp))
+ oper = 1;
+
+ if (tmp->caccess > 2)
+ id = 1;
+
+ if (!strcmp(Service, NickServ))
+ tabpointer = NSmsgtab;
+
+ if (!strcmp(Service, ChanServ))
+ tabpointer = CSmsgtab;
+
+ if (!strcmp(Service, OperServ))
+ tabpointer = OSmsgtab;
+
+ if (!strcmp(Service, MemoServ))
+ tabpointer = MSmsgtab;
+
+ while (tabpointer[i].cmd) {
+ if (!strcasecmp(tabpointer[i].cmd, args[0])) {
+ if ((tabpointer[i].flag & NEEDREGNICK) && !registered) {
+ uSend(Service, tmp, GetReply(ERR_NEEDREGNICK, tmp));
+ return;
+ } else if ((tabpointer[i].flag & NEEDACTNICK) && !activated) {
+ uSend(Service, tmp, GetReply(ERR_NEEDACTNICK, tmp));
+ return;
+ } else if ((tabpointer[i].flag & NEEDROOT) && !root) {
+ uSend(Service, tmp, GetReply(ERR_NEEDSRA, tmp));
+ return;
+ } else if ((tabpointer[i].flag & NEEDSERVOP) && !servop) {
+ uSend(Service, tmp, GetReply(ERR_NEEDSERVOP, tmp));
+ return;
+ } else if ((tabpointer[i].flag & NEEDOPER) && !oper) {
+ uSend(Service, tmp, GetReply(ERR_NEEDOPER, tmp));
+ return;
+ }
+
+ else if ((tabpointer[i].flag & NEEDID) && !id) {
+ uSend(Service, tmp, GetReply(ERR_NEEDID, tmp));
+ return;
+ }
+
+ if (tabpointer[i].params > numargs
+ && tabpointer[i].params != 0) {
+ uSend(Service, tmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(Service, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ Service, tabpointer[i].cmd);
+ return;
+ }
+#ifdef ANALYSE_FUNCTIONS
+ before = GetClock();
+#endif
+ tabpointer[i].func(tmp, args, numargs);
+#ifdef ANALYSE_FUNCTIONS
+ tabpointer[i].count++;
+ ticks = (GetClock() - before);
+ tabpointer[i].totaltime += ticks;
+#endif
+ return;
+ }
+ i++;
+ }
+
+ uSend(Service, tmp, GetReply(ERR_UNKNOWNCOMMAND, tmp), args[0]);
+ uSend(Service, tmp, GetReply(RPL_MOREHELP, tmp), Service);
+
+ return;
+}
+
+#ifdef ANALYSE_FUNCTIONS
+void NSdebug(UserList * tmp, char **args, int numargs)
+{
+
+ long average;
+ int i = 0;
+
+ uSend(NickServ, tmp, GetReply(RPL_DEBUGHEADER, tmp), NickServ);
+ uSend(NickServ, tmp, GetReply(RPL_DEBUGLINE1, tmp), "Command", "Count",
+ "Total", "Average");
+
+ while (NSmsgtab[i].cmd) {
+ if (NSmsgtab[i].count > 0)
+ average = NSmsgtab[i].totaltime / NSmsgtab[i].count;
+ else
+ average = 0;
+ uSend(NickServ, tmp, GetReply(RPL_DEBUGLINE2, tmp),
+ NSmsgtab[i].cmd, NSmsgtab[i].count, NSmsgtab[i].totaltime,
+ average);
+ i++;
+ }
+
+ uSend(NickServ, tmp, GetReply(RPL_DEBUGFOOTER, tmp));
+ return;
+
+}
+
+void OSdebug(UserList * tmp, char **args, int numargs)
+{
+
+ long average;
+ int i = 0;
+
+ uSend(OperServ, tmp, GetReply(RPL_DEBUGHEADER, tmp), OperServ);
+ uSend(OperServ, tmp, GetReply(RPL_DEBUGLINE1, tmp), "Command", "Count",
+ "Total", "Average");
+
+ while (OSmsgtab[i].cmd) {
+ if (OSmsgtab[i].count > 0)
+ average = OSmsgtab[i].totaltime / OSmsgtab[i].count;
+ else
+ average = 0;
+ uSend(OperServ, tmp, GetReply(RPL_DEBUGLINE2, tmp),
+ OSmsgtab[i].cmd, OSmsgtab[i].count, OSmsgtab[i].totaltime,
+ average);
+ i++;
+ }
+ uSend(OperServ, tmp, GetReply(RPL_DEBUGFOOTER, tmp));
+ return;
+
+}
+
+void MSdebug(UserList * tmp, char **args, int numargs)
+{
+
+ long average;
+ int i = 0;
+
+ uSend(MemoServ, tmp, GetReply(RPL_DEBUGHEADER, tmp), MemoServ);
+ uSend(MemoServ, tmp, GetReply(RPL_DEBUGLINE1, tmp), "Command", "Count",
+ "Total", "Average");
+
+ while (MSmsgtab[i].cmd) {
+ if (MSmsgtab[i].count > 0)
+ average = MSmsgtab[i].totaltime / MSmsgtab[i].count;
+ else
+ average = 0;
+ uSend(MemoServ, tmp, GetReply(RPL_DEBUGLINE2, tmp),
+ MSmsgtab[i].cmd, MSmsgtab[i].count, MSmsgtab[i].totaltime,
+ average);
+ i++;
+ }
+
+ uSend(MemoServ, tmp, GetReply(RPL_DEBUGFOOTER, tmp));
+ return;
+
+}
+
+void CSdebug(UserList * tmp, char **args, int numargs)
+{
+
+ long average;
+ int i = 0;
+
+ uSend(ChanServ, tmp, GetReply(RPL_DEBUGHEADER, tmp), ChanServ);
+ uSend(ChanServ, tmp, GetReply(RPL_DEBUGLINE1, tmp), "Command", "Count",
+ "Total", "Average");
+
+ while (CSmsgtab[i].cmd) {
+ if (CSmsgtab[i].count > 0)
+ average = CSmsgtab[i].totaltime / CSmsgtab[i].count;
+ else
+ average = 0;
+ uSend(ChanServ, tmp, GetReply(RPL_DEBUGLINE2, tmp),
+ CSmsgtab[i].cmd, CSmsgtab[i].count, CSmsgtab[i].totaltime,
+ average);
+ i++;
+ }
+
+ uSend(ChanServ, tmp, GetReply(RPL_DEBUGFOOTER, tmp));
+ return;
+
+}
+
+/* This one will return the time in microseconds -GZ */
+long GetClock(void)
+{
+
+ long clocks;
+ struct timeval *time;
+ struct timezone *tz;
+
+ time = &fcountt;
+ tz = &fcountz;
+ gettimeofday(time, tz);
+
+ clocks = fcountt.tv_sec * 1000000 + fcountt.tv_usec;
+
+ return clocks;
+}
+#endif
+
+int DoFloodCheck(UserList * tmp)
+{
+
+ long timenow = time(NULL);
+
+ if (tmp->flooder == 0) {
+ if (tmp->floodbytes < 7500) {
+ if ((timenow - tmp->lastmsg) > 10)
+ tmp->floodbytes = 0;
+ return 0;
+ } else {
+ tmp->flooder = 1;
+ return 1;
+ }
+ }
+
+ if ((timenow - tmp->lastmsg) < 10)
+ return 1;
+ else {
+ tmp->floodbytes /= 2;
+ if (tmp->floodbytes < 7500)
+ tmp->flooder = 0;
+ }
+
+ return 0;
+}
--- /dev/null
+#include "services.h"
+
+void *blech; /* yeah yeah, I know, I know. */
+
+void *smalloc(size_t size)
+{
+ AllocCalled++;
+ blech = malloc(size);
+
+ if (blech == NULL) {
+ perror("smalloc");
+ abort();
+ }
+
+ memset(blech, 0, size);
+ return blech;
+}
+
+void sfree(void *del)
+{
+ FreeCalled++;
+ free(del);
+}
+
+char *sstrdup(const char *s)
+{
+ AllocCalled++;
+ blech = strdup(s);
+
+ if (blech == NULL) {
+ perror("sstringdup");
+ abort();
+ }
+
+ return (char *) blech;
+}
--- /dev/null
+#include "services.h"
+
+/* NICKSERV.C -- Functions for handling both online nick control and
+ * maintenance of registered nick databases
+ */
+
+/*
+ * ===DOC===
+ * firstNick is the first nickname, and is static, lastNick is the last
+ * allocated nickname slot. thus for allocation we use lastNick->next
+ */
+
+int countRegAddy(char *);
+
+/* simple linked list with all the ghost stuff in them */
+typedef struct ghost_struct {
+ char ghost[NICKLEN];
+ struct ghost_struct *next;
+ struct ghost_struct *previous;
+} GhostList;
+
+int totalghosts = 0;
+
+GhostList *firstGhost = NULL;
+GhostList *lastGhost = NULL;
+
+GhostList *getGhost(char *);
+void addGhost(char *);
+void delGhost(char *);
+
+/* pretty simple, if someone desynchs doing something, yell about it,
+ * then kill them for the evil desynch
+ */
+
+void nDesynch(char *nick, char *type)
+{
+ GhostList *killme;
+
+ if (nick) {
+ killme = getGhost(nick);
+
+ if (killme)
+ return;
+
+ sSend(":%s KILL %s :%s!%s (Desynch, type: [%s])", NickServ, nick,
+ services[1].host, NickServ, type);
+ }
+ return;
+}
+
+
+/*
+ * ===DOC===
+ * getNickData will find a nick and retreieve data for it
+ * init*Data cleans up a user/nick ent
+ * killide, uhm, killides someone, :)
+ */
+
+void initUserData(UserList *);
+void annoyNickThief(UserList *);
+void killide(char *);
+void removeEnforcer(char *);
+
+/*
+ * ===DOC===
+ * addNewUser simply adds a new user connection, :>
+ */
+void addNewUser(char **args, int numargs)
+{
+ int i;
+ UserList *newnick;
+ struct access_mod *ak;
+ char realnamebuffer[129];
+ newnick = smalloc(sizeof(UserList));
+ initUserData(newnick);
+
+ strcpy(newnick->nick, args[1]);
+ if (args[4][0] == '~')
+ args[4]++;
+ strcpy(newnick->user, args[4]);
+ strcpy(newnick->host, args[5]);
+ strcpy(newnick->server, args[6]);
+
+ *realnamebuffer = 0;
+ if (numargs > 8) {
+ args[8]++;
+ strcpy(realnamebuffer, args[8]);
+ }
+ for (i = 9; i < numargs; i++) {
+ strcat(realnamebuffer, " ");
+ strcat(realnamebuffer, args[i]);
+ }
+ realnamebuffer[50] = 0;
+ strcpy(newnick->realname, realnamebuffer);
+
+ ak = isAKilled(newnick->nick, newnick->user, newnick->host);
+
+ if (ak) {
+ killUser(services[1], newnick, AKILLMSG);
+ remUser(args[1]);
+ if (!strcmp(ak->nick, "*")) {
+ /* We need to send any matching exempts first. Rationale: The fact
+ * that we've gotten to this point in the first place means that
+ * one or more servers don't have an akill in place which they
+ * should have. If we only send the Akill again then exempted users
+ * that try to connect to the server later on will no longer be
+ * able to use that server anymore either. Better to be save than
+ * sorry and send any matching exempts out. -- Remmy 20020623 */
+ send_matching_exempts(newnick->nick, newnick->user, newnick->host);
+ /* Now send the akill out... */
+ sSend(":%s AKILL %s %s :Autokilled by %s [%s]", myname,
+ ak->host, ak->user, ak->setby, ak->reason);
+ }
+ addGhost(args[1]);
+ timer(1800, delGhost, "delGhost", args[1]);
+ return;
+ }
+
+ /* Check if user is supposed to be jinxed or not */
+ ak = isHJinxed(newnick->nick, newnick->user, newnick->host);
+ if (ak) {
+ AddJinx(newnick->nick, "OperServ", "Host JINX");
+ if (match(newnick->host, "*aol.com"))
+ sSend(":%s GLOBOPS :Re-activating JINX for %s.", OperServ,
+ newnick-> nick);
+ sSend(":%s JINX %s", myname, newnick->nick);
+ }
+
+ newnick->reg = getRegNickData(args[1]);
+
+ if (newnick->reg && (newnick->reg->flags & NACTIVE)) {
+ newnick->reg->flags2 &= ~NSTICKYOP; /* TURN OFF STICKY OPER UNTIL WE GET +o */
+ if (newnick->reg->flags & NBANISH) {
+ killUser(services[1], newnick, NSBANISHMSG);
+ remUser(args[1]);
+ addGhost(args[1]);
+ timer(1800, delGhost, "delGhost", args[1]);
+ return;
+ }
+ if (!checkAccess(newnick->user, newnick->host, newnick->reg)) {
+ newnick->caccess = 1;
+ annoyNickThief(newnick);
+ } else {
+ newnick->caccess = 2;
+ strcpy(newnick->reg->nick, newnick->nick);
+ strcpy(newnick->reg->user, newnick->user);
+ strcpy(newnick->reg->host, newnick->host);
+ strcpy(newnick->reg->realname, newnick->realname);
+ newnick->reg->timestamp = CTime; /* MAKE SERVICES CLOCK MATTER MOST */
+ checkMemos(newnick);
+ }
+ }
+
+ i = 0;
+
+ i = addClone(newnick->nick, newnick->user, newnick->host);
+
+ addNick(newnick);
+ totalusers++;
+
+ if (!i) {
+ if (mostusers < totalusers) {
+ mostusers = totalusers;
+ if (mostusers % 5 == 0)
+ sSend
+ (":%s GLOBOPS :New user-record established. There are now %i users online.",
+ Serenity, mostusers);
+ }
+ }
+
+ /* Send out a message on connect */
+
+ uSend(Serenity, newnick, GetReply(RPL_GLOBALNOTICE, newnick));
+}
+
+/*
+ * ===DOC===
+ * addNewUserSN adds a new user connection using SNICK protocol. -GZ
+ */
+void addNewUserSN(char **args, int numargs)
+{
+ int i, identified = 0;
+ UserList *newnick;
+ char *p;
+ struct access_mod *ak;
+ char realnamebuffer[129];
+ char buffer[100];
+
+ newnick = smalloc(sizeof(UserList));
+ if (!newnick) {
+ Debug((DEBUG_ERROR, "Failed to smalloc a newnick in addNewUserSN!"));
+ return;
+ }
+
+ initUserData(newnick);
+
+ strcpy(newnick->nick, args[1]);
+ if (args[4][0] == '~')
+ args[4]++;
+ strcpy(newnick->user, args[4]);
+ strcpy(newnick->host, args[5]);
+ strcpy(newnick->server, args[6]);
+
+ *realnamebuffer = 0;
+ if (numargs > 9) {
+ args[9]++;
+ strcpy(realnamebuffer, args[9]);
+ }
+ for (i = 10; i < numargs; i++) {
+ strcat(realnamebuffer, " ");
+ strcat(realnamebuffer, args[i]);
+ }
+ realnamebuffer[50] = 0;
+ strcpy(newnick->realname, realnamebuffer);
+
+ ak = isAKilled(newnick->nick, newnick->user, newnick->host);
+
+ if (ak) {
+ killUser(services[1], newnick, AKILLMSG);
+ remUser(args[1]);
+ if (!strcmp(ak->nick, "*"))
+ sSend(":%s AKILL %s %s :Autokilled by %s [%s]", myname,
+ ak->host, ak->user, ak->setby, ak->reason);
+ addGhost(args[1]);
+ timer(1800, delGhost, "delGhost", args[1]);
+ return;
+ }
+
+
+ for (p = args[8]; *p; p++) {
+ switch (*p) {
+ case 'I':
+ identified = 1;
+ break;
+ case 'w':
+ newnick->webbie = 1;
+ break;
+ }
+ }
+
+ /* Check if user is supposed to be jinxed or not */
+ /* don't hostjinx an identified user --InnerFIRE */
+ if(!identified) {
+ ak = isHJinxed(newnick->nick, newnick->user, newnick->host);
+
+ if (ak) {
+ AddJinx(newnick->nick, "OperServ", "Host JINX");
+ sSend(":%s JINX %s", myname, newnick->nick);
+ }
+ }
+ newnick->reg = getRegNickData(args[1]);
+
+ if (newnick->reg && (newnick->reg->flags & NACTIVE)) {
+ newnick->reg->flags2 &= ~NSTICKYOP; /* TURN OFF STICKY OPER UNTIL WE GET +o */
+ if (newnick->reg->flags & NBANISH) {
+ killUser(services[1], newnick, NSBANISHMSG);
+ remUser(args[1]);
+ addGhost(args[1]);
+ timer(1800, delGhost, "delGhost", args[1]);
+ return;
+ }
+
+ if (identified) {
+ newnick->caccess = 3;
+ }
+
+ if (!identified
+ && !checkAccess(newnick->user, newnick->host, newnick->reg)) {
+ newnick->caccess = 1;
+ annoyNickThief(newnick);
+ } else if (!identified) {
+ newnick->caccess = 2;
+ newnick->reg->timestamp = CTime; /* MAKE SERVICES CLOCK MATTER MOST */
+ if (!identified)
+ checkMemos(newnick);
+ }
+ }
+
+ i = 0;
+
+ i = addClone(newnick->nick, newnick->user, newnick->host);
+
+ addNick(newnick);
+ totalusers++;
+
+ if (!i)
+ if (mostusers < totalusers)
+ mostusers = totalusers;
+
+ /* Inject the modes back into the buffer -GZ */
+
+ newnick->resynch = 1;
+
+ bzero(buffer, 100);
+
+ sprintf(buffer, ":%s MODE %s %s", args[1], args[1], args[8]);
+ parseLine(buffer);
+
+}
+
+/* changeNick, called when someone uses the NICK command to change their
+ * nicks obviously...changed from, to, and it hands off the timestamp
+ * so that last seen time can be updated
+ */
+void changeNick(char *from, char *to, char *ts)
+{
+ UserList *changeme, *tmp;
+
+ changeme = getNickData(from);
+ if (changeme == NULL) {
+ nDesynch(from, "NICK");
+ return;
+ }
+
+ /* ALOT of changing around goes on here....it rather sucks...ohwell */
+ tmp = smalloc(sizeof(UserList));
+ strcpy(tmp->nick, to);
+ strcpy(tmp->user, changeme->user);
+ strcpy(tmp->host, changeme->host);
+ strcpy(tmp->realname, changeme->realname);
+ tmp->webbie = changeme->webbie;
+ tmp->oflags = changeme->oflags;
+ tmp->floodlevel = changeme->floodlevel;
+ tmp->lastmsg = changeme->lastmsg;
+ changeNickOnAllChans(changeme, tmp);
+
+ /* If the user was jinxed (and nick thus got changed by SVSNICK) we should
+ * remove the jinx for the old nick and re-add it for the new nick. Without
+ * this change our jinx would get messed up. -- Remmy */
+ if (CheckJinx(changeme->nick)) {
+ DeleteJinx(changeme->nick);
+ AddJinx(to, myname, "JINX following SVSNICK nick change");
+ }
+
+ delNick(changeme);
+ addNick(tmp);
+
+ if (isAKilled(tmp->nick, tmp->user, tmp->host)) {
+ killUser(services[1], tmp, AKILLMSG);
+ remUser(to);
+ addGhost(to);
+ timer(1800, delGhost, "delGhost", to);
+ return;
+ }
+
+ tmp->reg = getRegNickData(to);
+
+ if (tmp->reg && (tmp->reg->flags & NACTIVE)) {
+ tmp->reg->flags2 &= ~NSTICKYOP; /* TURN OFF STICKY OPER BIT */
+
+ if ((tmp->reg->flags & NBANISH) && (!isOper(tmp))) {
+ killUser(services[1], tmp, NSBANISHMSG);
+ remUser(to);
+ addGhost(to);
+ timer(1800, delGhost, "delGhost", to);
+ return;
+ }
+ if (!checkAccess(tmp->user, tmp->host, tmp->reg)) {
+ tmp->caccess = 0;
+ annoyNickThief(tmp);
+ }
+
+ else {
+ tmp->caccess = 2;
+ strcpy(tmp->reg->nick, tmp->nick);
+ strcpy(tmp->reg->user, tmp->user);
+ strcpy(tmp->reg->host, tmp->host);
+ strcpy(tmp->reg->realname, tmp->realname);
+ if (isOper(tmp)) {
+ tmp->reg->flags2 |= NSTICKYOP; /* TURN ON STICKY OPER BIT */
+ }
+ if (ts[0] == ':')
+ ts++;
+ tmp->reg->timestamp = CTime; /* MAKE SERVICES TIME COUNT */
+
+ checkMemos(tmp);
+ }
+ }
+
+ /* Check for HOSTJINX */
+ if (isHJinxed(tmp->nick, tmp->user, tmp->host)) {
+ AddJinx(tmp->nick, "OperServ", "Host JINX");
+ sSend(":%s JINX %s", myname, tmp->nick);
+ }
+
+}
+
+
+/* set mode, only deals with user modes, for things like away, or other
+ * odd stuff, head to setFlags
+ */
+void setMode(char *nick, char *mode)
+{
+ UserList *changeme;
+ int i, c = 1;
+ changeme = getNickData(nick);
+
+ if (changeme == NULL) {
+ if (!isGhost(nick))
+ nDesynch(nick, "UMODE");
+ return;
+ }
+
+ if (*mode == ':')
+ mode++; /* We don't need to bother with the : */
+
+ for (i = 0; mode[i] != 0; i++) {
+ switch (mode[i]) {
+ case '-':
+ c = 0;
+ break;
+ case '+':
+ c = 1;
+ break;
+ case 'a':
+ if (c == 1) {
+ if (!isServop(changeme)) {
+ sSend(":%s SVSMODE %s -a 0", OperServ, changeme->nick);
+ break;
+ }
+ }
+ case 'y': /* NEW FLAG ADDITION FOR STAR-3.01+ LOCAL OPER DETECTION */
+ if (c == 1)
+ changeme->oflags |= NISHELPOP;
+ else
+ changeme->oflags &= ~NISHELPOP;
+ break;
+ case 'x':
+ if (c == 1)
+ changeme->oflags |= NISPLUSX;
+ else
+ changeme->oflags &= ~NISPLUSX;
+ break;
+ case 'i':
+ if (c == 1)
+ changeme->oflags |= NISINVIS;
+ else
+ changeme->oflags &= ~NISINVIS;
+ break;
+ case 'O':
+ case 'o':
+ if (c == 1) {
+ if (changeme->reg && changeme->reg->flags & NNETADM
+ && changeme->caccess == 3 && !changeme->resynch) {
+ uSend(NickServ, changeme,
+ GetReply(RPL_YOUAREROOT, changeme));
+ sSend(":%s SVSMODE %s +aNn", myname, changeme->nick);
+ }
+ else if (changeme->reg && changeme->reg->flags & NROOT
+ && changeme->caccess == 3 && !changeme->resynch) {
+ uSend(NickServ, changeme,
+ GetReply(RPL_YOUAREROOT, changeme));
+ sSend(":%s SVSMODE %s +an", myname, changeme->nick);
+ }
+ else if (changeme->reg
+ && changeme->reg->flags & NSERVOP
+ && changeme->caccess == 3
+ && !changeme->resynch) {
+ uSend(NickServ, changeme,
+ GetReply(RPL_YOUARESERVOP, changeme));
+ sSend(":%s SVSMODE %s +a", myname, changeme->nick);
+ }
+ changeme->oflags |= NISOPER;
+ } else {
+ changeme->oflags &= ~NISOPER;
+ }
+ break;
+
+ case 'A':
+ if (c == 1)
+ changeme->oflags |= NISADMIN;
+ else
+ changeme->oflags &= ~NISADMIN;
+ break;
+
+ }
+ }
+
+ mode--;
+
+ if (changeme->reg) {
+ if (isOper(changeme) && changeme->caccess > 1)
+ changeme->reg->flags2 |= NSTICKYOP;
+ else
+ changeme->reg->flags2 &= ~NSTICKYOP;
+ }
+
+ changeme->resynch = 0;
+ return;
+}
+
+
+/* set flags, like away, and you can use other things too I suppose...
+ */
+void setFlags(char *nick, int flag, char change)
+{
+ UserList *bah;
+ bah = getNickData(nick);
+ if (bah == NULL) {
+ nDesynch(nick, "SETFLAG(internal source)");
+ return;
+ }
+
+ else {
+ if (change == '+')
+ bah->oflags |= flag;
+ else
+ bah->oflags &= ~flag;
+ }
+
+}
+
+
+/* simple, is the person an oper or not? */
+int isOper(UserList * nick)
+{
+ if (nick == NULL)
+ return 0;
+ else {
+ /* added helpop for little o's.... */
+ if (nick->oflags & NISOPER || nick->oflags & NISHELPOP)
+ return 1;
+ else
+ return 0;
+ }
+}
+
+int isRoot(UserList * nick)
+{
+ if (!nick || !nick->reg)
+ return 0;
+
+ if ((nick->reg->flags & NROOT) && nick->caccess > 2)
+ return isOper(nick);
+ else
+ return 0;
+}
+
+int isServop(UserList * nick)
+{
+ if (!nick || !nick->reg)
+ return 0;
+
+ if (
+ (nick->reg->flags & NSERVOP || nick->reg->flags & NROOT) && nick->caccess > 2)
+ return isOper(nick);
+ else
+ return 0;
+}
+
+
+
+/* remover a user when they signoff, save their info, and clean up
+ * the nickname list
+ */
+void remUser(char *nick)
+{
+ UserList *killme;
+
+ killme = getNickData(nick);
+ if (killme == NULL)
+ return;
+
+ remFromAllChans(killme);
+ if (killme->reg && killme->caccess > 1) {
+ killme->reg->timestamp = CTime; /* Adjust their last seen when they leave */
+ cleanMemos(killme);
+ }
+ if (CheckJinx(killme->nick)) {
+ DeleteJinx(killme->nick);
+ if (match(killme->host, "*aol.com"))
+ sSend(":%s GLOBOPS :%s left IRC. JINX has been removed", OperServ,
+ killme->nick);
+ }
+ delClone(killme->user, killme->host);
+ delNick(killme);
+
+ totalusers--;
+}
+
+
+/* INTERNAL FUNCTION -- ADD NICK RECORD TO USERLIST LIST */
+void addNick(UserList * newnick)
+{
+ long hashEnt;
+
+ if (!firstUser) {
+ firstUser = newnick;
+ newnick->previous = NULL;
+ } else {
+ lastUser->next = newnick;
+ newnick->previous = lastUser;
+ }
+
+ lastUser = newnick;
+ newnick->next = NULL;
+
+ hashEnt = getHashKey(newnick->nick) % NICKHASHSIZE;
+ if (!UserHash[hashEnt].nick) {
+ UserHash[hashEnt].nick = newnick;
+ newnick->hashprev = NULL;
+ } else {
+ UserHash[hashEnt].lastnick->hashnext = newnick;
+ newnick->hashprev = UserHash[hashEnt].lastnick;
+ }
+
+ UserHash[hashEnt].lastnick = newnick;
+ newnick->hashnext = NULL;
+
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s hash entry is %i (ADD)", myname, newnick->nick,
+ hashEnt);
+#endif
+}
+
+void addRegNick(RegNickList * newnick)
+{
+ long hashEnt;
+
+ if (getRegNickData(newnick->nick)) {
+ sfree(newnick);
+ return;
+ }
+
+ if (!firstRegNick) {
+ firstRegNick = newnick;
+ newnick->previous = NULL;
+ } else {
+ lastRegNick->next = newnick;
+ newnick->previous = lastRegNick;
+ }
+
+ lastRegNick = newnick;
+ newnick->next = NULL;
+
+ hashEnt = getHashKey(newnick->nick) % NICKHASHSIZE;
+ if (!RegNickHash[hashEnt].nick) {
+ RegNickHash[hashEnt].nick = newnick;
+ newnick->hashprev = NULL;
+ } else {
+ RegNickHash[hashEnt].lastnick->hashnext = newnick;
+ newnick->hashprev = RegNickHash[hashEnt].lastnick;
+ }
+
+ RegNickHash[hashEnt].lastnick = newnick;
+ newnick->hashnext = NULL;
+
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s hash entry is %i (ADD)", myname, newnick->nick,
+ hashEnt);
+#endif
+}
+
+
+void delNick(UserList * killme)
+{
+ long hashEnt;
+ UserList *tmpnick;
+
+ if (!killme)
+ return;
+
+ if ((killme->next) || (killme->previous) || (killme == firstUser)) { /* ARE WE IN THE TREE... IF NOT SKIP IT */
+ if (killme->previous)
+ killme->previous->next = killme->next;
+ else
+ firstUser = killme->next;
+ if (killme->next)
+ killme->next->previous = killme->previous;
+ else
+ lastUser = killme->previous;
+
+ hashEnt = getHashKey(killme->nick) % NICKHASHSIZE;
+
+ for (tmpnick = UserHash[hashEnt].nick; tmpnick;
+ tmpnick = tmpnick->hashnext) {
+ if (tmpnick == killme) {
+ if (killme->hashprev)
+ killme->hashprev->hashnext = killme->hashnext;
+ else
+ UserHash[hashEnt].nick = killme->hashnext;
+ if (killme->hashnext)
+ killme->hashnext->hashprev = killme->hashprev;
+ else
+ UserHash[hashEnt].lastnick = killme->hashprev;
+ break;
+ }
+ }
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s hash entry is %i (DELETE)", myname,
+ killme->nick, hashEnt);
+#endif
+ }
+ sfree(killme);
+}
+
+void delRegNick(RegNickList * killme)
+{
+ long hashEnt;
+ RegNickList *tmpnick;
+ UserList *online;
+
+ MemoBox *memobox;
+ MemoList *memo, *nextmemo;
+
+ remfromallchanops(killme->nick); /* REMOVE FROM ALL CHANNEL ACCESS LISTS - SYNCRONIZE CHANSERV */
+
+ memobox = killme->memos; /* WIPE OUT MEMO BOX -- SYNCH MEMOSERV */
+
+ if (memobox) {
+ for (memo = memobox->firstMemo; memo; memo = nextmemo) {
+ nextmemo = memo->next;
+ delMemo(memobox, memo);
+ }
+ sfree(memobox);
+ }
+
+ online = getNickData(killme->nick);
+ if (online) {
+ online->reg = NULL;
+ }
+
+ if (killme->previous)
+ killme->previous->next = killme->next;
+ else
+ firstRegNick = killme->next;
+ if (killme->next)
+ killme->next->previous = killme->previous;
+ else
+ lastRegNick = killme->previous;
+
+ hashEnt = getHashKey(killme->nick) % NICKHASHSIZE;
+ for (tmpnick = RegNickHash[hashEnt].nick; tmpnick;
+ tmpnick = tmpnick->hashnext) {
+ if (tmpnick == killme) {
+ if (killme->hashprev)
+ killme->hashprev->hashnext = killme->hashnext;
+ else
+ RegNickHash[hashEnt].nick = killme->hashnext;
+ if (killme->hashnext)
+ killme->hashnext->hashprev = killme->hashprev; /* AAHHHHHAAA!!!! */
+ else
+ RegNickHash[hashEnt].lastnick = killme->hashprev;
+ break;
+ }
+ }
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s hash entry is %i (DELETE)", myname,
+ killme->nick, hashEnt);
+#endif
+ sfree(killme);
+}
+
+/* get the nick item for the specified nick... */
+UserList *getNickData(char *nick)
+{
+ long hashEnt;
+ UserList *tmpnick;
+
+ hashEnt = getHashKey(nick) % NICKHASHSIZE;
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s has hash entry %lu (SEARCH)", myname, nick,
+ hashEnt);
+#endif
+ if (UserHash[hashEnt].nick) {
+ for (tmpnick = UserHash[hashEnt].nick; tmpnick;
+ tmpnick = tmpnick->hashnext) {
+ if (!strcasecmp(tmpnick->nick, nick))
+ return tmpnick;
+ }
+ }
+ return NULL;
+}
+
+RegNickList *getRegNickData(char *nick)
+{
+ long hashEnt;
+ RegNickList *tmpnick;
+
+ hashEnt = getHashKey(nick) % NICKHASHSIZE;
+#ifdef HASHDEBUG
+ sSend(":%s GNOTICE :%s has hash entry %lu (SEARCH)", myname, nick,
+ hashEnt);
+#endif
+
+ if (RegNickHash[hashEnt].nick) {
+ for (tmpnick = RegNickHash[hashEnt].nick; tmpnick;
+ tmpnick = tmpnick->hashnext) {
+ if (!strcasecmp(tmpnick->nick, nick))
+ return tmpnick;
+ }
+ }
+
+ /* DIDN'T FIND IT THERE, NOW LOOK THE HARD WAY
+ OH, WE PRAY WE DON'T NEED THIS ANYMORE
+
+ for (tmpnick = firstRegNick; tmpnick; tmpnick = tmpnick->next)
+ if (!strcasecmp(nick,tmpnick->nick))
+ return tmpnick;
+ */
+ return NULL;
+}
+
+
+/* initNickData, this will clean up, or make it useable for new stuff
+ * to be put into...
+ */
+void initUserData(UserList * nick)
+{
+ nick->nick[0] = 0;
+ nick->user[0] = 0;
+ nick->host[0] = 0;
+ nick->server[0] = 0;
+ nick->realname[0] = 0;
+ nick->caccess = 0;
+ nick->oflags = 0;
+ nick->floodlevel = 0;
+ nick->lastmsg = 0;
+ nick->reg = NULL;
+ nick->firstLink = nick->lastLink = NULL;
+ nick->hashnext = nick->hashprev = NULL;
+}
+
+void initNickData(RegNickList * nick)
+{
+ nick->nick[0] = nick->user[0] = nick->host[0] = nick->realname[0] =
+ nick->password[0] = nick->password2[0] = nick->url[0] =
+ nick->email[0] = nick->info[0] = 0;
+ nick->timestamp = nick->timereg = 0;
+ nick->amasks = nick->flags = nick->chans = 0;
+ nick->firstAcc = nick->lastAcc = NULL;
+ nick->memos = NULL;
+ nick->next = nick->previous = nick->hashnext = nick->hashprev = NULL;
+}
+
+/* IMPORTANT: make sure you understand this function, especially if you add
+ * new commands to NickServ, it will tell you simply whether or not the
+ * person has proper access to do something, along with the caccess flag
+ */
+
+int checkAccess(char *user, char *host, RegNickList * nick)
+{
+ nAccessList *tmp;
+ char theirmask[HOSTLEN + USERLEN + 3];
+
+ if (!nick)
+ return 0;
+
+ sprintf(theirmask, "%s@%s", user, host);
+
+ if (!(nick->flags & NACTIVE))
+ return -1;
+
+ /* otherwise, check their access masks */
+ for (tmp = nick->firstAcc; tmp; tmp = tmp->next) {
+ if (!match(theirmask, tmp->mask))
+ return 1; /* match! */
+ }
+ return 0; /* NoMatch */
+}
+
+void sendToNickServ(UserList * tmp, char **args, int numargs)
+{
+ char from[NICKLEN];
+
+ if (tmp == NULL) {
+ nDesynch(from, "PRIVMSG");
+ return;
+ }
+
+ strcpy(from, tmp->nick);
+
+ if (!strcmp(args[0], "\001PING")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_PING1, tmp), args[1]);
+ else
+ uSend(NickServ, tmp, GetReply(RPL_PING2, tmp), args[1],
+ args[2]);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "help") && numargs == 1)
+ sendHelp(from, NickServ, NULL, 0);
+ else if (!strcasecmp(args[0], "help"))
+ sendHelp(from, NickServ, args, numargs);
+ else
+ msgtabCheck(NickServ, tmp, args, numargs);
+
+#ifdef SHOWSYNCHALL
+ sSend(REPLY_DBSYNCH, NickServ, tmp->nick, ((nextNsync - CTime) / 60));
+#endif
+}
+
+char LinkBuffer[512];
+
+char *ListLinkId(UserList * nick)
+{
+
+ nLinkList *tmp;
+
+ LinkBuffer[0] = '\0';
+
+ for (tmp = nick->firstLink; tmp; tmp = tmp->next) {
+ strcat(LinkBuffer, tmp->nick);
+ strcat(LinkBuffer, " ");
+ }
+ return LinkBuffer;
+}
+
+int AddLinkId(UserList * nick, char *remote)
+{
+
+ nLinkList *tmp;
+
+ for (tmp = nick->firstLink; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->nick, remote)) {
+ uSend(NickServ, nick, GetReply(ERR_ALREADYLINKID, nick),
+ remote);
+ return 0;
+ }
+ }
+
+ if (nick->linked >= MAXREMOTEID) {
+ uSend(NickServ, nick, GetReply(ERR_MAXLINKID, nick), MAXREMOTEID);
+ return 0;
+ }
+
+ tmp = smalloc(sizeof(nLinkList));
+ strcpy(tmp->nick, remote);
+
+ if (!nick->firstLink) {
+ nick->firstLink = tmp;
+ tmp->previous = NULL;
+ } else {
+ nick->lastLink->next = tmp;
+ tmp->previous = nick->lastLink;
+ }
+
+ nick->lastLink = tmp;
+ tmp->next = NULL;
+ nick->linked++;
+
+ return 1;
+}
+
+void NidentifyCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ int err;
+ RegNickList *rid;
+ time_t doot = time(NULL);
+ char sendfrom[80];
+ struct access_mod *ak;
+
+ int old_access;
+
+ old_access = tmp->caccess;
+
+ if (!strcasecmp(args[0], "SIDENTIFY")) {
+ if (!tmp->reg || !(tmp->reg->flags2 & NSIDENTIFY))
+ return;
+ }
+
+ /* Remote ID for nicknames. -GZ */
+
+ if (numargs > 2)
+ if (strcasecmp(args[2], from))
+ {
+ rid = getRegNickData(args[2]);
+ if (!rid)
+ {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[2]);
+ return;
+ }
+
+ if ((rid->flags & NBANISH) && (!isRoot(tmp)))
+ {
+ uSend(NickServ, tmp, GetReply(RPL_INFOBANISHED, tmp));
+ return;
+ }
+
+ if (!strncmp(args[1], rid->password, 15)) {
+ if (AddLinkId(tmp, rid->nick)) {
+ uSend(NickServ, tmp, GetReply(RPL_PASSOKAY, tmp),
+ rid->nick);
+ strcpy(rid->user, tmp->user);
+ strcpy(rid->host, tmp->host);
+ strcpy(rid->realname, tmp->realname);
+ rid->timestamp = CTime;
+ tmp->remotefailid = 0;
+ }
+ } else {
+ tmp->remotefailid++;
+ uSend(NickServ, tmp, GetReply(RPL_PASSNOTOKAY, tmp),
+ rid->nick);
+ }
+
+ /* Remote ID floodprotection to be, it's not pretty, but let's see how it will do. - GZ */
+
+ if (tmp->remotefailid == 3)
+ {
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK1, tmp));
+ sSend(":%s GLOBOPS :\002Warning:\002 Possible remote-ID hacking from %s!%s@%s (%s)", NickServ, tmp->nick, tmp->user, tmp->host, rid->nick);
+ }
+ else if (tmp->remotefailid == 6)
+ {
+ sSend(":%s GLOBOPS :\002Warning:\002 Continued remote-ID hacking from %s!%s@%s (%s)", NickServ, tmp->nick, tmp->user, tmp->host, rid->nick);
+ killUser(services[1], tmp, "Nickname hacking");
+ }
+
+ return;
+ }
+
+ if (!tmp->reg || !tmp->reg->flags & NACTIVE) {
+ uSend(NickServ, tmp, GetReply(ERR_NEEDACTNICK, tmp));
+ return;
+ }
+
+ if (!strncmp(args[1], tmp->reg->password, 15)) {
+ tmp->caccess = 3;
+ tmp->failid = 0; /* o O. it's the real person here better start all over. */
+ strcpy(tmp->reg->nick, tmp->nick);
+ strcpy(tmp->reg->user, tmp->user);
+ strcpy(tmp->reg->host, tmp->host);
+ strcpy(tmp->reg->realname, tmp->realname);
+ tmp->reg->timestamp = CTime;
+
+ /* Set user +I after succesful identification
+ * or +Iw for webbies */
+ if (tmp->reg->flags2 & NMSGMODE) {
+ tmp->webbie = 1;
+ sSend(":%s SVSMODE %s +Iw", myname, from);
+ } else {
+ /* Person is no longer a webbie. Since IRC ops sometimes want
+ * to test 'being' a webbie, we should reset the flags if
+ * they ID back to their own non webbie nick */
+ tmp->webbie = 0;
+ sSend(":%s SVSMODE %s +I-w", myname, from);
+ }
+
+ /* Tell them the password is ok */
+ uSend(NickServ, tmp, GetReply(RPL_PASSOKAY, tmp), tmp->nick);
+
+ tmp->oflags |= NISIDENT;
+
+ if (isOper(tmp))
+ tmp->reg->flags2 |= NSTICKYOP;
+
+ if ((tmp->reg->flags & NROOT) && isOper(tmp))
+ uSend(NickServ, tmp, GetReply(RPL_YOUAREROOT, tmp));
+ else if (tmp->reg->flags & NSERVOP && isOper(tmp))
+ uSend(NickServ, tmp, GetReply(RPL_YOUARESERVOP, tmp));
+
+ /* HELP FORGETFUL SERVOPS BY GIVING THEM THEIR +a BACK */
+ if ((tmp->reg->flags & NSERVOP) && isOper(tmp))
+ sSend(":%s SVSMODE %s +a", myname, from);
+
+ /* THIS IS FOR THE SERVICES ROOT, NETADMIN AND MASKS (+n/+N) */
+ if ((tmp->reg->flags & NNETADM) && isOper(tmp))
+ sSend(":%s SVSMODE %s +Nna", myname, from); /* Network Administrator */
+
+ else if ((tmp->reg->flags & NROOT) && isOper(tmp))
+ sSend(":%s SVSMODE %s +na", myname, from); /* Services Root */
+
+ /* Remove a jinx only if it was a hostjinx */
+ ak = isHJinxed(tmp->nick, tmp->user, tmp->host);
+
+ if (ak) {
+ DeleteJinx(tmp->nick) ;
+ sSend(":%s UNJINX %s", myname, tmp->nick);
+ }
+
+ checkMemos(tmp);
+
+ return;
+ } else {
+ if (tmp->caccess > 1) { /* Remove +I flag after failed ID */
+ sSend(":%s SVSMODE %s -I", myname, from);
+ }
+
+ tmp->caccess = 1; /* failed identify takes away even the access list ID */
+ uSend(NickServ, tmp, GetReply(RPL_PASSNOTOKAY, tmp), tmp->nick);
+
+ tmp->failid++; /* If you fail id, add one to it */
+ if (tmp->failid == 3) {
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK1, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK2, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK3, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK4, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK5, tmp));
+
+ sprintf(sendfrom, "Nickname Services <%s@%s>", NickServ,
+ NETHOST);
+ err =
+ sendMail(tmp->reg->email, sendfrom,
+ "Incorrect password notification.",
+ "Hello %s,\n\n"
+ "%s has determined that someone entered an incorrect password\n"
+ "for your nick several times. The IP address of this individual\n"
+ "is %s@%s .\n\n"
+ "In case you forgot the correct password for %s, it is: %s\n\n"
+ "If you receive more than three (3) of these notices, please visit\n"
+ "#help to request an IRC operator to assist you.\n\n"
+ "This email was sent at: %s\n"
+ "Please do not reply to this email as your response will not be read.\n",
+ tmp->nick, NickServ, tmp->user, tmp->host, tmp->nick,
+ tmp->reg->password, ctime(&(doot)));
+ logDump(nicklog,
+ "Automailed pass for the nick %s to %s due to hacking from %s@%s.",
+ from, tmp->reg->email, tmp->user, tmp->host);
+ }
+
+ if (tmp->failid > 5) {
+ sSend
+ (":%s GLOBOPS :\002Warning:\002 Nickname-hacking attempt from %s!%s@%s (user has been killed).",
+ NickServ, from, tmp->user, tmp->host);
+ uSend(NickServ, tmp, GetReply(RPL_EMAILHACK6, tmp));
+ logDump(nicklog, "Persisted hacking for the nick %s by %s@%s.",
+ from, tmp->user, tmp->host);
+ killUser(services[1], tmp, "Nickname hacking");
+ }
+
+ }
+}
+
+void NsetCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+
+ if (!strcasecmp(args[1], "kill") || !strcasecmp(args[1], "guard")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Nickname Guard",
+ (tmp->reg->flags & NKILL) ? "ON" : "OFF");
+ else {
+ if (!strcasecmp(args[2], "on")) {
+ tmp->reg->flags |= NKILL;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Nickname Guard", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ tmp->reg->flags &= ~NKILL;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Nickname Guard", "OFF");
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET GUARD");
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "noop")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Nickname No-Ops",
+ (tmp->reg->flags & NNOOP) ? "ON" : "OFF");
+ else {
+ if (!strcasecmp(args[2], "on")) {
+ tmp->reg->flags |= NNOOP;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Nickname No-Ops", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ tmp->reg->flags &= ~NNOOP;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Nickname No-Ops", "OFF");
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET NOOP");
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "sidentify")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Use SIDENTIFY",
+ (tmp->reg->flags2 & NSIDENTIFY) ? "ON" : "OFF");
+ else {
+ if (!strcasecmp(args[2], "on")) {
+ tmp->reg->flags2 |= NSIDENTIFY;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Use SIDENTIFY", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ tmp->reg->flags2 &= ~NSIDENTIFY;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Use SIDENTIFY", "OFF");
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET SIDENTIFY");
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "language")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Services Language", GetLanguage(tmp));
+ else {
+ if (!strcasecmp(args[2], "english")) {
+ tmp->reg->language = 0;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "dutch")) {
+ tmp->reg->language = 1;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "french")) {
+ tmp->reg->language = 2;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "german")) {
+ tmp->reg->language = 3;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "lcars")) {
+ tmp->reg->language = 4;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "spanish")) {
+ tmp->reg->language = 5;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else if (!strcasecmp(args[2], "cajun")) {
+ tmp->reg->language = 6;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Services Language", GetLanguage(tmp));
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET LANGUAGE");
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "hide")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Hostmask Hiding",
+ (tmp->reg->flags & NHIDE) ? "ON" : "OFF");
+ else {
+ if (!strcasecmp(args[2], "on")) {
+ tmp->reg->flags |= NHIDE;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Hostmask Hiding", "ON");
+ } else if (!strcasecmp(args[2], "off")) {
+ tmp->reg->flags &= ~NHIDE;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Hostmask Hiding", "OFF");
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET HIDE");
+ }
+ }
+ }
+
+ else if (!match(args[1], "password")) {
+ if (numargs < 3) {
+ uSend(NickServ, tmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ,
+ "SET PASSWORD");
+ } else {
+ if ((4 > strlen(args[2])) || (15 < strlen(args[2])))
+ uSend(NickServ, tmp, GetReply(ERR_BADPASSWORD, tmp));
+ else {
+ strncpy(tmp->reg->password, args[2], 15);
+ uSend(NickServ, tmp, GetReply(RPL_PASSWORDNOW, tmp),
+ tmp->reg->password);
+ tmp->reg->lastpwchange = CTime;
+ logDump(nicklog, "%s!%s@%s: changed password.\n", from,
+ tmp->user, tmp->host);
+
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "email")) {
+ if (numargs < 3)
+ uSend(NickServ, tmp, GetReply(RPL_NSETIS, tmp),
+ "Email Address",
+ (tmp->reg->flags & NEMAIL) ? "PUBLIC" : "PRIVATE");
+ else {
+ if (!strcasecmp(args[2], "on")
+ || !strcasecmp(args[2], "public")) {
+ tmp->reg->flags |= NEMAIL;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Email Address", "PUBLIC");
+ } else if (!strcasecmp(args[2], "off")
+ || !strcasecmp(args[2], "private")) {
+ tmp->reg->flags &= ~NEMAIL;
+ uSend(NickServ, tmp, GetReply(RPL_NSETNOW, tmp),
+ "Email Address", "PRIVATE");
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_BADSETTING, tmp),
+ args[2]);
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET EMAIL");
+ }
+ }
+ } else if (!strcasecmp(args[1], "address")) {
+ char sendfrom[80];
+ int err;
+
+ RegNickList *target;
+
+ if (numargs > 3) {
+ if (!isServop(tmp)) {
+ uSend(NickServ, tmp, GetReply(ERR_NEEDSERVOP, tmp));
+ return;
+ }
+
+ target = getRegNickData(args[3]);
+
+ if (!target) {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[3]);
+ return;
+ }
+
+ if ((!strchr(args[2], '@')) || (strlen(args[2]) < 5)
+ || (strlen(args[2]) > EMAILLEN)) {
+ uSend(NickServ, tmp, GetReply(ERR_VALIDEMAIL, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET ADDRESS");
+ return;
+ }
+
+ sSend(":%s GLOBOPS :%s changed email address for %s from %s to %s",
+ NickServ, from, args[3], target->email, args[2]);
+
+ logDump(nicklog, "%s!%s@%s: changed address for %s from '%s' to '%s'\n",
+ from, tmp->user, tmp->host, args[3], target->email, args[2]);
+
+ strcpy(target->email, args[2]);
+
+ return;
+ }
+
+ if (numargs < 3) {
+ uSend(NickServ, tmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ,
+ "SET ADDRESS");
+ } else {
+ srandom(time(NULL));
+
+ if ((!strchr(args[2], '@')) || (strlen(args[2]) < 5)
+ || (strlen(args[2]) > EMAILLEN)) {
+ uSend(NickServ, tmp, GetReply(ERR_VALIDEMAIL, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp),
+ NickServ, "SET ADDRESS");
+ return;
+ }
+
+ if (countRegAddy(args[2]) >= NickLimit) {
+ uSend(NickServ, tmp, GetReply(ERR_NICKLIMIT, tmp));
+ return;
+ }
+
+ if (VerifyEmail(args[2])) {
+ uSend(NickServ, tmp, GetReply(ERR_NOWEBMAIL, tmp));
+ return;
+ }
+
+ sprintf(tmp->reg->password2, "%lu", (long) random());
+ strcpy(tmp->reg->email, args[2]);
+ sprintf(sendfrom, "Nickname services <%s@%s>", NickServ,
+ NETHOST);
+ err =
+ sendMail(args[2], sendfrom, "Nickname activation key",
+ "\nYour nickname registration has been verified\n"
+ "To activate your nickname: switch to the nickname %s and\n"
+ "/msg %s ACTIVATE %s\n"
+ "%s is your activation key\n"
+ "Even when your nickname is registered, Do not lose this PLEASE.",
+ tmp->nick, NickServ, tmp->reg->password2,
+ tmp->reg->password2);
+ if (!err) {
+ uSend(NickServ, tmp, GetReply(RPL_TEMPDEAC1, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_TEMPDEAC2, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_TEMPDEAC3, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_TEMPDEAC4, tmp),
+ args[2]);
+ tmp->reg->flags &= ~NACTIVE;
+ tmp->reg->flags |= NDEACC;
+ logDump(nicklog, "%s!%s@%s: changed address to '%s'\n",
+ from, tmp->user, tmp->host, args[2]);
+ } else
+ uSend(NickServ, tmp, GetReply(ERR_NOMAILSENT, tmp));
+ }
+ }
+
+ else
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ,
+ "SET");
+}
+
+void NregisterCmd(UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+ time_t doot = time(NULL);
+ char scanhost[512];
+ char sendfrom[80];
+ int err;
+ UserList *msgtmp=tmp;
+ int donefudge=0;
+
+ srandom(time(NULL));
+
+ if(!match(args[1], "*webtv.net*"))
+ {
+ msgtmp = smalloc(sizeof(UserList));
+ memcpy(msgtmp,tmp,sizeof(UserList));
+ msgtmp->reg=smalloc(sizeof(RegNickList));
+ msgtmp->reg->flags2 = NMSGMODE;
+ msgtmp->webbie = 1;
+ uSend(NickServ,msgtmp,"You have been detected as a WebTV user, if that is not true, please ask anyone in #help to change your message mode.");
+ donefudge=1;
+ }
+
+ if (tmp->reg)
+ {
+ if (!tmp->reg->flags & NACTIVE)
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_NEEDTOACT, tmp));
+ uSend(NickServ, msgtmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ, "ACTIVATE");
+ }
+ else uSend(NickServ, msgtmp, GetReply(ERR_ALREADYREG, tmp));
+
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if ((!strncasecmp(from, "Guest", 5)) || (!strcasecmp(from, "done")) ||
+ (!strncasecmp(from, "SereneMIRC", 10)) || (!strncasecmp(from, "SerenePIRCH", 11)))
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_CANNOTREGTHIS, tmp));
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if (numargs < 3)
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(NickServ, msgtmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ, "REGISTER");
+
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if ((!strchr(args[1], '@')) || (strlen(args[1]) < 5) || (strlen(args[1]) > EMAILLEN))
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_VALIDEMAIL, tmp));
+ uSend(NickServ, msgtmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ, "REGISTER");
+
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if (VerifyEmail(args[1]))
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_NOWEBMAIL, tmp));
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ sprintf(scanhost, "*%s*", tmp->host);
+
+ if (!match(args[1], scanhost))
+ {
+ uSend(NickServ, tmp, GetReply(ERR_BANNEDEMAIL, tmp));
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if ((15 < strlen(args[2])) || (4 > strlen(args[2])))
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_BADPASSWORD, tmp));
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if (countRegAddy(args[1]) >= NickLimit)
+ {
+ uSend(NickServ, msgtmp, GetReply(ERR_NICKLIMIT, tmp));
+ sSend(":%s GLOBOPS :%s (%s) is trying to register too many nicks.", NickServ, from, args[1]);
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+ return;
+ }
+
+ if(donefudge)
+ {
+ sfree(msgtmp->reg);
+ sfree(msgtmp);
+ }
+
+ tmp->reg = smalloc(sizeof(RegNickList));
+ strcpy(tmp->reg->nick, tmp->nick);
+ strcpy(tmp->reg->user, tmp->user);
+ strcpy(tmp->reg->host, tmp->host);
+ sprintf(tmp->reg->password2, "%lu", (long) random());
+ tmp->reg->timestamp = CTime;
+ tmp->reg->timereg = CTime;
+ tmp->reg->lastpwchange = CTime;
+ tmp->reg->flags |= NREG;
+ tmp->reg->flags |= NHIDE;
+ if(donefudge) {
+ tmp->reg->flags2 = NMSGMODE;
+ tmp->webbie = 1;
+ }
+ tmp->caccess = 3;
+ strcpy(tmp->reg->email, args[1]);
+ strncpy(tmp->reg->password, args[2], 15);
+ sprintf(sendfrom, "Nickname Services <%s@%s>", NickServ, NETHOST);
+ err = sendMail(args[1], sendfrom, "Nickname activation key",
+ "Hello %s, Welcome to the Serenity-IRC network!\n\n"
+ "Your nickname registration has been verified.\n\n"
+ "To activate your nickname:\n\n"
+ "1) switch to the nickname %s\n"
+ "2) /msg %s ACTIVATE %s\n\n"
+ "%s is your activation key. %s is your password.\n\n"
+ "Please try to remember your password, you might need it\n"
+ "some day.\n\n"
+ "If you accidently lose your password, you can always\n"
+ "/join #help and ask one of our IRC Operators to recover\n"
+ "it for you. We will be more than glad to help you!\n\n"
+ "If you are new to IRC or Serenity-IRC, we would like to recommend\n"
+ "#help, as it is the place where you can obtain help or any\n"
+ "other kind of information that is IRC related.\n\n"
+ "Enjoy your stay on our safe and friendly network!\n\n"
+ "For additional help, try these commands:\n"
+ " /msg %s HELP\n"
+ " /msg %s HELP\n"
+ " /msg %s HELP\n"
+ "\nNOTICE: This mail sent by: %s@%s at %s",
+ tmp->nick, tmp->nick, NickServ, tmp->reg->password2,
+ tmp->reg->password2, tmp->reg->password, NickServ,
+ ChanServ, MemoServ, tmp->user, tmp->host,
+ ctime(&(doot)));
+
+ if (!err)
+ {
+ uSend(NickServ, tmp, GetReply(RPL_TEMPDEAC4, tmp), args[1]);
+ logDump(nicklog, "%s!%s@%s: ACTIVATION key sent to '%s'\n", from,
+ tmp->user, tmp->host, args[1]);
+ addRegNick(tmp->reg);
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_NOMAILSENT, tmp));
+ sfree(tmp->reg);
+ tmp->reg = NULL;
+ }
+ return;
+}
+
+void NactivateCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ time_t doot;
+
+ if (strcmp(args[1], tmp->reg->password2)) {
+ uSend(NickServ, tmp, GetReply(ERR_ACCESSDENIED, tmp));
+ return;
+ }
+
+ if (!(tmp->reg->flags & NACTIVE)) {
+ char user2[USERLEN], host2[HOSTLEN];
+
+ strcpy(user2, tmp->user);
+ strcpy(host2, tmp->host);
+
+ doot = time(NULL);
+
+ if (!(tmp->reg->flags & NDEACC)) {
+ mostnicks++;
+ strcpy(tmp->reg->nick, tmp->nick);
+ tmp->reg->timereg = time(NULL);
+ tmp->reg->firstAcc = tmp->reg->lastAcc = NULL;
+/* tmp->reg->firstAcc = smalloc(sizeof(nAccessList));
+ mask(user2, host2, 0, tmp->reg->firstAcc->mask);
+ tmp->reg->firstAcc->index = 1;
+ tmp->reg->firstAcc->next = tmp->reg->firstAcc->previous = NULL;
+ tmp->reg->lastAcc = tmp->reg->firstAcc; */
+ tmp->reg->amasks = 0;
+ tmp->caccess = 3;
+ tmp->reg->flags |= NACTIVE;
+ tmp->reg->flags |= NHIDE;
+ tmp->reg->url[0] = 0;
+ tmp->reg->chans = 0;
+ strcpy(tmp->reg->user, tmp->user);
+ strcpy(tmp->reg->host, tmp->host);
+ strcpy(tmp->reg->realname, tmp->realname);
+ /* Set user +I after succesful identification
+ * or +Iw for webbies */
+ if (tmp->reg->flags2 & NMSGMODE) {
+ tmp->webbie = 1;
+ sSend(":%s SVSMODE %s +Iw", myname, from);
+ } else {
+ /* Person is no longer a webbie. Since IRC ops sometimes want
+ * to test 'being' a webbie, we should reset the flags if
+ * they ID back to their own non webbie nick */
+ tmp->webbie = 0;
+ sSend(":%s SVSMODE %s +I-w", myname, from);
+ }
+
+ uSend(NickServ, tmp, GetReply(RPL_ACTIVATE1, tmp), from);
+/* uSend(NickServ, tmp, GetReply(RPL_ACTIVATE2, tmp),
+ tmp->reg->firstAcc->mask);
+ uSend(NickServ, tmp, GetReply(RPL_ACTIVATE3, tmp));*/
+ uSend(NickServ, tmp, GetReply(RPL_ACTIVATE4, tmp),
+ ctime(&(doot)));
+ uSend(NickServ, tmp, GetReply(RPL_ACTIVATE5, tmp),
+ tmp->reg->password);
+ uSend(NickServ, tmp, GetReply(RPL_ACTIVATE6, tmp));
+ logDump(nicklog, "%s!%s@%s: REGISTER\n", from, tmp->user,
+ tmp->host);
+ } else {
+ uSend(NickServ, tmp, GetReply(RPL_REACTIVATE, tmp));
+ tmp->reg->flags |= NACTIVE;
+ tmp->reg->flags &= ~NDEACC;
+ }
+ } else {
+ uSend(NickServ, tmp, GetReply(RPL_ALREADYACT, tmp));
+ }
+}
+
+char AccessString[128];
+char OptionString[128];
+
+char *GetAccessString(RegNickList * nick)
+{
+
+ AccessString[0] = '\0';
+
+ if (nick->flags & NROOT)
+ sprintf(AccessString, "Services Root Administrator");
+ else if (nick->flags & NSERVOP)
+ sprintf(AccessString, "Services Operator");
+ else if (nick->flags2 & NSTICKYOP)
+ sprintf(AccessString, "IRC Operator");
+
+ return AccessString;
+}
+
+char *GetOptionString(RegNickList * nick)
+{
+
+ OptionString[0] = '\0';
+ if (nick->flags & NKILL)
+ strcat(OptionString, "guard ");
+ if (nick->flags & NHOLD)
+ strcat(OptionString, "held ");
+ if (nick->flags & NMARKED)
+ strcat(OptionString, "marked ");
+ if (nick->flags & NNOOP)
+ strcat(OptionString, "noop ");
+ if (nick->flags & NHIDE)
+ strcat(OptionString, "hide ");
+ if (nick->flags2 & NMSGMODE)
+ strcat(OptionString, "msgmode ");
+ if (nick->flags & NVACATION)
+ strcat(OptionString, "vacation ");
+
+ return OptionString;
+}
+
+char *GetMemoString(RegNickList * nick)
+{
+
+ char redirect[128];
+ OptionString[0] = redirect[0] = '\0';
+
+ if (nick->memos) {
+ if (nick->memos->flags & MNOMEMO)
+ strcat(OptionString, "nomemo ");
+ if (nick->memos->flags & MNOFORWARD)
+ strcat(OptionString, "noforward ");
+ if ((nick->memos->flags & MFORWARDED)
+ && (nick->memos->redirect[0])) {
+ sprintf(redirect, "redirect[%s] ", nick->memos->redirect);
+ strcat(OptionString, redirect);
+ }
+ }
+
+ return OptionString;
+}
+
+char *GetAccess(UserList * nick)
+{
+
+ AccessString[0] = '\0';
+
+ switch (nick->caccess) {
+ case 1:
+ strcpy(AccessString, "Not Identified");
+ break;
+ case 2:
+ strcpy(AccessString, "Matching access list");
+ break;
+ case 3:
+ strcpy(AccessString, "Identified");
+ break;
+ default:
+ strcpy(AccessString, "Unknown");
+ break;
+ }
+
+ return AccessString;
+}
+
+void NinfoCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+
+ int i = 0;
+ nMarkList *ml = NULL;
+ RegNickList *err;
+ UserList *online = NULL;
+
+ if (numargs > 1)
+ err = getRegNickData(args[1]);
+ else
+ err = tmp->reg;
+
+ if (!err) {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp),
+ numargs > 1 ? args[1] : from);
+ return;
+ }
+
+ uSend(NickServ, tmp, GetReply(RPL_INFOHEADER, tmp), err->nick);
+
+ if (err->flags & NBANISH) {
+ uSend(NickServ, tmp, GetReply(RPL_INFOBANISHED, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_INFOFOOTER, tmp));
+ return;
+ }
+
+ if ((!(err->flags & NREG)) && (err->flags & NACTIVE)) {
+ uSend(NickServ, tmp, GetReply(RPL_INFODEREG, tmp), err->nick);
+ uSend(NickServ, tmp, GetReply(RPL_INFOFOOTER, tmp));
+ return;
+ }
+
+ if ((online = getNickData(err->nick)) && (err->flags & NREG))
+ uSend(NickServ, tmp, GetReply(RPL_INFONOWON, tmp), err->nick);
+
+ if ((err->flags & NACTIVE) && (err->flags & NREG)) {
+ struct tm *time;
+ char temp[80];
+
+ if (isOper(tmp)
+ || (!strcasecmp(err->nick, from)
+ && tmp->caccess == 3)) uSend(NickServ, tmp,
+ GetReply(RPL_INFOLASTSEEN1,
+ tmp), err->user,
+ err->host, err->realname);
+ else if (online)
+ uSend(NickServ, tmp, GetReply(RPL_INFOLASTSEEN1, tmp),
+ err->user, maskuser(online), err->realname);
+ else
+ uSend(NickServ, tmp, GetReply(RPL_INFOLASTSEEN1, tmp),
+ err->user, maskreguser(err), err->realname);
+
+ time = gmtime(&CTime);
+ strftime(temp, 80, "%a %d/%m/%Y %T %Z", time);
+ uSend(NickServ, tmp, GetReply(RPL_INFOTIMENOW, tmp), temp);
+
+ time = gmtime(&err->timestamp);
+ strftime(temp, 80, "%a %d/%m/%Y %T %Z", time);
+ uSend(NickServ, tmp, GetReply(RPL_INFOLASTSEEN2, tmp), temp);
+
+ time = gmtime(&err->timereg);
+ strftime(temp, 80, "%a %d/%m/%Y %T %Z", time);
+ uSend(NickServ, tmp, GetReply(RPL_INFOREGGEDON, tmp), temp);
+
+ if (err->flags & NEMAIL || isOper(tmp)
+ || (!strcasecmp(err->nick, from) && tmp->caccess == 3))
+ uSend(NickServ, tmp, GetReply(RPL_INFOEMAIL, tmp), err->email);
+
+ temp[0] = '\0';
+ strcpy(temp, GetAccessString(err));
+ if (temp[0])
+ uSend(NickServ, tmp, GetReply(RPL_INFOACCESS, tmp), temp);
+
+ temp[0] = '\0';
+ strcpy(temp, GetOptionString(err));
+ if (temp[0] && isOper(tmp))
+ uSend(NickServ, tmp, GetReply(RPL_INFOOPTIONS, tmp), temp);
+
+ temp[0] = '\0';
+ strcpy(temp, GetMemoString(err));
+ if (temp[0] && isOper(tmp))
+ uSend(NickServ, tmp, GetReply(RPL_INFOMEMO, tmp), temp);
+
+ temp[0] = '\0';
+ if (online)
+ strcpy(temp, ListLinkId(online));
+ if (temp[0])
+ uSend(NickServ, tmp, GetReply(RPL_INFOLINKID, tmp), temp);
+
+ if (online)
+ uSend(NickServ, tmp, GetReply(RPL_INFOCURRENTACC, tmp),
+ GetAccess(online));
+
+ if (isOper(tmp)) {
+ err->chans = countRegChans(err->nick);
+ if (err->memos)
+ uSend(NickServ, tmp, GetReply(RPL_INFODATA, tmp),
+ err->chans, err->memos->memos, err->amasks,
+ (online) ? online->floodbytes : 0);
+ else
+ uSend(NickServ, tmp, GetReply(RPL_INFODATA, tmp),
+ err->chans, 0, err->amasks,
+ (online) ? online->floodbytes : 0);
+
+ if (err->firstMark != NULL) {
+ for (ml = err->firstMark; ml != NULL; ml = ml->next) {
+ time = gmtime(&ml->timestamp);
+ strftime(temp, 80, "%d/%m/%Y", time);
+ uSend(NickServ, tmp, GetReply(RPL_INFOREMARK, tmp),
+ ++i, ml->markedby, temp, ml->remark);
+ }
+ }
+ }
+
+ uSend(NickServ, tmp, GetReply(RPL_INFOFOOTER, tmp));
+
+ return;
+ } else if (err->flags & NREG) {
+ uSend(NickServ, tmp, GetReply(RPL_INFOSTATUS, tmp),
+ "Registered but not activated");
+ if (isOper(tmp)) {
+ if ((err->flags & NMARKED) && isOper(tmp))
+ uSend(NickServ, tmp, GetReply(RPL_INFOOPTIONS, tmp),
+ "marked");
+ uSend(NickServ, tmp, GetReply(RPL_INFOEMAIL, tmp), err->email);
+ uSend(NickServ, tmp, GetReply(RPL_INFOREGBY, tmp), err->user,
+ err->host);
+ }
+
+ uSend(NickServ, tmp, GetReply(RPL_INFOFOOTER, tmp));
+
+ return;
+ } else {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp),
+ numargs > 1 ? args[1] : from);
+ return;
+ }
+}
+
+
+void NdropCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+
+ if (!strncmp(args[1], tmp->reg->password, 15)) {
+ mostnicks--;
+ uSend(NickServ, tmp, GetReply(RPL_NICKDROPPED, tmp), from);
+ logDump(nicklog, "%s!%s@%s: DROP\n", from, tmp->user, tmp->host);
+ delRegNick(tmp->reg);
+ return;
+ }
+}
+
+
+void addAccessMask(char *mask, UserList * nick)
+{
+
+ if (USERLEN + HOSTLEN + 3 < strlen(mask)) {
+ sSend
+ (":%s GLOBOPS :\002Warning:\002 %s tried to add a HUGE access mask",
+ NickServ, nick->nick);
+ uSend(NickServ, nick, GetReply(ERR_BADACCMASK, nick));
+ return;
+ }
+
+ if (nick->reg->amasks >= AccessLimit) {
+ uSend(NickServ, nick, GetReply(ERR_TOOMANYACCMASKS, nick));
+ return;
+ }
+
+ if (!addAccItem(nick->reg, mask))
+ uSend(NickServ, nick, GetReply(ERR_ACCMASKNOTADDED, nick), mask);
+ else
+ uSend(NickServ, nick, GetReply(RPL_ACCMASKADDED, nick), mask);
+}
+
+void delAccessMask(char *mask, UserList * nick)
+{
+ nAccessList *tmp;
+ char deleted[71];
+
+ if (!nick->reg->firstAcc)
+ return;
+ if (*mask == '-') {
+ for (tmp = nick->reg->firstAcc; tmp; tmp = tmp->next) {
+ delAccItem(nick->reg, tmp->mask, deleted);
+ }
+ uSend(NickServ, nick, GetReply(RPL_ACCLISTCLEARED, nick));
+ nick->reg->amasks = 0;
+ return;
+ } else {
+ if (delAccItem(nick->reg, mask, deleted)) {
+ uSend(NickServ, nick, GetReply(RPL_ACCMASKREMOVED, nick),
+ deleted);
+ nick->reg->amasks--;
+ } else if (!strchr(mask, '@'))
+ uSend(NickServ, nick, GetReply(ERR_ACCENTRYNOTFOUND, nick),
+ mask);
+ else
+ uSend(NickServ, nick, GetReply(ERR_ACCMASKNOTFOUND, nick),
+ mask);
+ }
+}
+
+void NaddMaskCmd(UserList * nick, char **args, int numargs)
+{
+
+ char user[USERLEN], host[HOSTLEN], theirmask[USERLEN + HOSTLEN + 3];
+
+ strcpy(user, nick->user);
+ strcpy(host, nick->host);
+
+ mask(user, host, 0, theirmask);
+
+ addAccessMask(theirmask, nick);
+
+ return;
+}
+
+void NmarkCmd(UserList * markedby, char **args, int numargs)
+{
+ int i, number = 0;
+ char markreason[128];
+ RegNickList *marktarget = NULL;
+
+ if (!strcasecmp(args[1], "add")) {
+
+ marktarget = getRegNickData(args[2]);
+
+ if (!marktarget) {
+ uSend(NickServ, markedby,
+ GetReply(ERR_NICKNOTREGGED, markedby), args[2]);
+ return;
+ }
+
+ bzero(markreason, 128);
+ strncpy(markreason, args[3], 127);
+ for (i = 4; i < numargs; i++) {
+ if ((strlen(markreason) + strlen(args[i])) > 126)
+ break;
+ strcat(markreason, " ");
+ strcat(markreason, args[i]);
+ }
+
+ add_mark((time_t) 0, markedby->nick, marktarget, markreason);
+ uSend(NickServ, markedby, GetReply(RPL_ADDREMARK, markedby),
+ marktarget->nick);
+
+ return;
+
+ } else if (!strcasecmp(args[1], "del")) {
+
+ marktarget = getRegNickData(args[2]);
+
+ if (!marktarget) {
+ uSend(NickServ, markedby,
+ GetReply(ERR_NICKNOTREGGED, markedby), args[2]);
+ return;
+ }
+
+ if (args[3][0] == '#')
+ number = atoi(&args[3][1]);
+ else
+ number = atoi(&args[3][0]);
+
+ if (!number) {
+ uSend(NickServ, markedby, GetReply(ERR_NOTAVALIDNUMBER, markedby),
+ args[3]);
+ return;
+ }
+
+ del_mark(marktarget, number);
+ uSend(NickServ, markedby, GetReply(RPL_DELREMARK, markedby),
+ marktarget->nick);
+ } else {
+ uSend(NickServ, markedby, GetReply(ERR_INCORRECTUSAGE, markedby),
+ "MARK");
+ uSend(NickServ, markedby, GetReply(RPL_MOREHELPCMD, markedby),
+ NickServ, "MARK");
+ return;
+ }
+}
+
+void add_mark(time_t timestamp, char *by, RegNickList *target, char *reason)
+{
+ nMarkList *ml = NULL, *add = NULL;
+
+ add = smalloc(sizeof(nMarkList));
+ strcpy(add->markedby, by);
+ strcpy(add->remark, reason);
+ if (!timestamp)
+ add->timestamp = CTime;
+ else
+ add->timestamp = timestamp;
+ add->next = NULL;
+
+ if (target->firstMark != NULL) {
+ for (ml = target->firstMark; ml->next != NULL; ml = ml->next)
+ ; /* Find last marker in list */
+ ml->next = add;
+ } else
+ target->firstMark = add;
+
+ return;
+}
+
+void del_mark(RegNickList *target, int number)
+{
+ int i;
+ nMarkList *ml, *tmp = NULL;
+
+ tmp = ml = target->firstMark;
+ for (i = 1; i < number && ml; i++) {
+ tmp = ml;
+ ml = ml->next; /* Find remark to delete in list */
+ }
+ if (ml) { /* We have a list with remarks */
+ if (tmp == ml) /* First element in list */
+ if (ml->next)
+ target->firstMark = ml->next;
+ else
+ target->firstMark = NULL;
+ else if (ml->next) /* Element in middle of list */
+ tmp->next = ml->next;
+ else
+ tmp->next = NULL; /* Last element in list */
+ sfree(ml);
+ }
+
+ return;
+}
+
+
+void NaccessCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ if (numargs < 2) {
+ uSend(NickServ, nick, GetReply(RPL_YOURACCESSIS, nick),
+ nick->caccess);
+ return;
+ }
+
+ if (!strcasecmp(args[1], "list")) {
+ nAccessList *tmp;
+ if (numargs < 3) {
+ uSend(NickServ, nick, GetReply(RPL_ACCESSHEADER, nick), from);
+ for (tmp = nick->reg->firstAcc; tmp; tmp = tmp->next)
+ uSend(NickServ, nick, GetReply(RPL_ACCESSLIST1, nick),
+ tmp->index, tmp->mask);
+ uSend(NickServ, nick, GetReply(RPL_ACCESSFOOTER, nick));
+ } else {
+ RegNickList *tmpnick;
+ nAccessList *tmp;
+
+ tmpnick = getRegNickData(args[2]);
+
+ if (!tmpnick) {
+ uSend(NickServ, nick, GetReply(ERR_NICKNOTREGGED, nick),
+ args[2]);
+ return;
+ }
+
+ if (!checkAccess(nick->user, nick->host, tmpnick)
+ && !isOper(nick)) {
+ uSend(NickServ, nick, GetReply(ERR_NOREMOTEACC, nick),
+ args[2]);
+ return;
+ }
+
+ uSend(NickServ, nick, GetReply(RPL_ACCESSHEADER, nick),
+ tmpnick->nick);
+
+ for (tmp = tmpnick->firstAcc; tmp; tmp = tmp->next)
+ uSend(NickServ, nick, GetReply(RPL_ACCESSLIST1, nick),
+ tmp->index, tmp->mask);
+ uSend(NickServ, nick, GetReply(RPL_ACCESSFOOTER, nick));
+ }
+ } else if (!strcasecmp(args[1], "add")) {
+ if (numargs < 3) {
+ uSend(NickServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(NickServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ NickServ, "ACCESS");
+ return;
+ }
+
+ addAccessMask(args[2], nick);
+ return;
+ } else if (!strncasecmp(args[1], "del", 3)) { /* also accepts delete */
+ if (numargs < 3) {
+ uSend(NickServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(NickServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ NickServ, "ACCESS");
+ return;
+ }
+
+ delAccessMask(args[2], nick);
+ return;
+ } else {
+ UserList *info;
+
+ info = getNickData(args[1]);
+
+ if (!info) {
+ uSend(NickServ, nick, GetReply(RPL_CURRENTACC, nick), args[1],
+ 0);
+ return;
+ }
+
+ else
+ uSend(NickServ, nick, GetReply(RPL_CURRENTACC, nick), args[1],
+ info->caccess);
+ }
+}
+
+
+void NghostCmd(UserList * nick, char **args, int numargs)
+{
+ RegNickList *tmp;
+ char ghoststr[NICKLEN + USERLEN + HOSTLEN + 13]; // 13 = Message overhead
+ int found_ghost = 0;
+
+ if (!strcasecmp(nick->nick, args[1])) {
+ uSend(NickServ, nick, GetReply(ERR_CANNOTGHOSTSELF, nick));
+ return;
+ }
+
+ tmp = getRegNickData(args[1]);
+
+ if (!tmp) {
+ uSend(NickServ, nick, GetReply(ERR_NICKNOTREGGED, nick), args[1]);
+ return;
+ }
+
+ found_ghost = isGhost(args[1]);
+
+ if ((!found_ghost) && (!getNickData(args[1]))) {
+ uSend(NickServ, nick, GetReply(ERR_NOTONLINE, nick), args[1]);
+ return;
+ }
+
+ if (strcasecmp(tmp->password, args[2])) {
+ uSend(NickServ, nick, GetReply(ERR_ACCESSDENIED, nick));
+ if (strcmp(tmp->host, nick->host))
+ nick->remotefailid++;
+
+ if (nick->remotefailid == 3) {
+ uSend(NickServ, nick, GetReply(RPL_EMAILHACK1, nick));
+ sSend
+ (":%s GLOBOPS :\002Warning:\002 Possible ghost-ID hacking from %s!%s@%s (%s)",
+ NickServ, nick->nick, nick->user, nick->host, tmp->nick);
+ } else if (nick->remotefailid == 6) {
+ sSend
+ (":%s GLOBOPS :\002Warning:\002 Continued ghost-ID hacking from %s!%s@%s (%s)",
+ NickServ, nick->nick, nick->user, nick->host, tmp->nick);
+ killUser(services[1], nick, "Nickname hacking");
+ }
+
+ return;
+ }
+
+ uSend(NickServ, nick, GetReply(RPL_NICKGHOSTED, nick), tmp->nick);
+
+ nick->remotefailid = 0;
+
+ if (found_ghost) {
+ delGhost(args[1]);
+ return;
+ }
+
+ sprintf(ghoststr, "Ghost by: %s!%s@%s", nick->nick, nick->user,
+ maskuser(nick));
+ killUser(services[1], getNickData(args[1]), ghoststr);
+ remUser(args[1]);
+}
+
+void NsetflagsCmd(UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+ RegNickList *nick;
+ int mode = 1, i;
+ char plusstring[15];
+ char minusstring[15];
+ int posid;
+
+ *plusstring = 0;
+ *minusstring = 0;
+
+ nick = getRegNickData(args[1]);
+ if (!nick) {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[1]);
+ return;
+ }
+
+ for (i = 0; (unsigned int)i < strlen(args[2]); i++) {
+ posid = 0;
+ switch (args[2][i]) {
+ case '+':
+ mode = 1;
+ break;
+ case '-':
+ mode = 0;
+ break;
+ case 'k':
+ posid = 1;
+ if (mode)
+ nick->flags |= NKILL;
+ else
+ nick->flags &= ~NKILL;
+ break;
+ case 'v':
+ posid = 1;
+ if (mode) {
+ nick->flags |= NVACATION;
+ if (nick->flags & NHOLD)
+ strcat(args[2], "-h");
+ } else
+ nick->flags &= ~NVACATION;
+ break;
+ case 'e':
+ posid = 1;
+ if (mode)
+ nick->flags |= NEMAIL;
+ else
+ nick->flags &= ~NEMAIL;
+ break;
+ case 'h':
+ posid = 1;
+ if (mode) {
+ nick->flags |= NHOLD;
+ if (nick->flags & NVACATION)
+ strcat(args[2], "-v");
+ } else
+ nick->flags &= ~NHOLD;
+ break;
+ case 'r':
+ posid = 1;
+ if (mode)
+ nick->flags |= NREG;
+ else
+ nick->flags &= ~NREG;
+ break;
+ case 'a':
+ posid = 1;
+ if (mode) {
+ nick->flags |= NACTIVE;
+ if (nick->flags & NDEACC)
+ strcat(args[2], "-d");
+ } else
+ nick->flags &= ~NACTIVE;
+ break;
+ case 'd':
+ posid = 1;
+ if (mode)
+ nick->flags |= NDEACC;
+ else
+ nick->flags &= ~NDEACC;
+ break;
+ case 's':
+ if (!isRoot(tmp))
+ uSend(NickServ, tmp, GetReply(ERR_NEEDSRA, tmp));
+ else {
+ posid = 1;
+ if (mode)
+ nick->flags |= NSERVOP;
+ else
+ nick->flags &= ~NSERVOP;
+ }
+ break;
+ case 'l':
+ posid = 1;
+ if (mode)
+ nick->flags |= NOPER;
+ else
+ nick->flags &= ~NOPER;
+ break;
+ case 'm':
+ posid = 1;
+ if (mode)
+ nick->flags |= NMARKED;
+ else
+ nick->flags &= ~NMARKED;
+ break;
+ case 'w':
+ posid = 1;
+ if (mode)
+ nick->flags2 |= NMSGMODE;
+ else
+ nick->flags2 &= ~NMSGMODE;
+ break;
+ default:
+ uSend(NickServ, tmp, GetReply(ERR_BADFLAG, tmp), args[2][i]);
+ break;
+ }
+ if (posid) {
+ char littlestring[2];
+ littlestring[0] = args[2][i];
+ littlestring[1] = 0;
+ if (mode)
+ strcat(plusstring, littlestring);
+ else
+ strcat(minusstring, littlestring);
+ }
+ }
+
+ if ((*plusstring) || (*minusstring)) {
+ uSend(NickServ, tmp, GetReply(RPL_CHANGEDFLAGS, tmp), nick->nick,
+ (*plusstring) ? "+" : "", plusstring,
+ (*minusstring) ? "-" : "", minusstring);
+ sSend(":%s GLOBOPS :%s set mode %s%s%s%s for %s.", NickServ, from,
+ (*plusstring) ? "+" : "", plusstring,
+ (*minusstring) ? "-" : "", minusstring, nick->nick);
+ logDump(operlog, "%s!%s@%s set flag(s): %s%s%s%s on %s", from,
+ tmp->user, tmp->host, (*plusstring) ? "+" : "", plusstring,
+ (*minusstring) ? "-" : "", minusstring, nick->nick);
+ }
+}
+
+void createpasswd(char *passwd, int length)
+{
+ static char saltchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+ int x;
+
+ passwd[length] = '\0';
+
+ for (x=0; x < length; x++)
+ {
+ passwd[x] = saltchars[random() % 64];
+ }
+ return;
+}
+
+void NbanishCmd(UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+ RegNickList *nick;
+
+ nick = getRegNickData(args[1]);
+ if (!nick)
+ {
+ nick = smalloc(sizeof(RegNickList));
+ strcpy(nick->nick, args[1]);
+ nick->flags |= NBANISH;
+ nick->flags |= NACTIVE;
+ nick->flags |= NREG;
+ addRegNick(nick);
+ }
+
+ strcpy(nick->nick, args[1]);
+ strcpy(nick->user, "banished");
+ sprintf(nick->host, "nicks.%s", NETHOST);
+ sprintf(nick->email, "nickserv@%s", NETHOST);
+ sprintf(nick->url, "http://www.%s", NETHOST);
+/* strcpy(nick->password, "notrouble");*/
+ createpasswd(nick->password,9);
+ strcpy(nick->password2, "7654321");
+ sprintf(nick->realname, "Banished by: %s", from);
+ nick->amasks = 0;
+ nick->timereg = 0;
+ nick->timestamp = 0;
+ nick->flags = 0;
+ nick->flags |= NBANISH;
+ nick->flags |= NACTIVE;
+ nick->flags |= NREG;
+ nick->firstAcc = nick->lastAcc = NULL;
+ killUser(services[1], getNickData(args[1]), NSBANISHMSG);
+ uSend(NickServ, tmp, GetReply(RPL_BANNEDNICK, tmp), args[1]);
+ sSend(":%s GLOBOPS :%s has permanently banned the nickname \002%s\002",
+ NickServ, from, args[1]);
+ logDump(operlog, "%s!%s@%s BANISHed %s", from, tmp->user, tmp->host,
+ args[1]);
+}
+
+void NgetkeyCmd(UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+ RegNickList *nick;
+
+ nick = getRegNickData(args[1]);
+
+ if (!nick || !(nick->flags & NREG))
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[1]);
+ else {
+ uSend(NickServ, tmp, GetReply(RPL_GETKEY, tmp), nick->nick,
+ nick->password2);
+ sSend(":%s GLOBOPS :%s used getkey on %s", NickServ, from,
+ args[1]);
+ }
+ return;
+}
+
+void NgetrealpassCmd (UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+ RegNickList *nick;
+ unsigned int flags;
+
+ nick = getRegNickData(args[1]);
+
+ if (!nick) uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[1]);
+ else
+ {
+ flags=0;
+ if (tmp->reg) flags=tmp->reg->flags;
+ uSend (NickServ, tmp, GetReply(RPL_GETREALPASS, tmp), nick->nick, nick->password);
+ if (!(flags&(NROOT)))
+ {
+ sSend (":%s GLOBOPS :%s used getrealpass on \002%s\002", NickServ, from, nick->nick);
+ logDump (operlog, "%s!%s@%s used GETREALPASS on %s", from, tmp->user, tmp->host, nick->nick);
+ }
+ }
+}
+
+void NgetpassCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ RegNickList *nick;
+ char sendfrom[80];
+ time_t doot = time(NULL);
+
+ nick = getRegNickData(args[1]);
+
+ if (!nick)
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[1]);
+ else {
+ sSend(":%s GLOBOPS :%s used getpass on \002%s\002", NickServ, from,
+ nick->nick);
+ uSend(NickServ, tmp, GetReply(RPL_GETPASS, tmp), nick->nick,
+ nick->email);
+ sprintf(sendfrom, "%s Password Recovery <%s@%s>", NickServ,
+ NickServ, NETHOST);
+ sendMail(nick->email, sendfrom, "Password",
+ "\nThe password for %s is %s\n"
+ "The activation code for %s is %s\n"
+ "\nThis password recovered by %s at %s", nick->nick,
+ nick->password, nick->nick, nick->password2, tmp->nick,
+ ctime(&(doot)));
+ logDump(operlog, "%s!%s@%s GETPASS %s", from, tmp->user, tmp->host,
+ args[1]);
+ }
+}
+
+void NdeleteCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ RegNickList *nick;
+
+ nick = getRegNickData(args[1]);
+
+ if (!nick) {
+ uSend(NickServ, tmp, GetReply(ERR_NICKNOTREGGED, tmp), args[1]);
+ return;
+ }
+
+ if ((nick->flags & NACTIVE) && !isServop(tmp)) {
+ uSend(NickServ, tmp, GetReply(ERR_NEEDSERVOP, tmp));
+ return;
+ }
+
+ if (nick) {
+ uSend(NickServ, tmp, GetReply(RPL_DELETE, tmp), nick->nick);
+ sSend
+ (":%s GLOBOPS :%s deleted the nickname \002%s\002 from the databases.",
+ NickServ, from, nick->nick);
+ delRegNick(nick);
+ logDump(nicklog, "%s DELETE %s", from, args[1]);
+ }
+}
+
+void NsaveCmd(UserList * tmp, char **args, int numargs)
+{
+ char *from = tmp->nick;
+
+ uSend(NickServ, tmp, GetReply(RPL_SAVE, tmp));
+ sSend
+ (":%s GLOBOPS :Synchronising \002NickServ database\002 to disk at the request of \002%s\002.",
+ NickServ, from);
+
+ saveNickData(firstRegNick);
+}
+
+void NwebtvcountCmd(UserList * tmp, char **args, int numargs)
+{
+ UserList *u;
+ int count = 0;
+
+ for (u = firstUser; u; u = u->next) {
+ if (u->webbie) {
+ sSend(":%s NOTICE %s :%s", NickServ, tmp->nick, u->nick);
+ count++;
+ }
+ }
+
+ sSend(":%s NOTICE %s :%d WebTV user(s) online.",
+ NickServ, tmp->nick, count);
+
+}
+
+void NlistCmd(UserList * tmp, char **args, int numargs)
+{
+ char nick[NICKLEN], user[USERLEN], host[HOSTLEN];
+ char searchargs[NICKLEN + USERLEN + HOSTLEN + 3];
+ RegNickList *reg;
+ UserList *online;
+ int i, x;
+
+ i = x = 0;
+
+ if (!strcasecmp(args[1], "-email")) {
+ char *s1;
+ int goodmask = 0;
+
+ if (numargs < 3) {
+ uSend(NickServ, tmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ,
+ "LIST");
+ return;
+ }
+
+ for (s1 = args[2]; *s1; s1++) {
+ if ((*s1 != '@') && (*s1 != '.') && (*s1 != '*')
+ && (*s1 != '?')) goodmask = 1;
+ }
+
+ if (!goodmask) {
+ uSend(NickServ, tmp, GetReply(ERR_VALIDEMAIL, tmp));
+ return;
+ }
+
+ strcpy(searchargs, args[2]);
+
+ uSend(NickServ, tmp, GetReply(RPL_NLISTHEADER, tmp), searchargs);
+
+ for (reg = firstRegNick; reg; reg = reg->next) {
+ if (!match(reg->email, searchargs)) {
+ i++;
+ uSend(NickServ, tmp, GetReply(RPL_NLIST1, tmp), i,
+ reg->nick, reg->email);
+ }
+ x++;
+ }
+ } else if (!strcasecmp(args[1], "-flags")) {
+ int showthis;
+ char showoper[32];
+
+ if (numargs < 3) {
+ uSend(NickServ, tmp, GetReply(ERR_BADPARAMS, tmp));
+ uSend(NickServ, tmp, GetReply(RPL_MOREHELPCMD, tmp), NickServ,
+ "LIST");
+ return;
+ }
+
+ showoper[0] = '\0';
+ strcpy(searchargs, args[2]);
+
+ uSend(NickServ, tmp, GetReply(RPL_NLISTHEADER, tmp), searchargs);
+
+ for (reg = firstRegNick; reg; reg = reg->next) {
+ showthis = 0;
+ switch (args[2][0]) {
+ case 'b':
+ if (reg->flags & NBANISH)
+ showthis = 1;
+ break;
+ case 'h':
+ if (reg->flags & NHOLD)
+ showthis = 1;
+ break;
+ case 'v':
+ if (reg->flags & NVACATION)
+ showthis = 1;
+ break;
+ case 's':
+ if (reg->flags & NNETADM) {
+ showthis = 1;
+ strcpy(showoper, " [Network Administrator]");
+ } else if (reg->flags & NROOT) {
+ showthis = 1;
+ strcpy(showoper, " [Services Root Administrator]");
+ } else if (reg->flags & NSERVOP) {
+ showthis = 1;
+ strcpy(showoper, " [Services Operator]");
+ }
+ break;
+ case 'l':
+ if (reg->flags & NOPER)
+ showthis = 1;
+ break;
+ case 'm':
+ if (reg->flags & NMARKED)
+ showthis = 1;
+ break;
+ case 'w':
+ if (reg->flags2 & NMSGMODE)
+ showthis = 1;
+ break;
+ }
+ if (showthis) {
+ i++;
+ uSend(NickServ, tmp, GetReply(RPL_NLIST2, tmp), i,
+ reg->nick, reg->user, reg->host, showoper);
+ }
+ x++;
+ }
+ } else {
+ int matchflag;
+
+ if (index(args[1], '!') && index(args[1], '@'))
+ sscanf(args[1], "%[^!]!%[^@]@%s", nick, user, host);
+ else {
+ uSend(NickServ, tmp, GetReply(ERR_PROPERHOST1, tmp));
+ return;
+ }
+
+ if (!strcmp(nick, "*") && !strcmp(user, "*") && !strcmp(host, "*")
+ && !isServop(tmp)) {
+ uSend(NickServ, tmp, GetReply(ERR_WIDEHOST, tmp));
+ return;
+ }
+
+ strcpy(searchargs, args[1]);
+
+ uSend(NickServ, tmp, GetReply(RPL_NLISTHEADER, tmp), searchargs);
+
+ for (reg = firstRegNick; reg; reg = reg->next) {
+
+ matchflag = 0;
+ if ((reg->flags2 & NSTICKYOP) && (!isOper(tmp))) {
+ if (!match(reg->nick, nick) && !match(reg->user, user)
+ && !match("IRCop.Serenity-IRC.Net", host))
+ matchflag = 1;
+ } else {
+ online = getNickData(reg->nick);
+ if (!isOper(tmp) && (online)
+ && (online->oflags & NISPLUSX)) {
+ if (!match(reg->nick, nick) && !match(reg->user, user)
+ && !match(return_user_mask(reg->host), host))
+ matchflag = 1;
+ } else {
+ if (!match(reg->nick, nick) && !match(reg->user, user)
+ && !match(reg->host, host))
+ matchflag = 1;
+ }
+ }
+
+ if (matchflag) {
+ i++;
+ uSend(NickServ, tmp, GetReply(RPL_NLIST3, tmp), i,
+ reg->nick, reg->user, reg->host);
+ }
+ x++;
+ }
+ }
+
+ if (i == 0)
+ uSend(NickServ, tmp, GetReply(ERR_NLISTEMPTY, tmp));
+
+ uSend(NickServ, tmp, GetReply(RPL_NLISTFOOTER, tmp), i, x, searchargs);
+}
+
+/*
+ * ===DOC===
+ * This function will basically bother a nick owner into giving a nick back
+ */
+void annoyNickThief(UserList * nick)
+{
+ char tmp[NICKLEN+1];
+ int assume_webbie = 0;
+
+ /* If someone is using a WebTV user nick but is not set as +w we'd
+ * still like them to be assumed a WebTv user and thus given a chance to
+ * identify to their nick. In this case we use message instead of notice
+ * (default). We set them as webbie for a short moment, then remove that
+ * mode after sending our message out. -- Remmy 20020616 */
+ if ((nick->reg->flags2 & NMSGMODE) && !nick->webbie)
+ nick->webbie = assume_webbie = 1;
+
+ uSend(NickServ, nick, GetReply(RPL_NICKWARN1, nick));
+ if ((nick->reg->flags & NKILL) && !isServop(nick)) {
+ uSend(NickServ, nick, GetReply(RPL_NICKWARN3, nick));
+ uSend(NickServ, nick, GetReply(RPL_NICKWARN2, nick));
+ sprintf(tmp, "6%s", nick->nick);
+ timer(15, killide, "killide", tmp); /* killide func, 60 secs */
+ }
+
+ /* Reset 'assumed webbie' */
+ if (assume_webbie)
+ nick->webbie = 0;
+}
+
+/* general ghost like stuff */
+void killide(char *info)
+{
+ char tmp[NICKLEN+1];
+ char newnick[16];
+ UserList *check;
+ char killcount;
+
+ killcount = info[0];
+ info++;
+
+ check = getNickData(info);
+
+ if (!check) /* THEY'VE ALREADY GONE */
+ return;
+
+ if (check->caccess > 1) /* AHA! THEY'VE ID'D... NEVER MIND. */
+ return;
+
+ switch (killcount) {
+ case '6':
+ uSend(NickServ, check, GetReply(RPL_NICKWARN4, check));
+ sprintf(tmp, "3%s", info);
+ timer(15, killide, "killide", tmp); /* 15 MORE SECONDS */
+ break;
+ case '3':
+ sSend(":%s 433 %s %s :Belongs to another user", myname, info, info);
+ uSend(NickServ, check, GetReply(RPL_NICKWARN5, check));
+ sprintf(newnick, "Guest%d", (((unsigned int) rand()) % 9998) + 1);
+ sSend(":%s SVSNICK %s %s 0", myname, info, newnick);
+ break;
+ }
+}
+
+void addGhost(char *ghost)
+{
+
+ GhostList *newghost = smalloc(sizeof(GhostList));
+ char host[HOSTLEN];
+
+ strcpy(newghost->ghost, ghost);
+
+ if (!firstGhost) {
+ firstGhost = newghost;
+ newghost->previous = NULL;
+ } else {
+ lastGhost->next = newghost;
+ newghost->previous = lastGhost;
+ }
+
+ lastGhost = newghost;
+ newghost->next = NULL;
+
+ sprintf(host, "nicks.%s", NETHOST);
+ addUser(ghost, "owned", host, "Nick Enforcement", "i");
+ totalusers++;
+ totalghosts++;
+}
+
+void delGhost(char *ghost)
+{
+ GhostList *killme;
+
+ totalusers--;
+ killme = getGhost(ghost);
+ if (!killme)
+ return;
+ sSend(":%s QUIT :Ahhh, they finally let me off work!", ghost);
+
+#ifdef DEBUG2
+ sSend(":%s GNOTICE :Removed ghost %s", myname, ghost);
+#endif
+
+ if (killme->previous)
+ killme->previous->next = killme->next;
+ else
+ firstGhost = killme->next;
+ if (killme->next)
+ killme->next->previous = killme->previous;
+ else
+ lastGhost = killme->previous;
+
+ sfree(killme);
+ totalghosts--;
+
+ return;
+}
+
+GhostList *getGhost(char *ghost)
+{
+ GhostList *tmp;
+ for (tmp = firstGhost; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->ghost, ghost))
+ return tmp;
+ }
+ return NULL;
+}
+
+int isGhost(char *ghost)
+{
+ if (getGhost(ghost))
+ return 1;
+ else
+ return 0;
+}
+
+int countRegAddy(char *email)
+{
+ RegNickList *tmp;
+ int count = 0;
+
+ for (tmp = firstRegNick; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->email, email))
+ count++;
+ }
+ return count;
+}
+
+void expireNicks(char *placeholder)
+{
+ time_t timestart, timeend;
+ RegNickList *tmp, *next;
+ UserList *online;
+#ifdef BACKUPDATABASE
+ char backup[30];
+ char cmd[500];
+#endif
+ int i = 0;
+ int zapped;
+
+ MemoBox *memobox;
+ MemoList *memo, *nextmemo;
+ long memocnt = 0;
+
+ mostnicks = 0;
+ timestart = time(NULL);
+#ifdef BACKUPDATABASE
+ strftime(backup, 30, "nickserv.db%d%m%Y", localtime(×tart));
+ sprintf(cmd, "cp %s/nickserv.db %s/%s",
+ DBDIR, DBDIR, backup);
+ system(cmd);
+#endif
+ for (tmp = firstRegNick; tmp; tmp = next) {
+ next = tmp->next;
+ zapped = 0;
+
+ if (tmp->timestamp > timestart) /* HOLD UP THERE -- NEGATIVE TIME? */
+ tmp->timestamp = timestart; /* FIX THAT RIGHT NOW */
+
+ online = getNickData(tmp->nick);
+ if (online && online->caccess == 3) { /* Is the user still online and ID'ed? *//* Update their timestamp and don't expire */
+ tmp->timestamp = timestart; /* Update their timestamp and don't expire */
+ }
+
+ if (!(tmp->flags & NREG) || tmp->flags & NHOLD
+ || tmp->flags & NBANISH) {
+ } else if ((tmp->flags & NVACATION)
+ && ((timestart - tmp->timestamp) >= (6 * NICKDROPTIME)))
+ zapped++;
+ else if (!(tmp->flags & NACTIVE)
+ && ((timestart - tmp->timestamp) >= (24 * 3600)))
+ zapped++;
+ else if (((timestart - tmp->timestamp) >= NICKDROPTIME) & !(tmp->flags & NVACATION))
+ zapped++;
+
+ if (zapped) {
+ logDump(nicklog, "%s EXPIRE", tmp->nick);
+ delRegNick(tmp);
+ i++;
+ } else {
+ mostnicks++;
+
+ memobox = tmp->memos;
+
+
+ if (memobox) {
+ for (memo = memobox->firstMemo; memo; memo = nextmemo) {
+ nextmemo = memo->next;
+ if ((timestart - memo->sent) >= MEMODROPTIME)
+ delMemo(memobox, memo);
+ else
+ memocnt++;
+ }
+ }
+ }
+ }
+
+ mostmemos = memocnt;
+ timeend = time(NULL);
+#ifdef SHOWSYNCH
+ sSend(":%s GLOBOPS :NickServ EXPIRE(%i/%lu) %lu seconds", NickServ, i,
+ mostnicks, (timeend - timestart));
+#endif
+ timer(2 * 3600, expireNicks, "expireNicks", "void");
+}
+
+void indexAccItems(RegNickList * nick);
+
+int addAccItem(RegNickList * nick, char *mask)
+{
+ nAccessList *tmp;
+
+ if (!nick)
+ return 0;
+ if (!strcmp(mask, "*@*") || !strcmp(mask, "*@*.*") ||
+ !strcmp(mask, "*@*.*.*") || !strcmp(mask, "*@*.*.*.*") ||
+ !strcmp(mask, "*@*.com") || !strcmp(mask, "*@*.org") ||
+ !strcmp(mask, "*@*.net") || !strcmp(mask, "*@*.edu") ||
+ index(mask, '!') || !index(mask, '@'))
+ return 0;
+ for (tmp = nick->firstAcc; tmp; tmp = tmp->next) {
+ if (!strcasecmp(mask, tmp->mask))
+ return 0;
+ }
+
+ tmp = smalloc(sizeof(nAccessList));
+ strcpy(tmp->mask, mask);
+
+ if (!nick->firstAcc) {
+ nick->firstAcc = tmp;
+ tmp->previous = NULL;
+ } else {
+ nick->lastAcc->next = tmp;
+ tmp->previous = nick->lastAcc;
+ }
+
+ nick->lastAcc = tmp;
+ tmp->next = NULL;
+ nick->amasks++;
+ indexAccItems(nick);
+ return 1;
+}
+
+int delAccItem(RegNickList * nick, char *mask, char *deletedmask)
+{
+ nAccessList *tmp;
+ int found = 0;
+ int x = 0;
+ if (!nick)
+ return 0;
+
+ x = atoi(mask);
+
+ for (tmp = nick->firstAcc; tmp; tmp = tmp->next) {
+ if (!strcasecmp(mask, tmp->mask) || (x && tmp->index == x)) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0) {
+ return 0;
+ }
+ strcpy(deletedmask, tmp->mask);
+ if (tmp->previous)
+ tmp->previous->next = tmp->next;
+ else
+ nick->firstAcc = tmp->next;
+ if (tmp->next)
+ tmp->next->previous = tmp->previous;
+ else
+ nick->lastAcc = tmp->previous;
+
+ sfree(tmp);
+ indexAccItems(nick);
+ return 1;
+}
+
+void indexAccItems(RegNickList * nick)
+{
+ nAccessList *tmp;
+ int i = 1;
+ for (tmp = nick->firstAcc; tmp; tmp = tmp->next) {
+ tmp->index = i;
+ i++;
+ }
+}
+
+void syncNickData(time_t next)
+{
+ nextNsync = next;
+ saveNickData(firstRegNick);
+}
+
+void syncMemoData(time_t next)
+{
+ nextMsync = next;
+ saveMemoData(firstRegNick);
+}
+
+/* LISTOPS is now moved here - also redone so it sorts by order and shows away -GZ */
+
+void NlistopsCmd(UserList * nick, char **args, int numargs)
+{
+ int i = 0;
+ int ucnt = 0;
+ UserList *tmp;
+
+ uSend(NickServ, nick, GetReply(RPL_LISTOPHEADER, nick));
+
+ for(tmp = firstUser; tmp; tmp = tmp->next)
+ {
+ ucnt++;
+ if(isOper(tmp) && isRoot(tmp))
+ {
+ i++;
+ uSend(NickServ, nick, GetReply(RPL_LISTOP1, nick), i,
+ tmp->nick, "[Services Root Administrator]",
+ (tmp->oflags & NISAWAY) ? " (AWAY)" : "");
+ }
+ }
+
+ for (tmp = firstUser; tmp; tmp = tmp->next)
+ {
+ if (isOper(tmp) && isServop(tmp) && !isRoot(tmp))
+ {
+ i++;
+ uSend(NickServ, nick, GetReply(RPL_LISTOP1, nick), i,
+ tmp->nick, "[Services Operator]",
+ (tmp->oflags & NISAWAY) ? " (AWAY)" : "");
+ }
+ }
+
+ for (tmp = firstUser; tmp; tmp = tmp->next)
+ {
+ if (isOper(tmp) && (tmp->oflags & NISADMIN) && !isServop(tmp))
+ {
+ i++;
+ uSend(NickServ, nick, GetReply(RPL_LISTOP1, nick), i,
+ tmp->nick, "[Server Administrator]",
+ (tmp->oflags & NISAWAY) ? " (AWAY)" : "");
+ }
+ }
+
+ for (tmp = firstUser; tmp; tmp = tmp->next)
+ {
+ if (isOper(tmp) && !isServop(tmp) && !(tmp->oflags & NISADMIN) &&
+ !(strstr(tmp->nick, "Opm")))
+ {
+ i++;
+ uSend(NickServ, nick, GetReply(RPL_LISTOP1, nick), i,
+ tmp->nick, "[IRC Operator]",
+ (tmp->oflags & NISAWAY) ? " (AWAY)" : "");
+ }
+ }
+
+ uSend(NickServ, nick, GetReply(RPL_LISTOPFOOTER, nick));
+}
+
+void NresendCmd (UserList * nick, char **args, int numargs)
+{
+ char *py,*email;
+ int err;
+ long int doot;
+ RegNickList *tmp;
+ char sendfrom[512];
+
+ py=nick->nick;
+ tmp = getRegNickData (args[1]);
+ if (!tmp)
+ {
+ sSend (":%s NOTICE %s :Nick %s is not registered.",NickServ,py,args[1]);
+ return;
+ }
+ email=tmp->email;
+ time (&doot);
+
+ sprintf (sendfrom, "Nickname Services <%s@%s>", NickServ, NETHOST);
+ err = sendMail (email, sendfrom, "Nickname activation key",
+ "Hello %s, Welcome to the Serenity-IRC network!\n\n"
+ "Your nickname registration has been verified.\n\n"
+ "To activate your nickname:\n\n"
+ "1) switch to the nickname %s\n"
+ "2) /msg %s ACTIVATE %s\n\n"
+ "%s is your activation key. %s is your password.\n\n"
+ "Please try to remember your password, you might need it\n"
+ "some day.\n\n"
+ "If you accidently lose your password, you can always\n"
+ "/join #help and ask one of our IRC Operators to recover\n"
+ "it for you. We will be more than glad to help you!\n\n"
+ "If you are new to IRC or Serenity-IRC, we would like to recommend\n"
+ "#help, as it is the place where you can obtain help or any\n"
+ "other kind of information that is IRC related.\n\n"
+ "Enjoy your stay on our safe and friendly network!\n\n"
+ "For additional help, try these commands:\n"
+ " /msg %s HELP\n"
+ " /msg %s HELP\n"
+ " /msg %s HELP\n",
+ tmp->nick, tmp->nick, NickServ, tmp->password2,
+ tmp->password2, tmp->password,
+ NickServ, ChanServ, MemoServ
+ );
+
+ if (!err)
+ {
+ logDump (nicklog, "%s!%s@%s: ACTIVATION key sent to '%s'\n", tmp->nick, tmp->user, tmp->host, args[1]);
+ sSend (":%s NOTICE %s :*** ACTIVATION key sent to '%s'\n", NickServ, py, args[1]);
+ sSend (":%s GLOBOPS :%s resent activation key to for nick %s",NickServ,py,args[1]);
+ }
+ else
+ {
+ sSend (":%s NOTICE %s :Error: No email sent to %s",NickServ,py,args[1]);
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * Language handling core code
+ *
+ */
+
+#include "services.h"
+#include "languages/english.h"
+#include "languages/dutch.h"
+#include "languages/french.h"
+#include "languages/german.h"
+#include "languages/lcars.h"
+#include "languages/spanish.h"
+#include "languages/cajun.h"
+
+struct LangTable LT[] = {
+ {"English", 0, (struct FormatTable *) NULL},
+ {"Dutch", 0, (struct FormatTable *) NULL},
+ {"French", 0, (struct FormatTable *) NULL},
+ {"German", 0, (struct FormatTable *) NULL},
+ {"Lcars", 0, (struct FormatTable *) NULL},
+ {"Spanish", 0, (struct FormatTable *) NULL},
+ {"Cajun", 0, (struct FormatTable *) NULL},
+ {"-", 0, (struct FormatTable *) NULL}
+};
+
+int LoadTables(void)
+{
+
+ int i, j, z;
+
+ printf("Loading languages...\n");
+ i = 0;
+ while (LT[i].language[0] != '-') {
+ printf("%s", LT[i].language);
+ if (!strcmp(LT[i].language, "English"))
+ LT[i].numtable = EnglishReplies;
+ if (!strcmp(LT[i].language, "Dutch"))
+ LT[i].numtable = DutchReplies;
+ if (!strcmp(LT[i].language, "French"))
+ LT[i].numtable = FrenchReplies;
+ if (!strcmp(LT[i].language, "German"))
+ LT[i].numtable = GermanReplies;
+ if (!strcmp(LT[i].language, "Lcars"))
+ LT[i].numtable = LcarsReplies;
+ if (!strcmp(LT[i].language, "Spanish"))
+ LT[i].numtable = SpanishReplies;
+ if (!strcmp(LT[i].language, "Cajun"))
+ LT[i].numtable = CajunReplies;
+ j = 0;
+ while (LT[i].numtable[j].numeric != -1)
+ j++;
+ z = LT[i].numtable[j - 1].numeric;
+ printf("[%i]...\n", j);
+ LT[i].numerics = --j;
+ i++;
+ }
+ printf("\n");
+ return 0;
+}
+
+char *GetReply(int numeric, UserList * nick)
+{
+
+ int language;
+
+ if (nick->reg)
+ language = nick->reg->language;
+ else
+ language = 0;
+
+ if (numeric > LT[language].numerics)
+ language = 0;
+
+ if (numeric > LT[language].numerics)
+ strcpy(retnum, "Unknown numeric requested...");
+ else
+ strcpy(retnum, LT[language].numtable[numeric].format);
+
+ return retnum;
+}
+
+char *GetLanguage(UserList * nick)
+{
+
+ if (nick->reg)
+ strcpy(retlanguage, LT[nick->reg->language].language);
+ else
+ strcpy(retlanguage, "English");
+
+ return retlanguage;
+}
+
+struct LangTable *GetLanguageTab(void)
+{
+ return(LT);
+}
--- /dev/null
+/* 542 */
+
+#include "services.h"
+
+int HJCheck(char *);
+
+long getkilltime(char *s)
+{
+/* THIS FUNCTION RETURNS A TIME IN SECONDS BASED ON INPUT STRING
+ FORMATS ALLOWED:
+ <value>h = hours
+ <value>d = days
+ <value>w = weeks
+ MISSING LETTER IS ASSUMED TO MEAN MINUTES (BACKWARDS COMPATIBLE)
+ MISSING VALUE WILL BE ASSUMED AS 1.
+
+ THIS FUNCTION IS USED BY Oautokill and Oignore FOR TIME COMPUTATION */
+
+ long base_mult;
+ char mult_char[2];
+ int value_width;
+ int base_value;
+
+ base_mult = 60L; /* INITIALIZE TO CONVERT MINS TO SECS */
+ strcpy(mult_char, "m");
+ base_value = 1;
+
+ if ((!strcasecmp(s, "add")) || (!(*s))) /* COMPATIBILITY FOR OLD FUNCTION */
+ return 0;
+
+ value_width = strlen(s) - 1;
+
+ if (isalpha(s[value_width])) { /* IF THERE'S A LETTER ON THE END, PARSE IT */
+ mult_char[0] = s[value_width];
+
+ if (!strcasecmp(mult_char, "h"))
+ base_mult = 3600L;
+ else if (!strcasecmp(mult_char, "d"))
+ base_mult = 86400L;
+ else if (!strcasecmp(mult_char, "w"))
+ base_mult = 604800L;
+
+ if (value_width > 0) {
+ base_value = atoi(s);
+ if (base_value < 1)
+ base_value = 1;
+ }
+ } else {
+ base_value = atoi(s);
+ if (base_value < 0)
+ base_value = 0;
+ }
+
+ return ((long) (base_value) * base_mult);
+}
+
+char *expand_time(long t)
+{
+/* EXPANDS TIME IN SECONDS TO FULLY QUALIFIED STRING
+ USED BY AUTOKILL FUNCTIONS FOR DISPLAY */
+
+ static char retstr[128];
+ int temp1;
+
+ *retstr = 0;
+
+ if (t == 0) {
+ strcpy(retstr, "forever");
+ } else {
+ if (t >= 604800L) {
+ temp1 = (int) (t / 604800L);
+ t = t % 604800L;
+ sprintf(retstr, "%d week%s", temp1, (temp1 == 1 ? "" : "s"));
+ }
+ if (t >= 86400L) {
+ temp1 = (int) (t / 86400L);
+ t = t % 86400L;
+ if (*retstr)
+ strcat(retstr, ", ");
+ sprintf(retstr, "%s%d day%s", retstr, temp1,
+ (temp1 == 1 ? "" : "s"));
+ }
+ if (t >= 3600L) {
+ temp1 = (int) (t / 3600L);
+ t = t % 3600L;
+ if (*retstr)
+ strcat(retstr, ", ");
+ sprintf(retstr, "%s%d hour%s", retstr, temp1,
+ (temp1 == 1 ? "" : "s"));
+ }
+
+ temp1 = (int) (t / 60L);
+
+ if ((*retstr) && (temp1 > 0))
+ strcat(retstr, ", ");
+
+ if ((!(*retstr)) && (temp1 == 0))
+ temp1 = 1;
+
+ if (temp1)
+ sprintf(retstr, "%s%d minute%s", retstr, temp1,
+ (temp1 == 1 ? "" : "s"));
+ }
+
+ return ((char *) retstr);
+}
+
+void sendToOperServ(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ if (!strcmp(args[0], "\001PING")) {
+ if (numargs < 3)
+ uSend(OperServ, nick, GetReply(RPL_PING1, nick), args[1]);
+ else
+ uSend(OperServ, nick, GetReply(RPL_PING2, nick), args[1],
+ args[2]);
+ return;
+ }
+ if (!isOper(nick)) {
+ uSend(OperServ, nick, GetReply(ERR_NEEDOPER, nick));
+ return;
+ }
+
+ if (!strcasecmp(args[0], "help") && numargs > 1) {
+ sendHelp(from, OperServ, args, numargs);
+ return;
+ } else if (!strcasecmp(args[0], "help")) {
+ sendHelp(from, OperServ, NULL, 0);
+ return;
+ }
+
+ msgtabCheck(OperServ, nick, args, numargs);
+}
+
+void OrollupCmd(UserList * nick, char **args, int numargs)
+{
+ int akills_placed = 0;
+ ChanList *chan;
+ cNickList *inspectnick, *nextnick = NULL;
+ char mask[NICKLEN + USERLEN + HOSTLEN + 2];
+
+ chan = getChanData (args[1]);
+ if (!chan)
+ {
+ uSend (OperServ, nick, GetReply (ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ for (inspectnick = chan->firstUser; inspectnick; inspectnick = nextnick)
+ {
+ nextnick = inspectnick->next;
+
+ if (!(inspectnick->person->reg) ||
+ !(inspectnick->person->reg->flags & NACTIVE))
+ { /* Only set an akill if the person is not a registered nick,
+ we should also look at ID status, but won't because we
+ don't want to hurt too many 'innocents' */
+ if (!isAKilled(inspectnick->person->nick, inspectnick->person->user,
+ inspectnick->person->host)) {
+ strcpy(mask, "*!*@");
+ strcat(mask, inspectnick->person->host);
+ add_access_mod((3 * 3600), mask, OperServ, A_AKILL,
+ "Excessive abuse");
+ akills_placed++;
+ }
+ }
+ }
+ sSend(":%s GLOBOPS :%s rolled up %s. (%d akills added)", OperServ,
+ nick->nick, args[1], akills_placed);
+ logDump(operlog, "%s!%s@%s rolled %s up.", nick->nick, nick->user,
+ nick->host, args[1]);
+}
+
+void OaccessmodCmd(UserList * nick, char **args, int numargs)
+{
+ char type;
+ char *from = nick->nick;
+ long t;
+ int i;
+ char amreason[80];
+ char amtype[9];
+
+ if (!match(args[0], "a*kill")) {
+ strcpy(amtype, "Autokill");
+ type = A_AKILL;
+ } else if (!strcasecmp(args[0], "ignore")) {
+ strcpy(amtype, "Ignore");
+ type = A_IGNORE;
+ } else if (!strcasecmp(args[0], "exempt")) {
+ strcpy(amtype, "Exempt");
+ type = A_EXEMPT;
+ } else if (!strcasecmp(args[0], "hostjinx")) {
+ strcpy(amtype, "Hostjinx");
+ type = A_HOSTJINX;
+ } else
+ return;
+
+ if (numargs < 2) {
+ list_access_mod(from, type, NULL);
+ return;
+ }
+ if (!strcasecmp(args[1], "list")) {
+ if (numargs < 3)
+ list_access_mod(from, type, NULL);
+ else
+ list_access_mod(from, type, args[2]);
+ return;
+ }
+
+ if (!isServop(nick) && !isRoot(nick)) {
+ uSend(OperServ, nick, GetReply(ERR_NEEDSERVOP, nick));
+ return;
+ }
+
+ if (numargs < 3) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ,
+ amtype);
+ return;
+ }
+
+ if (args[1][0] == '-' || !strcasecmp(args[1], "del")
+ || !strcasecmp(args[1], "delete")) {
+ if (args[2][0] != '#')
+ if (!check_mask(args[2], 0)) {
+ uSend(OperServ, nick, GetReply(ERR_BADMASK, nick), args[2]);
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick),
+ OperServ, amtype);
+ return;
+ }
+ remove_access_mod(from, type, args[2]);
+ return;
+ }
+ if (numargs < 4) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ,
+ amtype);
+ return;
+ } else {
+ t = getkilltime(args[1]);
+ if (!check_mask(args[2], 0)) {
+ uSend(OperServ, nick, GetReply(ERR_BADMASK, nick), args[2]);
+ return;
+ }
+
+ if (find_access_mod(type, args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_MASKEXISTS, nick), args[2],
+ amtype);
+ return;
+ }
+
+ bzero(amreason, 80);
+ strncpy(amreason, args[3], 79);
+ for (i = 4; i < numargs; i++) {
+ if ((strlen(amreason) + strlen(args[i])) > 78)
+ break;
+ strcat(amreason, " ");
+ strcat(amreason, args[i]);
+ }
+
+ uSend(OperServ, nick, GetReply(RPL_AKILLADDED, nick), amtype,
+ args[2], expand_time(t), amreason);
+ logDump(operlog, "%s!%s@%s added %s for %s for %s [%s]", from,
+ nick->user, nick->host, amtype, args[2], expand_time(t),
+ amreason);
+ add_access_mod(t, args[2], from, type, amreason);
+ return;
+ }
+}
+
+void OmodeCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ int on = 1, onarg = 3, i = 0, valid = 1;
+ ChanList *tmp = getChanData(args[1]);
+ cBanList *tmpban;
+ cNickList *tmpnick;
+ char string[512];
+
+ if (!tmp) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHCHAN, nick), args[1]);
+ return;
+ }
+
+ if ((args[2][0] != '+') && (args[2][0] != '-')) {
+ uSend(OperServ, nick, GetReply(ERR_INVALIDMODES, nick), args[2]);
+ return;
+ }
+
+ for (i = 0; args[2][i]; i++) {
+ if (!valid)
+ break;
+
+ switch (args[2][i]) {
+ case '+':
+ on = 1;
+ break;
+ case '-':
+ on = 0;
+ break;
+ case 'b':
+ if (numargs > onarg) {
+ if (on) {
+ tmpban = smalloc(sizeof(cBanList));
+ strcpy(tmpban->ban, args[onarg]);
+ addChanBan(tmp, tmpban);
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Added ban %s on %s", myname,
+ args[onarg], tmp->name);
+#endif
+ } else {
+ tmpban = getChanBan(tmp, args[onarg]);
+ if (tmpban) {
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Removed ban %s on %s", myname,
+ args[onarg], tmp->name);
+#endif
+ delChanBan(tmp, tmpban);
+ }
+ }
+ onarg++;
+ } else
+ valid = 0;
+ break;
+
+ case 'i':
+ if (on) {
+ tmp->modes |= PM_I;
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +i", myname, tmp->name);
+#endif
+ } else {
+ tmp->modes -= PM_I;
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -i", myname, tmp->name);
+#endif
+ }
+ break;
+
+ case 'l':
+ if (on) {
+ if (numargs > onarg) {
+ int chan_limit = atoi(args[onarg]);
+ if (chan_limit > 0) {
+ tmp->modes |= PM_L;
+ if (tmp->reg)
+ tmp->reg->limit = chan_limit;
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +l %lu", myname,
+ tmp->name, tmp->reg->limit);
+#endif
+ } else
+ valid = 0;
+ onarg++;
+ }
+ } else {
+ tmp->modes -= PM_L;
+ if (tmp->reg)
+ tmp->reg->limit = 0;
+#ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -l", myname, tmp->name,
+ tmp->reg->limit);
+#endif
+ }
+ break;
+
+ case 'k':
+ if (numargs > onarg) {
+ if (on) {
+ tmp->modes |= PM_K;
+ if (tmp->reg)
+ strcpy(tmp->reg->key, args[onarg]);
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +k %s", myname, tmp->name,
+ tmp->reg->key);
+# endif
+ } else {
+ tmp->modes -= PM_K;
+ if (tmp->reg)
+ tmp->reg->key[0] = '\0';
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -k %s", myname,
+ tmp->reg->name, args[onarg]);
+# endif
+ }
+ onarg++;
+ } else
+ valid = 0;
+ break;
+
+ case 'm':
+ if (on) {
+ tmp->modes |= PM_M;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +m", myname, tmp->name);
+# endif
+ } else {
+ tmp->modes -= PM_M;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -m", myname, tmp->name);
+# endif
+ }
+ break;
+
+ case 'n':
+ if (on) {
+ tmp->modes |= PM_N;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +n", myname, tmp->name);
+# endif
+ } else {
+ tmp->modes -= PM_N;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -m", myname, tmp->name);
+# endif
+ }
+ break;
+
+ case 'o':
+ if (numargs > onarg) {
+ if (on) {
+ tmpnick =
+ getChanUserData(tmp, getNickData(args[onarg]));
+ if (tmpnick) {
+ tmpnick->op |= CHANOP;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Oped %s in %s", myname,
+ args[onarg], tmp->name);
+# endif
+ } else
+ valid = 0;
+ } else {
+ tmpnick =
+ getChanUserData(tmp, getNickData(args[onarg]));
+ if (tmpnick) {
+ tmpnick->op &= ~CHANOP;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :DeOped %s in %s", myname,
+ args[onarg], tmp->name);
+# endif
+ } else
+ valid = 0;
+ }
+ onarg++;
+ } else
+ valid = 0;
+ break;
+
+ case 'p':
+ if (on) {
+ tmp->modes |= PM_P;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +p", myname, tmp->name);
+# endif
+ } else {
+ tmp->modes -= PM_P;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -p", myname, tmp->name);
+# endif
+ }
+ break;
+
+ case 's':
+ if (on) {
+ if ((tmp->reg) && isServop(nick))
+ tmp->reg->flags |= CPRIVATE;
+ tmp->modes |= PM_S;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +s", myname, tmp->name);
+# endif
+ } else {
+ if ((tmp->reg) && isServop(nick))
+ tmp->reg->flags &= ~CPRIVATE;
+
+ tmp->modes -= PM_S;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -s", myname, tmp->name);
+# endif
+ }
+ break;
+
+ case 't':
+ if (on) {
+ tmp->modes |= PM_T;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s +t", myname, tmp->name);
+# endif
+ } else {
+ tmp->modes -= PM_T;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Set %s -t", myname, tmp->name);
+# endif
+ }
+ break;
+
+ case 'v':
+ if (numargs > onarg) {
+ if (on) {
+ tmpnick =
+ getChanUserData(tmp, getNickData(args[onarg]));
+ if (tmpnick) {
+ tmpnick->op |= CHANVOICE;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :Voiced %s in %s", myname,
+ args[onarg], tmp->name);
+# endif
+ } else
+ valid = 0;
+ } else {
+ tmpnick =
+ getChanUserData(tmp, getNickData(args[onarg]));
+ if (tmpnick) {
+ tmpnick->op &= ~CHANVOICE;
+# ifdef CDEBUG
+ sSend(":%s GNOTICE :DeVoiced %s in %s", myname,
+ args[onarg], tmp->name);
+# endif
+ } else
+ valid = 0;
+ }
+ onarg++;
+ } else
+ valid = 0;
+ break;
+ }
+ }
+
+ if (!valid) {
+ uSend(OperServ, nick, GetReply(ERR_INVALIDMODES, nick), args[2]);
+ return;
+ }
+
+ string[0] = 0;
+ for (i = 2; i < onarg && args[i]; i++) {
+ strcat(string, args[i]);
+ strcat(string, " ");
+ }
+ string[strlen(string) - 1] = 0;
+
+ sSend(":%s MODE %s %s", OperServ, args[1], string);
+ sSend(":%s GLOBOPS :%s MODE %s (%s)", OperServ, from, args[1], string);
+ logDump(operlog, "%s!%s@%s MODE %s (%s)", from, nick->user, nick->host,
+ args[1], string);
+}
+
+void OrawCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char msg[512];
+ int i = 2;
+
+ if (!args[1])
+ return;
+ strcpy(msg, args[1]);
+ while (i < numargs) {
+ strcat(msg, " ");
+ strcat(msg, args[i]);
+ i++;
+ }
+ sSend("%s", msg);
+ logDump(rootlog, "%s!%s@%s RAW (%s)", from, nick->user, nick->host,
+ msg);
+ return;
+}
+
+void OinjectCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char msg[512];
+ int i = 2;
+
+ if (!args[1])
+ return;
+ strcpy(msg, args[1]);
+ while (i < numargs) {
+ strcat(msg, " ");
+ strcat(msg, args[i]);
+ i++;
+ }
+ parseLine(msg);
+ logDump(rootlog, "%s!%s@%s INJECT (%s)", from, nick->user, nick->host, msg);
+ return;
+}
+
+void OrootOpsCmd (UserList *nick, char **args, int num)
+{
+ int i,l,s;
+ UserList *tmp;
+ char msg[4096];
+
+ *msg=0;s=0;
+ for (i=1;i<num;i++)
+ {
+ l=strlen (args[i]);
+ if ((s+l)>4095) break;;
+ strcat (msg," ");
+ strcat (msg,args[i]);
+ s+=l;
+ }
+ for (tmp=firstUser;tmp;tmp=tmp->next)
+ {
+ if (!tmp->reg) continue;
+ if (tmp->reg->flags&(NROOT))
+ {
+ sSend (":%s NOTICE %s :*** RootOps from %s: %s",OperServ,tmp->nick,nick->nick,msg+1);
+ }
+ }
+ return;
+}
+
+void OrestartCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char msg[256];
+
+ *msg = 0;
+
+ if (numargs > 1) {
+ int i = 2;
+
+ strcpy(msg, " (");
+ strcat(msg, args[1]);
+
+ while (i < numargs) {
+ strcat(msg, " ");
+ strcat(msg, args[i]);
+ i++;
+ }
+ strcat(msg, ")");
+ }
+
+ sSend(":%s GLOBOPS :RESTART From %s%s", myname, from, msg);
+ logDump(operlog, "%s!%s@%s RESTART%s", from, nick->user, nick->host,
+ msg);
+ uSend(OperServ, nick, GetReply(RPL_RESTARTING, nick));
+ srestart();
+}
+
+void OshutdownCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char msg[256];
+
+ *msg = 0;
+
+ if (numargs > 1) {
+ int i = 2;
+
+ strcpy(msg, " (");
+ strcat(msg, args[1]);
+
+ while (i < numargs) {
+ strcat(msg, " ");
+ strcat(msg, args[i]);
+ i++;
+ }
+ strcat(msg, ")");
+ }
+
+ sSend(":%s GLOBOPS :SHUTDOWN From %s%s", myname, from, msg);
+ logDump(operlog, "%s!%s@%s SHUTDOWN%s", from, nick->user, nick->host,
+ msg);
+
+ uSend(OperServ, nick, GetReply(RPL_SHUTTINGDOWN, nick));
+ sshutdown(0);
+}
+
+void OjupeCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char jpreason[80];
+ aJupe *jupeptr, *jupeptr2;
+ int i;
+
+ if (!strcasecmp(args[1], "add")) {
+ if (!isServop(nick) && !isRoot(nick)) {
+ uSend(OperServ, nick, GetReply(ERR_NEEDSERVOP, nick));
+ return;
+ }
+
+ if (numargs < 4) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JUPE");
+ return;
+ }
+
+ if (CheckJupe(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_THISEXISTS, nick), args[2], "jupe");
+ return;
+ }
+
+ if (CheckServer(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_THISEXISTS, nick), args[2], "server");
+ return;
+ }
+
+ strncpy(jpreason, args[3], sizeof(jpreason));
+ for (i = 4; i < numargs; i++) {
+ if ((strlen(jpreason) + strlen(args[i])) > 78)
+ break;
+
+ strcat(jpreason, " ");
+ strcat(jpreason, args[i]);
+ }
+
+ AddJupe(args[2], from, CTime, jpreason, 1);
+
+ sSend(":%s GLOBOPS :Server %s Jupitered by %s: %s", myname, args[2], from, jpreason);
+ uSend(OperServ, nick, GetReply(RPL_JINXADDED, nick), "JUPE", args[2]);
+ logDump(operlog, "%s!%s@%s Jupitered Server %s: %s", from, nick->user, nick->host, args[2], jpreason);
+ return;
+ } else if (!strcasecmp(args[1], "del")) {
+ if (!isServop(nick) && !isRoot(nick)) {
+ uSend(OperServ, nick, GetReply(ERR_NEEDSERVOP, nick));
+ return;
+ }
+
+ if (numargs < 3) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JUPE");
+ return;
+ }
+ if (!CheckJupe(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHJINX, nick), "JUPE", args[2]);
+ return;
+ }
+
+ DeleteJupe(args[2]);
+
+ sSend(":%s SQUIT %s", myname, args[2]);
+ sSend(":%s GLOBOPS :%s Un-jupitered by %s", myname, args[2], from);
+ uSend(OperServ, nick, GetReply(RPL_JINXREMOVED, nick), "JUPE", args[2]);
+ logDump(operlog, "%s!%s@%s removed JUPE for %s", from, nick->user, nick->host, args[2]);
+
+ return;
+ } else if (!strcasecmp(args[1], "list")) {
+ if (JupeList == NULL) {
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTEMPTY, nick), "JUPE");
+ return;
+ }
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTHEADER, nick), "JUPE");
+ for (jupeptr = JupeList; jupeptr; jupeptr = jupeptr2) {
+ jupeptr2 = jupeptr->next;
+ uSend(OperServ, nick, GetReply(RPL_JINXLIST1, nick), jupeptr->server, jupeptr->juper, jupeptr->reason, ctime(&(jupeptr->date)));
+ }
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTFOOTER, nick), "JUPE");
+ } else {
+ uSend(OperServ, nick, GetReply(ERR_UNKNOWNCOMMAND, nick), args[1]);
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JUPE");
+ return;
+ }
+}
+
+void ObroadcastCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ int i;
+
+ char broadcast[256];
+ memset(broadcast, '\0', 255);
+
+ for (i = 1; i < numargs &&
+ strlen(broadcast) + strlen(args[i]) <= 255; i++) {
+ strcat(broadcast, args[i]);
+ strcat(broadcast, " ");
+ }
+
+ sSend
+ (":%s NOTICE $*.Serenity-IRC.Net :\002[GLOBAL NOTICE]\002 %s (Please do not reply.)",
+ Serenity, broadcast);
+ sSend(":%s GLOBOPS :%s used global broadcast.", myname, from);
+ logDump(operlog, "%s used global broadcast (%s).", from, broadcast);
+ return;
+}
+
+void OsvsjoinCmd(UserList * nick, char **args, int numargs)
+{
+ if (!getNickData(args[1])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHNICK, nick), args[1]);
+ return;
+ }
+
+ if (args[2][0] != '#') {
+ uSend(OperServ, nick, GetReply(ERR_BADCHANNELNAME, nick), args[2]);
+ return;
+ }
+
+ sSend(":%s GLOBOPS :%s pushed %s into %s.",
+ OperServ, nick->nick, args[1], args[2]);
+ sSend(":%s SVSJOIN %s %s", myname, args[1], args[2]);
+
+ logDump(operlog, "%s pushed %s into %s.", nick->nick, args[1], args[2]);
+ return;
+}
+
+void OsvspartCmd(UserList * nick, char **args, int numargs)
+{
+ if (!getChanData(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHCHAN, nick), args[2]);
+ return;
+ }
+
+ if (!getNickData(args[1])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHNICK, nick), args[1]);
+ return;
+ }
+
+ sSend(":%s GLOBOPS :%s pulled %s out of %s.",
+ myname, nick->nick, args[1], args[2]);
+ sSend(":%s SVSPART %s %s", myname, args[1], args[2]);
+
+ logDump(operlog, "%s pulled %s out of %s.", nick->nick, args[1], args[2]);
+ return;
+}
+
+void OsvsbeamCmd(UserList * nick, char **args, int numargs)
+{
+ if (!getChanData(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHCHAN, nick), args[2]);
+ return;
+ }
+
+ if (!getNickData(args[1])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHNICK, nick), args[1]);
+ return;
+ }
+
+ if (args[3][0] != '#') {
+ uSend(OperServ, nick, GetReply(ERR_BADCHANNELNAME, nick), args[3]);
+ return;
+ }
+
+ sSend(":%s GLOBOPS :%s beamed %s from %s to %s.",
+ myname, nick->nick, args[1], args[2], args[3]);
+ sSend(":%s SVSPART %s %s", OperServ, args[1], args[2]);
+ sSend(":%s SVSJOIN %s %s", OperServ, args[1], args[3]);
+
+ logDump(operlog, "%s beamed %s from %s to %s.", nick->nick, args[1], args[2], args[3]);
+ return;
+}
+
+void OsvsnoopCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ aServer *server;
+ UserList *tmp;
+
+ if (!strcasecmp(args[1], "ADD")) {
+
+ server = GetServer(args[2]);
+ if (!server) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHSERVER, nick),
+ args[2]);
+ return;
+ }
+
+ if (server->svsnoop == 1) {
+ uSend(OperServ, nick, GetReply(ERR_ALREADYSVSNOOP, nick),
+ args[2]);
+ return;
+ }
+
+ server->svsnoop = 1;
+ sSend(":%s GLOBOPS :%s activated SVSNOOP for %s.", myname, from,
+ args[2]);
+ sSend(":%s SVSNOOP %s +", myname, server->name);
+
+ for (tmp = firstUser; tmp; tmp = tmp->next) {
+ if (isOper(tmp) && !strcasecmp(tmp->server, server->name)) {
+ setMode(tmp->nick, "-NnAaOo");
+ }
+ }
+ }
+
+ else if (!strcasecmp(args[1], "DEL")) {
+
+ server = GetServer(args[2]);
+ if (!server) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHSERVER, nick),
+ args[2]);
+ return;
+ }
+
+ if (server->svsnoop == 0) {
+ uSend(OperServ, nick, GetReply(ERR_NOTSVNOOP, nick), args[2]);
+ return;
+ }
+
+ server->svsnoop = 0;
+ sSend(":%s GLOBOPS :%s deactivated SVSNOOP for %s.", myname, from,
+ args[2]);
+ sSend(":%s SVSNOOP %s -", myname, server->name);
+ }
+
+ logDump(operlog, "%s used SVSNOOP (%s).", from, args[2]);
+ return;
+}
+
+void OekillCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ char ereason[80];
+
+ int i;
+
+ if (numargs < 3 || !strcasecmp(args[1], "LIST")) {
+
+ if (EmailList == NULL) {
+ uSend(OperServ, nick, GetReply(RPL_EKILLEMPTY, nick));
+ return;
+ }
+
+ uSend(OperServ, nick, GetReply(RPL_EKILLHEAD, nick));
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+ uSend(OperServ, nick, GetReply(RPL_EKILLDATA, nick),
+ emailptr->email, emailptr->by, emailptr->reason,
+ ctime(&(emailptr->time)));
+ }
+ uSend(OperServ, nick, GetReply(RPL_EKILLEND, nick));
+ return;
+
+ }
+
+ if ((!strchr(args[2], '@')) || (strlen(args[2]) < 5)
+ || (strlen(args[2]) > EMAILLEN)) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ return;
+ }
+
+ if (numargs < 3) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ return;
+ }
+
+ if (!strcasecmp(args[1], "DEL")) {
+ if (!CheckEmail(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHEKILL, nick),
+ args[2]);
+ return;
+ }
+
+ uSend(OperServ, nick, GetReply(RPL_EKILLDELED, nick), args[2]);
+ sSend(":%s GLOBOPS :%s removed dynamic EKILL for %s", OperServ,
+ from, args[2]);
+ DeleteEmail(args[2]);
+ return;
+ }
+
+ if (numargs < 4) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ return;
+ }
+
+ if (!strcasecmp(args[1], "ADD")) {
+
+ if (CheckEmail(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_EKILLEXISTS, nick),
+ args[2]);
+ return;
+ }
+
+ bzero(ereason, 80);
+ strncpy(ereason, args[3], 79);
+
+ for (i = 4; i < numargs; i++) {
+ if ((strlen(ereason) + strlen(args[i])) > 78)
+ break;
+ strcat(ereason, " ");
+ strcat(ereason, args[i]);
+ }
+
+ uSend(OperServ, nick, GetReply(RPL_EKILLADDED, nick), args[2]);
+ sSend(":%s GLOBOPS :%s added dynamic EKILL for %s (%s)", OperServ,
+ from, args[2], ereason);
+ AddEmail(args[2], from, ereason);
+ }
+
+ return;
+}
+
+void OlistCmd(UserList * nick, char **args, int numargs)
+{
+ HostCloneList *clonelist;
+ int i = 0;
+
+ if (!strcasecmp(args[1], "PERMIGNORES")) {
+ uSend(OperServ, nick, GetReply(RPL_PERMCLONEIGNHEAD, nick));
+ for (clonelist = firstPermClone; clonelist;
+ clonelist = clonelist->next) {
+ i++;
+ uSend(OperServ, nick, GetReply(RPL_PERMCLONEIGNDATA, nick), i,
+ clonelist->host);
+ }
+ uSend(OperServ, nick, GetReply(RPL_PERMCLONEIGNEND, nick));
+ }
+ return;
+}
+
+void OuptimeCmd(UserList * nick, char **args, int numargs)
+{
+ long blah;
+ int days, hours, mins, seconds;
+
+ blah = time(NULL);
+ blah -= startup;
+ days = (int) (blah / (24 * 3600));
+ blah %= (24 * 3600);
+ hours = (int) (blah / (3600));
+ blah %= (3600);
+ mins = (int) (blah / (60));
+ blah %= (60);
+ seconds = blah;
+ uSend(OperServ, nick, GetReply(RPL_UPTIME1, nick));
+ uSend(OperServ, nick, GetReply(RPL_UPTIME2, nick), days, hours, mins,
+ seconds);
+ return;
+}
+
+void OallocstatCmd(UserList * nick, char **args, int numargs)
+{
+#ifndef WIN32
+ char *from = nick->nick;
+ FILE *fp;
+
+ char psline[128];
+
+ uSend(OperServ, nick, GetReply(RPL_ALLOCSTAT1, nick), AllocCalled);
+ uSend(OperServ, nick, GetReply(RPL_ALLOCSTAT2, nick), FreeCalled);
+
+ /* Ax0n: Added -w for wrap, incase we are invoked /very/long/path/services */
+ sprintf(psline, "ps -uaxw | grep services");
+ fp = popen(psline, "r");
+ if (fp) {
+ while (sfgets(psline, 128, fp)) {
+ if (match(psline, "*grep*"))
+ sSend(":%s NOTICE %s :%s", OperServ, from, psline);
+ }
+ fclose(fp);
+ }
+ return;
+#endif
+}
+
+void OsyncCmd(UserList * nick, char **args, int numargs)
+{
+ save_access_mod();
+ strcpy(args[0], "save");
+ sendToNickServ(nick, args, numargs);
+ sendToChanServ(nick, args, numargs);
+ sSend(":%s GLOBOPS :Synchronizing all remaining databases to disk...",
+ OperServ);
+ savedynamicekills();
+}
+
+void OtriggerCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+
+ if (index(args[1], '@')) {
+ char user[USERLEN];
+ char host[HOSTLEN];
+ HostClone *hc;
+ UserClone *uc;
+ sscanf(args[1], "%[^@]@%s", user, host);
+ hc = getCloneData(host);
+ if (hc)
+ uc = getUserCloneData(hc, user);
+ else
+ uc = NULL;
+ if (uc && hc) {
+ if (numargs < 3)
+ uSend(OperServ, nick, GetReply(RPL_CLONESTATUS1, nick),
+ user, host, uc->clones, uc->trigger);
+ else {
+ int i = atoi(args[2]);
+ if (i > 0) {
+ uc->trigger = i;
+ sSend(":%s GLOBOPS :%s@%s retriggered to %i by %s",
+ OperServ, user, host, i, from);
+ } else
+ uSend(OperServ, nick,
+ GetReply(ERR_INVALIDTRIGLEVEL, nick));
+ }
+ } else
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHTRIGGER, nick), user,
+ host);
+ } else {
+ char host[HOSTLEN];
+ HostClone *hc;
+ strcpy(host, args[1]);
+ hc = getCloneData(host);
+ if (hc) {
+ if (numargs < 3)
+ uSend(OperServ, nick, GetReply(RPL_CLONESTATUS2, nick),
+ host, hc->clones, hc->trigger);
+ else {
+ int i = atoi(args[2]);
+ if (i > 0) {
+ hc->trigger = i;
+ sSend(":%s GLOBOPS :%s retriggered to %i by %s",
+ OperServ, host, i, from);
+ } else
+ uSend(OperServ, nick,
+ GetReply(ERR_INVALIDTRIGLEVEL, nick));
+ }
+ } else {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHCHAN, nick), host);
+ }
+ }
+}
+
+void OclonesetCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char date[20];
+ struct tm *t;
+ HostClone *hc;
+ HostCloneList *permignore;
+ int tempflags = 0;
+ int goodhost = 0;
+
+ if (!strcasecmp(args[1], "list")) {
+ sSend(":%s NOTICE %s :Listing PERMIGNORES only:", OperServ, from);
+ for (permignore = firstPermClone; permignore; permignore = permignore->next) {
+ t = localtime(&(permignore->setwhen));
+ strftime(date, 20, "%m/%d/%y-%I:%M%p", t);
+
+ sSend(":%s NOTICE %s :%s %-40s (%s)",
+ OperServ, from, date, permignore->host,
+ permignore->setby);
+ }
+ sSend(":%s NOTICE %s :End of list", OperServ, from);
+ return;
+ }
+
+ hc = getCloneData(args[1]);
+
+ if (!hc) {
+ for (permignore = firstPermClone; permignore;
+ permignore = permignore->next) {
+ if (!strcasecmp(permignore->host, args[1])) {
+ tempflags = CLONE_PERMIGNORE;
+ break;
+ }
+ }
+ } else
+ tempflags = hc->flags;
+
+ if (numargs < 3) {
+ if (tempflags)
+ uSend(OperServ, nick, GetReply(RPL_HASCLONEFLAGS, nick),
+ args[1],
+ (tempflags & CLONE_KILLFLAG) ? " Auto Remove" : "",
+ (tempflags & CLONE_IGNOREFLAG) ? " Ignore All" : "",
+ (tempflags & CLONE_PERMIGNORE) ? " Perm Ignore" : "");
+ else
+ uSend(OperServ, nick, GetReply(RPL_NOCLONEFLAGS, nick),
+ args[1]);
+ } else {
+ if (!strcasecmp(args[2], "kill")) {
+ if (hc) {
+ hc->flags |= CLONE_KILLFLAG;
+ tempflags = hc->flags;
+ goodhost = 1;
+ }
+ } else if (!strcasecmp(args[2], "-kill")) {
+ if (hc) {
+ hc->flags &= ~CLONE_KILLFLAG;
+ tempflags = hc->flags;
+ goodhost = 1;
+ }
+ } else if (!strcasecmp(args[2], "ignore")) {
+ if (hc) {
+ hc->flags |= CLONE_IGNOREFLAG;
+ tempflags = hc->flags;
+ goodhost = 1;
+ }
+ } else if (!strcasecmp(args[2], "-ignore")) {
+ if (hc) {
+ hc->flags &= ~CLONE_IGNOREFLAG;
+ tempflags = hc->flags;
+ goodhost = 1;
+ }
+ } else if (!strcasecmp(args[2], "permignore")) {
+
+ if (!hc && tempflags) {
+ uSend(OperServ, nick, GetReply(ERR_PERMIGNEXISTS, nick),
+ args[1]);
+ goodhost = 2;
+ }
+
+ if (hc) {
+ if (hc->flags & CLONE_PERMIGNORE) {
+ uSend(OperServ, nick,
+ GetReply(ERR_PERMIGNEXISTS, nick), args[1]);
+ goodhost = 2;
+ } else {
+ hc->flags |= CLONE_PERMIGNORE;
+ permignore =
+ smalloc(sizeof(struct hostcloneliststruct));
+ strcpy(permignore->host, hc->host);
+ strcpy(permignore->setby, from);
+ permignore->setwhen = CTime;
+ permignore->next = firstPermClone;
+ permignore->prev = NULL;
+ if (permignore->next)
+ permignore->next->prev = permignore;
+ firstPermClone = permignore;
+ tempflags = hc->flags;
+ goodhost = 1;
+ }
+ }
+ } else if (!strcasecmp(args[2], "-permignore")) {
+ if (hc) {
+ hc->flags &= ~CLONE_PERMIGNORE;
+ tempflags = hc->flags;
+ }
+
+ for (permignore = firstPermClone; permignore;
+ permignore = permignore->next) {
+ if (!strcasecmp(args[1], permignore->host)) {
+ if (permignore->prev)
+ permignore->prev->next = permignore->next;
+ if (permignore->next)
+ permignore->next->prev = permignore->prev;
+ if (permignore == firstPermClone)
+ firstPermClone = permignore->next;
+ sfree(permignore);
+ goodhost = 1;
+ break;
+ }
+ }
+
+ if (!goodhost) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHPERMIGN, nick),
+ args[1]);
+ return;
+ }
+ }
+
+ else {
+ uSend(OperServ, nick, GetReply(ERR_UNKNOWNFLAG, nick),
+ args[1]);
+ return;
+ }
+
+ if (goodhost == 1) {
+ if (tempflags)
+ sSend(":%s GLOBOPS :%s changed flags for %s (now%s%s%s).",
+ OperServ, from, args[1],
+ (tempflags & CLONE_KILLFLAG) ? " Auto Remove" : "",
+ (tempflags & CLONE_IGNOREFLAG) ? " Ignore All" : "",
+ (tempflags & CLONE_PERMIGNORE) ? " Perm Ignore" :
+ "");
+ else
+ sSend(":%s GLOBOPS :%s changed flags for %s (now NONE).",
+ OperServ, from, args[1]);
+ } else if (goodhost != 2)
+ uSend(OperServ, nick, GetReply(ERR_UNKNOWHOST, nick), args[1]);
+ }
+}
+
+void OmkillCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ char *s1;
+ char *at; // Position on '@' in the mask
+ char *start, *end;
+ int i = 0;
+ char user[USERLEN];
+ char host[HOSTLEN];
+ int goodmask = 1; // Innocent until proven guilty
+
+ /* Check the input received for validity */
+ start = s1 = args[1];
+ end = start + strlen(args[1]) + 1;
+ at = index(args[1], '@');
+
+ while (*s1 && goodmask) {
+ /* Wildcards are not allowed, nor is !, nor is a dot in the userpart.
+ * Only one @ is allowed in the mask */
+ if ((*s1 == '?') || (*s1 == '*') || (*s1 == '!') ||
+ ((*s1 == '.') && (s1 < at)) || ((*s1 == '@') && (s1 > at)))
+ goodmask = 0;
+ s1++;
+ }
+
+ /* Check that we won't overflow our buffer if we'd split the string up */
+ if (at) {
+ if ((end - at) > HOSTLEN || ((at - start) + 1) > USERLEN)
+ goodmask = 0;
+ } else {
+ if ((end - start) + 1 > HOSTLEN)
+ goodmask = 0;
+ }
+
+ /* Did we find an error in the mask? Then we give up here */
+ if (!goodmask) {
+ uSend(OperServ, nick, GetReply(ERR_BADMASK, nick), args[1]);
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ,
+ args[0]);
+ return;
+ }
+
+ if (at)
+ sscanf(args[1], "%[^@]@%s", user, host);
+ else {
+ strcpy(host, args[1]);
+ strcpy(user, "*");
+ }
+
+ i = killMassClones(user, host);
+
+ if (i) {
+ sSend(":%s GLOBOPS :%s masskilled %s@%s (%i matches)", OperServ,
+ from, user, host, i);
+ logDump(operlog, "%s!%s@%s masskilled %s@%s (%i matches)", from,
+ nick->user, nick->host, user, host, i);
+ } else
+ uSend(OperServ, nick, GetReply(ERR_NOMATCH, nick), user, host);
+}
+
+void OmapCmd(UserList * nick, char **args, int numargs)
+{
+
+ aServer *srvptr;
+ aServer *srvptr2;
+
+// printf("%s", 3408932); /* <- manual core if uncommented, useful for core-debugging -GZ */
+
+ if (ServerList == NULL)
+ return;
+
+ uSend(OperServ, nick, GetReply(RPL_MAPHEAD, nick));
+ for (srvptr = ServerList; srvptr; srvptr = srvptr2) {
+ srvptr2 = srvptr->next;
+ uSend(OperServ, nick, GetReply(RPL_MAPDATA, nick), srvptr->name, srvptr->version);
+ }
+ uSend(OperServ, nick, GetReply(RPL_MAPDATA, nick), myname, PACKAGE " v" VERSION);
+ uSend(OperServ, nick, GetReply(RPL_MAPEND, nick));
+ return;
+}
+
+void OjinxCmd(UserList * nick, char **args, int numargs)
+{
+
+ char *from = nick->nick;
+ UserList *target;
+ aJinx *jinxptr, *jinxptr2;
+ int i;
+ char reason[1000];
+
+ bzero(reason, 1000);
+
+ if (!strcasecmp(args[1], "add")) {
+ if (numargs < 4) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JINX");
+ return;
+ }
+
+ if (!(target = getNickData(args[2]))) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHNICK, nick), args[2]);
+ return;
+ }
+
+ if (CheckJinx(target->nick)) {
+ uSend(OperServ, nick, GetReply(ERR_JINXEXIST, nick), "JINX",
+ target->nick);
+ return;
+ }
+
+ if (isRoot(target)) {
+ uSend(OperServ, nick, GetReply(ERR_CANTJINXSRA, nick));
+ sSend(":%s GLOBOPS :\002Warning:\002 %s attempted to JINX \002%s\002.", OperServ, from, args[2]);
+ return;
+ }
+
+ sprintf(reason, args[3]);
+ for (i = 4; i < numargs; i++) {
+ strcat(reason, " ");
+ strcat(reason, args[i]);
+ }
+
+ AddJinx(target->nick, from, reason);
+
+ sSend(":%s GLOBOPS :%s added a JINX for \002%s\002 (%s)", OperServ, from, target->nick, reason);
+ sSend(":%s JINX %s", myname, target->nick);
+ uSend(OperServ, nick, GetReply(RPL_JINXADDED, nick), "JINX", target->nick);
+ logDump(operlog, "%s!%s@%s Added a JINX for %s", from, nick->user,
+ nick->host, target->nick);
+
+ return;
+ } else if (!strcasecmp(args[1], "del")) {
+
+ if (numargs < 3) {
+ uSend(OperServ, nick, GetReply(ERR_BADPARAMS, nick));
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JINX");
+ return;
+ }
+
+ if (!CheckJinx(args[2])) {
+ uSend(OperServ, nick, GetReply(ERR_NOSUCHJINX, nick), "JINX", args[2]);
+ return;
+ }
+
+ DeleteJinx(args[2]);
+ sSend(":%s GLOBOPS :%s removed the JINX for \002%s\002.", OperServ, from, args[2]);
+ uSend(OperServ, nick, GetReply(RPL_JINXREMOVED, nick), "JINX", args[2]);
+ sSend(":%s UNJINX %s", myname, args[2]);
+ logDump(operlog, "%s!%s@%s removed a JINX for %s", from,
+ nick->user, nick->host, args[2]);
+
+ return;
+ } else if (!strcasecmp(args[1], "list")) {
+
+ if (JinxList == NULL) {
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTEMPTY, nick), "JINXES");
+ return;
+ }
+
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTHEADER, nick), "JINXES");
+ for (jinxptr = JinxList; jinxptr; jinxptr = jinxptr2) {
+ jinxptr2 = jinxptr->next;
+ uSend(OperServ, nick, GetReply(RPL_JINXLIST1, nick), jinxptr->nick, jinxptr->by, jinxptr->reason, ctime(&(jinxptr->time)));
+ }
+ uSend(OperServ, nick, GetReply(RPL_JINXLISTFOOTER, nick), "JINXES");
+ } else {
+ uSend(OperServ, nick, GetReply(ERR_UNKNOWNCOMMAND, nick), args[1]);
+ uSend(OperServ, nick, GetReply(RPL_MOREHELPCMD, nick), OperServ, "JINX");
+ }
+
+ return;
+}
+
+void OenforceCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ RegNickList *reg;
+ int i;
+
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ i = 0;
+
+ if (EmailList == NULL)
+ return;
+
+ sSend(":%s GLOBOPS :Enforcing EKILLS. (Requested by %s)", OperServ,
+ from);
+
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+
+ for (reg = firstRegNick; reg; reg = reg->next) {
+ if (!match(reg->email, emailptr->email)) {
+ i++;
+ logDump(nicklog, "%s DELETE %s (EKILL ENFORCE for %s)",
+ from, reg->nick, reg->email);
+ delRegNick(reg);
+ }
+ }
+ }
+
+ logDump(nicklog, "EKILL ENFORCE requested by %s", from);
+ sSend
+ (":%s GLOBOPS :Deleted %i nicks from database. (EKILL ENFORCE by %s)",
+ NickServ, i, from);
+}
+
+void OlistOpsCmd (UserList *nick, char **args, int numargs)
+{
+ char *psn;
+ UserList *tn;
+ aServer *svr;
+ unsigned int flags;
+
+ psn=nick->server;
+ if (numargs>1) psn=args[1];
+ svr=GetServer (psn);
+ if (!svr)
+ {
+ uSend (OperServ,nick,"No such server: %s",psn);
+ return;
+ }
+ uSend (OperServ,nick,"*** Online opers for server %s:",svr->name);
+ for (tn=firstUser;tn;tn=tn->next) if (!match (tn->server,psn))
+ {
+ flags=tn->oflags;
+ printf ("%s %08X\n",tn->nick,flags);
+ if (flags&NISADMIN) uSend (OperServ,nick,"Admin: %s",tn->nick);
+ else if (flags&NISOPER) uSend (OperServ,nick,"Oper: %s",tn->nick);
+ }
+ uSend (OperServ,nick,"*** End of Oper list.");
+ return;
+}
--- /dev/null
+#include "services.h"
+
+int ToRecvQ(char *buffer)
+{
+
+ if (!recvQ.messages) {
+ strcpy(recvQ.buffer, buffer);
+ recvQ.messages = 1;
+ recvQ.length = strlen(buffer);
+ return 1;
+ } else if ((recvQ.length + strlen(buffer)) < MAXRQ) {
+ strcat(recvQ.buffer, buffer);
+ recvQ.messages++;
+ recvQ.length += strlen(buffer);
+ return 1;
+ }
+
+ return 0;
+}
+
+int FromRecvQ(void)
+{
+
+ if (!recvQ.messages)
+ return 1;
+ else {
+ breakLine(recvQ.buffer);
+ recvQ.messages = 0;
+#ifdef DEBUG
+ printf("[RECVQ (%i)]\n%s\n", recvQ.length, recvQ.buffer);
+#endif
+ return 1;
+ }
+
+ return 0;
+}
+
+int ToSendQ(char *buffer)
+{
+
+ if (!sendQ.messages) {
+ strcpy(sendQ.buffer, buffer);
+ sendQ.messages = 1;
+ sendQ.length = strlen(buffer);
+ return 1;
+ } else if ((sendQ.length + strlen(buffer)) < MAXSQ) {
+ strcat(sendQ.buffer, buffer);
+ sendQ.messages++;
+ sendQ.length += strlen(buffer);
+ return 1;
+ }
+
+ return 0;
+}
+
+int FromSendQ(void)
+{
+
+ if (!sendQ.messages)
+ return 1;
+ else {
+ sendQ.messages = 0;
+#ifdef DEBUG
+ printf("[SENDQ (%i)]\n%s\n", sendQ.length, sendQ.buffer);
+#endif
+/* fputs(sendQ.buffer, servout);*/
+ send(server,sendQ.buffer, strlen(sendQ.buffer), 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+int listenOnPort(int portnum)
+{
+ struct sockaddr_in me;
+ int sock;
+ memset(&me, 0, sizeof(struct sockaddr));
+ me.sin_addr.s_addr = INADDR_ANY; /* any address... */
+ me.sin_family = AF_INET;
+ me.sin_port = htons((u_short) portnum);
+
+ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ return -1;
+ else if (bind(sock, (struct sockaddr *) &me, sizeof(me)))
+ return -1;
+ else if (listen(sock, 5))
+ return -1;
+ else
+ return sock; /* we can accept() now, whoopdeedoodoo */
+}
+
+int ConnectToServer(char *hostname, int portnum)
+{
+ struct sockaddr_in sa;
+ struct hostent *hp;
+ int s;
+
+ if ((hp = resolve(hostname)) == NULL) {
+ errno = ECONNREFUSED;
+ return (-1);
+ }
+
+ bzero(&sa, sizeof(sa));
+ bcopy(hp->h_addr, (char *) &sa.sin_addr, hp->h_length); /* set address */
+ sa.sin_family = hp->h_addrtype;
+ sa.sin_port = htons((u_short) portnum);
+
+ if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) /* get socket */
+ return (-1);
+
+ if (connect(s, (struct sockaddr *) &sa, sizeof sa) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+
+/* various resolving functions...*/
+
+struct hostent *resolve(char *stuff)
+{
+ struct hostent *hp;
+
+ if ((hp = lookupHost(stuff)) == NULL)
+ hp = lookupIP(stuff);
+
+ return hp;
+}
+
+struct hostent *lookupHost(char *host)
+{
+ struct hostent *hp;
+
+ alarm(5);
+ hp = gethostbyname(host);
+ alarm(0);
+ return hp;
+}
+
+struct hostent *lookupIP(char *ip)
+{
+ int p1, p2, p3, p4;
+ char doot[4];
+ struct hostent *hp;
+
+ p1 = p2 = p3 = p4 = 0;
+
+ sscanf(ip, "%i.%i.%i.%i", &p1, &p2, &p3, &p4);
+ doot[0] = p1;
+ doot[1] = p2;
+ doot[2] = p3;
+ doot[3] = p4;
+ alarm(5);
+ hp = gethostbyaddr(doot, 4, AF_INET);
+ alarm(0);
+ return hp;
+}
+
+/*
+ * a renewed sSend that is solely used for advanced sending to users.
+ *
+ * - Advanced flood-protection
+ * - Multilangual support
+ * - WebTV support
+ *
+ * Added by GZ (April 2000)
+ */
+
+void uSend(char *Service, UserList * nick, char *format, ...)
+{
+ static char sBuffer[513];
+ char sendstring[1024];
+ va_list stuff;
+ va_start(stuff, format);
+
+ vsnprintf(sBuffer, 511, format, stuff);
+
+ if (!isServop(nick))
+ nick->floodbytes += strlen(sBuffer);
+
+ strcat(sBuffer, "\r\n");
+
+ if (nick->webbie)
+ sprintf(sendstring, ":%s PRIVMSG %s :", Service, nick->nick);
+ else
+ sprintf(sendstring, ":%s NOTICE %s :", Service, nick->nick);
+
+ strcat(sendstring, sBuffer);
+ ToSendQ(sendstring);
+}
+
+/*
+ * a printf() type function for sending data to sockets, very handy
+ */
+
+void sSend(char *format, ...)
+{
+ static char sBuffer[513];
+
+ va_list stuff;
+ va_start(stuff, format);
+ vsnprintf(sBuffer, 511, format, stuff);
+ strcat(sBuffer, "\r\n");
+ ToSendQ(sBuffer);
+}
+
+void sockSend(int sock, char *format, ...)
+{
+ static char sBuffer[513];
+ int bufferLen;
+ va_list stuff;
+
+ va_start(stuff, format);
+
+ vsnprintf(sBuffer, 511, format, stuff);
+ strcat(sBuffer, "\n");
+ bufferLen = strlen(sBuffer);
+/* write(sock, sBuffer, bufferLen);*/
+ send(sock, sBuffer, bufferLen, 0);
+
+#ifdef DEBUG
+ printf("sock-> (%i) %s\n", sock, sBuffer);
+#endif
+}
+
+void logDump(FILE * fp, char *format, ...)
+{
+ char buffer[512];
+ char stuff[80];
+ time_t doot = time(NULL);
+ va_list crud;
+
+ va_start(crud, format);
+ vsnprintf(buffer, 512, format, crud);
+ strftime(stuff, 80, "%H:%M:%S[%d/%m/%Y]", localtime(&doot));
+ fprintf(fp, "(%s) %s\n", stuff, buffer);
+
+ return;
+}
+
+/* send a mail, the arguments should speak for themselves... */
+
+int sendMail(char *to, char *from, char *subject, char *format, ...)
+{
+ /* if you fill more than this up I will personally kill you */
+ char mail[65536];
+ va_list stuff;
+ FILE *fp;
+
+ fp = popen("/usr/sbin/sendmail -t", "w");
+ if (fp) {
+ va_start(stuff, format);
+ vsnprintf(mail, 65535, format, stuff);
+ fprintf(fp, "From: %s\n", from);
+ fprintf(fp, "To: %s\n", to);
+ fprintf(fp, "Subject: %s\n", subject);
+ fprintf(fp, "\n%s\n", mail);
+ fprintf(fp, ".\n");
+ pclose(fp);
+ return 0;
+ }
+ return -1;
+}
+
+
+/*
+ * Add a new user, be that ChanServ or a nick in holding.
+ * in the 'mode' variable you can specify +iogsw or any other ircd
+ * compatible modes.
+ */
+
+void addUser(char *nick, char *user, char *host, char *name, char *mode)
+{
+ sSend("NICK %s 1 0 %s %s %s :%s", nick, user, host, myname, name);
+ sSend(":%s MODE %s :%s", nick, nick, mode);
+}
+
+void killUser(Service serv, UserList * user, char *message)
+{
+ if (!user)
+ return;
+ sSend(":%s KILL %s :%s!%s (%s)", serv.name, user->nick, serv.host,
+ serv.name, message);
+ remUser(user->nick);
+}
+
+void userMode(UserList * user, char *mode)
+{
+ sSend(":%s MODE %s :%s", myname, user->nick, mode);
+ setMode(user->nick, mode);
+}
+
+/*
+ * Break up a string of data into seperate parts and parse those.
+ * (parseLine())
+ * I'm not sure but this function could be done better(?) if someone
+ * wants to improve it...
+ */
+
+char junk[4096];
+
+void breakLine(char *tmpbuffer)
+{
+ int i = 0, a = 0;
+ static char sendBuffer[4096];
+
+ if (*junk) {
+ strcpy(sendBuffer, junk);
+ *junk = 0;
+ a = strlen(sendBuffer);
+ } else
+ a = 0;
+
+ while (*tmpbuffer) {
+ i = 0;
+
+ while ((*tmpbuffer) && (*tmpbuffer != '\r')
+ && (*tmpbuffer != '\n')) {
+ sendBuffer[a] = *tmpbuffer;
+ a++;
+ tmpbuffer++;
+ }
+
+ sendBuffer[a] = 0;
+ a = 0;
+
+ /* danger, assuming VERY specific IRCD behavior */
+
+ while ((*tmpbuffer == '\r') || (*tmpbuffer == '\n')) {
+ i = 1;
+ tmpbuffer++;
+ }
+
+ if (!i) {
+ strcpy(junk, sendBuffer);
+ break;
+ } else
+ parseLine(sendBuffer);
+ }
+}
+
+
+/*
+ * parseLine takes server data and moshes it around in here to see what
+ * to do with it. :>
+ * This will get called to *often*, so I'd like to make it very streanlined
+ * if it can be done in assembly...:>
+ * Also, I am assuming ircd will send commands in uppercase only, if this is
+ * not the case, then it should be fixed, strcasecmp is a more expensive
+ * function and all....
+ */
+
+void parseLine(char *line)
+{
+
+ UserList *tmp;
+ int i = 0;
+ int cmdpointer = 0;
+ char *args2[253];
+ char *args[256];
+ char realargs[256][513]; /* 2D arrays...C doesn't do them well...*shrug* */
+ int numargs = 0;
+
+ if (!(*line))
+ return;
+
+ for (i = 0; i < 256; i++)
+ args[i] = realargs[i];
+
+ strcpy(coreBuffer, line);
+ CTime = time(NULL);
+
+ numargs = breakString(255, line, args, " \t");
+
+ /* ensure the next item is null so we can check it later */
+ args[numargs] = NULL;
+
+ if (args[0][0] == ':')
+ {
+ args[0]++;
+ cmdpointer = 1;
+ }
+
+ if (!cmdpointer)
+ { /* LINE DOES NOT START WITH : -- COMMAND IS FIRST */
+ if ((!strcmp(args[0], "PING")) || (!strcmp(args[0], "8")))
+ {
+ sSend("PONG :%s", myname);
+ return;
+ }
+
+ /* Close my link? nuhuh. */
+ else if ((!strcmp(args[0], "ERROR") || (!strcmp(args[0], "5"))) && !strcmp(args[1], ":Closing"))
+ {
+ sshutdown(0);
+ return;
+ }
+ else if ((!strcmp(args[0], "SERVER")) || (!strcmp(args[0], "'")))
+ {
+ AddServer(args[1], args[3]);
+ strcpy(hostservername, args[1]);
+ synched = 0;
+ return;
+ }
+ else if ((!strcmp(args[0], "NICK")) || (!strcmp(args[0], "&")))
+ {
+ addNewUser(args, numargs); /* nickserv.c, add new user. */
+ return;
+ }
+ else if ((!strcmp(args[0], "SNICK")) || (!strcmp(args[0], "}")))
+ {
+ addNewUserSN(args, numargs); /* nickserv.c, add new user. */
+ return;
+ }
+ /* Server SQUIT'ing - remove it from our little list. */
+ else if ((!strcmp(args[0], "SQUIT")) || (!strcmp(args[0], "-")))
+ {
+ DeleteServer(args[1]);
+ }
+ }
+ else
+ { /* : FIRST, NICK OR SERVER FOLLOWED BY COMMAND */
+ if ((!strcmp(args[1], "PRIVMSG")) || (!strcmp(args[1], "!")))
+ {
+ tmp = getNickData(args[0]);
+
+ if (!tmp) return;
+ synched = 1;
+
+ if (strchr(args[2], '#') || strchr(args[2], '$'))
+ return;
+
+ args[3]++;
+ for (i = 3; i < numargs; i++)
+ args2[i - 3] = args[i];
+ numargs -= 3;
+ args2[numargs] = NULL;
+
+ if (!strncasecmp(args[2], OperServ, strlen(OperServ)) || !strcasecmp(args[2], "Oper"))
+ sendToOperServ(tmp, args2, numargs);
+ else if (!strncasecmp(args[2], NickServ, strlen(NickServ)) || !strcasecmp(args[2], "Nick"))
+ sendToNickServ(tmp, args2, numargs);
+ else if (!strncasecmp(args[2], ChanServ, strlen(ChanServ)) || !strcasecmp(args[2], "Chan"))
+ sendToChanServ(tmp, args2, numargs);
+ else if (!strncasecmp(args[2], MemoServ, strlen(MemoServ)) || !strcasecmp(args[2], "Memo"))
+ sendToMemoServ(tmp, args2, numargs);
+ else if (!strncasecmp(args[2], WebServ, strlen(WebServ)))
+ sendToWebServ(tmp, args2, numargs);
+ else
+ uSend(NickServ, getNickData(args[0]),
+ GetReply(ERR_THISISNONICKDUMMY,
+ getNickData(args[0])));
+ return;
+ }
+
+ /* Make sure servers don't mess up the JINX tables -GZ */
+ else if ((!strcmp(args[1], "JINX")) || (!strcmp(args[1], "t")))
+ {
+ /* We no longer have pure hostjinx'es as we did before...
+ However, I'm not 100% sure yet if this check should
+ stay or go. I'm leaving CheckHostJinx in jinx.c for now.
+ -- Remmy 20020430 */
+ /* CheckHostJinx(args[0], args[2], 1); */
+ return;
+ }
+
+ else if ((!strcmp(args[1], "UNJINX")) || (!strcmp(args[1], "t")))
+ {
+ /* CheckHostJinx(args[0], args[2], 0); */
+ return;
+ }
+
+ /* Some server is introducing another server - store it. -GZ */
+
+ else if ((!strcmp(args[1], "SERVER")) || (!strcmp(args[0], "'")))
+ {
+ AddServer(args[2], args[4]);
+ return;
+ }
+
+/* First, when someone leaves lets deal with that... */
+
+ else if ((!strcmp(args[1], "QUIT")) || (!strcmp(args[1], ",")))
+ {
+ remUser(args[0]); /* nickserv.c, remove user. */
+ if (CheckJinx(args[0]))
+ {
+ DeleteJinx(args[0]);
+ sSend(":%s GLOBOPS :%s left IRC. JINX has been removed",
+ OperServ, args[0]);
+ }
+ return;
+ }
+
+ /* Nick change */
+ else if ((!strcmp(args[1], "NICK")) || (!strcmp(args[1], "&")))
+ {
+ tmp = getNickData(args[0]);
+
+ changeNick(args[0], args[2], args[3]);
+ return;
+ }
+
+ /* Deal with MODE -- ignoring services itself */
+
+ else if ((!strcmp(args[1], "MODE") || (!strcmp(args[1], "G")))
+ && !strcmp(args[0], args[2]))
+ {
+ if (strcasecmp(args[0], OperServ)
+ && strcasecmp(args[0], NickServ)
+ && strcasecmp(args[0], ChanServ)
+ && strcasecmp(args[0], MemoServ)
+ && strcasecmp(args[0], WebServ)
+ && strcasecmp(args[0], "Nick")
+ && strcasecmp(args[0], "Chan")
+ && strcasecmp(args[0], "Memo")
+ && strcasecmp(args[0], "Oper")) setMode(args[0], args[3]);
+ return;
+ }
+
+ /* MODE got to here -- must be a channel mode */
+
+ else if ((!strcmp(args[1], "MODE")) || (!strcmp(args[1], "G")))
+ {
+ if(numargs > 0) {
+ setChanMode(args, numargs);
+ } else {
+ logDump(chanlog, "Recieved MODE %s with %i arguments!\n", args, numargs);
+ }
+ return;
+ }
+
+ /* TOPIC Change */
+
+ else if ((!strcmp(args[1], "TOPIC")) || (!strcmp(args[1], ")")))
+ {
+ setChanTopic(args, numargs);
+ return;
+ }
+
+ /* USER SETS AWAY MODE */
+
+ else if ((!strcmp(args[1], "AWAY")) || (!strcmp(args[1], "6")))
+ {
+ if (numargs < 3)
+ setFlags(args[0], NISAWAY, '-');
+ else
+ setFlags(args[0], NISAWAY, '+');
+ return;
+ }
+
+ else if ((!strcmp(args[1], "SJOIN")) || (!strcmp(args[1], "|")))
+ {
+ int c, d;
+ char buffer[600];
+ char modes[200];
+
+ bzero(buffer, 600);
+ bzero(modes, 200);
+ /* locate where nicklist starts and put it in one string */
+ for (d = 3; d < 8; d++) if (args[d][0] == ':') break;
+ for (c = d; c < numargs; c++)
+ {
+ strcat(buffer, args[c]);
+ strcat(buffer, " ");
+ }
+
+ /* extract channelmodes out of SJOIN and convert it to
+ * an every day MODE command and inject it back into
+ * our parser. -GZ
+ */
+
+ if (strcasecmp(args[5], "<none>"))
+ {
+ sprintf(modes, ":%s MODE %s ", args[0], args[3]);
+ for (c = 4; c < d; c++)
+ {
+ strcat(modes, args[c]);
+ strcat(modes, " ");
+ }
+ parseLine(modes);
+ }
+
+ /* Parse the rest of the SJOIN */
+
+ ParseSJOIN(args[3], buffer);
+ return;
+ }
+
+ /* JOINS CHANNEL -- Add user to chanlist */
+
+ else if ((!strcmp(args[1], "JOIN")) || (!strcmp(args[1], "C")))
+ {
+ tmp = getNickData(args[0]);
+
+ if (!tmp) return;
+
+ addUserToChan(tmp, args[2]);
+ return;
+ }
+
+ /* USER PARTS CHANNEL -- Clean off channel list */
+
+ else if ((!strcmp(args[1], "PART")) || (!strcmp(args[1], "D")))
+ {
+ remUserFromChan(getNickData(args[0]), args[2]);
+ return;
+ }
+
+ /* USER KICKED FROM CHANNEL -- CLEAN UP */
+
+ else if ((!strcmp(args[1], "KICK")) || (!strcmp(args[1], "H")))
+ {
+ if (numargs > 3) doKick(getNickData(args[0]), getNickData(args[3]), args[2]);
+ return;
+ }
+
+ /* looks at kills, and DONT KILL SERVICES! }:> */
+
+ else if ((!strcmp(args[1], "KILL")) || (!strcmp(args[1], ".")))
+ {
+ int ncheck;
+
+ for (ncheck = 0; ncheck < 5; ncheck++)
+ {
+ if (!strcasecmp(args[2], services[ncheck].name))
+ {
+ addUser(services[ncheck].name, services[ncheck].uname,
+ services[ncheck].host, services[ncheck].rname,
+ services[ncheck].mode);
+ killUser(services[ncheck], getNickData(args[0]),
+ "Killing services is bad form!");
+ sSend(":%s GLOBOPS :%s attempted to kill services",
+ services[ncheck].name, args[0]);
+ return;
+ }
+ }
+
+ if (CheckJinx(args[2]))
+ {
+ DeleteJinx(args[2]);
+ sSend(":%s GLOBOPS :%s left IRC. JINX has been removed",
+ OperServ, args[2]);
+ }
+
+ if (isGhost(args[2]))
+ {
+ delGhost(args[2]);
+ return;
+ }
+ else
+ {
+ remUser(args[2]); /* nickserv.c, remove user from /killism */
+ }
+ return;
+ }
+
+ else if ((!strcmp(args[1], "MOTD")) || (!strcmp(args[1], "F")))
+ {
+ tmp = getNickData(args[0]);
+ showMotd(args[0]);
+ return;
+ }
+
+ else if ((!strcmp(args[1], "VERSION")) || (!strcmp(args[1], "+")))
+ {
+ tmp = getNickData(args[0]);
+ sSend(":%s 351 %s services-%s %s :H", myname, args[0], VERSION, myname);
+ return;
+ }
+
+ /* SQUIT SOMETHING -- A JUPE? */
+
+ else if ((!strcmp(args[1], "SQUIT")) || (!strcmp(args[1], "-")))
+ {
+ time_t jupe;
+ if (!index(args[0], '.')) /* IF NO "." IT'S A NICK -- LOG IT */
+ {
+ jupe = time(NULL);
+
+ DeleteJupe(args[2]);
+
+ sSend(":%s GLOBOPS :%s Un-jupitered by %s", myname, args[2], args[0]);
+ logDump(operlog, "%s Un-jupitered by %s", args[2], args[0]);
+ }
+ return;
+ }
+ }
+ /* WELP, IF WE GOT HERE, IT'S NOT THAT IMPORTANT */
+}
--- /dev/null
+/*
+ * various functions that do useful crap.
+ */
+
+#include "services.h"
+
+/*
+ * this will assign an integer # of arguments and place them each in a
+ * * sequential order in a character array of any number of args.
+ */
+
+/*
+ * ===DOC===
+ * This function returns data much like an argc/argv setup.
+ * send it an integer, the string of data you want broken up, an array for
+ * storage, and a delimiter character to seperate sets of data by.
+ * Ex: I call fixUpData like this:
+ * int blah;
+ * char *holdme[];
+ * ...
+ * breakString(blah, "WD is a good programmer", holdme[], ' ');
+ * now:
+ * blah == 5
+ * holdme[0] == "WD", holdme[2] == "a", holdme[4] == "programmer", etc.
+ * (All strings end in \0)
+ * the idea for this was given to me by JoelKatz (David Schwartz) of DALnet
+ *
+ */
+
+#define MAXVIRTSIZE (3 + 5 + 1)
+
+int checkDelim(char, char *);
+
+int checkDelim(char it, char *delims)
+{
+ while (*delims) {
+ if (it == *delims)
+ return 1;
+ else
+ delims++;
+ }
+ return 0;
+}
+
+
+int breakString(int maxargs, char *string, char **args, char *delimiter)
+{
+ int x, a;
+
+ x = a = 0;
+
+ while ((*string) && (x < maxargs)) {
+ while (*string && !checkDelim(*string, delimiter)) {
+ args[x][a] = *string;
+ a++;
+ string++;
+ }
+ args[x][a] = 0;
+ x++;
+ while (*string && checkDelim(*string, delimiter))
+ string++;
+ a = 0;
+ }
+ return x;
+}
+
+
+/*
+ * ===DOC===
+ * * Simple, really.
+ * * int i;
+ * * ...
+ * * i=match("IamAfooAren'ti", "*foo*")
+ * * ...
+ * * i==0.
+ * * i=match("IamAfooAren'ti", "*bar*")
+ * * ..
+ * * i==1;
+ */
+
+/*
+ * Note, thanx to RogerY and Redtrio for this wonderful code. Please
+ * keep this notice intact. -- TazQ
+ */
+
+/*
+ * My wildcard matching functions. I think it works well :) Seems to be
+ * working stablely, but not too sure.
+ */
+int match(char *str, char *wld)
+{
+ int i = check_match(wld);
+ switch (i) {
+ case 0:
+ return strcasecmp(str, wld);
+ break;
+ case 1:
+ return 0;
+ break;
+ }
+
+ if (!(*wld) || !(*str))
+ return 1;
+ while (*wld || *str) {
+ if (tolower(*wld) == tolower(*str)) {
+ wld++;
+ str++;
+ } else if (tolower(*wld) != tolower(*str) && *wld == '*') {
+ int i = 0;
+ char *st;
+ st = (char *) smalloc(strlen(wld) + 1);
+ while (*wld == '*' && *wld) {
+ wld++;
+ if (!*wld) {
+ sfree(st);
+ return 0;
+ }
+ }
+ while (*wld && *wld != '*' && *wld != '?') {
+ st[i] = *wld;
+ i++;
+ wld++;
+ }
+ st[i] = '\0';
+ while (*str && strncasecmp(st, str, strlen(st)))
+ str++;
+ if (!strncasecmp(st, str, strlen(st)))
+ str += strlen(st);
+ else {
+ sfree(st);
+ return 1;
+ }
+ sfree(st);
+ } else if (tolower(*wld) != tolower(*str) && *wld == '?' && *wld
+ && *str) {
+ wld++;
+ str++;
+ } else if (tolower(*wld) != tolower(*str))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * experimental matching code (WD) I hope this runs faster, who knows...
+ */
+int check_match(char *mask)
+{
+ if (!index(mask, '*') && !index(mask, '?'))
+ return 0;
+ else if (!strcmp(mask, "*"))
+ return 1;
+ else
+ return 2;
+}
+
+int exp_match(char *string, char *mask)
+{
+ int i = check_match(mask);
+ if (!i)
+ return strcasecmp(string, mask);
+ else if (i == 1 && *string)
+ return 0;
+ else {
+ char *str = string;
+ char *wld = mask;
+
+ while (*str || *wld) {
+ if (*wld == '*') {
+ wld++;
+ if (*wld) {
+ str = index(str, *wld);
+ if (!*str && *wld)
+ return 1;
+ } else
+ return 0;
+ } else if (*wld == '?') {
+ str++;
+ wld++;
+ } else if (*str == *wld) {
+ str++;
+ wld++;
+ } else if (!*str && !*wld)
+ return 0;
+ else
+ return 1;
+ }
+ return 1;
+ }
+}
+
+#define mklower(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : c)
+
+void strtolower(char *str)
+{
+ char tmp;
+ int i;
+
+ for (i = 0; str[i]; i++) {
+ tmp = mklower(str[i]);
+ str[i] = tmp;
+ }
+}
+
+char *sfgets(char *str, int len, FILE * fp)
+{
+ if (!fgets(str, len, fp))
+ return NULL;
+ else {
+ if (str[0])
+ str[strlen(str) - 1] = 0;
+ return str;
+ }
+}
+
+int killMassClones(char *usermask, char *hostmask)
+{
+ UserList *tmp;
+ char clonestr[15];
+ int i = 0;
+
+ for (tmp = firstUser; tmp; tmp = tmp->next) {
+ if (!match(tmp->host, hostmask) && !match(tmp->user, usermask)) {
+ i++;
+ sprintf(clonestr, "\ 2clone\ 2 (%d)", i);
+ killUser(services[0], tmp, clonestr);
+ }
+ }
+ return i;
+}
+
+HostClone *firstClone = NULL;
+HostClone *lastClone = NULL;
+
+void initCloneData(HostClone * hc)
+{
+ hc->host[0] = 0;
+ hc->firstUser = hc->lastUser = NULL;
+ hc->trigger = DEFHOSTCLONETRIGGER;
+ hc->clones = 0;
+ hc->flags = DEFCLONEFLAGS;
+ hc->next = hc->previous = hc->hashnext = hc->hashprev = NULL;
+}
+
+int addClone(char *nick, char *user, char *host)
+{
+ HostClone *hc;
+ HostCloneList *clonelist;
+ long hashEnt;
+ int i, killcnt;
+ char tempstr[USERLEN + HOSTLEN + 4];
+
+ hc = getCloneData(host);
+ if (!hc) {
+ hc = smalloc(sizeof(HostClone));
+ initCloneData(hc);
+ strcpy(hc->host, host);
+ hc->clones = 1;
+ if (!firstClone) {
+ firstClone = hc;
+ hc->previous = NULL;
+ } else {
+ lastClone->next = hc;
+ hc->previous = lastClone;
+ }
+ lastClone = hc;
+ hc->next = NULL;
+
+ hashEnt = getHashKey(host) % CLONEHASHSIZE;
+ if (!CloneHash[hashEnt].clone) {
+ CloneHash[hashEnt].clone = hc;
+ hc->hashprev = NULL;
+ } else {
+ CloneHash[hashEnt].lastclone->hashnext = hc;
+ hc->hashprev = CloneHash[hashEnt].lastclone;
+ }
+ CloneHash[hashEnt].lastclone = hc;
+ hc->hashnext = NULL;
+
+ for (clonelist = firstPermClone; clonelist;
+ clonelist = clonelist->next) {
+ if (!strcasecmp(host, clonelist->host)) {
+ hc->flags = CLONE_PERMIGNORE;
+ break;
+ }
+ }
+
+ } else
+ hc->clones++;
+
+ i = addUserClone(hc, user);
+
+ if (hc->flags & CLONE_IGNOREFLAG || hc->flags & CLONE_PERMIGNORE)
+ return 0;
+
+ if (i) {
+ sSend(":%s GLOBOPS :%i possible clones from %s@%s", OperServ, i,
+ user, host);
+ return 0;
+ }
+
+ if (hc->flags & CLONE_PERMIGNORE)
+ return 0;
+
+ if (hc->clones >= hc->trigger) {
+ sSend(":%s GLOBOPS :%i possible clones from *@%s", OperServ,
+ hc->clones, host);
+ if (hc->clones >= hc->trigger) {
+ if (hc->flags & CLONE_KILLFLAG) {
+ sSend(":%s KILL %s :%s!%s (No Clones Allowed.)", NickServ,
+ nick, services[1].host, NickServ);
+ return 1;
+ } else if (hc->clones > DEFHOSTILEHOSTCLONES) {
+ killcnt = killMassClones("*", host);
+ sSend(":%s GLOBOPS :%s masskilled *@%s (%i matches)",
+ OperServ, OperServ, host, killcnt);
+ logDump(operlog,
+ "%s masskilled *@%s [AUTO-TRIGGER] (%i matches)",
+ OperServ, host, killcnt);
+ strcpy(tempstr, "*!*@");
+ strcat(tempstr, host);
+ add_access_mod((3 * 3600), tempstr, OperServ, A_AKILL,
+ "Excessive Cloning Not Permitted.");
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int addUserClone(HostClone * hc, char *user)
+{
+ UserClone *uc = getUserCloneData(hc, user);
+
+ if (!uc) {
+ uc = smalloc(sizeof(UserClone));
+ uc->user[0] = 0;
+ uc->clones = 1;
+ uc->trigger = DEFUSERCLONETRIGGER;
+
+ strcpy(uc->user, user);
+
+ if (!hc->firstUser) {
+ hc->firstUser = uc;
+ uc->previous = NULL;
+ } else {
+ hc->lastUser->next = uc;
+ uc->previous = hc->lastUser;
+ }
+ hc->lastUser = uc;
+ uc->next = NULL;
+ } else
+ uc->clones++;
+
+ return (((uc->clones >= (uc->trigger)) ? uc->clones : 0));
+}
+
+void delClone(char *user, char *host)
+{
+ HostClone *hc = getCloneData(host);
+ if (hc) {
+ UserClone *uc = getUserCloneData(hc, user);
+ if (uc) {
+ hc->clones--;
+ uc->clones--;
+ if (!uc->clones)
+ delUserClone(hc, uc);
+ if (!hc->clones) {
+ long hashEnt;
+ HostClone *tmp;
+ if (hc->previous)
+ hc->previous->next = hc->next;
+ else
+ firstClone = hc->next;
+ if (hc->next)
+ hc->next->previous = hc->previous;
+ else
+ lastClone = hc->previous;
+ hashEnt = getHashKey(hc->host) % CLONEHASHSIZE;
+ for (tmp = CloneHash[hashEnt].clone; tmp;
+ tmp = tmp->hashnext) {
+ if (tmp == hc) {
+ if (hc->hashprev)
+ hc->hashprev->hashnext = hc->hashnext;
+ else
+ CloneHash[hashEnt].clone = hc->hashnext;
+ if (hc->hashnext)
+ hc->hashnext->hashprev = hc->hashprev;
+ else
+ CloneHash[hashEnt].lastclone = hc->hashprev;
+ }
+ }
+ sfree(hc);
+ }
+ }
+ }
+}
+
+void delUserClone(HostClone * hc, UserClone * uc)
+{
+ if (uc->previous)
+ uc->previous->next = uc->next;
+ else
+ hc->firstUser = uc->next;
+ if (uc->next)
+ uc->next->previous = uc->previous;
+ else
+ hc->lastUser = uc->previous;
+
+ free(uc);
+}
+
+HostClone *getCloneData(char *host)
+{
+ long hashEnt;
+ hashEnt = getHashKey(host) % CLONEHASHSIZE;
+ if (!CloneHash[hashEnt].clone)
+ return NULL;
+ else {
+ HostClone *tmp;
+ for (tmp = CloneHash[hashEnt].clone; tmp; tmp = tmp->hashnext) {
+ if (!strcasecmp(host, tmp->host))
+ return tmp;
+ }
+ return NULL;
+ }
+}
+
+UserClone *getUserCloneData(HostClone * hc, char *user)
+{
+ UserClone *tmp;
+
+ for (tmp = hc->firstUser; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->user, user))
+ return tmp;
+ }
+ return NULL;
+}
+
+char *Maskchecksum(char *data, char *salt)
+{
+ char static tmp[HOSTLEN + 1] ;
+
+ strncpy(tmp,crypt(data, salt),HOSTLEN) ;
+ return (tmp) ;
+}
+
+int str2array(char **pparv, char *string, char *delim)
+{
+ char *tok;
+ int pparc = 0;
+
+ tok = (char *) strtok(string, delim);
+ while (tok != NULL) {
+ pparv[pparc++] = tok;
+ tok = (char *) strtok(NULL, delim);
+ }
+ return pparc;
+}
+
+char *return_user_mask(char *s)
+{
+ static char mask[HOSTLEN + 1];
+ char *csum;
+ char *dot, *ptr ;
+ static char destroy[HOSTLEN + 1], *parv[HOSTLEN + 1];
+ char salt[12] = "$1$\0\0\0\0\0\0\0\0\0";
+ int len = 0, overflow = 0, parc = 0;
+
+ strncpy(destroy, s, HOSTLEN);
+ len = strlen(destroy);
+
+ if ((len + MAXVIRTSIZE) > HOSTLEN) {
+ overflow = (len + MAXVIRTSIZE) - HOSTLEN;
+ ptr = &destroy[overflow];
+ } else {
+ ptr = &destroy[0];
+ }
+ memset(mask, 0, HOSTLEN);
+
+ parc = str2array(parv, ptr, ".");
+
+ if (strlen(s) > HOSTLEN) {
+ s[HOSTLEN] = 0;
+ }
+
+ if (parc == 4) {
+ len = strlen(parv[3]);
+ if (isdigit(parv[3][len - 1])) {
+ /* Numeric IP, lets use the last octets of the IP address
+ * as salt */
+ strcat(salt, parv[3]);
+ strcat(salt, parv[2]);
+ csum = Maskchecksum(s, salt);
+ sprintf(mask, "%s.%s.%s.%i", parv[0], parv[1],parv[2],csum[15]+256+csum[19]);
+ return mask;
+ }
+ }
+
+ /* Hostname.... lets use it as our salt... */
+ strncat(salt, s, 8);
+ csum = Maskchecksum(s, salt);
+
+ dot = (char *) strchr(s, '.');
+
+ if (dot == NULL) {
+ sprintf(mask, "Serene%i%i%i%i%i%i.%s",csum[14]%10,csum[15]%10,csum[16]%10,csum[17]%10,csum[18]%10,csum[19]%10, s);
+ return mask;
+ } else {
+ sprintf(mask, "Serene%i%i%i%i%i%i.%s",csum[14]%10,csum[15]%10,csum[16]%10,csum[17]%10,csum[18]%10,csum[19]%10, dot + 1);
+ return mask;
+ }
+}
+
+char *maskuser(UserList * tmp)
+{
+ static char newmask[128];
+
+ if (tmp->reg && tmp->reg->flags & NNETADM)
+ strcpy(newmask, "NetAdmin.Serenity-IRC.Net");
+ else if (tmp->reg && tmp->reg->flags & NROOT)
+ strcpy(newmask, "SRA.Serenity-IRC.Net");
+ else if (tmp->reg && tmp->reg->flags & NSERVOP)
+ strcpy(newmask, "ServOp.Serenity-IRC.Net");
+ else if (tmp->oflags & NISADMIN)
+ strcpy(newmask, "Admin.Serenity-IRC.Net");
+ else if (tmp->oflags & NISOPER)
+ strcpy(newmask, "IRCop.Serenity-IRC.Net");
+ else if (tmp->oflags & NISPLUSX)
+ strcpy(newmask, return_user_mask(tmp->host));
+ else
+ strcpy(newmask, tmp->host);
+
+ return newmask;
+}
+
+char *maskreguser(RegNickList * tmp)
+{
+ static char newmask[128];
+
+ if (tmp->flags & NNETADM) strcpy(newmask, "NetAdmin.Serenity-IRC.Net");
+ else if (tmp->flags & NROOT) strcpy(newmask, "SRA.Serenity-IRC.Net");
+ else if (tmp->flags & NSERVOP) strcpy(newmask, "Servop.Serenity-IRC.Net");
+ else if (tmp->flags2 & NSTICKYOP) strcpy(newmask, "IRCop.Serenity-IRC.Net");
+ else if (tmp->flags & NHIDE) strcpy(newmask, return_user_mask(tmp->host));
+/* {
+ strcpy(vol_mask, tmp->host);
+
+ parc = str2array(tempmask, vol_mask, ".");
+
+ masksum = maskchecksum(tmp->host);
+
+ if (parc == 4)
+ {
+ len = strlen(tempmask[3]);
+ if (strchr("0123456789", tempmask[3][len - 1]))
+ {
+ sprintf(newmask, "%s.%s.%s.%i", tempmask[0], tempmask[1],
+ tempmask[2], masksum[9] + 256 + masksum[10]);
+ return newmask;
+ }
+ }
+
+ firstdot = strchr(tmp->host, '.');
+
+ if (firstdot == NULL)
+ sprintf(newmask, "Serene%i%i.%s", masksum[7], masksum[8], tmp->host);
+ else
+ sprintf(newmask, "Serene%i%i.%s", masksum[7], masksum[8], firstdot + 1);
+ }*/
+ else strcpy(newmask, tmp->host);
+
+ return newmask;
+}
+
+void loadpermignores()
+{
+ FILE *ignore_file;
+ HostCloneList *permclone;
+ char buffer[256];
+ int count = 0;
+
+ firstPermClone = NULL;
+
+ ignore_file = fopen(DBDIR "/permignore.db", "r");
+
+ if (!ignore_file) {
+ return;
+ }
+
+ while (sfgets(buffer, 256, ignore_file)) {
+
+ if (strcmp(buffer, "-") != 0) {
+ sSend(":%s GLOBOPS :Sync error in permignore.db", OperServ);
+ fprintf(corelog, "Sync error in permignore.db");
+ fclose(ignore_file);
+ return;
+ }
+
+ permclone = smalloc(sizeof(struct hostcloneliststruct));
+
+ fscanf(ignore_file, "%s\n", permclone->host);
+ fscanf(ignore_file, "%s\n", permclone->setby);
+ fscanf(ignore_file, "%lu\n", (long *) &(permclone->setwhen));
+ count++;
+
+ permclone->next = firstPermClone;
+ permclone->prev = NULL;
+ if (permclone->next)
+ permclone->next->prev = permclone;
+ firstPermClone = permclone;
+ }
+ fclose(ignore_file);
+}
+
+void savepermignores()
+{
+ FILE *ignore_file;
+ HostCloneList *permclone;
+
+ ignore_file = fopen(DBDIR "/permignore.db", "w");
+ if (ignore_file == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open ./permignore.db"));
+ return;
+ }
+
+ for (permclone = firstPermClone; permclone;
+ permclone = permclone->next) {
+ fprintf(ignore_file, "-\n");
+ fprintf(ignore_file, "%s\n", permclone->host);
+ fprintf(ignore_file, "%s\n", permclone->setby);
+ fprintf(ignore_file, "%lu\n", (unsigned long) permclone->setwhen);
+ }
+ fclose(ignore_file);
+}
+
+/* This will add a server to the internal list of servers. */
+
+void AddServer(char *name, char *version)
+{
+
+ aServer *Serverptr;
+
+ Serverptr = make_server();
+ strncpy(Serverptr->name, name, sizeof(Serverptr->name));
+ strncpy(Serverptr->version, version, sizeof(Serverptr->version));
+
+ if (ServerList == NULL)
+ ServerList = Serverptr;
+ else {
+ ServerList->prev = Serverptr;
+ Serverptr->next = ServerList;
+ ServerList = Serverptr;
+ }
+
+ return;
+}
+
+/* This function will make an empty server structure */
+
+aServer *make_server()
+{
+ aServer *Serverptr;
+
+ Serverptr = (aServer *) smalloc(sizeof(aServer));
+
+ Serverptr->name[0] = '\0';
+ Serverptr->version[0] = '\0';
+ Serverptr->svsnoop = 0;
+ Serverptr->prev = Serverptr->next = NULL;
+
+ return Serverptr;
+}
+
+void free_server(srvptr)
+aServer *srvptr;
+{
+ free((char *) srvptr);
+}
+
+void DeleteServer(char *name)
+{
+
+ aServer *srvptr;
+ aServer *srvptr2;
+
+ if (ServerList == NULL)
+ return;
+
+ for (srvptr = ServerList; srvptr; srvptr = srvptr2) {
+ srvptr2 = srvptr->next;
+ if (!strcmp(srvptr->name, name)) {
+ if (srvptr->prev)
+ srvptr->prev->next = srvptr->next;
+ else
+ ServerList = srvptr->next;
+ if (srvptr->next)
+ srvptr->next->prev = srvptr->prev;
+ free_server(srvptr);
+ return;
+ }
+ }
+
+ return;
+}
+
+int CheckServer(char *name)
+{
+
+ aServer *srvptr;
+ aServer *srvptr2;
+
+ if (ServerList == NULL)
+ return 0;
+
+ for (srvptr = ServerList; srvptr; srvptr = srvptr2) {
+ srvptr2 = srvptr->next;
+ if (!strcasecmp(srvptr->name, name)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void AddJupe(char *server, char *juper, time_t date, char *reason, int now)
+{
+ aJupe *jupeptr;
+
+ jupeptr = make_jupe();
+
+ strncpy(jupeptr->server, server, sizeof(jupeptr->server));
+ strncpy(jupeptr->juper, juper, sizeof(jupeptr->juper));
+ jupeptr->date = date;
+ strncpy(jupeptr->reason, reason, sizeof(jupeptr->reason));
+
+ if (JupeList == NULL)
+ JupeList = jupeptr;
+ else {
+ JupeList->prev = jupeptr;
+ jupeptr->next = JupeList;
+ JupeList = jupeptr;
+ }
+
+ if (now == 1) {
+ jupeptr->synced = 1;
+ if (CheckServer(jupeptr->server))
+ {
+ sSend(":OperServ SQUIT %s :Enforcing Jupe set by %s on %s", jupeptr->server, jupeptr->juper, ctime(&(jupeptr->date)));
+ DeleteServer(jupeptr->server);
+ }
+
+ sSend("SERVER %s 2 JupiteredServer :Jupitered by %s %s", jupeptr->server, jupeptr->juper, ctime(&jupeptr->date));
+ } else
+ jupeptr->synced = 0;
+}
+
+void sync_jupes(char *doot)
+{
+ aJupe *jupeptr;
+ aJupe *jupeptr2;
+
+ for (jupeptr = JupeList; jupeptr; jupeptr = jupeptr2) {
+ jupeptr2 = jupeptr->next;
+
+ if (jupeptr->synced != 1) {
+ if (CheckServer(jupeptr->server))
+ {
+ sSend(":OperServ SQUIT %s :Enforcing Jupe set by %s on %s", jupeptr->server, jupeptr->juper, ctime(&(jupeptr->date)));
+ DeleteServer(jupeptr->server);
+ }
+
+ sSend("SERVER %s 2 JupiteredServer :Jupitered by %s %s", jupeptr->server, jupeptr->juper, ctime(&jupeptr->date));
+ jupeptr->synced = 1;
+ }
+ }
+
+ return;
+}
+
+aJupe *make_jupe()
+{
+ aJupe *jupeptr;
+
+ jupeptr = (aJupe *) smalloc(sizeof(aJupe));
+
+ jupeptr->server[0] = '\0';
+ jupeptr->juper[0] = '\0';
+ jupeptr->date = 0;
+ jupeptr->reason[0] = '\0';
+
+ jupeptr->prev = jupeptr->next = NULL;
+
+ return jupeptr;
+}
+
+void free_jupe(aJupe *jupeptr)
+{
+ free((char *) jupeptr);
+}
+
+void DeleteJupe(char *server)
+{
+ aJupe *jupeptr;
+ aJupe *jupeptr2;
+
+ if (JupeList == NULL)
+ return;
+ for (jupeptr = JupeList; jupeptr; jupeptr = jupeptr2) {
+ jupeptr2 = jupeptr->next;
+ if (strcmp(jupeptr->server, server) == 0) {
+ if (jupeptr->prev)
+ jupeptr->prev->next = jupeptr->next;
+ else
+ JupeList = jupeptr->next;
+ if (jupeptr->next)
+ jupeptr->next->prev = jupeptr->prev;
+ free_jupe(jupeptr);
+ return;
+ }
+ }
+
+ return;
+}
+
+int CheckJupe(char *server)
+{
+ aJupe *jupeptr;
+ aJupe *jupeptr2;
+
+ if (JupeList == NULL)
+ return 0;
+
+ for (jupeptr = JupeList; jupeptr; jupeptr = jupeptr2) {
+ jupeptr2 = jupeptr->next;
+ if (!strcasecmp(jupeptr->server, server)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/* This will add an email address to the internal list of banned email addresses. */
+
+void AddEmail(char *email, char *by, char *reason)
+{
+
+ anEmail *Emailptr;
+
+ Emailptr = make_email();
+ strncpy(Emailptr->email, email, sizeof(Emailptr->email));
+ strncpy(Emailptr->by, by, sizeof(Emailptr->by));
+ Emailptr->time = CTime;
+ strncpy(Emailptr->reason, reason, sizeof(Emailptr->reason));
+
+ if (EmailList == NULL)
+ EmailList = Emailptr;
+ else {
+ EmailList->prev = Emailptr;
+ Emailptr->next = EmailList;
+ EmailList = Emailptr;
+ }
+
+ return;
+}
+
+/* This function will make an empty email structure */
+
+anEmail *make_email()
+{
+ anEmail *Emailptr;
+
+ Emailptr = (anEmail *) smalloc(sizeof(anEmail));
+
+ Emailptr->email[0] = '\0';
+ Emailptr->by[0] = '\0';
+ Emailptr->time = 0;
+ Emailptr->reason[0] = '\0';
+ Emailptr->prev = Emailptr->next = NULL;
+
+ return Emailptr;
+}
+
+void free_email(emailptr)
+anEmail *emailptr;
+{
+ free((char *) emailptr);
+}
+
+void DeleteEmail(char *email)
+{
+
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ if (EmailList == NULL)
+ return;
+
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+ if (!strcmp(emailptr->email, email)) {
+ if (emailptr->prev)
+ emailptr->prev->next = emailptr->next;
+ else
+ EmailList = emailptr->next;
+ if (emailptr->next)
+ emailptr->next->prev = emailptr->prev;
+ free_email(emailptr);
+ return;
+ }
+ }
+
+ return;
+}
+
+int CheckEmail(char *email)
+{
+
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ if (EmailList == NULL)
+ return 0;
+
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+ if (!match(emailptr->email, email)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int VerifyEmail(char *email)
+{
+
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ if (EmailList == NULL)
+ return 0;
+
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+ if (!match(email, emailptr->email)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void savedynamicekills()
+{
+ FILE *dekill_file;
+ anEmail *emailptr;
+ anEmail *emailptr2;
+
+ if (EmailList == NULL)
+ return;
+
+ dekill_file = fopen(DBDIR "/dekill.db", "w");
+
+ if (dekill_file == NULL) {
+ Debug((DEBUG_ERROR, "Failed to open ./dekill.db"));
+ return;
+ }
+
+ for (emailptr = EmailList; emailptr; emailptr = emailptr2) {
+ emailptr2 = emailptr->next;
+ fprintf(dekill_file, "-\n");
+ fprintf(dekill_file, "%s\n", emailptr->email);
+ fprintf(dekill_file, "%s\n", emailptr->by);
+ fprintf(dekill_file, "%s\n", emailptr->reason);
+ fprintf(dekill_file, "%lu\n", (unsigned long) emailptr->time);
+ }
+
+ fclose(dekill_file);
+ return;
+}
+
+void loaddynamicekills()
+{
+ FILE *dekill_file;
+ char buffer[256];
+ int count = 0;
+
+ anEmail *emailptr;
+
+ EmailList = NULL;
+
+ dekill_file = fopen(DBDIR "/dekill.db", "r");
+
+ if (!dekill_file) {
+ return;
+ }
+
+ while (sfgets(buffer, 256, dekill_file)) {
+
+ if (strcmp(buffer, "-") != 0) {
+ sSend(":%s GLOBOPS :Sync error in dekill.db", OperServ);
+ fprintf(corelog, "Sync error in dekill.db");
+ fclose(dekill_file);
+ return;
+ }
+
+ emailptr = make_email();
+
+ fscanf(dekill_file, "%s\n", emailptr->email);
+ fscanf(dekill_file, "%s\n", emailptr->by);
+ fscanf(dekill_file, "%s\n", emailptr->reason);
+ fscanf(dekill_file, "%lu\n", (long *) &(emailptr->time));
+
+ if (EmailList == NULL)
+ EmailList = emailptr;
+ else {
+ EmailList->prev = emailptr;
+ emailptr->next = EmailList;
+ EmailList = emailptr;
+ }
+ count++;
+ }
+
+ fclose(dekill_file);
+
+ return;
+}
+
+aServer *GetServer(char *server)
+{
+
+ aServer *srvptr;
+ aServer *srvptr2;
+
+ if (ServerList == NULL)
+ return NULL;
+ for (srvptr = ServerList; srvptr; srvptr = srvptr2) {
+ srvptr2 = srvptr->next;
+ if (!match(srvptr->name, server))
+ return srvptr;
+ }
+
+ return NULL;
+}
+
+#ifdef ANALYSE_FUNCTIONS
+void AnalyseFunction(char *function)
+{
+ GetClock();
+ return;
+}
+#endif
--- /dev/null
+#include "services.h"
+
+typedef struct timer_struct Timer;
+
+struct timer_struct {
+ time_t run;
+ unsigned int id;
+ void (*func) (char *);
+ char *desc;
+ char *args;
+ Timer *next, *prev;
+};
+
+unsigned int timers = 0;
+unsigned int timersused = 0;
+
+time_t lastcheck;
+
+void delTimer(Timer *);
+
+Timer *firstTimer = NULL, *lastTimer = NULL;
+
+unsigned int timer(long seconds, void (*func) (char *), char *desc, char *args)
+{
+ Timer *newtimer;
+
+ int goodvalue = 0;
+
+ CTime = time(NULL);
+
+ if (seconds <= 0) {
+ func(args);
+ return 0;
+ }
+
+ timersused++;
+ timers++;
+
+ if (!timers) /* WHOOPS -- WE ROLLED OVER */
+ timers++;
+
+ while (!goodvalue) {
+ goodvalue = 1;
+ for (newtimer = firstTimer; newtimer; newtimer = newtimer->next) {
+ if (newtimer->id == timers) {
+ goodvalue = 0;
+ break;
+ }
+ }
+ if (!goodvalue) {
+ timers++;
+ if (!timers) /* STILL ROLLING OVER */
+ timers++;
+ }
+ }
+
+ newtimer = smalloc(sizeof(Timer));
+ newtimer->id = timers;
+ newtimer->func = func;
+ newtimer->desc = desc;
+ newtimer->args = smalloc(strlen(args) + 1);
+ strcpy(newtimer->args, args);
+ newtimer->run = CTime + seconds;
+
+ if (!firstTimer) {
+ firstTimer = newtimer;
+ newtimer->prev = NULL;
+ } else {
+ lastTimer->next = newtimer;
+ newtimer->prev = lastTimer;
+ }
+ lastTimer = newtimer;
+ newtimer->next = NULL;
+
+ return timers;
+}
+
+void checktimers(void)
+{
+
+ Timer *tmp, *next;
+ CTime = time(NULL);
+
+ if (lastcheck == CTime)
+ return;
+
+ for (tmp = firstTimer; tmp; tmp = next) {
+ next = tmp->next;
+ if (tmp->run <= CTime) {
+ sprintf(timerbuff, "%s(%s)", tmp->desc, tmp->args);
+ timertime = CTime;
+ tmp->func(tmp->args);
+ delTimer(tmp);
+ }
+ }
+}
+
+void delTimer(Timer * deltimer)
+{
+ timersused--;
+
+ if (deltimer->prev)
+ deltimer->prev->next = deltimer->next;
+ else
+ firstTimer = deltimer->next;
+
+ if (deltimer->next)
+ deltimer->next->prev = deltimer->prev;
+ else
+ lastTimer = deltimer->prev;
+
+ sfree(deltimer->args);
+ sfree(deltimer);
+}
+
+int cancel_timer(unsigned int id)
+{
+ Timer *tmp;
+ for (tmp = firstTimer; tmp; tmp = tmp->next) {
+ if (tmp->id == id) {
+ delTimer(tmp);
+ return 1;
+ }
+ }
+ return 0;
+}
--- /dev/null
+
+#include "services.h"
+
+extern void doRegChanMode(RegChanList *);
+extern void makeModeLockStr(RegChanList *, char *);
+extern int countRegAddy(char *);
+extern char *showchanoplevel(int);
+extern int isFounder(RegChanList *, UserList *);
+extern cAkickList *getChanAkick(RegChanList * chan, char *akick);
+extern void createGhostChannel(char *);
+extern void deleteGhostChannel(char *);
+
+void WNregisterCmd(UserList *, char **, int);
+void WnickCmd(UserList *, char **, int);
+void WbanCmd(UserList *, char **, int);
+void WunbanCmd(UserList *, char **, int);
+void WkickCmd(UserList *, char **, int);
+void WwhoisCmd(UserList *, char **, int);
+void WchanmodeCmd(UserList *, char **, int);
+void WinviteCmd(UserList *, char **, int);
+
+void sendToWebServ(UserList * nick, char **args, int numargs)
+{
+
+ char *from = nick->nick;
+
+ if (!strcmp(args[0], "\001PING")) {
+ if (numargs < 3)
+ uSend(WebServ, nick, GetReply(RPL_PING1, nick), args[1]);
+ else
+ uSend(WebServ, nick, GetReply(RPL_PING2, nick), args[1],
+ args[2]);
+ return;
+ }
+
+ if (!strcasecmp(args[0], "HELP") && numargs == 1) {
+ sendHelp(from, WebServ, NULL, 0);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "HELP")) {
+ sendHelp(from, WebServ, args, numargs);
+ return;
+ }
+
+ if (!nick->webbie) {
+ sSend
+ (":%s PRIVMSG %s :Your nick is not yet registered as a WebTV user. Please register first.",
+ WebServ, from);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "WHOIS")) {
+ WwhoisCmd(nick, args, numargs);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "NICK")) {
+ WnickCmd(nick, args, numargs);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "KICK"))
+ {
+ WkickCmd(nick, args, numargs);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "BAN")) {
+ WbanCmd(nick, args, numargs);
+ return;
+ }
+
+ else if (!strcasecmp(args[0], "UNBAN")) {
+ WunbanCmd(nick, args, numargs);
+ return;
+ }
+
+ else if (!match(args[0], "CHANMODE"))
+ WchanmodeCmd(nick, args, numargs);
+
+ else if (!match(args[0], "INVITE")) {
+ WinviteCmd(nick, args, numargs);
+ }
+ else {
+ sSend (":%s PRIVMSG %s :%s is an unknown command to me. Please use /msg WebServ HELP or /join help for further information. ",WebServ,from,args[0]);
+ return;
+ }
+
+}
+
+BadNickList *firstBadNick = NULL;
+BadNickList *lastBadNick = NULL;
+
+void addBadNick (char *nickmask)
+{
+ BadNickList *newbad;
+
+ if (!nickmask)
+ return;
+
+ newbad = smalloc (sizeof (BadNickList));
+ strncpy (newbad->nickmask, nickmask, NICKLEN + 2);
+
+ if (!firstBadNick) {
+ firstBadNick = newbad;
+ newbad->prev = NULL;
+ } else {
+ newbad->prev = lastBadNick;
+ lastBadNick->next = newbad;
+ }
+
+ newbad->next = NULL;
+ lastBadNick = newbad;
+}
+
+int isBadNick (char *nickmask)
+{
+ BadNickList *tmp;
+
+ for (tmp = firstBadNick; tmp; tmp = tmp->next) {
+ if (!match (nickmask, tmp->nickmask))
+ return 1;
+ }
+
+ return 0;
+}
+
+void WNregisterCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ time_t doot = time(NULL);
+ char sendfrom[80];
+ int err;
+
+ srandom(time(NULL));
+
+ if (tmp->reg) {
+ if (!tmp->reg->flags & NACTIVE) {
+ sSend
+ (":%s PRIVMSG %s :Your nickname is already registered to activate it, \002/msg %s HELP ACTIVATE\002.",
+ WebServ, from, WebServ);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ } else {
+ sSend(":%s PRIVMSG %s :Your nickname is already registered.",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ }
+ return;
+ }
+
+ if ((!strncasecmp(from, "Guest", 5)) || (!strcasecmp(from, "done")) ||
+ (!strncasecmp(from, "SereneMIRC", 10)) || (!strncasecmp(from, "SerenePIRCH", 11))) {
+ sSend
+ (":%s PRIVMSG %s :This nickname cannot be registered. Please choose another.",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ return;
+ }
+
+ if (numargs < 3) {
+ sSend
+ (":%s PRIVMSG %s :You must specify an e-mail address and a password to register",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ return;
+ }
+ if ((!strchr(args[1], '@')) || (strlen(args[1]) < 5)
+ || (strlen(args[1]) > EMAILLEN)) {
+ sSend
+ (":%s PRIVMSG %s :Please specify a valid e-mail address in the form of user@host",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ return;
+ }
+
+ if (match(args[1], "*webtv.net*")) {
+ sSend
+ (":%s PRIVMSG %s :Sorry, this service is for WebTV users only",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ return;
+ }
+
+ if ((15 < strlen(args[2])) || (4 > strlen(args[2]))) {
+ sSend
+ (":%s PRIVMSG %s :Please specify a password that is between 4 to 15 characters long.",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ return;
+ }
+
+ if (countRegAddy(args[1]) >= NickLimit) {
+ sSend(":%s PRIVMSG %s :You have too many nicks registered.",
+ WebServ, from);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ sSend(":%s GLOBOPS :%s (%s) is trying to register too many nicks.", WebServ, from, args[1]);
+ return;
+ }
+
+ tmp->reg = smalloc(sizeof(RegNickList));
+ bzero(tmp->reg, sizeof(RegNickList));
+ strcpy(tmp->reg->nick, tmp->nick);
+ strcpy(tmp->reg->user, tmp->user);
+ strcpy(tmp->reg->host, tmp->host);
+ sprintf(tmp->reg->password2, "%lu", (long) random());
+ tmp->reg->timestamp = CTime;
+ tmp->reg->timereg = CTime;
+ tmp->reg->lastpwchange = CTime;
+ tmp->reg->flags |= NREG;
+ tmp->reg->flags2 |= NMSGMODE;
+ tmp->caccess = 3;
+ strcpy(tmp->reg->email, args[1]);
+ strncpy(tmp->reg->password, args[2], 15);
+ sprintf(sendfrom, "Nickname Services <%s@%s>", WebServ, NETHOST);
+ err = sendMail(args[1], sendfrom, "Nickname activation key",
+ "\nYour nickname registration has been verified\n"
+ "To activate your nickname: switch to the nickname %s and\n"
+ "/msg %s ACTIVATE %s\n"
+ "%s is your activation key. %s is your password.\n"
+ "Even when your nickname is registered, Do not lose this PLEASE.\n\n"
+ "For additional help, try these commands:\n"
+ " /msg %s HELP\n"
+ " /msg %s HELP\n"
+ "\nNOTICE: This mail sent by: %s@%s at %s",
+ tmp->nick, NickServ, tmp->reg->password2,
+ tmp->reg->password2, tmp->reg->password, NickServ, WebServ,
+ tmp->user, tmp->host, ctime(&(doot)));
+ if (!err) {
+ sSend(":%s PRIVMSG %s :Registration key sent to %s", WebServ, from,
+ args[1]);
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ logDump(nicklog, "%s!%s@%s: ACTIVATION key sent to '%s'\n", from,
+ tmp->user, tmp->host, args[1]);
+ addRegNick(tmp->reg);
+ } else {
+ sSend
+ (":%s PRIVMSG %s :Mail could not be sent due to %s address error",
+ WebServ, from, err == -2 ? "sender" : "recipient");
+ sSend(":%s PRIVMSG %s :-", WebServ, from);
+ sfree(tmp->reg);
+ tmp->reg = NULL;
+ }
+ return;
+}
+
+void WwhoisCmd(UserList * tmp, char **args, int numargs)
+{
+
+ char *from = tmp->nick;
+ UserList *err;
+
+ if (numargs < 2) {
+ sSend
+ (":%s PRIVMSG %s :You will need to supply a nickname for this command.",
+ WebServ, from);
+ return;
+ }
+
+ if (!(err = getNickData(args[1]))) {
+ sSend(":%s PRIVMSG %s :%s no such nick.", WebServ, from, args[1]);
+ return;
+ }
+
+ if (isOper(err)) {
+ sSend(":%s PRIVMSG %s :%s is %s!%s@IRCop.Serenity-IRC.Net (%s)",
+ WebServ, from, err->nick, err->nick, err->user,
+ err->realname);
+ return;
+ } else {
+ sSend(":%s PRIVMSG %s :%s is %s!%s@%s (%s)", WebServ, from,
+ err->nick, err->nick, err->user, return_user_mask(err->host),
+ err->realname);
+ return;
+ }
+}
+
+void WkickCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+ cNickList *tmpnick;
+ UserList *victim;
+
+ char reason[1024];
+ int i;
+
+ if (numargs < 3) {
+ sSend(":%s PRIVMSG %s :You must specify a channel and a nickname.",
+ WebServ, from);
+ return;
+ }
+
+
+ reason[0] = '\0';
+
+ if (numargs > 3) {
+ for (i = 3; i < numargs; i++) {
+ strcat(reason, args[i]);
+ strcat(reason, " ");
+ }
+ }
+
+ if (strlen(reason) > 200) {
+ sSend(":%s PRIVMSG %s :Reason too long.", WebServ, from);
+ return;
+ }
+
+ tmp = getRegChanData(args[1]);
+ chan = getChanData(args[1]);
+
+ if (!chan) {
+ sSend(":%s PRIVMSG %s :No such channel.", WebServ, from);
+ return;
+ }
+ if (!tmp) {
+ sSend(":%s PRIVMSG %s :%s is not registered.", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop(nick)) {
+ sSend(":%s PRIVMSG %s :Access denied. This channel is FROZEN.",
+ WebServ, from);
+ return;
+ }
+
+ if (numargs > 2)
+ tmpnick = getChanUserData(chan, getNickData(args[2]));
+ else
+ tmpnick = getChanUserData(chan, nick);
+
+ if (!tmpnick) {
+ sSend(":%s PRIVMSG %s :%s is not in %s", WebServ, from, args[2],
+ args[1]);
+ return;
+ }
+
+ victim = getNickData(args[2]);
+
+ if (victim && isRoot( victim)) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ }
+
+ a = getChanOp(tmp, from);
+
+ if (!a || !getChanOp(tmp, from)) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ }
+
+ if (a < AOP) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ } else {
+ if (numargs < 4) {
+ sSend(":%s KICK %s %s :Kicked by %s", WebServ, args[1],
+ args[2], from);
+ } else {
+ sSend(":%s KICK %s %s :%s", WebServ, args[1], args[2], reason);
+ }
+ return;
+ }
+}
+
+void WbanCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+
+ if (numargs < 3) {
+ sSend(":%s PRIVMSG %s :You must specify a channel and a mask.",
+ WebServ, from);
+ return;
+ }
+
+ tmp = getRegChanData(args[1]);
+ chan = getChanData(args[1]);
+
+ if (!chan) {
+ sSend(":%s PRIVMSG %s :No such channel.", WebServ, from);
+ return;
+ }
+ if (!tmp) {
+ sSend(":%s PRIVMSG %s :%s is not registered.", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop(nick)) {
+ sSend(":%s PRIVMSG %s :Access denied. This channel is FROZEN.",
+ WebServ, from);
+ return;
+ }
+
+ a = getChanOp(tmp, from);
+
+ if (!a || !getChanOp(tmp, from)) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ }
+
+ if (a < AOP) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ } else {
+ sSend(":%s PRIVMSG %s :%s banned %s from %s", WebServ, args[1],
+ from, args[2], args[1]);
+ sSend(":%s MODE %s +b %s", WebServ, args[1], args[2]);
+ return;
+ }
+}
+
+void WnickCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ UserList *err;
+ int find = 0;
+ char *s = NULL;
+
+ if (numargs < 2) {
+ sSend(":%s PRIVMSG %s :You must specify a nickname.", WebServ,
+ from);
+ return;
+ }
+
+ if ((err = getNickData(args[1]))) {
+ sSend(":%s PRIVMSG %s :The nickname %s is already in use.",
+ WebServ, from, args[1]);
+ return;
+ }
+
+ /* Here's a new additional check to scan for non-allowed ASCII chars */
+
+ s = args[1];
+
+ while (*s) {
+ if ((*s!=45 && *s < 48) || *s > 125) {
+ find = 1;
+ break;
+ } else if (*s > 57 && *s < 65) {
+ find = 1;
+ break;
+ }
+ s++;
+ }
+
+ if (find) {
+ sSend
+ (":%s PRIVMSG %s :Illegal characters, please try another nickname.",
+ WebServ, from);
+ return;
+ }
+
+ /* As this function uses SVSNICK they could use any nick they'd like in
+ * theory, even ones we'd rather not have them use. Let's check our
+ * BadNickList (from services.conf) to see if the nick is 'ok' or not.
+ * -- Remmy, 20020616 */
+ if (isBadNick(args[1])) {
+ sSend(":%s PRIVMSG %s :You're forbidden to use the nick %s. Please select another nickname.", WebServ, from, args[1]);
+ return;
+ }
+
+ sSend(":%s PRIVMSG %s :Your nick is now %s", WebServ, from, args[1]);
+ sSend(":%s SVSNICK %s %s %lu", myname, from, args[1], CTime);
+
+ return;
+}
+
+void WunbanCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+
+ if (numargs < 3) {
+ sSend(":%s PRIVMSG %s :You must specify a channel and a mask.",
+ WebServ, from);
+ return;
+ }
+
+ tmp = getRegChanData(args[1]);
+ chan = getChanData(args[1]);
+
+ if (!chan) {
+ sSend(":%s PRIVMSG %s :No such channel.", WebServ, from);
+ return;
+ }
+ if (!tmp) {
+ sSend(":%s PRIVMSG %s :%s is not registered.", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop(nick)) {
+ sSend(":%s PRIVMSG %s :Access denied. This channel is FROZEN.",
+ WebServ, from);
+ return;
+ }
+
+ a = getChanOp(tmp, from);
+
+ if (!a || !getChanOp(tmp, from)) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ }
+
+ if (a < AOP) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ } else {
+ sSend(":%s PRIVMSG %s :%s unbanned %s from %s", WebServ, args[1],
+ from, args[2], args[1]);
+ sSend(":%s MODE %s -b %s", WebServ, args[1], args[2]);
+ return;
+ }
+}
+
+void WchanmodeCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ int a;
+ RegChanList *tmp;
+ ChanList *chan;
+
+ if (numargs < 3) {
+ sSend(":%s PRIVMSG %s :You must specify a channel and a mode.",
+ WebServ, from);
+ return;
+ }
+
+ tmp = getRegChanData(args[1]);
+ chan = getChanData(args[1]);
+
+ if (!chan) {
+ sSend(":%s PRIVMSG %s :No such channel.", WebServ, from);
+ return;
+ }
+ if (!tmp) {
+ sSend(":%s PRIVMSG %s :%s is not registered.", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ if ((tmp->flags & CFREEZE) && !isServop(nick)) {
+ sSend(":%s PRIVMSG %s :Access denied. This channel is FROZEN.",
+ WebServ, from);
+ return;
+ }
+
+ a = getChanOp(tmp, from);
+
+ if (!a || !getChanOp(tmp, from)) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ }
+
+ if (a < AOP) {
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ return;
+ } else {
+ if (!strcasecmp(args[2], "INVITE")) {
+ sSend(":%s MODE %s +i", WebServ, args[1]);
+ sSend(":%s PRIVMSG %s :%s sets %s INVITE-ONLY.", WebServ,
+ args[1], from, args[1]);
+ doRegChanMode(tmp);
+ } else if (!strcasecmp(args[2], "SECRET")) {
+ sSend(":%s PRIVMSG %s :%s sets %s SECRET.", WebServ, args[1],
+ from, args[1]);
+ sSend(":%s MODE %s +s", WebServ, args[1]);
+ doRegChanMode(tmp);
+ } else if (!strcasecmp(args[2], "PRIVATE")) {
+ sSend(":%s PRIVMSG %s :%s sets %s PRIVATE.", WebServ, args[1],
+ from, args[1]);
+ sSend(":%s MODE %s +p", WebServ, args[1]);
+ doRegChanMode(tmp);
+
+ } else if (!strcasecmp(args[2], "MODERATE")) {
+ sSend(":%s PRIVMSG %s :%s sets %s MODERATE.", WebServ, args[1],
+ from, args[1]);
+ sSend(":%s MODE %s +m", WebServ, args[1]);
+ doRegChanMode(tmp);
+
+ } else if (!strcasecmp(args[2], "OFF")) {
+ if ((tmp->flags & CFORCES)) {
+ sSend(":%s PRIVMSG %s :Access denied.", WebServ, from);
+ return;
+ }
+ sSend(":%s PRIVMSG %s :%s sets %s free of modes.", WebServ,
+ args[1], from, args[1]);
+ sSend(":%s MODE %s -sipm", WebServ, args[1]);
+ doRegChanMode(tmp);
+ } else {
+ sSend(":%s PRIVMSG %s :Unknown chanmode", WebServ, from);
+ }
+ return;
+ }
+}
+
+void WinviteCmd(UserList * nick, char **args, int numargs)
+{
+ char *from = nick->nick;
+ RegChanList *chan;
+
+ if (numargs < 2) {
+ sSend(":%s PRIVMSG %s :You must specify a channel.", WebServ,
+ from);
+ return;
+ }
+
+ chan = getRegChanData(args[1]);
+
+ if (!chan) {
+ sSend(":%s PRIVMSG %s :%s isn't registered", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ if ((chan->flags & CFREEZE) && !isServop(nick)) {
+ sSend(":%s PRIVMSG %s :Access denied. This channel is FROZEN.",
+ WebServ, from);
+ return;
+ }
+
+ if ((1 > getChanOp(chan, from)) && (!isOper(nick)))
+ sSend(":%s PRIVMSG %s :Access denied", WebServ, from);
+ else
+ sSend(":%s INVITE %s :%s", WebServ, from, chan->name);
+}
+
+void WghostCmd(UserList * nick, char **args, int numargs)
+{
+ RegNickList *tmp;
+ char *from = nick->nick;
+ char ghoststr[80];
+ int found_ghost = 0;
+
+ if (numargs < 3) {
+ sSend
+ (":%s PRIVMSG %s :You must specify a nick and its password to ghost it.",
+ WebServ, nick->nick);
+ return;
+ }
+
+ if (!strcasecmp(nick->nick, args[1])) {
+ sSend(":%s PRIVMSG %s :You cannot ghost yourself.", WebServ, from);
+ return;
+ }
+
+ tmp = getRegNickData(args[1]);
+
+ if (!tmp) {
+ sSend(":%s PRIVMSG %s :%s is not registered.", WebServ, from,
+ args[1]);
+ return;
+ }
+
+ found_ghost = isGhost(args[1]);
+
+ if ((!found_ghost) && (!getNickData(args[1]))) {
+ sSend(":%s PRIVMSG %s :%s is not online or a %s ghost.", WebServ,
+ from, args[1], WebServ);
+ return;
+ }
+
+ if (strcasecmp(tmp->password, args[2])) {
+ sSend(":%s PRIVMSG %s :Access Denied.", WebServ, from);
+ return;
+ }
+
+ sSend(":%s PRIVMSG %s :%s has been Ghosted, have a nice day. :)",
+ WebServ, nick->nick, args[1]);
+
+ if (found_ghost) {
+ delGhost(args[1]);
+ return;
+ }
+
+ sprintf(ghoststr, "Ghost by: %s", from);
+ killUser(services[1], getNickData(args[1]), ghoststr);
+ remUser(args[1]);
+}