unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

limit.c (4962B)

      1 /*
      2  * Channel Mode +l
      3  * (C) Copyright 2021 Syzop and the UnrealIRCd team
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 1, or (at your option)
      8  * any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program; if not, write to the Free Software
     17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #include "unrealircd.h"
     21 
     22 ModuleHeader MOD_HEADER
     23   = {
     24 	"chanmodes/limit",
     25 	"6.0",
     26 	"Channel Mode +l",
     27 	"UnrealIRCd Team",
     28 	"unrealircd-6",
     29     };
     30 
     31 typedef struct ChannelLimit ChannelLimit;
     32 struct ChannelLimit {
     33 	int limit;
     34 };
     35 
     36 /* Global variables */
     37 ModDataInfo *mdlimit = NULL;
     38 Cmode_t EXTMODE_LIMIT = 0L;
     39 
     40 #define IsLimit(x)	((x)->mode.mode & EXTMODE_LIMIT)
     41 
     42 /* Just for buffers, nothing else */
     43 #define LIMITLEN	32
     44 
     45 /* Forward declarations */
     46 int limit_can_join(Client *client, Channel *channel, const char *key, char **errmsg);
     47 int cmode_limit_is_ok(Client *client, Channel *channel, char mode, const char *para, int type, int what);
     48 void *cmode_limit_put_param(void *r_in, const char *param);
     49 const char *cmode_limit_get_param(void *r_in);
     50 const char *cmode_limit_conv_param(const char *param_in, Client *client, Channel *channel);
     51 int cmode_limit_free_param(void *r, int soft);
     52 void *cmode_limit_dup_struct(void *r_in);
     53 int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx);
     54 int transform_channel_limit(const char *param);
     55 
     56 MOD_INIT()
     57 {
     58 	CmodeInfo creq;
     59 	ModDataInfo mreq;
     60 
     61 	MARK_AS_OFFICIAL_MODULE(modinfo);
     62 
     63 	memset(&creq, 0, sizeof(creq));
     64 	creq.paracount = 1;
     65 	creq.is_ok = cmode_limit_is_ok;
     66 	creq.letter = 'l';
     67 	creq.put_param = cmode_limit_put_param;
     68 	creq.get_param = cmode_limit_get_param;
     69 	creq.conv_param = cmode_limit_conv_param;
     70 	creq.free_param = cmode_limit_free_param;
     71 	creq.dup_struct = cmode_limit_dup_struct;
     72 	creq.sjoin_check = cmode_limit_sjoin_check;
     73 	CmodeAdd(modinfo->handle, creq, &EXTMODE_LIMIT);
     74 
     75 	HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, limit_can_join);
     76 	return MOD_SUCCESS;
     77 }
     78 
     79 MOD_LOAD()
     80 {
     81 	return MOD_SUCCESS;
     82 }
     83 
     84 MOD_UNLOAD()
     85 {
     86 	return MOD_SUCCESS;
     87 }
     88 
     89 /** Can the user join the channel? */
     90 int limit_can_join(Client *client, Channel *channel, const char *key, char **errmsg)
     91 {
     92 	ChannelLimit *r = (ChannelLimit *)GETPARASTRUCT(channel, 'l');
     93 
     94 	/* Is the channel +l? */
     95 	if (r && r->limit && (channel->users >= r->limit))
     96 	{
     97 		Hook *h;
     98 		for (h = Hooks[HOOKTYPE_CAN_JOIN_LIMITEXCEEDED]; h; h = h->next) 
     99 		{
    100 			int i = (*(h->func.intfunc))(client,channel,key,errmsg);
    101 			if (i != 0)
    102 				return i;
    103 		}
    104 		*errmsg = STR_ERR_CHANNELISFULL;
    105 		return ERR_CHANNELISFULL;
    106 	}
    107 
    108 	return 0;
    109 }
    110 
    111 int cmode_limit_is_ok(Client *client, Channel *channel, char mode, const char *param, int type, int what)
    112 {
    113 	if ((type == EXCHK_ACCESS) || (type == EXCHK_ACCESS_ERR))
    114 	{
    115 		/* Permitted for +hoaq */
    116 		if (IsUser(client) && check_channel_access(client, channel, "hoaq"))
    117 			return EX_ALLOW;
    118 		return EX_DENY;
    119 	} else
    120 	if (type == EXCHK_PARAM)
    121 	{
    122 		/* Actually any value is valid, we just morph it */
    123 		return EX_ALLOW;
    124 	}
    125 
    126 	/* fallthrough -- should not be used */
    127 	return EX_DENY;
    128 }
    129 
    130 void *cmode_limit_put_param(void *k_in, const char *param)
    131 {
    132 	ChannelLimit *fld = (ChannelLimit *)k_in;
    133 
    134 	if (!fld)
    135 		fld = safe_alloc(sizeof(ChannelLimit));
    136 
    137 	fld->limit = transform_channel_limit(param);
    138 
    139 	return fld;
    140 }
    141 
    142 const char *cmode_limit_get_param(void *r_in)
    143 {
    144 	ChannelLimit *r = (ChannelLimit *)r_in;
    145 	static char retbuf[32];
    146 
    147 	if (!r)
    148 		return NULL;
    149 
    150 	snprintf(retbuf, sizeof(retbuf), "%d", r->limit);
    151 	return retbuf;
    152 }
    153 
    154 const char *cmode_limit_conv_param(const char *param, Client *client, Channel *channel)
    155 {
    156 	static char retbuf[32];
    157 	int v = transform_channel_limit(param);
    158 	snprintf(retbuf, sizeof(retbuf), "%d", v);
    159 	return retbuf;
    160 }
    161 
    162 int cmode_limit_free_param(void *r, int soft)
    163 {
    164 	safe_free(r);
    165 	return 0;
    166 }
    167 
    168 void *cmode_limit_dup_struct(void *r_in)
    169 {
    170 	ChannelLimit *r = (ChannelLimit *)r_in;
    171 	ChannelLimit *w = safe_alloc(sizeof(ChannelLimit));
    172 
    173 	memcpy(w, r, sizeof(ChannelLimit));
    174 
    175 	return (void *)w;
    176 }
    177 
    178 int cmode_limit_sjoin_check(Channel *channel, void *ourx, void *theirx)
    179 {
    180 	ChannelLimit *our = (ChannelLimit *)ourx;
    181 	ChannelLimit *their = (ChannelLimit *)theirx;
    182 
    183 	if (our->limit == their->limit)
    184 		return EXSJ_SAME;
    185 	else if (our->limit > their->limit)
    186 		return EXSJ_WEWON;
    187 	else
    188 		return EXSJ_THEYWON;
    189 }
    190 
    191 int transform_channel_limit(const char *param)
    192 {
    193 	int v = atoi(param);
    194 	if (v <= 0)
    195 		v = 1; /* setting +l with a negative number makes no sense */
    196 	if (v > 1000000)
    197 		v = 1000000; /* some kind of limit, 1 million (mrah...) */
    198 	return v;
    199 }