Dev:Extended Bans API

Writing a custom extended ban type is relatively easy as all you have to deal with is strings and/or return a value.

= Creating an extban = Similar to Dev:Channel Mode API you call the function to register your extban from MOD_INIT and you throw a struct at it like this: MOD_INIT { ExtbanInfo extban;

memset(&extban, 0, sizeof(extban)); extban.flag = 'X'; extban.is_ok = mymod_is_ok; extban.conv_param = mymod_conv_param; extban.is_banned = mymod_is_banned; extban.options = EXTBOPT_ACTMODIFIER; ExtbanAdd(modinfo->handle, extban);

So basically you pass: 1) the module handle, 2) a ExtbanInfo struct

The ExtbanInfo struct contains the following (regular) variables which you may set:
 * flag: specifies which letter the extban uses. For example 'X' would mean +b ~X:..etc.. Naturally there may be no other module using this letter.
 * options: TODO

Other than that, the ExtbanInfo struct contains of function pointers which you must set. Only conv_param and is_banned are required. See below.

conv_param
Convert input parameter to a 'correct' parameter. For example if you wish +b ~X:blah to be converted to +b ~X:blah!*@*.

Declaration of the conv_param function: char *conv_param(char *para)

You should return a string (a char * to static storage!), or NULL if you wish to reject an invalid parameter. For better "is this parameter okay?" checking you can also use the is_ok function (in addition).

Example code: /* Silly example that converts ~X:somestring where somestring will be of max 8 characters in size. */ char *mymod_conv_param(char *para) { static char ret[3 + 8 + 1]; /* ~X:12345678 */

if (strlen(para) == 3) return NULL; /* just "+b ~X:" is rejected */

snprintf(ret, sizeof(ret), "~X:%s", para + 3); /* could use strlcpy here but this illustrates it better */ return ret; }

There is also some help from the UnrealIRCd side:
 * instead of writing your own conv_param you can use extban_conv_param_nuh which will accept and convert input to a nick!user@host (resulting in something like ~X:nick!user@host)
 * similarly you can use extban_conv_param_nuh_or_extban which will allow a nick!user@host or another extban, so to allow extban stacking (eg: ~X:~r:*somerealname*)

is_ok
Access and parameter checking. This is completely optional and actually often not used. See also conv_param.

Declaration of the is_ok function: int is_ok(Client *client, Channel *channel, char *para, int checkt, int what, int what2)

The is_ok function is called in a number of cases:
 * If checkt is EXBCHK_ACCESS then the function is called to check if the user may set/unset the mode. You must only check access and NOT send any error message(s). If access is granted you should return EX_ALLOW. If you want to disallow a set/unset then return EX_DENY. Normally IRC Operators with override capabilities may still override a deny, if you also want to prevent IRCOp's from (un)setting then you can return EX_ALWAYS_DENY.
 * When checkt is EXCHK_ACCESS_ERR it means your function is called (again) to check access but this time you may send an error message to the user (in fact, you are expected to), indicating why setting or unsetting is not permitted.
 * Finally, when checkt is EXCHK_PARAM then you are supposed to check the correctness of the parameter being passed. If it's not good (eg: you expect ~X:num where num is a value between 1 and 20 and you recieve 'lalala' or '30') then you return EX_DENY. Otherwise you return EX_ALLOW. You should also send an error message to the user telling them what's wrong.

Example: TODO

is_banned
Check if a user is affected by this ban.

Declaration: int is_banned(Client *client, Channel *channel, char *ban, int bancheckt, char **msg, char **errmsg)

Return: simply return 1 if the user is banned and 0 otherwise.

The bancheckt decides what kind of check you need to do:

Example code: /* Dull example of a ~X:blah ban type where 'blah' must match the exact nick name of the user. No wildcards. */ int mymod_is_banned(Client *client, Channel *channel, char *banin, int type, char **msg, char **errmsg) {   ban += 3; /* we don't care about the "~X:" part, so skip over it. */

if (!stricmp(ban, client->name)) return 1; return 0; }