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 }