mirror of
https://github.com/pissnet/pissircd.git
synced 2025-08-06 10:15:24 +01:00
- First big part of modulized extended channelmodes system
This commit is contained in:
parent
ded7f11727
commit
41a0896d6d
19 changed files with 1016 additions and 56 deletions
21
Changes
21
Changes
|
@ -2280,3 +2280,24 @@ seen. gmtime warning still there
|
|||
- Will now error at too large cloak keys (2147483647 and greater) because it's dangerous
|
||||
and could cause cloak key differences (ex: mixed ia32&ia64 networks).
|
||||
- Some minor text/documentation fixes.
|
||||
- First big part of modulized extended channelmodes system:
|
||||
- Adds room for at least 32 (new) channel modes.
|
||||
- Supports both paramless and 1-parameter modes.
|
||||
- Modulized: modules can add new channelmodes, but are unloadable (permanent).
|
||||
- Everything is ifdef'd, and EXTCMODE is disabled by default in config.h
|
||||
- It will send CHANMODES= in the PROTOCTL message on server link, this enables
|
||||
servers and services to see which modes are supported and of what type
|
||||
they are (1-parameter, paramless, etc).
|
||||
And now the bad part:
|
||||
- The system has not been fully tested, it will contain bugs (for example I'm
|
||||
aware of some memory leaks).
|
||||
- A few features are missing: warning/error on linking if chanmodes mismatch, unloading
|
||||
of channel modes (not planned soon), 005 broadcasts on change and maybe more..
|
||||
- The function (and maybe variable) names will be changed in the next weeks/months
|
||||
- You should be carefull with parameter modes + services. Things will get desynced
|
||||
if services don't recognize it's a parameter mode. This also applies to clients
|
||||
without 005 CHANMODES= support.
|
||||
- No documentation
|
||||
|
||||
I really suggest module coders to wait a few weeks till the system is ready..
|
||||
In the meantime, don't report bugs or ask for support on this.
|
||||
|
|
12
help.conf
12
help.conf
|
@ -56,7 +56,7 @@ help Opercmds {
|
|||
" LAG SETHOST SETIDENT CHGHOST CHGIDENT";
|
||||
" CHGNAME SQUIT CONNECT DCCDENY UNDCCDENY";
|
||||
" SAJOIN SAPART SAMODE RPING TRACE";
|
||||
" OPERMOTD SDESC MKPASSWD CLOSE";
|
||||
" OPERMOTD SDESC MKPASSWD CLOSE MODULE";
|
||||
" ==----------------oOo---------------==";
|
||||
};
|
||||
|
||||
|
@ -926,6 +926,16 @@ help Mkpasswd {
|
|||
" Example: MKPASSWD crypt mpsare";
|
||||
};
|
||||
|
||||
help Module {
|
||||
" This will give you a list of all modules loaded in the form:";
|
||||
" *** name - version (description) [optional flags here]";
|
||||
" flags can be:";
|
||||
" [PERM]: permanent module (not possible to unload/reload)";
|
||||
" [Unloading]: module is in the process of unloading";
|
||||
" -";
|
||||
" Syntax: MODULE";
|
||||
};
|
||||
|
||||
help Close {
|
||||
" This command will disconnect all unknown connections from the";
|
||||
" IRC server.";
|
||||
|
|
|
@ -226,6 +226,18 @@ extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ );
|
|||
|
||||
/* IRCu/Hybrid/Unreal way now :) -Stskeeps */
|
||||
|
||||
#ifdef EXTCMODE
|
||||
#define EXPAR1 extchmstr[0]
|
||||
#define EXPAR2 extchmstr[1]
|
||||
#define EXPAR3 extchmstr[2]
|
||||
#define EXPAR4 extchmstr[3]
|
||||
#else
|
||||
#define EXPAR1 ""
|
||||
#define EXPAR2 ""
|
||||
#define EXPAR3 ""
|
||||
#define EXPAR4 ""
|
||||
#endif /* EXTCMODE */
|
||||
|
||||
#define PROTOCTL_CLIENT_1 \
|
||||
"MAP" \
|
||||
" KNOCK" \
|
||||
|
@ -248,6 +260,18 @@ extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ );
|
|||
MAXTARGETS, \
|
||||
TOPICLEN
|
||||
|
||||
#ifdef PREFIX_AQ
|
||||
#define CHPFIX "(qaohv)~&@%+"
|
||||
#define CHPAR1 "be"
|
||||
#else
|
||||
#define CHPFIX "(ohv)@%+"
|
||||
#define CHPAR1 "beqa"
|
||||
#endif /* PREFIX_AQ */
|
||||
|
||||
#define CHPAR2 "k"
|
||||
#define CHPAR3 "lfL"
|
||||
#define CHPAR4 "psmntirRcOAQKVGCuzNSM"
|
||||
|
||||
#define PROTOCTL_CLIENT_2 \
|
||||
"WALLCHOPS" \
|
||||
" WATCH=%i" \
|
||||
|
@ -255,39 +279,27 @@ extern struct SLink *find_user_link( /* struct SLink *, struct Client * */ );
|
|||
" MODES=%i" \
|
||||
" CHANTYPES=%s" \
|
||||
" PREFIX=%s" \
|
||||
" CHANMODES=%s,%s,%s,%s" \
|
||||
" CHANMODES=%s%s,%s%s,%s%s,%s%s" \
|
||||
" NETWORK=%s" \
|
||||
" CASEMAPPING=%s" \
|
||||
" :are supported by this server"
|
||||
|
||||
#ifndef PREFIX_AQ
|
||||
#define PROTOCTL_PARAMETERS_2 \
|
||||
MAXWATCH, \
|
||||
MAXSILES, \
|
||||
MAXMODEPARAMS, \
|
||||
"#", \
|
||||
"(ohv)@%+", \
|
||||
"beqa", \
|
||||
"kfL", \
|
||||
"l", \
|
||||
"psmntirRcOAQKVGCuzNSM", \
|
||||
ircnet005, \
|
||||
"ascii"
|
||||
#else
|
||||
#define PROTOCTL_PARAMETERS_2 \
|
||||
MAXWATCH, \
|
||||
MAXSILES, \
|
||||
MAXMODEPARAMS, \
|
||||
"#", \
|
||||
"(qaohv)~&@%+", \
|
||||
"be", \
|
||||
"kfL", \
|
||||
"l", \
|
||||
"psmntirRcOAQKVGCuzNSM", \
|
||||
ircnet005, \
|
||||
"ascii"
|
||||
#endif
|
||||
/* Server-Server PROTOCTL -Stskeeps */
|
||||
MAXWATCH, \
|
||||
MAXSILES, \
|
||||
MAXMODEPARAMS, \
|
||||
"#", \
|
||||
CHPFIX, \
|
||||
CHPAR1, EXPAR1, \
|
||||
CHPAR2, EXPAR2, \
|
||||
CHPAR3, EXPAR3, \
|
||||
"psmntirRcOAQKVGCuzNSM", EXPAR4, \
|
||||
ircnet005, \
|
||||
"ascii"
|
||||
|
||||
/* Server-Server PROTOCTL -Stskeeps
|
||||
* Please check send_proto() for more. -- Syzop
|
||||
*/
|
||||
#define PROTOCTL_SERVER "NOQUIT" \
|
||||
" TOKEN" \
|
||||
" NICKv2" \
|
||||
|
|
|
@ -544,6 +544,13 @@
|
|||
*/
|
||||
#define SIXBONE_HACK
|
||||
|
||||
/*
|
||||
* Extended channel modes. This extends the channel modes with yet another
|
||||
* 32 possible modes which can also be used in modules.
|
||||
* This is currently considered experimental however.
|
||||
*/
|
||||
#undef EXTCMODE
|
||||
|
||||
/* ------------------------- END CONFIGURATION SECTION -------------------- */
|
||||
#define MOTD MPATH
|
||||
#define RULES RPATH
|
||||
|
|
13
include/h.h
13
include/h.h
|
@ -585,3 +585,16 @@ extern char trouble_info[1024];
|
|||
extern void rejoin_doparts(aClient *sptr);
|
||||
extern void rejoin_dojoinandmode(aClient *sptr);
|
||||
extern void ident_failed(aClient *cptr);
|
||||
|
||||
extern char extchmstr[4][64];
|
||||
#ifdef EXTCMODE
|
||||
extern int extcmode_default_requirechop(aClient *, aChannel *, char *, int, int);
|
||||
extern int extcmode_default_requirehalfop(aClient *, aChannel *, char *, int, int);
|
||||
extern int extcmode_delete(char);
|
||||
extern ExtCMode extcmode_get(aExtCMtable *);
|
||||
extern void extcmode_init(void);
|
||||
extern aExtCMtableParam *extcmode_get_struct(aExtCMtableParam *, char);
|
||||
extern void make_extcmodestr();
|
||||
extern aExtCMtableParam *extcmode_duplicate_paramlist(aExtCMtableParam *);
|
||||
extern void extcmode_free_paramlist(aExtCMtableParam *);
|
||||
#endif
|
||||
|
|
|
@ -163,6 +163,7 @@ struct _Module
|
|||
ModuleChild *children;
|
||||
ModuleObject *objects;
|
||||
ModuleInfo modinfo; /* Used to store handle info for module */
|
||||
unsigned permanent:1; /* permanent module? (can't unload/reload) */
|
||||
};
|
||||
/*
|
||||
* Symbol table
|
||||
|
|
109
include/struct.h
109
include/struct.h
|
@ -1218,9 +1218,118 @@ struct ListOptions {
|
|||
TS topictimemax;
|
||||
};
|
||||
|
||||
#ifdef EXTCMODE
|
||||
|
||||
#define EXTCMODETABLESZ 32
|
||||
typedef unsigned long ExtCMode;
|
||||
|
||||
/** These define's are used for the aExtCMtable->is_ok() routines.
|
||||
* (these 3 type of checks are seperated because of operoverride and stuff)
|
||||
*/
|
||||
|
||||
#define EXCHK_ACCESS 0 /* Check access */
|
||||
#define EXCHK_ACCESS_ERR 1 /* Check access and send error if needed */
|
||||
#define EXCHK_PARAM 2 /* Check parameter and send error if needed */
|
||||
|
||||
#define EXSJ_SAME 0 /* Parameters are the same */
|
||||
#define EXSJ_WEWON 1 /* We won! w00t */
|
||||
#define EXSJ_THEYWON 2 /* They won :( */
|
||||
|
||||
typedef struct ExtCMtable aExtCMtable;
|
||||
typedef struct ExtCMtableParam aExtCMtableParam;
|
||||
|
||||
/** Extended channel mode table.
|
||||
* This table contains all extended channelmode info like the flag, mode, their
|
||||
* functions, etc..
|
||||
*/
|
||||
struct ExtCMtable {
|
||||
/** mode character (like 'Z') */
|
||||
char flag;
|
||||
|
||||
/** unique flag (like 0x10) */
|
||||
ExtCMode mode;
|
||||
|
||||
/** # of paramters (1 or 0) */
|
||||
int paracount;
|
||||
|
||||
/** access and parameter checking.
|
||||
* aClient *: the client
|
||||
* aChannel *: the channel
|
||||
* para *: the parameter (NULL for paramless modes)
|
||||
* int: check type (see EXCHK_*)
|
||||
* int: what (MODE_ADD or MODE_DEL)
|
||||
* return value: 1=ok, 0=bad
|
||||
*/
|
||||
int (*is_ok)(aClient *,aChannel *, char *para, int, int);
|
||||
|
||||
/** NOTE: The routines below are NULL for paramless modes */
|
||||
|
||||
/** Store parameter in memory for channel.
|
||||
* aExtCMtableParam *: the list (usually chptr->mode.extmodeparams).
|
||||
* char *: the parameter.
|
||||
* return value: the head of the list, RTFS if you wonder why.
|
||||
* design notes: only alloc a new paramstruct if you need to, search for
|
||||
* any current one first (like in case of mode +y 5 and then +y 6 later without -y).
|
||||
*/
|
||||
aExtCMtableParam * (*put_param)(aExtCMtableParam *, char *);
|
||||
|
||||
/** Get readable string version" of the stored parameter.
|
||||
* aExtCMtableParam *: the list (usually chptr->mode.extmodeparams).
|
||||
* return value: a pointer to the string (temp. storage)
|
||||
*/
|
||||
char * (*get_param)(aExtCMtableParam *);
|
||||
|
||||
/** Convert input parameter to output.
|
||||
* Like +l "1aaa" becomes "1".
|
||||
* char *: the input parameter.
|
||||
* return value: pointer to output string (temp. storage)
|
||||
*/
|
||||
char * (*conv_param)(char *);
|
||||
|
||||
/** free and remove parameter from list.
|
||||
* aExtCMtableParam *: the list (usually chptr->mode.extmodeparams).
|
||||
* return value: the head of the list, RTFS if you wonder why.
|
||||
*/
|
||||
aExtCMtableParam * (*free_param)(aExtCMtableParam *);
|
||||
|
||||
/** duplicate a struct and return a pointer to duplicate.
|
||||
* This is usually just a malloc + memcpy.
|
||||
* aExtCMtableParam *: source struct itself (no list).
|
||||
* return value: pointer to newly allocated struct.
|
||||
*/
|
||||
aExtCMtableParam * (*dup_struct)(aExtCMtableParam *);
|
||||
|
||||
/** Compares 2 parameters and decides who wins the sjoin fight.
|
||||
* When syncing channel modes (m_sjoin) a parameter conflict may occur, things like
|
||||
* +l 5 vs +l 10. This function should determinate who wins the fight, this decision
|
||||
* should of course not be random but the same at every server on the net.
|
||||
* examples of such comparisons are "highest wins" (+l) and a strcmp() check (+k/+L).
|
||||
* aChannel *: channel the fight is about.
|
||||
* aExtCMtableParam *: our parameter
|
||||
* aExtCMtableParam *: their parameter
|
||||
*/
|
||||
int (*sjoin_check)(aChannel *, aExtCMtableParam *, aExtCMtableParam *);
|
||||
};
|
||||
|
||||
extern aExtCMtable *ExtCMode_Table;
|
||||
extern unsigned short ExtCMode_highest;
|
||||
|
||||
#define EXTCM_PAR_HEADER aExtCMtableParam *prev, *next; char flag;
|
||||
|
||||
struct ExtCMtableParam {
|
||||
EXTCM_PAR_HEADER
|
||||
/** other fields are placed after this header in your own paramstruct */
|
||||
};
|
||||
|
||||
#endif /* EXTCMODE */
|
||||
|
||||
/* mode structure for channels */
|
||||
struct SMode {
|
||||
long mode;
|
||||
#ifdef EXTCMODE
|
||||
ExtCMode extmode;
|
||||
aExtCMtableParam *extmodeparam;
|
||||
#endif
|
||||
int limit;
|
||||
char key[KEYLEN + 1];
|
||||
char link[LINKLEN + 1];
|
||||
|
|
|
@ -35,7 +35,7 @@ OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \
|
|||
SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \
|
||||
SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \
|
||||
SRC/S_SVS.OBJ SRC/EVENTS.OBJ SRC/UMODES.OBJ SRC/AUTH.OBJ SRC/CIDR.OBJ SRC/SSL.OBJ \
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/EXTCMODES.OBJ
|
||||
|
||||
MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OBJ \
|
||||
SRC/M_SETNAME.OBJ SRC/M_SETHOST.OBJ SRC/M_CHGIDENT.OBJ SRC/M_SVSMOTD.OBJ \
|
||||
|
@ -231,6 +231,9 @@ src/cidr.obj: src/cidr.c $(INCLUDES)
|
|||
src/random.obj: src/random.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/random.c
|
||||
|
||||
src/extcmodes.obj: src/extcmodes.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/extcmodes.c
|
||||
|
||||
src/ssl.obj: src/ssl.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/ssl.c
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \
|
|||
SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \
|
||||
SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \
|
||||
SRC/S_SVS.OBJ SRC/EVENTS.OBJ SRC/UMODES.OBJ SRC/AUTH.OBJ SRC/CIDR.OBJ SRC/SSL.OBJ \
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/EXTCMODES.OBJ
|
||||
|
||||
MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OBJ \
|
||||
SRC/M_SETNAME.OBJ SRC/M_SETHOST.OBJ SRC/M_CHGIDENT.OBJ SRC/M_SVSMOTD.OBJ \
|
||||
|
@ -234,6 +234,9 @@ src/cidr.obj: src/cidr.c $(INCLUDES)
|
|||
src/random.obj: src/random.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/random.c
|
||||
|
||||
src/extcmodes.obj: src/extcmodes.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/extcmodes.c
|
||||
|
||||
src/ssl.obj: src/ssl.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/ssl.c
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \
|
|||
SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \
|
||||
SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \
|
||||
SRC/S_SVS.OBJ SRC/EVENTS.OBJ SRC/UMODES.OBJ SRC/AUTH.OBJ SRC/CIDR.OBJ SRC/SSL.OBJ \
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/ZIP.OBJ
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/ZIP.OBJ SRC/EXTCMODES.OBJ
|
||||
|
||||
MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OBJ \
|
||||
SRC/M_SETNAME.OBJ SRC/M_SETHOST.OBJ SRC/M_CHGIDENT.OBJ SRC/M_SVSMOTD.OBJ \
|
||||
|
@ -241,6 +241,9 @@ src/cidr.obj: src/cidr.c $(INCLUDES)
|
|||
src/random.obj: src/random.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/random.c
|
||||
|
||||
src/extcmodes.obj: src/extcmodes.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/extcmodes.c
|
||||
|
||||
src/zip.obj: src/zip.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/zip.c
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ OBJ_FILES=SRC/CHANNEL.OBJ SRC/SEND.OBJ SRC/SOCKET.OBJ \
|
|||
SRC/S_KLINE.OBJ SRC/S_EXTRA.OBJ SRC/IRCSPRINTF.OBJ SRC/LUSERS.OBJ \
|
||||
SRC/SCACHE.OBJ SRC/ALN.OBJ SRC/BADWORDS.OBJ SRC/WEBTV.OBJ SRC/RES.OBJ SRC/MODULES.OBJ \
|
||||
SRC/S_SVS.OBJ SRC/EVENTS.OBJ SRC/UMODES.OBJ SRC/AUTH.OBJ SRC/CIDR.OBJ SRC/SSL.OBJ \
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/ZIP.OBJ
|
||||
SRC/SERVICE.OBJ SRC/DEBUG.OBJ SRC/RANDOM.OBJ SRC/ZIP.OBJ SRC/EXTCMODES.OBJ
|
||||
|
||||
MOD_FILES=SRC/L_COMMANDS.OBJ SRC/M_CHGHOST.OBJ SRC/M_SDESC.OBJ SRC/M_SETIDENT.OBJ \
|
||||
SRC/M_SETNAME.OBJ SRC/M_SETHOST.OBJ SRC/M_CHGIDENT.OBJ SRC/M_SVSMOTD.OBJ \
|
||||
|
@ -236,6 +236,9 @@ src/cidr.obj: src/cidr.c $(INCLUDES)
|
|||
src/random.obj: src/random.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/random.c
|
||||
|
||||
src/extcmodes.obj: src/extcmodes.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/extcmodes.c
|
||||
|
||||
src/zip.obj: src/zip.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) src/zip.c
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ OBJS=auth.o aln.o badwords.o channel.o cloak.o crule.o dbuf.o \
|
|||
s_bsd.o s_conf.o s_debug.o s_err.o s_extra.o s_kline.o \
|
||||
s_misc.o s_numeric.o s_serv.o s_svs.o $(STRTOUL) socket.o \
|
||||
ssl.o s_user.o scache.o send.o support.o umodes.o \
|
||||
version.o webtv.o whowas.o zip.o cidr.o random.o
|
||||
version.o webtv.o whowas.o zip.o cidr.o random.o extcmodes.o
|
||||
|
||||
SRC=$(OBJS:%.o=%.c)
|
||||
|
||||
|
@ -240,5 +240,8 @@ cidr.o: cidr.c $(INCLUDES)
|
|||
random.o: random.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) -c random.c
|
||||
|
||||
extcmodes.o: extcmodes.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) -c extcmodes.c
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
|
|
328
src/channel.c
328
src/channel.c
|
@ -83,8 +83,15 @@ static int check_channelmask(aClient *, aClient *, char *);
|
|||
int del_banid(aChannel *, char *);
|
||||
static void set_mode(aChannel *, aClient *, int, char **, u_int *,
|
||||
char[MAXMODEPARAMS][MODEBUFLEN + 3], int);
|
||||
|
||||
#ifdef EXTCMODE
|
||||
static void make_mode_str(aChannel *, long, ExtCMode, long, int,
|
||||
char[MAXMODEPARAMS][MODEBUFLEN + 3], char *, char *, char);
|
||||
#else
|
||||
static void make_mode_str(aChannel *, long, long, int,
|
||||
char[MAXMODEPARAMS][MODEBUFLEN + 3], char *, char *, char);
|
||||
#endif
|
||||
|
||||
static int do_mode_char(aChannel *, long, char, char *,
|
||||
u_int, aClient *,
|
||||
u_int *, char[MAXMODEPARAMS][MODEBUFLEN + 3], char);
|
||||
|
@ -168,13 +175,20 @@ void make_cmodestr(void)
|
|||
{
|
||||
char *p = &cmodestring[0];
|
||||
aCtab *tab = &cFlagTab[0];
|
||||
|
||||
#ifdef EXTCMODE
|
||||
int i;
|
||||
#endif
|
||||
while (tab->mode != 0x0)
|
||||
{
|
||||
*p = tab->flag;
|
||||
p++;
|
||||
tab++;
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
if (ExtCMode_Table[i].flag)
|
||||
*p++ = ExtCMode_Table[i].flag;
|
||||
#endif
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
|
@ -829,8 +843,12 @@ void channel_modes(aClient *cptr, char *mbuf, char *pbuf, aChannel *chptr)
|
|||
{
|
||||
aCtab *tab = &cFlagTab[0];
|
||||
char bcbuf[1024];
|
||||
#ifdef EXTCMODE
|
||||
int i;
|
||||
#endif
|
||||
|
||||
*mbuf++ = '+';
|
||||
/* Paramless first */
|
||||
while (tab->mode != 0x0)
|
||||
{
|
||||
if ((chptr->mode.mode & tab->mode))
|
||||
|
@ -838,6 +856,14 @@ void channel_modes(aClient *cptr, char *mbuf, char *pbuf, aChannel *chptr)
|
|||
*mbuf++ = tab->flag;
|
||||
tab++;
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (ExtCMode_Table[i].flag && !ExtCMode_Table[i].paracount &&
|
||||
(chptr->mode.extmode & ExtCMode_Table[i].mode))
|
||||
*mbuf++ = ExtCMode_Table[i].flag;
|
||||
}
|
||||
#endif
|
||||
if (chptr->mode.limit)
|
||||
{
|
||||
*mbuf++ = 'l';
|
||||
|
@ -884,6 +910,18 @@ void channel_modes(aClient *cptr, char *mbuf, char *pbuf, aChannel *chptr)
|
|||
}
|
||||
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (ExtCMode_Table[i].flag && ExtCMode_Table[i].paracount &&
|
||||
(chptr->mode.extmode & ExtCMode_Table[i].mode))
|
||||
{
|
||||
*mbuf++ = ExtCMode_Table[i].flag;
|
||||
strcat(pbuf, ExtCMode_Table[i].get_param(chptr->mode.extmodeparam));
|
||||
strcat(pbuf, " ");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*mbuf++ = '\0';
|
||||
return;
|
||||
|
@ -1319,10 +1357,7 @@ void bounce_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[])
|
|||
{
|
||||
char pvar[MAXMODEPARAMS][MODEBUFLEN + 3];
|
||||
int pcount;
|
||||
long oldm, oldl;
|
||||
|
||||
oldm = chptr->mode.mode;
|
||||
oldl = chptr->mode.limit;
|
||||
set_mode(chptr, cptr, parc, parv, &pcount, pvar, 1);
|
||||
|
||||
if (chptr->creationtime)
|
||||
|
@ -1343,13 +1378,10 @@ void do_mode(aChannel *chptr, aClient *cptr, aClient *sptr, int parc, char *parv
|
|||
{
|
||||
char pvar[MAXMODEPARAMS][MODEBUFLEN + 3];
|
||||
int pcount;
|
||||
long oldm, oldl;
|
||||
char tschange = 0, isbounce = 0; /* fwd'ing bounce */
|
||||
|
||||
if (**parv == '&')
|
||||
isbounce = 1;
|
||||
oldm = chptr->mode.mode;
|
||||
oldl = chptr->mode.limit;
|
||||
|
||||
set_mode(chptr, sptr, parc, parv, &pcount, pvar, 0);
|
||||
|
||||
|
@ -1455,14 +1487,22 @@ void do_mode(aChannel *chptr, aClient *cptr, aClient *sptr, int parc, char *parv
|
|||
* contain the +x-y stuff, and the parabuf will contain the parameters.
|
||||
* If bounce is set to 1, it will make the string it needs for a bounce.
|
||||
*/
|
||||
#ifdef EXTCMODE
|
||||
void make_mode_str(aChannel *chptr, long oldm, ExtCMode oldem, long oldl, int pcount,
|
||||
char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, char bounce)
|
||||
#else
|
||||
void make_mode_str(aChannel *chptr, long oldm, long oldl, int pcount,
|
||||
char pvar[MAXMODEPARAMS][MODEBUFLEN + 3], char *mode_buf, char *para_buf, char bounce)
|
||||
#endif
|
||||
{
|
||||
|
||||
char tmpbuf[MODEBUFLEN+3], *tmpstr;
|
||||
aCtab *tab = &cFlagTab[0];
|
||||
char *x = mode_buf;
|
||||
int what, cnt, z;
|
||||
#ifdef EXTCMODE
|
||||
int i;
|
||||
#endif
|
||||
char *m;
|
||||
what = 0;
|
||||
|
||||
|
@ -1488,6 +1528,25 @@ void make_mode_str(aChannel *chptr, long oldm, long oldl, int pcount,
|
|||
}
|
||||
tab++;
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
/* + paramless extmodes... */
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (!ExtCMode_Table[i].flag || ExtCMode_Table[i].paracount)
|
||||
continue;
|
||||
/* have it now and didn't have it before? */
|
||||
if ((chptr->mode.extmode & ExtCMode_Table[i].mode) &&
|
||||
!(oldem & ExtCMode_Table[i].mode))
|
||||
{
|
||||
if (what != MODE_ADD)
|
||||
{
|
||||
*x++ = bounce ? '-' : '+';
|
||||
what = MODE_ADD;
|
||||
}
|
||||
*x++ = ExtCMode_Table[i].flag;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*x = '\0';
|
||||
/* - param-less modes */
|
||||
|
@ -1509,6 +1568,28 @@ void make_mode_str(aChannel *chptr, long oldm, long oldl, int pcount,
|
|||
tab++;
|
||||
}
|
||||
|
||||
#ifdef EXTCMODE
|
||||
/* - extmodes (both "param modes" and paramless don't have
|
||||
* any params when unsetting...
|
||||
*/
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (!ExtCMode_Table[i].flag /* || ExtCMode_Table[i].paracount */)
|
||||
continue;
|
||||
/* don't have it now and did have it before */
|
||||
if (!(chptr->mode.extmode & ExtCMode_Table[i].mode) &&
|
||||
(oldem & ExtCMode_Table[i].mode))
|
||||
{
|
||||
if (what != MODE_DEL)
|
||||
{
|
||||
*x++ = bounce ? '+' : '-';
|
||||
what = MODE_DEL;
|
||||
}
|
||||
*x++ = ExtCMode_Table[i].flag;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*x = '\0';
|
||||
/* user limit */
|
||||
if (chptr->mode.limit != oldl)
|
||||
|
@ -1566,7 +1647,12 @@ void make_mode_str(aChannel *chptr, long oldm, long oldl, int pcount,
|
|||
*m = '\0';
|
||||
}
|
||||
if (bounce)
|
||||
{
|
||||
chptr->mode.mode = oldm;
|
||||
#ifdef EXTCMODE
|
||||
chptr->mode.extmode = oldem;
|
||||
#endif
|
||||
}
|
||||
z = strlen(para_buf);
|
||||
if (para_buf[z - 1] == ' ')
|
||||
para_buf[z - 1] = '\0';
|
||||
|
@ -2208,6 +2294,88 @@ int do_mode_char(aChannel *chptr, long modetype, char modechar, char *param,
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifdef EXTCMODE
|
||||
/** Check access and if granted, set the extended chanmode to the requested value in memory.
|
||||
* note: if bounce is requested then the mode will not be set.
|
||||
* @returns amount of params eaten (0 or 1)
|
||||
*/
|
||||
int do_extmode_char(aChannel *chptr, int modeindex, char *param, u_int what,
|
||||
aClient *cptr, u_int *pcount, char pvar[MAXMODEPARAMS][MODEBUFLEN + 3],
|
||||
char bounce)
|
||||
{
|
||||
int paracnt = (what == MODE_ADD) ? ExtCMode_Table[modeindex].paracount : 0;
|
||||
int x;
|
||||
|
||||
/* Expected a param and it isn't there? */
|
||||
if (paracnt && (!param || (*pcount >= MAXMODEPARAMS)))
|
||||
return 0;
|
||||
|
||||
if (!IsServer(cptr) &&
|
||||
#ifndef NO_OPER_OVERRIDE
|
||||
!IsSkoAdmin(cptr) &&
|
||||
#endif
|
||||
(ExtCMode_Table[modeindex].is_ok(cptr, chptr, param, EXCHK_ACCESS_ERR, what) == FALSE))
|
||||
return paracnt; /* Denied & error msg sent */
|
||||
|
||||
/* Check for multiple changes in 1 command (like +y-y+y 1 2, or +yy 1 2). */
|
||||
for (x = 0; x < *pcount; x++)
|
||||
{
|
||||
if (pvar[x][1] == ExtCMode_Table[modeindex].flag)
|
||||
{
|
||||
/* this is different than the old chanmode system, coz:
|
||||
* "mode #chan +kkL #a #b #c" will get "+kL #a #b" which is wrong :p.
|
||||
* we do eat the parameter. -- Syzop
|
||||
*/
|
||||
return paracnt;
|
||||
}
|
||||
}
|
||||
|
||||
/* w00t... a parameter mode */
|
||||
if (ExtCMode_Table[modeindex].paracount)
|
||||
{
|
||||
if (what == MODE_DEL)
|
||||
{
|
||||
if (!(chptr->mode.extmode & ExtCMode_Table[modeindex].mode))
|
||||
return paracnt; /* There's nothing to remove! [TODO: -> 0] */
|
||||
/* del means any parameter is ok, the one-who-is-set will be used */
|
||||
ircsprintf(pvar[*pcount], "-%c", ExtCMode_Table[modeindex].flag);
|
||||
} else {
|
||||
/* add: is the parameter ok? */
|
||||
if (ExtCMode_Table[modeindex].is_ok(cptr, chptr, param, EXCHK_PARAM, what) == FALSE)
|
||||
return paracnt;
|
||||
/* is it already set at the same value? if so, ignore it. */
|
||||
if (chptr->mode.extmode & ExtCMode_Table[modeindex].mode)
|
||||
{
|
||||
char *p, *p2;
|
||||
p = ExtCMode_Table[modeindex].get_param(chptr->mode.extmodeparam);
|
||||
p2 = ExtCMode_Table[modeindex].conv_param(param);
|
||||
if (p && p2 && !strcmp(p, p2))
|
||||
return paracnt; /* ignore... */
|
||||
}
|
||||
ircsprintf(pvar[*pcount], "+%c%s",
|
||||
ExtCMode_Table[modeindex].flag, ExtCMode_Table[modeindex].conv_param(param));
|
||||
(*pcount)++;
|
||||
}
|
||||
}
|
||||
|
||||
if (bounce) /* bounce here means: only check access and return return value */
|
||||
return paracnt;
|
||||
|
||||
if (what == MODE_ADD)
|
||||
{ /* + */
|
||||
chptr->mode.extmode |= ExtCMode_Table[modeindex].mode;
|
||||
if (ExtCMode_Table[modeindex].paracount)
|
||||
chptr->mode.extmodeparam = ExtCMode_Table[modeindex].put_param(chptr->mode.extmodeparam, param);
|
||||
} else
|
||||
{ /* - */
|
||||
chptr->mode.extmode &= ~(ExtCMode_Table[modeindex].mode);
|
||||
if (ExtCMode_Table[modeindex].paracount)
|
||||
chptr->mode.extmodeparam = ExtCMode_Table[modeindex].free_param(chptr->mode.extmodeparam);
|
||||
}
|
||||
return paracnt;
|
||||
}
|
||||
#endif /* EXTCMODE */
|
||||
|
||||
/*
|
||||
* ListBits(bitvalue, bitlength);
|
||||
* written by Stskeeps
|
||||
|
@ -2254,13 +2422,18 @@ void set_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[], u_int *pco
|
|||
unsigned int htrig = 0;
|
||||
long oldm, oldl;
|
||||
int checkrestr = 0, warnrestr = 1;
|
||||
|
||||
#ifdef EXTCMODE
|
||||
int extm;
|
||||
ExtCMode oldem;
|
||||
#endif
|
||||
paracount = 1;
|
||||
*pcount = 0;
|
||||
|
||||
oldm = chptr->mode.mode;
|
||||
oldl = chptr->mode.limit;
|
||||
|
||||
#ifdef EXTCMODE
|
||||
oldem = chptr->mode.extmode;
|
||||
#endif
|
||||
if (RESTRICT_CHANNELMODES && MyClient(cptr) && !IsAnOper(cptr) && !IsServer(cptr)) /* "cache" this */
|
||||
checkrestr = 1;
|
||||
|
||||
|
@ -2297,11 +2470,22 @@ void set_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[], u_int *pco
|
|||
tab++;
|
||||
}
|
||||
if (found == 1)
|
||||
{
|
||||
modetype = foundat.mode;
|
||||
} else {
|
||||
#ifdef EXTCMODE
|
||||
/* Maybe in extmodes */
|
||||
for (extm=0; extm <= ExtCMode_highest; extm++)
|
||||
{
|
||||
if (ExtCMode_Table[extm].flag == *curchr)
|
||||
{
|
||||
found = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (found == 0)
|
||||
modetype = 0;
|
||||
|
||||
if (modetype == 0)
|
||||
{
|
||||
if (!MyClient(cptr))
|
||||
break;
|
||||
|
@ -2325,12 +2509,26 @@ void set_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[], u_int *pco
|
|||
}
|
||||
|
||||
#ifndef NO_OPEROVERRIDE
|
||||
if (found == 1)
|
||||
{
|
||||
if ((Halfop_mode(modetype) == FALSE) && opermode == 2 && htrig != 1)
|
||||
{
|
||||
opermode = 0;
|
||||
htrig = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
else if (found == 2) {
|
||||
/* Extended mode */
|
||||
if ((ExtCMode_Table[extm].is_ok(cptr, chptr, parv[paracount], EXCHK_ACCESS, what) == FALSE) &&
|
||||
(opermode == 2) && (htrig != 1))
|
||||
{
|
||||
opermode = 0;
|
||||
htrig = 1;
|
||||
}
|
||||
}
|
||||
#endif /* EXTCMODE */
|
||||
#endif /* !NO_OPEROVERRIDE */
|
||||
|
||||
/* We can afford to send off a param */
|
||||
if (parc <= paracount)
|
||||
|
@ -2338,15 +2536,29 @@ void set_mode(aChannel *chptr, aClient *cptr, int parc, char *parv[], u_int *pco
|
|||
if (parv[paracount] &&
|
||||
strlen(parv[paracount]) >= MODEBUFLEN)
|
||||
parv[paracount][MODEBUFLEN-1] = '\0';
|
||||
if (found == 1)
|
||||
{
|
||||
paracount +=
|
||||
do_mode_char(chptr, modetype, *curchr,
|
||||
parv[paracount], what, cptr, pcount, pvar,
|
||||
bounce);
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
else if (found == 2)
|
||||
{
|
||||
paracount += do_extmode_char(chptr, extm, parv[paracount],
|
||||
what, cptr, pcount, pvar, bounce);
|
||||
}
|
||||
#endif /* EXTCMODE */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EXTCMODE
|
||||
make_mode_str(chptr, oldm, oldem, oldl, *pcount, pvar, modebuf, parabuf, bounce);
|
||||
#else
|
||||
make_mode_str(chptr, oldm, oldl, *pcount, pvar, modebuf, parabuf, bounce);
|
||||
#endif
|
||||
|
||||
#ifndef NO_OPEROVERRIDE
|
||||
if (htrig == 1)
|
||||
|
@ -4982,6 +5194,11 @@ CMD_FUNC(m_sjoin)
|
|||
{
|
||||
aCtab *acp;
|
||||
bcopy(&chptr->mode, &oldmode, sizeof(Mode));
|
||||
#ifdef EXTCMODE
|
||||
/* Fun.. we have to duplicate all extended modes too... */
|
||||
oldmode.extmodeparam = NULL;
|
||||
oldmode.extmodeparam = extcmode_duplicate_paramlist(chptr->mode.extmodeparam);
|
||||
#endif
|
||||
/* merge the modes */
|
||||
strlcpy(modebuf, parv[3], sizeof modebuf);
|
||||
parabuf[0] = '\0';
|
||||
|
@ -5023,7 +5240,27 @@ CMD_FUNC(m_sjoin)
|
|||
oldmode.msgs, oldmode.per);
|
||||
Addit('f', modeback);
|
||||
}
|
||||
|
||||
#ifdef EXTCMODE
|
||||
/* First, check if we have something they don't have..
|
||||
* note that: oldmode.* = us, chptr->mode.* = them.
|
||||
*/
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if ((ExtCMode_Table[i].flag) &&
|
||||
(oldmode.extmode & ExtCMode_Table[i].mode) &&
|
||||
!(chptr->mode.extmode & ExtCMode_Table[i].mode))
|
||||
{
|
||||
if (ExtCMode_Table[i].paracount)
|
||||
{
|
||||
char *parax = ExtCMode_Table[i].get_param(oldmode.extmodeparam);
|
||||
Addit(ExtCMode_Table[i].flag, parax);
|
||||
} else {
|
||||
Addsingle(ExtCMode_Table[i].flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Add single char modes... */
|
||||
for (acp = cFlagTab; acp->mode; acp++)
|
||||
{
|
||||
if ((oldmode.mode & acp->mode) &&
|
||||
|
@ -5072,6 +5309,27 @@ CMD_FUNC(m_sjoin)
|
|||
Addit('f', modeback);
|
||||
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
/* Now, check if they have something we don't have..
|
||||
* note that: oldmode.* = us, chptr->mode.* = them.
|
||||
*/
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if ((ExtCMode_Table[i].flag) &&
|
||||
!(oldmode.extmode & ExtCMode_Table[i].mode) &&
|
||||
(chptr->mode.extmode & ExtCMode_Table[i].mode))
|
||||
{
|
||||
if (ExtCMode_Table[i].paracount)
|
||||
{
|
||||
char *parax = ExtCMode_Table[i].get_param(chptr->mode.extmodeparam);
|
||||
Addit(ExtCMode_Table[i].flag, parax);
|
||||
} else {
|
||||
Addsingle(ExtCMode_Table[i].flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* now, if we had diffent para modes - this loop really could be done better, but */
|
||||
|
||||
/* do we have an difference? */
|
||||
|
@ -5133,6 +5391,43 @@ CMD_FUNC(m_sjoin)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef EXTCMODE
|
||||
/* Now, check for any param differences in extended channel modes..
|
||||
* note that: oldmode.* = us, chptr->mode.* = them.
|
||||
* if we win: copy oldmode to chptr mode, if they win: send the mode
|
||||
*/
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (ExtCMode_Table[i].flag && ExtCMode_Table[i].paracount &&
|
||||
(oldmode.extmode & ExtCMode_Table[i].mode) &&
|
||||
(chptr->mode.extmode & ExtCMode_Table[i].mode))
|
||||
{
|
||||
int r;
|
||||
char *parax;
|
||||
r = ExtCMode_Table[i].sjoin_check(chptr, oldmode.extmodeparam, chptr->mode.extmodeparam);
|
||||
switch (r)
|
||||
{
|
||||
case EXSJ_WEWON:
|
||||
parax = ExtCMode_Table[i].get_param(oldmode.extmodeparam);
|
||||
Debug((DEBUG_DEBUG, "sjoin: we won: '%s'", parax));
|
||||
chptr->mode.extmodeparam = ExtCMode_Table[i].put_param(oldmode.extmodeparam, parax);
|
||||
break;
|
||||
case EXSJ_THEYWON:
|
||||
parax = ExtCMode_Table[i].get_param(chptr->mode.extmodeparam);
|
||||
Debug((DEBUG_DEBUG, "sjoin: they won: '%s'", parax));
|
||||
Addit(ExtCMode_Table[i].flag, parax);
|
||||
break;
|
||||
case EXSJ_SAME:
|
||||
Debug((DEBUG_DEBUG, "sjoin: equal"));
|
||||
break;
|
||||
default:
|
||||
ircd_log(LOG_ERROR, "channel.c:m_sjoin:param diff checker: got unk. retval 0x%x??", r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Addsingle('\0');
|
||||
|
||||
if (modebuf[1])
|
||||
|
@ -5144,6 +5439,11 @@ CMD_FUNC(m_sjoin)
|
|||
sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",
|
||||
sptr->name, chptr->chname, modebuf, parabuf);
|
||||
}
|
||||
#ifdef EXTCMODE
|
||||
/* free the oldmode.* crap :( */
|
||||
extcmode_free_paramlist(oldmode.extmodeparam);
|
||||
oldmode.extmodeparam = NULL; /* just to be sure ;) */
|
||||
#endif
|
||||
}
|
||||
|
||||
/* we should be synched by now, */
|
||||
|
|
222
src/extcmodes.c
Normal file
222
src/extcmodes.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, s_unreal.c
|
||||
* (C) 2003 Bram Matthys (Syzop) and the UnrealIRCd Team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "msg.h"
|
||||
#include "proto.h"
|
||||
#include "channel.h"
|
||||
#include "version.h"
|
||||
#include <time.h>
|
||||
#ifdef _WIN32
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "h.h"
|
||||
|
||||
#ifdef EXTCMODE
|
||||
|
||||
extern char cmodestring[512];
|
||||
|
||||
extern void make_cmodestr(void);
|
||||
|
||||
char extchmstr[4][64];
|
||||
|
||||
aExtCMtable *ExtCMode_Table = NULL;
|
||||
unsigned short ExtCMode_highest = 0;
|
||||
|
||||
void make_extcmodestr()
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
extchmstr[0][0] = extchmstr[1][0] = extchmstr[2][0] = extchmstr[3][0] = '\0';
|
||||
|
||||
/* type 1: lists (like b/e) */
|
||||
/* [NOT IMPLEMENTED IN EXTCMODES] */
|
||||
|
||||
/* type 2: 1 par to set/unset */
|
||||
/* [NOT IMPLEMENTED] */
|
||||
|
||||
/* type 3: 1 param to set, 0 params to unset */
|
||||
p = extchmstr[2];
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
if (ExtCMode_Table[i].paracount && ExtCMode_Table[i].flag)
|
||||
*p++ = ExtCMode_Table[i].flag;
|
||||
*p = '\0';
|
||||
|
||||
/* type 4: paramless modes */
|
||||
p = extchmstr[3];
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
if (!ExtCMode_Table[i].paracount && ExtCMode_Table[i].flag)
|
||||
*p++ = ExtCMode_Table[i].flag;
|
||||
*p = '\0';
|
||||
printf("dect: %s/%s/%s/%s\n", extchmstr[0], extchmstr[1], extchmstr[2], extchmstr[3]);
|
||||
}
|
||||
|
||||
|
||||
void extcmode_init(void)
|
||||
{
|
||||
ExtCMode val = 1;
|
||||
int i;
|
||||
ExtCMode_Table = (aExtCMtable *)MyMalloc(sizeof(aExtCMtable) * EXTCMODETABLESZ);
|
||||
bzero(ExtCMode_Table, sizeof(aExtCMtable) * EXTCMODETABLESZ);
|
||||
for (i = 0; i < EXTCMODETABLESZ; i++)
|
||||
{
|
||||
ExtCMode_Table[i].mode = val;
|
||||
val *= 2;
|
||||
}
|
||||
ExtCMode_highest = 0;
|
||||
memset(&extchmstr, 0, sizeof(extchmstr));
|
||||
}
|
||||
|
||||
ExtCMode extcmode_get(aExtCMtable *req)
|
||||
{
|
||||
short i = 0, j = 0;
|
||||
ExtCMode tmp;
|
||||
|
||||
while (i < EXTCMODETABLESZ)
|
||||
{
|
||||
if (!ExtCMode_Table[i].flag)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
if (i == EXTCMODETABLESZ)
|
||||
{
|
||||
Debug((DEBUG_DEBUG, "extcmode_get failed, no space"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = ExtCMode_Table[i].mode;
|
||||
memcpy(&ExtCMode_Table[i], req, sizeof(aExtCMtable));
|
||||
ExtCMode_Table[i].mode = tmp;
|
||||
Debug((DEBUG_DEBUG, "extcmode_get(flag = '%c') returning %04x",
|
||||
req->flag, ExtCMode_Table[i].mode));
|
||||
/* Update extended channel mode table highest */
|
||||
for (j = 0; j < EXTCMODETABLESZ; j++)
|
||||
if (ExtCMode_Table[j].flag)
|
||||
if (j > ExtCMode_highest)
|
||||
ExtCMode_highest = j;
|
||||
make_cmodestr();
|
||||
make_extcmodestr();
|
||||
return (ExtCMode_Table[i].mode);
|
||||
}
|
||||
|
||||
|
||||
int extcmode_delete(char ch)
|
||||
{
|
||||
int i = 0;
|
||||
Debug((DEBUG_DEBUG, "extcmode_delete %c", ch));
|
||||
|
||||
/* TODO: remove from all channels */
|
||||
|
||||
while (i < EXTCMODETABLESZ)
|
||||
{
|
||||
if (ExtCMode_Table[i].flag == ch)
|
||||
{
|
||||
ExtCMode_Table[i].flag = '\0';
|
||||
return 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** searches in chptr extmode parameters and returns entry or NULL. */
|
||||
aExtCMtableParam *extcmode_get_struct(aExtCMtableParam *p, char ch)
|
||||
{
|
||||
|
||||
while(p)
|
||||
{
|
||||
if (p->flag == ch)
|
||||
return p;
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* bit inefficient :/ */
|
||||
aExtCMtableParam *extcmode_duplicate_paramlist(aExtCMtableParam *lst)
|
||||
{
|
||||
int i;
|
||||
aExtCMtable *tbl;
|
||||
aExtCMtableParam *head = NULL, *n;
|
||||
|
||||
while(lst)
|
||||
{
|
||||
tbl = NULL;
|
||||
for (i=0; i <= ExtCMode_highest; i++)
|
||||
{
|
||||
if (ExtCMode_Table[i].flag == lst->flag)
|
||||
{
|
||||
tbl = &ExtCMode_Table[i]; /* & ? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
n = tbl->dup_struct(lst);
|
||||
if (head)
|
||||
{
|
||||
AddListItem(n, head);
|
||||
} else {
|
||||
head = n;
|
||||
}
|
||||
lst = lst->next;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
void extcmode_free_paramlist(aExtCMtableParam *lst)
|
||||
{
|
||||
aExtCMtableParam *n; /* prolly not needed but I'm afraid of aliasing and stuff :p */
|
||||
|
||||
while(lst)
|
||||
{
|
||||
n = lst;
|
||||
DelListItem(n, lst);
|
||||
}
|
||||
}
|
||||
|
||||
int extcmode_default_requirechop(aClient *cptr, aChannel *chptr, char *para, int checkt, int what)
|
||||
{
|
||||
if (IsPerson(cptr) && is_chan_op(cptr, chptr))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extcmode_default_requirehalfop(aClient *cptr, aChannel *chptr, char *para, int checkt, int what)
|
||||
{
|
||||
if (IsPerson(cptr) &&
|
||||
(is_chan_op(cptr, chptr) || is_half_op(cptr, chptr)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* EXTCMODE */
|
|
@ -856,6 +856,9 @@ int InitwIRCD(int argc, char *argv[])
|
|||
setup_signals();
|
||||
init_ircstats();
|
||||
umode_init();
|
||||
#ifdef EXTCMODE
|
||||
extcmode_init();
|
||||
#endif
|
||||
clear_scache_hash_table();
|
||||
#ifdef FORCE_CORE
|
||||
corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
|
||||
|
@ -1096,6 +1099,9 @@ int InitwIRCD(int argc, char *argv[])
|
|||
load_tunefile();
|
||||
make_umodestr();
|
||||
make_cmodestr();
|
||||
#ifdef EXTCMODE
|
||||
make_extcmodestr();
|
||||
#endif
|
||||
if (!find_Command_simple("AWAY") || !find_Command_simple("KILL") ||
|
||||
!find_Command_simple("OPER") || !find_Command_simple("PING"))
|
||||
{
|
||||
|
|
|
@ -89,7 +89,8 @@ Module *Module_Find(char *name)
|
|||
|
||||
for (p = Modules; p; p = p->next)
|
||||
{
|
||||
if (!(p->flags & MODFLAG_TESTING) || (p->flags & MODFLAG_DELAYED))
|
||||
if (!p->permanent &&
|
||||
(!(p->flags & MODFLAG_TESTING) || (p->flags & MODFLAG_DELAYED)))
|
||||
continue;
|
||||
if (!strcmp(p->header->name, name))
|
||||
{
|
||||
|
@ -120,6 +121,7 @@ char *Module_Create(char *path_)
|
|||
ModuleHeader *mod_header;
|
||||
int ret = 0;
|
||||
Module *mod = NULL, **Mod_Handle = NULL;
|
||||
int *x;
|
||||
int betaversion,tag;
|
||||
Debug((DEBUG_DEBUG, "Attempting to load module from %s",
|
||||
path_));
|
||||
|
@ -166,6 +168,10 @@ char *Module_Create(char *path_)
|
|||
return (NULL);
|
||||
}
|
||||
mod = (Module *)Module_make(mod_header, Mod);
|
||||
irc_dlsym(Mod, "permanent_module", x);
|
||||
if (x && (*x == 1))
|
||||
mod->permanent = 1;
|
||||
|
||||
irc_dlsym(Mod, "Mod_Init", Mod_Init);
|
||||
if (!Mod_Init)
|
||||
{
|
||||
|
@ -310,7 +316,7 @@ void Unload_all_loaded_modules(void)
|
|||
for (mi = Modules; mi; mi = next)
|
||||
{
|
||||
next = mi->next;
|
||||
if (!(mi->flags & MODFLAG_LOADED) || (mi->flags & MODFLAG_DELAYED))
|
||||
if (!(mi->flags & MODFLAG_LOADED) || (mi->flags & MODFLAG_DELAYED) || mi->permanent)
|
||||
continue;
|
||||
irc_dlsym(mi->dll, "Mod_Unload", Mod_Unload);
|
||||
if (Mod_Unload)
|
||||
|
@ -703,12 +709,14 @@ int m_module(aClient *cptr, aClient *sptr, int parc, char *parv[])
|
|||
}
|
||||
for (mi = Modules; mi; mi = mi->next)
|
||||
{
|
||||
char delayed[32];
|
||||
char tmp[256];
|
||||
tmp[0] = '\0';
|
||||
if (mi->flags & MODFLAG_DELAYED)
|
||||
strcpy(delayed, "[Unloading]");
|
||||
strcat(tmp, "[Unloading] ");
|
||||
if (mi->permanent)
|
||||
strcat(tmp, "[PERM] ");
|
||||
sendto_one(sptr, ":%s NOTICE %s :*** %s - %s (%s) %s", me.name, sptr->name,
|
||||
mi->header->name, mi->header->version, mi->header->description,
|
||||
(mi->flags & MODFLAG_DELAYED) ? delayed : "");
|
||||
mi->header->name, mi->header->version, mi->header->description, tmp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
230
src/modules/m_chmodetst.c
Normal file
230
src/modules/m_chmodetst.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Test for modulized channelmode system, adds 2 modes:
|
||||
* +w (paramless)
|
||||
* +y <0-100> (1 parameter)
|
||||
*
|
||||
* It's incomplete (like error signaling) but for testing purposes only.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "msg.h"
|
||||
#include "proto.h"
|
||||
#include "channel.h"
|
||||
#include <time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "h.h"
|
||||
#ifdef STRIPBADWORDS
|
||||
#include "badwords.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "version.h"
|
||||
#endif
|
||||
|
||||
#ifndef DYNAMIC_LINKING
|
||||
ModuleHeader m_chmodetst_Header
|
||||
#else
|
||||
#define m_chmodetst_Header Mod_Header
|
||||
ModuleHeader Mod_Header
|
||||
#endif
|
||||
= {
|
||||
"chmodetst", /* Name of module */
|
||||
"channelmode test", /* Version */
|
||||
"channelmode +w", /* Short description of module */
|
||||
"3.2-b8-1",
|
||||
NULL,
|
||||
};
|
||||
|
||||
ExtCMode EXTCMODE_TEST = 0L; /* Just for testing */
|
||||
ExtCMode EXTCMODE_TEST2 = 0L; /* Just for testing */
|
||||
|
||||
int permanent_module = 1;
|
||||
|
||||
int modey_is_ok(aClient *sptr, aChannel *chptr, char *para, int checkt, int what);
|
||||
aExtCMtableParam * modey_put_param(aExtCMtableParam *lst, char *para);
|
||||
char *modey_get_param(aExtCMtableParam *lst);
|
||||
char *modey_conv_param(char *param);
|
||||
aExtCMtableParam * modey_free_param(aExtCMtableParam *lst);
|
||||
aExtCMtableParam *modey_dup_struct(aExtCMtableParam *src);
|
||||
int modey_sjoin_check(aChannel *chptr, aExtCMtableParam *ourx, aExtCMtableParam *theirx);
|
||||
aExtCMtableParam *modey_dup_struct(aExtCMtableParam *src);
|
||||
int modey_sjoin_check(aChannel *chptr, aExtCMtableParam *ourx, aExtCMtableParam *theirx);
|
||||
|
||||
typedef struct {
|
||||
EXTCM_PAR_HEADER
|
||||
short val;
|
||||
} aModewentry;
|
||||
|
||||
/* The purpose of these ifdefs, are that we can "static" link the ircd if we
|
||||
* want to
|
||||
*/
|
||||
|
||||
/* This is called on module init, before Server Ready */
|
||||
#ifdef DYNAMIC_LINKING
|
||||
DLLFUNC int Mod_Init(ModuleInfo *modinfo)
|
||||
#else
|
||||
int m_dummy_Init(ModuleInfo *modinfo)
|
||||
#endif
|
||||
{
|
||||
aExtCMtable req;
|
||||
ircd_log(LOG_ERROR, "debug: mod_init called from chmodetst module");
|
||||
sendto_realops("chmodetst loading...");
|
||||
/* TODO: load mode here */
|
||||
/* +w doesn't do anything, it's just for testing */
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.paracount = 0;
|
||||
req.is_ok = extcmode_default_requirechop;
|
||||
req.flag = 'w';
|
||||
EXTCMODE_TEST = extcmode_get(&req);
|
||||
/* +y doesn't do anything except that you can set/unset it with a
|
||||
* numeric parameter (1-100)
|
||||
*/
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.paracount = 1;
|
||||
req.is_ok = modey_is_ok;
|
||||
req.put_param = modey_put_param;
|
||||
req.get_param = modey_get_param;
|
||||
req.conv_param = modey_conv_param;
|
||||
req.free_param = modey_free_param;
|
||||
req.sjoin_check = modey_sjoin_check;
|
||||
req.dup_struct = modey_dup_struct;
|
||||
req.flag = 'y';
|
||||
EXTCMODE_TEST2 = extcmode_get(&req);
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
/* Is first run when server is 100% ready */
|
||||
#ifdef DYNAMIC_LINKING
|
||||
DLLFUNC int Mod_Load(int module_load)
|
||||
#else
|
||||
int m_dummy_Load(int module_load)
|
||||
#endif
|
||||
{
|
||||
return MOD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Called when module is unloaded */
|
||||
#ifdef DYNAMIC_LINKING
|
||||
DLLFUNC int Mod_Unload(int module_unload)
|
||||
#else
|
||||
int m_dummy_Unload(int module_unload)
|
||||
#endif
|
||||
{
|
||||
/* Aaaaaaaargh... we are assumed to be a permanent module */
|
||||
sendto_realops("Mod_Unload was called??? Arghhhhhh..");
|
||||
return MOD_FAILED;
|
||||
}
|
||||
|
||||
int modey_is_ok(aClient *sptr, aChannel *chptr, char *para, int checkt, int what)
|
||||
{
|
||||
short t;
|
||||
|
||||
if ((checkt == EXCHK_ACCESS) || (checkt == EXCHK_ACCESS_ERR))
|
||||
{
|
||||
if (!is_chan_op(sptr, chptr))
|
||||
{
|
||||
if (checkt == EXCHK_ACCESS_ERR)
|
||||
sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, sptr->name, chptr->chname);
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
if (checkt == EXCHK_PARAM)
|
||||
{
|
||||
t = (short)atoi(para);
|
||||
if ((t < 0) || (t > 100))
|
||||
{
|
||||
sendto_one(sptr, ":%s NOTICE %s :chanmode +y requires a parameter in the range 0..100",
|
||||
me.name, sptr->name);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
aExtCMtableParam * modey_put_param(aExtCMtableParam *lst, char *para)
|
||||
{
|
||||
aModewentry *r;
|
||||
|
||||
r = (aModewentry *)extcmode_get_struct(lst, 'y');
|
||||
Debug((DEBUG_DEBUG, "modey_put_param: get_struct returned 0x%x", r));
|
||||
if (!r)
|
||||
{
|
||||
/* Need to create one */
|
||||
r = (aModewentry *)malloc(sizeof(aModewentry));
|
||||
memset(r, 0, sizeof(aModewentry));
|
||||
r->flag = 'y';
|
||||
AddListItem(r, lst);
|
||||
}
|
||||
r->val = (short)atoi(para);
|
||||
return lst;
|
||||
}
|
||||
|
||||
char *modey_get_param(aExtCMtableParam *lst)
|
||||
{
|
||||
aModewentry *r;
|
||||
static char tmpret[16];
|
||||
|
||||
r = (aModewentry *)extcmode_get_struct(lst, 'y');
|
||||
if (!r)
|
||||
return NULL;
|
||||
sprintf(tmpret, "%hu", r->val);
|
||||
return tmpret;
|
||||
}
|
||||
|
||||
/* no this is not useless, imagine the parameter "1blah" :P */
|
||||
char *modey_conv_param(char *param)
|
||||
{
|
||||
short i;
|
||||
static char tmpret2[16];
|
||||
i = (short)atoi(param);
|
||||
sprintf(tmpret2, "%hu", i);
|
||||
return tmpret2;
|
||||
}
|
||||
|
||||
aExtCMtableParam * modey_free_param(aExtCMtableParam *lst)
|
||||
{
|
||||
aModewentry *r;
|
||||
r = (aModewentry *)extcmode_get_struct(lst, 'y');
|
||||
Debug((DEBUG_DEBUG, "modey_free_param: lst=0x%x, r=0x%x", lst, r));
|
||||
if (r)
|
||||
{
|
||||
DelListItem(r, lst);
|
||||
free(r);
|
||||
}
|
||||
Debug((DEBUG_DEBUG, "modey_free_param: returning 0x%x", lst));
|
||||
return lst;
|
||||
}
|
||||
|
||||
aExtCMtableParam *modey_dup_struct(aExtCMtableParam *src)
|
||||
{
|
||||
aModewentry *n = (aModewentry *)malloc(sizeof(aModewentry));
|
||||
memcpy(n, src, sizeof(aModewentry));
|
||||
return (aExtCMtableParam *)n;
|
||||
}
|
||||
|
||||
int modey_sjoin_check(aChannel *chptr, aExtCMtableParam *ourx, aExtCMtableParam *theirx)
|
||||
{
|
||||
aModewentry *our = (aModewentry *)ourx;
|
||||
aModewentry *their = (aModewentry *)theirx;
|
||||
|
||||
if (our->val == their->val)
|
||||
return EXSJ_SAME;
|
||||
if (our->val > their->val)
|
||||
return EXSJ_WEWON;
|
||||
else
|
||||
return EXSJ_THEYWON;
|
||||
}
|
|
@ -85,6 +85,9 @@ char serveropts[] = {
|
|||
#endif
|
||||
#ifdef ZIP_LINKS
|
||||
'Z',
|
||||
#endif
|
||||
#ifdef EXTCMODE
|
||||
'E',
|
||||
#endif
|
||||
'\0'
|
||||
};
|
||||
|
|
|
@ -1065,13 +1065,16 @@ CMD_FUNC(m_server_remote)
|
|||
*/
|
||||
void send_proto(aClient *cptr, ConfigItem_link *aconf)
|
||||
{
|
||||
char buf[512];
|
||||
sprintf(buf, "CHANMODES=%s%s,%s%s,%s%s,%s%s",
|
||||
CHPAR1, EXPAR1, CHPAR2, EXPAR2, CHPAR3, EXPAR3, CHPAR4, EXPAR4);
|
||||
#ifdef ZIP_LINKS
|
||||
if (aconf->options & CONNECT_ZIP)
|
||||
{
|
||||
sendto_one(cptr, "PROTOCTL %s ZIP", PROTOCTL_SERVER);
|
||||
sendto_one(cptr, "PROTOCTL %s ZIP %s", PROTOCTL_SERVER, buf);
|
||||
} else {
|
||||
#endif
|
||||
sendto_one(cptr, "PROTOCTL %s", PROTOCTL_SERVER);
|
||||
sendto_one(cptr, "PROTOCTL %s %s", PROTOCTL_SERVER, buf);
|
||||
#ifdef ZIP_LINKS
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue