├── files ├── README.md ├── examplemod.c ├── react.c ├── polite-tag.c ├── extwarn.c ├── dumpcmds.c ├── showwebirc.c ├── webirconly.c ├── noinvite.c ├── restrict-chans.c ├── findchmodes.c ├── getlegitusers.c ├── rehashgem.c ├── display-name.c ├── uline_nickhost.c ├── message_commonchans.c ├── banfix_voice.c ├── operoverride_ext.c ├── kiwiirc-tags.c ├── logged-in-from.c ├── cmdslist.c ├── plainusers.c ├── tracetklbug.c ├── listsg.c ├── filehost.c ├── reduced-moderation.c ├── sacycle.c ├── chgswhois.c ├── irccloud-tags.c ├── block_no_tls.c ├── topicgreeting.c ├── pubnetinfo.c ├── allsend.c ├── upgrade-notify.c ├── clones.c ├── commandsno.c ├── mtag-extban.c ├── welcomemessages.c ├── incredibly-lazy-ops.c ├── block_notlsident.c ├── hidebans.c ├── anti_amsg.c ├── recover.c ├── helpop.c ├── portsifresi.c ├── redact.c ├── dictionary.c ├── operpasswd.c └── nicklock.c ├── .gitignore ├── .github └── pull_request_template.md └── README.md /files/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore editor files 2 | *\#* 3 | *~ 4 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | IMPORTANT!! 2 | 3 | DO NOT file a PR for modules that are not yours! 4 | You should contact the 3rd party module author/maintainer instead. 5 | 6 | The UnrealIRCd team only accepts changes from the module maintainer. 7 | We cannot judge PR's on the maintainer's behalf. All changes, 8 | small or big, must come from the module maintainer to maintain 9 | a clear division of responsibilities. 10 | 11 | Only file a PR if: 12 | * You are the maintainer of the existing module, OR 13 | * You are submitting a new module and have read 14 | https://www.unrealircd.org/docs/Rules_for_3rd_party_modules_in_unrealircd-contrib 15 | 16 | Thanks! 17 | -------------------------------------------------------------------------------- /files/examplemod.c: -------------------------------------------------------------------------------- 1 | /** third/examplemod 2 | * (C) Copyright 2019 Bram Matthys ("Syzop") 3 | * License: GPLv2 4 | */ 5 | #include "unrealircd.h" 6 | 7 | ModuleHeader MOD_HEADER 8 | = { 9 | "third/examplemod", /* name */ 10 | "1.0.0", /* version */ 11 | "This is a simple test module", /* description */ 12 | "Bram Matthys (Syzop)", /* author */ 13 | "unrealircd-5", 14 | }; 15 | 16 | MOD_INIT() 17 | { 18 | return MOD_SUCCESS; 19 | } 20 | 21 | /*** <<>> 22 | module 23 | { 24 | // THE FOLLOWING FIELDS ARE MANDATORY: 25 | 26 | // Documentation, as displayed in './unrealircd module info nameofmodule', and possibly at other places: 27 | documentation "https://www.unrealircd.org/docs/"; 28 | 29 | // This is displayed in './unrealircd module info ..' and also if compilation of the module fails: 30 | troubleshooting "In case of problems, check the FAQ at ... or e-mail me at ..."; 31 | 32 | // Minimum version necessary for this module to work: 33 | min-unrealircd-version "5.*"; 34 | 35 | // THE FOLLOWING FIELDS ARE OPTIONAL: 36 | 37 | // Maximum version that this module supports: 38 | max-unrealircd-version "5.*"; 39 | 40 | // This text is displayed after running './unrealircd module install ...' 41 | // It is recommended not to make this an insane number of lines and refer to a URL instead 42 | // if you have lots of text/information to share: 43 | post-install-text { 44 | "The module is installed. Now all you need to do is add a loadmodule line:"; 45 | "loadmodule \"third/examplemod\";"; 46 | "And /REHASH the IRCd."; 47 | "The module does not need any other configuration."; 48 | } 49 | } 50 | *** <<>> 51 | */ 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is the unrealircd-contrib repository. It contains 3rd party modules for UnrealIRCd 6. 2 | 3 | ## Use at your own risk 4 | 5 | These third party modules are **not** written by the UnrealIRCd team and not tested by us. 6 | Use these modules at your own risk. **In case of problems, contact 7 | the author of the module.** 8 | 9 | ## For end-users 10 | To view a list of available modules online, go to https://modules.unrealircd.org/ 11 | 12 | On the command line you can use the [UnrealIRCd module manager](https://www.unrealircd.org/docs/Module_manager) 13 | to list and (un)install modules, eg: 14 | * ```./unrealircd module list``` - to list all modules 15 | * ```./unrealircd module info third/something``` - to show all information about a specific module 16 | * ```./unrealircd module install third/something``` - to install the specified module 17 | 18 | ## Bugs, fixes and enhancements 19 | If you find a bug or would like to submit a fix or enhancement in a module, then 20 | you must contact the author/maintainer of the module. 21 | The [UnrealIRCd modules forum](https://forums.unrealircd.org/viewforum.php?f=54) 22 | may also be a useful place to visit. 23 | 24 | **Do NOT contact the UnrealIRCd team and do not file a PR.** 25 | We are not the correct person to judge if a fix or enhancement is good or bad. 26 | After all, the UnrealIRCd team does not maintain or even test the functionality of the module, 27 | that responsibility is delegated to the module maintainer. 28 | Pull Requests (PRs) for existing modules are only accepted from the maintainer of that module. 29 | 30 | Only if you do not receive a response from the module author and there are grave 31 | issues then you can contact the UnrealIRCd team for removal of the module or 32 | change of maintainership. 33 | 34 | ## For module coders 35 | If you are a module coder and want to add your module to this repository 36 | as well, then read the rules and procedure at: 37 | https://www.unrealircd.org/docs/Rules_for_3rd_party_modules_in_unrealircd-contrib 38 | -------------------------------------------------------------------------------- /files/react.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2022 Valerie Pond 4 | draft/react 5 | 6 | React to a message 7 | */ 8 | /*** <<>> 9 | module 10 | { 11 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/react/README.md"; 12 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 13 | min-unrealircd-version "6.*"; 14 | max-unrealircd-version "6.*"; 15 | post-install-text { 16 | "The module is installed. Now all you need to do is add a loadmodule line:"; 17 | "loadmodule \"third/react\";"; 18 | "You need to restart your server for this to show up in CLIENTTAGDENY"; 19 | "The module does not need any other configuration."; 20 | } 21 | } 22 | *** <<>> 23 | */ 24 | 25 | 26 | #include "unrealircd.h" 27 | 28 | ModuleHeader MOD_HEADER 29 | = { 30 | "third/react", 31 | "0.1", 32 | "+draft/react (IRCv3)", 33 | "Valware", 34 | "unrealircd-6", 35 | }; 36 | 37 | int i3react_mtag_is_ok(Client *client, const char *name, const char *value); 38 | void mtag_add_i3react(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature); 39 | 40 | MOD_INIT() 41 | { 42 | MessageTagHandlerInfo mtag; 43 | 44 | MARK_AS_GLOBAL_MODULE(modinfo); 45 | 46 | memset(&mtag, 0, sizeof(mtag)); 47 | mtag.is_ok = i3react_mtag_is_ok; 48 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 49 | mtag.name = "+draft/react"; 50 | MessageTagHandlerAdd(modinfo->handle, &mtag); 51 | 52 | HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_i3react); 53 | 54 | return MOD_SUCCESS; 55 | } 56 | 57 | MOD_LOAD() 58 | { 59 | return MOD_SUCCESS; 60 | } 61 | 62 | MOD_UNLOAD() 63 | { 64 | return MOD_SUCCESS; 65 | } 66 | 67 | int i3react_mtag_is_ok(Client *client, const char *name, const char *value) 68 | { 69 | if (BadPtr(value) || !strlen(value) || strlen(value) > 10) 70 | return 0; 71 | 72 | return 1; 73 | } 74 | 75 | void mtag_add_i3react(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature) 76 | { 77 | MessageTag *m; 78 | 79 | if (IsUser(client)) 80 | { 81 | m = find_mtag(recv_mtags, "+draft/react"); 82 | if (m) 83 | { 84 | m = duplicate_mtag(m); 85 | AddListItem(m, *mtag_list); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /files/polite-tag.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2023 Valerie Pond 4 | +draft/polite 5 | 6 | */ 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/polite-tag/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/polite-tag\";"; 17 | "The module does not need any other configuration."; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | 24 | #include "unrealircd.h" 25 | #define MTAG_POLITE "+draft/polite" // can be changed at a later date 26 | 27 | ModuleHeader MOD_HEADER = { 28 | "third/polite-tag", 29 | "1.0", 30 | "+draft/polite tag - Lets a user mark their message as polite (don't highlight)", 31 | "Valware", 32 | "unrealircd-6", 33 | }; 34 | 35 | int polite_mtag_is_ok(Client *client, const char *name, const char *value); 36 | void mtag_add_polite(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature); 37 | 38 | MOD_INIT() 39 | { 40 | MessageTagHandlerInfo mtag; 41 | 42 | MARK_AS_GLOBAL_MODULE(modinfo); 43 | 44 | memset(&mtag, 0, sizeof(mtag)); 45 | mtag.is_ok = polite_mtag_is_ok; 46 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 47 | mtag.name = MTAG_POLITE; 48 | MessageTagHandlerAdd(modinfo->handle, &mtag); 49 | 50 | HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_polite); 51 | 52 | return MOD_SUCCESS; 53 | } 54 | 55 | MOD_LOAD() 56 | { 57 | return MOD_SUCCESS; 58 | } 59 | 60 | MOD_UNLOAD() 61 | { 62 | return MOD_SUCCESS; 63 | } 64 | 65 | int polite_mtag_is_ok(Client *client, const char *name, const char *value) 66 | { 67 | if (value == NULL) // this tag has no value 68 | return 1; 69 | return 0; 70 | } 71 | 72 | void mtag_add_polite(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature) 73 | { 74 | MessageTag *m; 75 | 76 | if (IsUser(client)) 77 | { 78 | m = find_mtag(recv_mtags, MTAG_POLITE); 79 | if (m) 80 | { 81 | m = duplicate_mtag(m); 82 | AddListItem(m, *mtag_list); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /files/extwarn.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/extwarn"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/extwarn\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/extwarn"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | #define CheckAPIError(apistr, apiobj) \ 27 | do { \ 28 | if(!(apiobj)) { \ 29 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 30 | return MOD_FAILED; \ 31 | } \ 32 | } while(0) 33 | 34 | // Quality fowod declarations 35 | EVENT(extwarn_event); 36 | 37 | // Dat dere module header 38 | ModuleHeader MOD_HEADER = { 39 | "third/extwarn", // Module name 40 | "2.1.0", // Version 41 | "Enables additional configuration error checking", // Description 42 | "Gottem", // Author 43 | "unrealircd-6", // Modversion 44 | }; 45 | 46 | // Initialisation routine (register hooks, commands and modes or create structs etc) 47 | MOD_INIT() { 48 | // Delay event by 10 seconds so the config is fully available ;];]]; 49 | CheckAPIError("EventAdd(extwarn_event)", EventAdd(modinfo->handle, "extwarn_event", extwarn_event, NULL, 10000, 1)); 50 | 51 | MARK_AS_GLOBAL_MODULE(modinfo); 52 | return MOD_SUCCESS; 53 | } 54 | 55 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 56 | MOD_LOAD() { 57 | return MOD_SUCCESS; 58 | } 59 | 60 | // Called on unload/rehash obv 61 | MOD_UNLOAD() { 62 | return MOD_SUCCESS; // We good 63 | } 64 | 65 | EVENT(extwarn_event) { 66 | // Check for missing operclasses lol 67 | ConfigItem_oper *oper; 68 | ConfigItem_operclass *operclass; 69 | for(oper = conf_oper; oper; oper = (ConfigItem_oper *)oper->next) { // Checkem configured opers 70 | if(!(operclass = find_operclass(oper->operclass))) // None found, throw warning yo 71 | config_warn("[extwarn] Unknown operclass '%s' found in oper block for '%s'", oper->operclass, oper->name); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /files/dumpcmds.c: -------------------------------------------------------------------------------- 1 | /* 2 | * third/dumpcmds - Dump IRC commands to a file (data/cmds.txt) 3 | * (C) Copyright 2010-2019 Bram Matthys (Syzop) 4 | * License: GPLv2 5 | */ 6 | 7 | #include "unrealircd.h" 8 | 9 | ModuleHeader MOD_HEADER 10 | = { 11 | "third/dumpcmds", 12 | "1.0", 13 | "Dump IRC commands to a file", 14 | "Syzop", 15 | "unrealircd-6", 16 | }; 17 | 18 | EVENT(do_dumpcmds); 19 | 20 | MOD_INIT() 21 | { 22 | EventAdd(modinfo->handle, "do_dumpcmds", do_dumpcmds, NULL, 2000, 1); 23 | 24 | return MOD_SUCCESS; 25 | } 26 | 27 | MOD_LOAD() 28 | { 29 | return MOD_SUCCESS; 30 | } 31 | 32 | 33 | MOD_UNLOAD() 34 | { 35 | return MOD_SUCCESS; 36 | } 37 | 38 | extern MODVAR RealCommand *CommandHash[256]; 39 | 40 | static char *command_flags(RealCommand *c) 41 | { 42 | static char buf[512]; 43 | 44 | *buf = '\0'; 45 | if (c->flags & CMD_UNREGISTERED) 46 | strlcat(buf, "|UNREGISTERED", sizeof(buf)); 47 | if (c->flags & CMD_USER) 48 | strlcat(buf, "|USER", sizeof(buf)); 49 | if (c->flags & CMD_SERVER) 50 | strlcat(buf, "|SERVER", sizeof(buf)); 51 | if (c->flags & CMD_OPER) 52 | strlcat(buf, "|OPER", sizeof(buf)); 53 | 54 | return *buf ? buf + 1 : buf; 55 | } 56 | 57 | EVENT(do_dumpcmds) 58 | { 59 | FILE *fd; 60 | int i; 61 | RealCommand *c; 62 | char fname[512]; 63 | 64 | snprintf(fname, sizeof(fname), "%s/cmds.txt", PERMDATADIR); 65 | 66 | unreal_log(ULOG_INFO, "dumpcmds", "DUMPCMDS_DUMPING_TO_FILE", NULL, 67 | "[dumpcmds] Dumping commands to $file...", 68 | log_data_string("file", fname)); 69 | fd = fopen(fname, "w"); 70 | 71 | if (!fd) 72 | return; 73 | 74 | for (i=0; i < 256; i++) 75 | { 76 | for (c = CommandHash[i]; c; c = c->next) 77 | fprintf(fd, "%s %s\n", c->cmd, command_flags(c)); 78 | } 79 | fclose(fd); 80 | } 81 | 82 | /*** <<>> 83 | module 84 | { 85 | documentation "https://www.unrealircd.org/docs/dumpcmds%20module"; 86 | 87 | // This is displayed in './unrealircd module info ..' and also if compilation of the module fails: 88 | troubleshooting "Contact syzop@unrealircd.org if this module fails to compile"; 89 | 90 | // Minimum version necessary for this module to work: 91 | min-unrealircd-version "6.*"; 92 | 93 | post-install-text { 94 | "The module is installed. Now all you need to do is add a loadmodule line:"; 95 | "loadmodule \"third/dumpcmds\";"; 96 | "And /REHASH the IRCd."; 97 | "The module does not need any other configuration."; 98 | "The list of available IRC commands will be dumped to data/dumpcmds.txt"; 99 | } 100 | } 101 | *** <<>> 102 | */ 103 | -------------------------------------------------------------------------------- /files/showwebirc.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by k4be 3 | ** Website: https://github.com/pirc-pl/unrealircd-modules/ 4 | ** License: GPLv3 https://www.gnu.org/licenses/gpl-3.0.html 5 | */ 6 | 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/pirc-pl/unrealircd-modules/blob/master/README.md"; 11 | troubleshooting "In case of problems, contact k4be on irc.pirc.pl."; 12 | min-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed. Now all you need to do is add a loadmodule line:"; 15 | "loadmodule \"third/showwebirc\";"; 16 | "Configure, who can see the webirc and websocket info (default is NOBODY!):"; 17 | "set { whois-details { webirc { everyone none; self full; oper full; }; websocket { everyone none; self full; oper full; } } }"; 18 | "And /REHASH the IRCd."; 19 | "Please note that you need to use the '/WHOIS nick nick' command to see websocket info"; 20 | "for remote users."; 21 | } 22 | } 23 | *** <<>> 24 | */ 25 | 26 | #include "unrealircd.h" 27 | 28 | ModuleHeader MOD_HEADER = { 29 | "third/showwebirc", /* Name of module */ 30 | "6.0", /* Version */ 31 | "Add whois info for WEBIRC and websocket users", /* Short description of module */ 32 | "k4be", 33 | "unrealircd-6" 34 | }; 35 | 36 | int showwebirc_whois(Client *client, Client *target, NameValuePrioList **list); 37 | 38 | MOD_INIT() { 39 | HookAdd(modinfo->handle, HOOKTYPE_WHOIS, 0, showwebirc_whois); 40 | 41 | return MOD_SUCCESS; 42 | } 43 | 44 | MOD_LOAD() { 45 | return MOD_SUCCESS; 46 | } 47 | 48 | MOD_UNLOAD() { 49 | return MOD_SUCCESS; 50 | } 51 | 52 | int showwebirc_whois(Client *client, Client *target, NameValuePrioList **list){ 53 | int policy; 54 | ModDataInfo *moddata; 55 | 56 | /* WEBIRC */ 57 | moddata = findmoddata_byname("webirc", MODDATATYPE_CLIENT); 58 | if(moddata != NULL){ 59 | policy = whois_get_policy(client, target, "webirc"); 60 | if(moddata_client(target, moddata).l && policy > WHOIS_CONFIG_DETAILS_NONE){ 61 | add_nvplist_numeric_fmt(list, 0, "webirc", client, RPL_WHOISSPECIAL, "%s :is connecting via WEBIRC", target->name); 62 | } 63 | } 64 | 65 | /* websocket */ 66 | if(!MyUser(target)) 67 | return 0; /* this is not known for remote users */ 68 | 69 | moddata = findmoddata_byname("websocket", MODDATATYPE_CLIENT); 70 | if(moddata != NULL){ 71 | policy = whois_get_policy(client, target, "websocket"); 72 | if(moddata_client(target, moddata).l && policy > WHOIS_CONFIG_DETAILS_NONE){ 73 | add_nvplist_numeric_fmt(list, 0, "websocket", client, RPL_WHOISSPECIAL, "%s :is connecting via websocket", target->name); 74 | } 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /files/webirconly.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 3 | Copyright Ⓒ 2022 Valerie Pond 4 | */ 5 | /*** <<>> 6 | module 7 | { 8 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/webirconly/README.md"; 9 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 10 | min-unrealircd-version "6.*"; 11 | max-unrealircd-version "6.*"; 12 | post-install-text { 13 | "The module is installed. Now all you need to do is add a loadmodule line:"; 14 | "loadmodule \"third/webirconly\";"; 15 | "And /REHASH the IRCd."; 16 | "The module does not need any other configuration."; 17 | } 18 | } 19 | *** <<>> 20 | */ 21 | #include "unrealircd.h" 22 | 23 | Cmode_t EXTCMODE_WEBONLY; 24 | 25 | #define WEBIRCONLY_FLAG 'W' 26 | 27 | #define IsWebircOnly(channel) (channel->mode.mode & EXTCMODE_WEBONLY) 28 | #define IsWebircUser(x) (IsUser(x) && webircchecklol(x)) 29 | 30 | static int webircchecklol(Client *cptr); 31 | 32 | ModuleHeader MOD_HEADER = { 33 | "third/webirconly", // Module name 34 | "1.1", // Module Version 35 | "WebIRC Only - Provides channelmode W (webirc only channel)", // Description 36 | "Valware", // Author 37 | "unrealircd-6", // Unreal Version 38 | }; 39 | 40 | int webirconly_check (Client *client, Channel *channel, const char *key, char **errmsg); 41 | 42 | typedef struct { 43 | // Change this or add more variables, whatever suits you fam 44 | char flag; 45 | int p; 46 | } aModeX; 47 | 48 | // Initialisation routine (register hooks, commands and modes or create structs etc) 49 | MOD_INIT() { 50 | CmodeInfo req; 51 | 52 | memset(&req, 0, sizeof(req)); 53 | req.paracount = 0; 54 | req.letter = WEBIRCONLY_FLAG; 55 | req.is_ok = extcmode_default_requirehalfop; 56 | CmodeAdd(modinfo->handle, req, &EXTCMODE_WEBONLY); 57 | HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, webirconly_check); 58 | 59 | 60 | MARK_AS_GLOBAL_MODULE(modinfo); 61 | return MOD_SUCCESS; 62 | } 63 | 64 | 65 | MOD_LOAD() { 66 | return MOD_SUCCESS; 67 | } 68 | 69 | MOD_UNLOAD() { 70 | return MOD_SUCCESS; 71 | } 72 | int webirconly_check (Client *client, Channel *channel, const char *key, char **errmsg) 73 | { 74 | 75 | if ((IsWebircOnly(channel) && !IsWebircUser(client)) && !IsOper(client)) { 76 | *errmsg = ":%s That channel is for web users only.",channel->name; 77 | return ERR_NEEDREGGEDNICK; 78 | } 79 | return 0; 80 | } 81 | 82 | // copied and edited from third/showwwebirc by k4be lol 83 | static int webircchecklol(Client *cptr) { 84 | ModDataInfo *moddata; 85 | moddata = findmoddata_byname("webirc", MODDATATYPE_CLIENT); 86 | if(moddata == NULL) { return 0; } 87 | if(moddata_client(cptr, moddata).l){ return 1; } 88 | return 0; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /files/noinvite.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/noinvite"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/noinvite\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/noinvite"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | #define UMODE_FLAG 'N' // No invite 27 | 28 | // Commands to override 29 | #define OVR_INVITE "INVITE" 30 | 31 | #define CheckAPIError(apistr, apiobj) \ 32 | do { \ 33 | if(!(apiobj)) { \ 34 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 35 | return MOD_FAILED; \ 36 | } \ 37 | } while(0) 38 | 39 | // Quality fowod declarations 40 | int noinvite_hook(Client *client, Client *target, Channel *channel, int *override); 41 | 42 | long extumode_noinvite = 0L; // Store bitwise value latur 43 | 44 | // Dat dere module header 45 | ModuleHeader MOD_HEADER = { 46 | "third/noinvite", // Module name 47 | "2.1.0", // Version 48 | "Adds umode +N to block invites", // Description 49 | "Gottem", // Author 50 | "unrealircd-6", // Modversion 51 | }; 52 | 53 | // Initialisation routine (register hooks, commands and modes or create structs etc) 54 | MOD_INIT() { 55 | // Add a global umode (i.e. propagate to all servers), allow anyone to set/remove it on themselves 56 | CheckAPIError("UmodeAdd(extumode_noinvite)", UmodeAdd(modinfo->handle, UMODE_FLAG, UMODE_GLOBAL, 0, NULL, &extumode_noinvite)); 57 | 58 | MARK_AS_GLOBAL_MODULE(modinfo); 59 | 60 | HookAdd(modinfo->handle, HOOKTYPE_PRE_INVITE, 0, noinvite_hook); 61 | return MOD_SUCCESS; 62 | } 63 | 64 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 65 | MOD_LOAD() { 66 | return MOD_SUCCESS; // We good 67 | } 68 | 69 | // Called on unload/rehash obv 70 | MOD_UNLOAD() { 71 | return MOD_SUCCESS; // We good 72 | } 73 | 74 | int noinvite_hook(Client *client, Client *target, Channel *channel, int *override) { 75 | if(!IsULine(client) && !IsOper(client) && (target->umodes & extumode_noinvite)) { 76 | sendto_one(client, NULL, ":%s NOTICE %s :%s has blocked all invites", me.name, channel->name, target->name); 77 | return HOOK_DENY; 78 | } 79 | return HOOK_CONTINUE; 80 | } 81 | -------------------------------------------------------------------------------- /files/restrict-chans.c: -------------------------------------------------------------------------------- 1 | /** 2 | * LICENSE: GPLv3 or later 3 | * Copyright Ⓒ 2023 Valerie Pond 4 | * 5 | * Restricts channels to registered users 6 | * Requested by Chris[A] 7 | * 8 | * Deprecated: Exists in source with more options, see restrict-commands:channel-create 9 | * 10 | */ 11 | /*** <<>> 12 | module 13 | { 14 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/restrict-chans/README.md"; 15 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 16 | min-unrealircd-version "6.*"; 17 | max-unrealircd-version "6.1.6"; 18 | post-install-text { 19 | "The module is installed. Now all you need to do is add a loadmodule line:"; 20 | "loadmodule \"third/restrict-chans\";"; 21 | "And /REHASH the IRCd."; 22 | "The module does not need any other configuration."; 23 | } 24 | } 25 | *** <<>> 26 | */ 27 | #include "unrealircd.h" 28 | int isreg_can_join(Client *client, Channel *channel, const char *key); 29 | int isreg_check_join(Client *client, Channel *channel, const char *key, char **errmsg); 30 | ModuleHeader MOD_HEADER = 31 | { 32 | "third/restrict-chans", 33 | "1.3", 34 | "Restrict channel creation to logged-in users", 35 | "Valware", 36 | "unrealircd-6", 37 | }; 38 | MOD_INIT() 39 | { 40 | MARK_AS_GLOBAL_MODULE(modinfo); 41 | 42 | HookAdd(modinfo->handle, HOOKTYPE_CAN_JOIN, 0, isreg_check_join); 43 | HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_JOIN, 0, isreg_can_join); 44 | return MOD_SUCCESS; 45 | } 46 | 47 | MOD_LOAD() 48 | { 49 | return MOD_SUCCESS; 50 | } 51 | MOD_UNLOAD() 52 | { 53 | return MOD_SUCCESS; 54 | } 55 | 56 | MOD_TEST() 57 | { 58 | return MOD_SUCCESS; 59 | } 60 | 61 | int isreg_check_join(Client *client, Channel *channel, const char *key, char **errmsg) 62 | { 63 | Client *serv_server; 64 | if (!(serv_server = find_server(SASL_SERVER, NULL)) || !(serv_server = find_server(SERVICES_NAME, NULL))) 65 | return HOOK_CONTINUE; 66 | 67 | if (has_channel_mode(channel, 'P')) // it's permanent, continue; 68 | return HOOK_CONTINUE; 69 | if (channel->users == 0) 70 | { 71 | if (IsLoggedIn(client)) 72 | return HOOK_CONTINUE; 73 | 74 | *errmsg = "%s :You must be logged in to create new channels", channel->name; 75 | return ERR_CANNOTDOCOMMAND; 76 | } 77 | return HOOK_CONTINUE; 78 | 79 | } 80 | 81 | int isreg_can_join(Client *client, Channel *channel, const char *key) 82 | { 83 | Client *serv_server; 84 | if (!(serv_server = find_server(SASL_SERVER, NULL)) || !(serv_server = find_server(SERVICES_NAME, NULL))) 85 | return HOOK_CONTINUE; 86 | 87 | if (has_channel_mode(channel, 'P')) // it's permanent, continue; 88 | return HOOK_CONTINUE; 89 | /* allow people to join permanent empty channels and allow opers to create new channels */ 90 | if (channel->users == 0) 91 | { 92 | if (IsLoggedIn(client)) 93 | return HOOK_CONTINUE; 94 | 95 | sendnumeric(client, ERR_CANNOTDOCOMMAND, channel->name, "You must be logged in to create new channels"); 96 | return HOOK_DENY; 97 | } 98 | return HOOK_CONTINUE; 99 | } 100 | -------------------------------------------------------------------------------- /files/findchmodes.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by k4be 3 | ** Website: https://github.com/pirc-pl/unrealircd-modules/ 4 | ** License: GPLv3 https://www.gnu.org/licenses/gpl-3.0.html 5 | */ 6 | 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/pirc-pl/unrealircd-modules/blob/master/README.md"; 11 | troubleshooting "In case of problems, contact k4be on irc.pirc.pl."; 12 | min-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed. Now all you need to do is add a loadmodule line:"; 15 | "loadmodule \"third/findchmodes\";"; 16 | "And /REHASH the IRCd."; 17 | "The module does not need any other configuration."; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | #include "unrealircd.h" 24 | 25 | #define MSG_FINDCHMODES "FINDCHMODES" 26 | #define USAGE() { sendnotice(client, "Usage: /%s +character", MSG_FINDCHMODES); } 27 | 28 | /* copied from chanmodes/key.c */ 29 | typedef struct ChannelKey ChannelKey; 30 | struct ChannelKey { 31 | char key[KEYLEN+1]; 32 | }; 33 | 34 | CMD_FUNC(cmd_findchmodes); 35 | 36 | ModuleHeader MOD_HEADER = { 37 | "third/findchmodes", /* Name of module */ 38 | "6.0", /* Version */ 39 | "Find channels by channel modes", /* Short description of module */ 40 | "k4be", 41 | "unrealircd-6" 42 | }; 43 | 44 | 45 | MOD_INIT() { 46 | CommandAdd(modinfo->handle, MSG_FINDCHMODES, cmd_findchmodes, MAXPARA, CMD_USER); 47 | return MOD_SUCCESS; 48 | } 49 | 50 | MOD_LOAD() { 51 | return MOD_SUCCESS; 52 | } 53 | 54 | MOD_UNLOAD() { 55 | return MOD_SUCCESS; 56 | } 57 | 58 | CMD_FUNC(cmd_findchmodes) { 59 | unsigned int hashnum; 60 | char modebuf[BUFSIZE], parabuf[BUFSIZE]; 61 | Channel *channel; 62 | int count = 0; 63 | ChannelKey *r; 64 | const char *arg = parv[1]; 65 | 66 | if(!IsOper(client)){ 67 | sendnumeric(client, ERR_NOPRIVILEGES); 68 | return; 69 | } 70 | if(parc < 2 || BadPtr(parv[1])){ 71 | USAGE(); 72 | return; 73 | } 74 | 75 | if(*arg == '+') arg++; 76 | if(strlen(arg) != 1 || !isalpha(*arg)){ 77 | USAGE(); 78 | return; 79 | } 80 | 81 | for (hashnum = 0; hashnum < CHAN_HASH_TABLE_SIZE; hashnum++){ 82 | for (channel = hash_get_chan_bucket(hashnum); channel; channel = channel->hnextch){ 83 | if (!ValidatePermissionsForPath("channel:see:list:secret",client,NULL,channel,NULL)) continue; 84 | *modebuf = *parabuf = '\0'; 85 | modebuf[1] = '\0'; 86 | r = (ChannelKey *)GETPARASTRUCT(channel, 'k'); 87 | // using "me" here to get args for all channels, never retrieve channel keys though 88 | channel_modes((r && *r->key)?client:(Client *)&me, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel, 0); 89 | if(strchr(modebuf, *arg)){ 90 | sendnumeric(client, RPL_CHANNELMODEIS, channel->name, modebuf, parabuf); 91 | if(IsMember(client, channel)){ 92 | sendnotice(client, "[findchmodes +%c] Notice: You're on %s", *arg, channel->name); 93 | } 94 | count++; 95 | } 96 | } 97 | } 98 | if(count == 0){ 99 | sendnotice(client, "[findchmodes +%c] Notice: No channels found", *arg); 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /files/getlegitusers.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/getlegitusers"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/getlegitusers\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/getlegitusers"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | #include "unrealircd.h" 24 | 25 | #define MSG_GETLEGITUSERS "GETLEGITUSERS" // Actual command name 26 | 27 | #define CheckAPIError(apistr, apiobj) \ 28 | do { \ 29 | if(!(apiobj)) { \ 30 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 31 | return MOD_FAILED; \ 32 | } \ 33 | } while(0) 34 | 35 | CMD_FUNC(getlegitusers); // Register that shit 36 | 37 | // Quality module header yo 38 | ModuleHeader MOD_HEADER = { 39 | "third/getlegitusers", 40 | "2.1.0", // Version 41 | "Command /getlegitusers to show user/bot count across the network", 42 | "Gottem", // Author 43 | "unrealircd-6", // Modversion 44 | }; 45 | 46 | // Module initialisation 47 | MOD_INIT() { 48 | CheckAPIError("CommandAdd(GETLEGITUSERS)", CommandAdd(modinfo->handle, MSG_GETLEGITUSERS, getlegitusers, 1, CMD_USER)); 49 | 50 | MARK_AS_GLOBAL_MODULE(modinfo); 51 | return MOD_SUCCESS; 52 | } 53 | 54 | MOD_LOAD() { 55 | return MOD_SUCCESS; // We good fam 56 | } 57 | 58 | // Called on mod unload 59 | MOD_UNLOAD() { 60 | return MOD_SUCCESS; 61 | } 62 | 63 | CMD_FUNC(getlegitusers) { 64 | long total, legit, bots; // Just some counters lol 65 | Client *acptr; // Client pointer for the iteration of the client list 66 | 67 | if(!IsUser(client) || !IsOper(client)) { // Is the thing executing the command even a user and opered up? 68 | sendnumeric(client, ERR_NOPRIVILEGES); // Lolnope 69 | return; 70 | } 71 | 72 | bots = total = legit = 0; // Initialise dem counters 73 | 74 | // Iterate over all known clients 75 | list_for_each_entry(acptr, &client_list, client_node) { 76 | if(acptr->user) { // Sanity check 77 | total++; // Increment total count since this IS a user 78 | if(IsULine(acptr)) { 79 | bots++; // Surely this must be a bot then 80 | continue; 81 | } 82 | if(acptr->user->joined > 0) // But are they joined to more than one chan ? 83 | legit++; // Increment legitimate user count 84 | else 85 | sendnotice(client, "*** [getlegitusers] Found unknown user %s!%s@%s", acptr->name, acptr->user->username, acptr->user->realhost); 86 | } 87 | } 88 | 89 | // Server notice to the executing oper 90 | sendnotice(client, "*** [getlegitusers] %ld clients are on at least one channel and %ld are not present on any channel. The other %ld are services agents.", legit, total - (legit + bots), bots); 91 | } 92 | -------------------------------------------------------------------------------- /files/rehashgem.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/rehashgem"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/rehashgem\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/rehashgem"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | // Quality fowod declarations 27 | int rehashgem_rehashflag(Client *client, const char *flag); 28 | 29 | // Dat dere module header 30 | ModuleHeader MOD_HEADER = { 31 | "third/rehashgem", // Module name 32 | "2.1.0", // Version 33 | "Implements an additional rehash flag -gem (global except me)", // Description 34 | "Gottem", // Author 35 | "unrealircd-6", // Modversion 36 | }; 37 | 38 | // Initialisation routine (register hooks, commands and modes or create structs etc) 39 | MOD_INIT() { 40 | MARK_AS_GLOBAL_MODULE(modinfo); 41 | 42 | // Add a hook with priority 0 (i.e. normal) that returns an int 43 | HookAdd(modinfo->handle, HOOKTYPE_REHASHFLAG, 0, rehashgem_rehashflag); 44 | return MOD_SUCCESS; 45 | } 46 | 47 | // Actually load the module here 48 | MOD_LOAD() { 49 | return MOD_SUCCESS; // We good 50 | } 51 | 52 | // Called on unload/rehash obv 53 | MOD_UNLOAD() { 54 | return MOD_SUCCESS; // We good 55 | } 56 | 57 | // Actual hewk function m8 58 | int rehashgem_rehashflag(Client *client, const char *flag) { 59 | Client *acptr; // For iterating em servers 60 | const char *sflag; // For grabbing suffixes to "-gem" like "-gemssl" 61 | unsigned int scount; 62 | if(match_simple("-gem*", flag)) { // Got em match? 63 | scount = 0; 64 | sflag = (strlen(flag) > 4 ? (flag + 4) : NULL); // If the flag is longer than -gem, get the rest (dirty lil hack to make -gemssl etc work lel) =] 65 | unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD", client, "[rehashgem] $client.details is broadcasting REHASH -$flag to all other servers", 66 | log_data_string("flag", (sflag ? sflag : "all")) 67 | ); 68 | 69 | // Rehash reports messages like "oper is remotely rehashing", "loading IRCd config" and "config loaded without problems" for every server, to _their local opers only_ 70 | // Some messages also go to GLOBOPS (I think MOTD related shit) =] 71 | sendto_server(NULL, 0, 0, NULL, ":%s REHASH -global -%s", client->name, (sflag ? sflag : "all")); 72 | list_for_each_entry(acptr, &global_server_list, client_node) { // Still need to count em servers kek 73 | if(acptr == &me) 74 | continue; 75 | scount++; 76 | } 77 | unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD", client, "[rehashgem] Done broadcasting to $servercount $servertxt (might include services)", 78 | log_data_integer("servercount", scount), 79 | log_data_string("servertxt", (scount == 1 ? "server" : "servers")) 80 | ); 81 | } 82 | return HOOK_CONTINUE; 83 | } 84 | -------------------------------------------------------------------------------- /files/display-name.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2022 Valerie Pond 4 | draft/display-name 5 | 6 | */ 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/display-name/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/display-name\";"; 17 | "You need to restart your server for this to show up in CLIENTTAGDENY"; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | 24 | #define MTAG_DISPLAYNAME "+draft/display-name" 25 | #include "unrealircd.h" 26 | 27 | ModuleHeader MOD_HEADER = 28 | { 29 | "third/display-name", 30 | "1.0", 31 | "+draft/display-name (IRCv3)", 32 | "Valware", 33 | "unrealircd-6", 34 | }; 35 | int i3display_name_mtag_is_ok(Client *client, const char *name, const char *value); 36 | void mtag_add_i3_display_name(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature); 37 | int IsValidDisplayName(Client *client, const char *value); 38 | 39 | MOD_INIT() 40 | { 41 | MessageTagHandlerInfo mtag; 42 | 43 | MARK_AS_GLOBAL_MODULE(modinfo); 44 | 45 | memset(&mtag, 0, sizeof(mtag)); 46 | mtag.is_ok = i3display_name_mtag_is_ok; 47 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 48 | mtag.name = MTAG_DISPLAYNAME; 49 | MessageTagHandlerAdd(modinfo->handle, &mtag); 50 | 51 | HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_i3_display_name); 52 | 53 | 54 | return MOD_SUCCESS; 55 | } 56 | 57 | MOD_LOAD() 58 | { 59 | return MOD_SUCCESS; 60 | } 61 | 62 | MOD_UNLOAD() 63 | { 64 | return MOD_SUCCESS; 65 | } 66 | 67 | int i3display_name_mtag_is_ok(Client *client, const char *name, const char *value) 68 | { 69 | /* we COULD return IsValidDisplayName() direcly but I don't like that. */ 70 | int IsValid = IsValidDisplayName(client,value); 71 | return IsValid; 72 | } 73 | 74 | void mtag_add_i3_display_name(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature) 75 | { 76 | MessageTag *m; 77 | 78 | if (IsUser(client)) 79 | { 80 | m = find_mtag(recv_mtags, MTAG_DISPLAYNAME); 81 | if (m) 82 | { 83 | m = duplicate_mtag(m); 84 | AddListItem(m, *mtag_list); 85 | } 86 | } 87 | } 88 | 89 | int IsValidDisplayName(Client *client, const char *value) 90 | { 91 | if (BadPtr(value)) 92 | { 93 | sendto_one(client, NULL, "FAIL * DISPLAY_NAME_ERRONEOUS :Your display-name cannot be empty."); 94 | return 0; 95 | } 96 | const char *illegalchars = "!+%@&~#$:'\"?*,."; 97 | const char *p; 98 | if (strstr(value,"\n") || strstr(value,"\r")) 99 | { 100 | sendto_one(client, NULL, "FAIL * DISPLAY_NAME_ERRONEOUS :The display-name you used contained an illegal character"); 101 | return 0; 102 | } 103 | for (p = value; *p; p++) 104 | { 105 | if (strchr(illegalchars, *p)) 106 | { 107 | sendto_one(client, NULL, "FAIL * DISPLAY_NAME_ERRONEOUS :The display-name you used contained an illegal character (%s).",illegalchars); 108 | return 0; 109 | } 110 | } 111 | if (strlen(value) > NICKLEN) 112 | { 113 | sendto_one(client, NULL, "FAIL * DISPLAY_NAME_TOO_LONG :The display-name you used exceeded the maximum length and was not included. (Maximum length: %d)", NICKLEN); 114 | return 0; 115 | } 116 | return 1; 117 | } 118 | -------------------------------------------------------------------------------- /files/uline_nickhost.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/uline_nickhost"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/uline_nickhost\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/uline_nickhost"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | // Commands to override 27 | #define OVR_PRIVMSG "PRIVMSG" 28 | #define OVR_NOTICE "NOTICE" 29 | 30 | #define CheckAPIError(apistr, apiobj) \ 31 | do { \ 32 | if(!(apiobj)) { \ 33 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 34 | return MOD_FAILED; \ 35 | } \ 36 | } while(0) 37 | 38 | #if UNREAL_VERSION >= 0x06020000 39 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, clictx, client, recv_mtags, parc, parv)) 40 | #else 41 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, client, recv_mtags, parc, parv)) 42 | #endif 43 | 44 | // Quality fowod declarations 45 | CMD_OVERRIDE_FUNC(uline_nickhost_override); 46 | 47 | // Dat dere module header 48 | ModuleHeader MOD_HEADER = { 49 | "third/uline_nickhost", // Module name 50 | "2.1.1", // Version 51 | "Requires people to address services like NickServ@services.my.net", // Description 52 | "Gottem", // Author 53 | "unrealircd-6", // Modversion 54 | }; 55 | 56 | // Initialisation routine (register hooks, commands and modes or create structs etc) 57 | MOD_INIT() { 58 | MARK_AS_GLOBAL_MODULE(modinfo); 59 | return MOD_SUCCESS; 60 | } 61 | 62 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 63 | MOD_LOAD() { 64 | CheckAPIError("CommandOverrideAdd(PRIVMSG)", CommandOverrideAdd(modinfo->handle, OVR_PRIVMSG, 0, uline_nickhost_override)); 65 | CheckAPIError("CommandOverrideAdd(NOTICE)", CommandOverrideAdd(modinfo->handle, OVR_NOTICE, 0, uline_nickhost_override)); 66 | return MOD_SUCCESS; // We good 67 | } 68 | 69 | // Called on unload/rehash obv 70 | MOD_UNLOAD() { 71 | return MOD_SUCCESS; // We good 72 | } 73 | 74 | // Now for the actual override 75 | CMD_OVERRIDE_FUNC(uline_nickhost_override) { 76 | // Gets args: CommandOverride *ovr, ClientContext *clictx, Client *client, MessageTag *recv_mtags, int parc, const char *parv[] 77 | Client *acptr; // Pointer to target client 78 | char nickhost[NICKLEN + HOSTLEN + 2]; // Full nick@server mask thingy, HOSTLEN is the limit for server names anyways so ;] 79 | 80 | // Check argument sanity and see if we can find a target pointer (and if that's a U-Line as well) 81 | if(BadPtr(parv[1]) || !(acptr = find_user(parv[1], NULL)) || !IsULine(acptr)) { 82 | CallCommandOverrideCompatU06020000(); // Run original function yo 83 | return; 84 | } 85 | 86 | ircsnprintf(nickhost, sizeof(nickhost), "%s@%s", acptr->name, acptr->direction->name); 87 | if(strcasecmp(parv[1], nickhost)) { // Check if exact match (case-insensitivity is a go) 88 | sendnotice(client, "*** Please use %s when addressing services bots", nickhost); // Notice lol 89 | return; 90 | } 91 | CallCommandOverrideCompatU06020000(); 92 | } 93 | -------------------------------------------------------------------------------- /files/message_commonchans.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/message_commonchans"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/message_commonchans\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/message_commonchans"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | #define UMODE_FLAG 'c' 27 | 28 | #define CheckAPIError(apistr, apiobj) \ 29 | do { \ 30 | if(!(apiobj)) { \ 31 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 32 | return MOD_FAILED; \ 33 | } \ 34 | } while(0) 35 | 36 | // Quality fowod declarations 37 | #if UNREAL_VERSION >= 0x06020000 38 | int commchans_hook_cansend_user(Client *client, Client *to, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx); 39 | #else 40 | int commchans_hook_cansend_user(Client *client, Client *to, const char **text, const char **errmsg, SendType sendtype); 41 | #endif 42 | 43 | long extumode_commonchans = 0; // Store bitwise value latur 44 | 45 | // Dat dere module header 46 | ModuleHeader MOD_HEADER = { 47 | "third/message_commonchans", // Module name 48 | "2.1.1", // Version 49 | "Adds umode +c to prevent people who aren't sharing a channel with you from messaging you", // Description 50 | "Gottem", // Author 51 | "unrealircd-6", // Modversion 52 | }; 53 | 54 | // Initialisation routine (register hooks, commands and modes or create structs etc) 55 | MOD_INIT() { 56 | // Add a global umode (i.e. propagate to all servers), allow anyone to set/remove it on themselves 57 | CheckAPIError("UmodeAdd(extumode_commonchans)", UmodeAdd(modinfo->handle, UMODE_FLAG, UMODE_GLOBAL, 0, NULL, &extumode_commonchans)); 58 | 59 | MARK_AS_GLOBAL_MODULE(modinfo); 60 | 61 | HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_USER, -100, commchans_hook_cansend_user); // High priority lol 62 | return MOD_SUCCESS; 63 | } 64 | 65 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 66 | MOD_LOAD() { 67 | return MOD_SUCCESS; // We good 68 | } 69 | 70 | // Called on unload/rehash obv 71 | MOD_UNLOAD() { 72 | // Clean up any structs and other shit 73 | return MOD_SUCCESS; // We good 74 | } 75 | 76 | // Actual hewk function m8 77 | #if UNREAL_VERSION >= 0x06020000 78 | int commchans_hook_cansend_user(Client *client, Client *to, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx) 79 | #else 80 | int commchans_hook_cansend_user(Client *client, Client *to, const char **text, const char **errmsg, SendType sendtype) 81 | #endif 82 | { 83 | if(sendtype != SEND_TYPE_PRIVMSG && sendtype != SEND_TYPE_NOTICE) 84 | return HOOK_CONTINUE; 85 | if(!text || !*text) 86 | return HOOK_CONTINUE; 87 | 88 | if(!MyUser(client) || client == to || IsULine(client) || IsULine(to) || IsOper(client) || !(to->umodes & extumode_commonchans) || has_common_channels(client, to)) 89 | return HOOK_CONTINUE; 90 | 91 | sendnumeric(client, ERR_CANTSENDTOUSER, to->name, "You need to be on a common channel in order to privately message them"); 92 | *text = NULL; 93 | 94 | // Can't return HOOK_DENY here cuz Unreal will abort() in that case :D 95 | return HOOK_CONTINUE; 96 | } 97 | -------------------------------------------------------------------------------- /files/banfix_voice.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/banfix_voice"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/banfix_voice\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/banfix_voice"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | #include "unrealircd.h" 24 | 25 | #define CheckAPIError(apistr, apiobj) \ 26 | do { \ 27 | if(!(apiobj)) { \ 28 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 29 | return MOD_FAILED; \ 30 | } \ 31 | } while(0) 32 | 33 | #if UNREAL_VERSION >= 0x06020000 34 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, clictx, client, recv_mtags, parc, parv)) 35 | #else 36 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, client, recv_mtags, parc, parv)) 37 | #endif 38 | 39 | CMD_OVERRIDE_FUNC(check_banned_butvoiced); 40 | 41 | // Mod header obv fam =] 42 | ModuleHeader MOD_HEADER = { 43 | "third/banfix_voice", 44 | "2.1.1", // Version 45 | "Correct some odd behaviour in regards to banned-but-voiced users", 46 | "Gottem", // Author 47 | "unrealircd-6", // Modversion 48 | }; 49 | 50 | // Initialise that shit 51 | MOD_INIT() { 52 | MARK_AS_GLOBAL_MODULE(modinfo); 53 | return MOD_SUCCESS; // We good 54 | } 55 | 56 | // Here we actually load the m0d 57 | MOD_LOAD() { 58 | CheckAPIError("CommandOverrideAdd(PRIVMSG)", CommandOverrideAdd(modinfo->handle, "PRIVMSG", 0, check_banned_butvoiced)); 59 | CheckAPIError("CommandOverrideAdd(NOTICE)", CommandOverrideAdd(modinfo->handle, "NOTICE", 0, check_banned_butvoiced)); 60 | return MOD_SUCCESS; // WE GOOD 61 | } 62 | 63 | MOD_UNLOAD() { 64 | return MOD_SUCCESS; // What can go wrong? 65 | } 66 | 67 | // Now for the actual override 68 | CMD_OVERRIDE_FUNC(check_banned_butvoiced) { 69 | const char *target; // First argument is the target 70 | int v; // Has voice 71 | int noticed; // To store if this was a notice, also if b& 72 | Channel *channel; // Channel pointer obv 73 | 74 | // In case of U-Lines and opers, let's just pass it back to the core function 75 | if(MyUser(client) && !IsULine(client) && !IsOper(client) && !BadPtr(parv[1])) { 76 | target = parv[1]; 77 | if(target[0] != '#') { // If first character of target isn't even #, bans don't apply at all, so... 78 | CallCommandOverrideCompatU06020000(); // Run original function yo 79 | return; 80 | } 81 | 82 | // is_banned() for BANCHK_MSG returns a true value for quiet bans nowadays, so we only need to check if the user is *just* voiced [[=[=[=[=[==[ 83 | if((channel = find_channel(target)) && is_banned(client, channel, BANCHK_MSG, NULL, NULL)) { 84 | noticed = (strcmp(ovr->command->cmd, "NOTICE") == 0); // Was it an attempt to send a notice? 85 | v = check_channel_access(client, channel, "v"); // User has voice? 86 | 87 | // Apparently when you're banned (not necessarily ~quiet) and try to /notice #chan, you won't see a "you are banned" message, so let's fix dat too =] 88 | if((noticed || (v && !noticed)) && !check_channel_access(client, channel, "hoaq")) { // If not at least hop 89 | sendnumeric(client, ERR_CANNOTSENDTOCHAN, channel->name, "[BF] You are banned", target); // Send error 90 | return; // Stop processing 91 | } 92 | } 93 | } 94 | 95 | CallCommandOverrideCompatU06020000(); 96 | } 97 | -------------------------------------------------------------------------------- /files/operoverride_ext.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/operoverride_ext"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/operoverride_ext\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/operoverride_ext"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | #include "unrealircd.h" 24 | 25 | int operoverride_ext_hook_prelocaljoin(Client *client, Channel *channel, const char *key); 26 | 27 | ModuleHeader MOD_HEADER = { 28 | "third/operoverride_ext", 29 | "2.1.0", // Version 30 | "Additional OperOverride functionality", 31 | "Gottem", // Author 32 | "unrealircd-6", // Modversion 33 | }; 34 | 35 | MOD_TEST() { 36 | return MOD_SUCCESS; 37 | } 38 | 39 | MOD_INIT() { 40 | MARK_AS_GLOBAL_MODULE(modinfo); 41 | 42 | HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_JOIN, 0, operoverride_ext_hook_prelocaljoin); 43 | return MOD_SUCCESS; 44 | } 45 | 46 | MOD_LOAD() { 47 | return MOD_SUCCESS; 48 | } 49 | 50 | MOD_UNLOAD() { 51 | return MOD_FAILED; 52 | } 53 | 54 | int operoverride_ext_hook_prelocaljoin(Client *client, Channel *channel, const char *key) { 55 | int i; 56 | int canjoin[3]; 57 | char oomsg[512]; 58 | const char *log_event; 59 | char *errmsg = NULL; // Actually won't be used but is necessary so can_join() won't break lol 60 | 61 | // can_join() actually returns 0 if we *can* join a channel, so we don't need to bother checking any further conditions 62 | // i.e. when can_join() == 0 then there is nothing to override ;] 63 | if(!can_join(client, channel, key, &errmsg)) 64 | return HOOK_CONTINUE; 65 | 66 | if(!IsOper(client) && IsULine(client)) 67 | return HOOK_CONTINUE; 68 | 69 | oomsg[0] = '\0'; 70 | canjoin[0] = 1; 71 | canjoin[1] = 1; 72 | canjoin[2] = 1; 73 | log_event = "OPEROVERRIDE_EXT_UNKNOWN"; // Can't really happen but let's set something anyways =] 74 | 75 | if(is_banned(client, channel, BANCHK_JOIN, NULL, NULL)) { 76 | canjoin[0] = 0; 77 | if(ValidatePermissionsForPath("channel:override:message:ban", client, NULL, channel, NULL)) { 78 | canjoin[0] = 1; 79 | sprintf(oomsg, "joined %s through ban", channel->name); 80 | log_event = "OPEROVERRIDE_EXT_BAN"; 81 | } 82 | } 83 | 84 | if(has_channel_mode(channel, 'R') && !IsRegNick(client)) { 85 | canjoin[1] = 0; 86 | if(ValidatePermissionsForPath("channel:override:message:regonly", client, NULL, channel, NULL)) { 87 | canjoin[1] = 1; 88 | sprintf(oomsg, "joined +R channel %s without invite", channel->name); 89 | log_event = "OPEROVERRIDE_EXT_REGONLY"; 90 | } 91 | } 92 | 93 | if(has_channel_mode(channel, 'i') && !find_invex(channel, client)) { 94 | canjoin[2] = 0; 95 | if(ValidatePermissionsForPath("channel:override:invite:self", client, NULL, channel, NULL)) { 96 | canjoin[2] = 1; 97 | sprintf(oomsg, "joined +i channel %s without invite", channel->name); 98 | log_event = "OPEROVERRIDE_EXT_INVITE"; 99 | } 100 | } 101 | 102 | for(i = 0; i < (sizeof(canjoin) / sizeof(canjoin[0])); i++) { 103 | if(canjoin[i] == 0) 104 | return HOOK_CONTINUE; 105 | } 106 | 107 | if(oomsg[0]) { 108 | if(!IsULine(client)) 109 | unreal_log(ULOG_INFO, "operoverride_ext", log_event, client, "OperOverride -- $client.details $oomsg", log_data_string("oomsg", oomsg)); 110 | return HOOK_ALLOW; 111 | } 112 | return HOOK_CONTINUE; 113 | } 114 | -------------------------------------------------------------------------------- /files/kiwiirc-tags.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2022 Valerie Pond 4 | 5 | 6 | 7 | */ 8 | /*** <<>> 9 | module 10 | { 11 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/kiwiirc-tags/README.md"; 12 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 13 | min-unrealircd-version "6.0.7"; 14 | max-unrealircd-version "6.*"; 15 | post-install-text { 16 | "The module is installed. Now all you need to do is add a loadmodule line:"; 17 | "loadmodule \"third/kiwiirc-tags\";"; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | 24 | #define MTAG_FILEUPLOAD "+kiwiirc.com/fileuploader" 25 | #define MTAG_CONFERENCE "+kiwiirc.com/conference" 26 | #define MTAG_TICTACTOE_OLD "+data" /* current */ 27 | #define MTAG_TICTACTOE "+kiwiirc.com/ttt" /* supported in near future */ 28 | #include "unrealircd.h" 29 | 30 | ModuleHeader MOD_HEADER = 31 | { 32 | "third/kiwiirc-tags", 33 | "1.0", 34 | "Provides support for KiwiIRC's MessageTags", 35 | "Valware", 36 | "unrealircd-6", 37 | }; 38 | int kiwiirc_tag(Client *client, const char *name, const char *value); 39 | void mtag_add_kiwiirc_tag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature); 40 | 41 | MOD_INIT() 42 | { 43 | MessageTagHandlerInfo mtag; 44 | 45 | MARK_AS_GLOBAL_MODULE(modinfo); 46 | 47 | memset(&mtag, 0, sizeof(mtag)); 48 | mtag.is_ok = kiwiirc_tag; 49 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 50 | mtag.name = MTAG_FILEUPLOAD; 51 | MessageTagHandlerAdd(modinfo->handle, &mtag); 52 | 53 | memset(&mtag, 0, sizeof(mtag)); 54 | mtag.is_ok = kiwiirc_tag; 55 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 56 | mtag.name = MTAG_CONFERENCE; 57 | MessageTagHandlerAdd(modinfo->handle, &mtag); 58 | 59 | memset(&mtag, 0, sizeof(mtag)); 60 | mtag.is_ok = kiwiirc_tag; 61 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 62 | mtag.name = MTAG_TICTACTOE_OLD; 63 | MessageTagHandlerAdd(modinfo->handle, &mtag); 64 | 65 | memset(&mtag, 0, sizeof(mtag)); 66 | mtag.is_ok = kiwiirc_tag; 67 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 68 | mtag.name = MTAG_TICTACTOE; 69 | MessageTagHandlerAdd(modinfo->handle, &mtag); 70 | 71 | HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_kiwiirc_tag); 72 | 73 | 74 | return MOD_SUCCESS; 75 | } 76 | 77 | MOD_LOAD() 78 | { 79 | return MOD_SUCCESS; 80 | } 81 | 82 | MOD_UNLOAD() 83 | { 84 | return MOD_SUCCESS; 85 | } 86 | 87 | int kiwiirc_tag(Client *client, const char *name, const char *value) 88 | { 89 | if (!strlen(value)) 90 | { 91 | sendto_one(client, NULL, "FAIL * MESSAGE_TAG_TOO_SHORT %s :That message tag must contain a value.", name); 92 | return 0; 93 | } 94 | else if (strlen(value) > 3500) 95 | { 96 | sendnumericfmt(client, ERR_INPUTTOOLONG, "Input line was too long"); 97 | return 0; 98 | } 99 | return 1; 100 | } 101 | 102 | /** Only allow one at a time =] */ 103 | void mtag_add_kiwiirc_tag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature) 104 | { 105 | MessageTag *m; 106 | 107 | if (IsUser(client)) 108 | { 109 | 110 | m = find_mtag(recv_mtags, MTAG_FILEUPLOAD); 111 | if (m) 112 | { 113 | m = duplicate_mtag(m); 114 | AddListItem(m, *mtag_list); 115 | return; 116 | } 117 | m = find_mtag(recv_mtags, MTAG_CONFERENCE); 118 | if (m) 119 | { 120 | m = duplicate_mtag(m); 121 | AddListItem(m, *mtag_list); 122 | return; 123 | } 124 | m = find_mtag(recv_mtags, MTAG_TICTACTOE_OLD); 125 | if (m) 126 | { 127 | m = duplicate_mtag(m); 128 | AddListItem(m, *mtag_list); 129 | return; 130 | } 131 | m = find_mtag(recv_mtags, MTAG_TICTACTOE); 132 | if (m) 133 | { 134 | m = duplicate_mtag(m); 135 | AddListItem(m, *mtag_list); 136 | return; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /files/logged-in-from.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 3 | Copyright 2023 Ⓒ Valerie Pond 4 | 5 | Taken from DalekIRC 6 | */ 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/logged-in-from/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/logged-in-from\";"; 17 | "And /REHASH the IRCd."; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | 24 | #include "unrealircd.h" 25 | 26 | /** "Logged in from" whois fields */ 27 | int loggedinfrom_whois(Client *requester, Client *acptr, NameValuePrioList **list); 28 | 29 | /* Our module header */ 30 | ModuleHeader MOD_HEADER = { 31 | "third/logged-in-from", 32 | "1.1", 33 | "Extra /WHOIS information pertaining to account usage.", 34 | "Valware", 35 | "unrealircd-6", 36 | }; 37 | 38 | /** Module initialization */ 39 | MOD_INIT() { 40 | MARK_AS_GLOBAL_MODULE(modinfo); 41 | 42 | /* Add our hooks */ 43 | HookAdd(modinfo->handle, HOOKTYPE_WHOIS, 0, loggedinfrom_whois); 44 | 45 | return MOD_SUCCESS; // hooray 46 | } 47 | /** Called upon module load */ 48 | MOD_LOAD() 49 | { 50 | 51 | return MOD_SUCCESS; 52 | } 53 | 54 | /** Called upon unload */ 55 | MOD_UNLOAD() 56 | { 57 | return MOD_SUCCESS; 58 | } 59 | 60 | /** 61 | * In this whois hook, we let the user see their own "places they are logged in from". 62 | * Opers can also see this information. 63 | */ 64 | int loggedinfrom_whois(Client *requester, Client *acptr, NameValuePrioList **list) 65 | { 66 | Client *client; 67 | char buf[512]; 68 | 69 | if (!IsLoggedIn(acptr)) // not logged in, return 70 | return 0; 71 | 72 | if (!IsOper(requester) && strcasecmp(acptr->user->account,requester->user->account)) // only show to the self 73 | return 0; 74 | 75 | int i = 1; 76 | 77 | /** 78 | * We go through each user on the network looking for people who are logged into the 79 | * same account. 80 | */ 81 | list_for_each_entry(client, &client_list, client_node) 82 | { 83 | if (IsUser(client) && !strcasecmp(client->user->account,acptr->user->account)) 84 | { 85 | add_nvplist_numeric_fmt(list, 999900 + i, "loggedin", acptr, 320, "%s :is logged in from %s!%s@%s (%i)%s", 86 | acptr->name, 87 | client->name, 88 | client->user->username, 89 | client->user->realhost, 90 | i, 91 | (client == requester) ? " (You)" : ""); 92 | ++i; 93 | } 94 | } 95 | 96 | /** 97 | * We show the user how many places they're logged in, and then show the ^ above output (lower prio) 98 | */ 99 | if (acptr->user->account) 100 | add_nvplist_numeric_fmt(list, 999900, "loggedin", acptr, 320, "%s :is logged in from \x02%i place%s\x02:", acptr->name, i - 1, (i-1 == 1) ? "" : "s"); 101 | 102 | 103 | /** 104 | * This is where we add some extended information so that people logged in from multiple 105 | * places may see more information about where they're logged in. 106 | */ 107 | if (acptr != requester && !IsOper(requester)) // wouldn't otherwise get to see their extended information... 108 | { 109 | // we add their real host and ip as if it were there all along :') 110 | add_nvplist_numeric_fmt(list, -90000, "realhost", acptr, 378, "%s :is connecting from *@%s %s", 111 | acptr->name, 112 | acptr->user->realhost, 113 | acptr->ip); 114 | 115 | // and show what modes they're using. 116 | add_nvplist_numeric_fmt(list, -100000, "modes", acptr, 379, "%s :is using modes %s %s", 117 | acptr->name, get_usermode_string(acptr), 118 | acptr->user->snomask ? acptr->user->snomask : ""); 119 | } 120 | return 0; 121 | } 122 | -------------------------------------------------------------------------------- /files/cmdslist.c: -------------------------------------------------------------------------------- 1 | /* 2 | LICENSE: GPLv3-or-later 3 | Copyright Ⓒ 2023 Valerie Pond 4 | 5 | */ 6 | 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/cmdslist/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/cmdslist\";"; 17 | "And /REHASH the IRCd."; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | #include "unrealircd.h" 24 | 25 | ModuleHeader MOD_HEADER 26 | = { 27 | "third/cmdslist", 28 | "1.0", 29 | "Request and subscribe to commands", 30 | "Valware", 31 | "unrealircd-6", 32 | }; 33 | 34 | #define CMDSLIST_CAP "valware.uk/cmdslist" 35 | 36 | #define CMD_CMDSLIST "CMDSLIST" 37 | 38 | CMD_FUNC(CMDLIST); 39 | 40 | /* Variables */ 41 | long CAP_CMDSLIST = 0L; 42 | 43 | /* I don't find something else like this in the source so *shrugs* */ 44 | static int user_can_do_command(RealCommand *c, Client *client) 45 | { 46 | if (c->flags & CMD_UNREGISTERED && (!IsUser(client) && MyConnect(client))) 47 | return 1; 48 | if (c->flags & CMD_USER && IsUser(client)) 49 | return 1; 50 | if (c->flags & CMD_OPER && IsOper(client)) 51 | return 1; 52 | return 0; 53 | } 54 | 55 | int operhewk(Client *client, int add, const char *oper_block, const char *operclass) 56 | { 57 | RealCommand *c; 58 | int i, type; 59 | if (!HasCapabilityFast(client, CAP_CMDSLIST)) 60 | return 0; 61 | for (i=0; i < 256; i++) 62 | { 63 | for (c = CommandHash[i]; c; c = c->next) 64 | { 65 | if (c->flags ^ CMD_OPER) 66 | continue; 67 | 68 | sendto_one(client, NULL, ":%s CMDSLIST %s%s", me.name, (add) ? "+" : "-", c->cmd); 69 | } 70 | } 71 | return 0; 72 | } 73 | 74 | /* send list of new commands the user can use from being a user who is connected */ 75 | int send_cmds_list_connect(Client *client) 76 | { 77 | RealCommand *c; 78 | int i, type; 79 | 80 | if (!HasCapabilityFast(client, CAP_CMDSLIST) || !MyUser(client)) 81 | return 0; 82 | 83 | for (i=0; i < 256; i++) 84 | { 85 | for (c = CommandHash[i]; c; c = c->next) 86 | { 87 | if (c->flags & CMD_USER) 88 | { 89 | if (c->flags & CMD_UNREGISTERED) 90 | continue; 91 | 92 | if (user_can_do_command(c, client)) 93 | sendto_one(client, NULL, ":%s CMDSLIST +%s", me.name, c->cmd); 94 | } 95 | 96 | // if they can't do it anymore because they're now fully connected 97 | else if (c->flags & CMD_UNREGISTERED && c->flags ^ CMD_USER) 98 | sendto_one(client, NULL, ":%s CMDSLIST -%s", me.name, c->cmd); 99 | } 100 | } 101 | return 0; 102 | } 103 | 104 | int send_cmds_list(Client *client) 105 | { 106 | RealCommand *c; 107 | int i, type; 108 | 109 | if (!HasCapabilityFast(client, CAP_CMDSLIST)) 110 | return 0; 111 | 112 | add_fake_lag(client, 2000); 113 | for (i=0; i < 256; i++) 114 | { 115 | for (c = CommandHash[i]; c; c = c->next) 116 | if (user_can_do_command(c, client)) 117 | sendto_one(client, NULL, ":%s CMDSLIST +%s", me.name, c->cmd); 118 | } 119 | return 0; 120 | } 121 | 122 | 123 | 124 | MOD_INIT() 125 | { 126 | ClientCapabilityInfo cap; 127 | 128 | HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, send_cmds_list_connect); 129 | HookAdd(modinfo->handle, HOOKTYPE_LOCAL_OPER, 0, operhewk); 130 | memset(&cap, 0, sizeof(cap)); 131 | cap.name = CMDSLIST_CAP; 132 | ClientCapabilityAdd(modinfo->handle, &cap, &CAP_CMDSLIST); 133 | CommandAdd(modinfo->handle, CMD_CMDSLIST, CMDLIST, 0, CMD_USER | CMD_UNREGISTERED); 134 | return MOD_SUCCESS; 135 | } 136 | 137 | MOD_LOAD() 138 | { 139 | return MOD_SUCCESS; 140 | } 141 | 142 | MOD_UNLOAD() 143 | { 144 | return MOD_SUCCESS; 145 | } 146 | 147 | CMD_FUNC(CMDLIST) 148 | { 149 | if (!HasCapabilityFast(client, CAP_CMDSLIST)) 150 | return; 151 | send_cmds_list(client); 152 | } 153 | -------------------------------------------------------------------------------- /files/plainusers.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/plainusers"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/plainusers\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/plainusers"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | // Command strings 27 | #define MSG_PLAINUSERS "PLAINUSERS" 28 | #define MSG_PLAINUSERS_SHORT "PUSERS" 29 | 30 | // Dem macros yo 31 | #define CheckAPIError(apistr, apiobj) \ 32 | do { \ 33 | if(!(apiobj)) { \ 34 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 35 | return MOD_FAILED; \ 36 | } \ 37 | } while(0) 38 | 39 | CMD_FUNC(plainusers); // Register command function 40 | 41 | // Dat dere module header 42 | ModuleHeader MOD_HEADER = { 43 | "third/plainusers", // Module name 44 | "2.1.1", // Version 45 | "Allows opers to list all users NOT connected over SSL/TLS", // Description 46 | "Gottem", // Author 47 | "unrealircd-6", // Modversion 48 | }; 49 | 50 | // Initialisation routine (register hooks, commands and modes or create structs etc) 51 | MOD_INIT() { 52 | CheckAPIError("CommandAdd(PLAINUSERS)", CommandAdd(modinfo->handle, MSG_PLAINUSERS, plainusers, 0, CMD_USER)); 53 | CheckAPIError("CommandAdd(PUSERS)", CommandAdd(modinfo->handle, MSG_PLAINUSERS_SHORT, plainusers, 0, CMD_USER)); 54 | 55 | MARK_AS_GLOBAL_MODULE(modinfo); 56 | return MOD_SUCCESS; 57 | } 58 | 59 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 60 | MOD_LOAD() { 61 | return MOD_SUCCESS; // We good 62 | } 63 | 64 | // Called on unload/rehash obv 65 | MOD_UNLOAD() { 66 | return MOD_SUCCESS; // We good 67 | } 68 | 69 | CMD_FUNC(plainusers) { 70 | // Gets args: ClientContext *clictx, Client *client, MessageTag *recv_mtags, int parc, const char *parv[] 71 | char ubuf[224]; // For sending multiple nicks at once instead of spamming the fuck out of people 72 | Client *acptr; // For iteration lol 73 | int count; // Count em too yo 74 | if(!IsUser(client) || !IsOper(client)) { 75 | sendnumeric(client, ERR_NOPRIVILEGES); // lmao no privlelgdges 76 | return; // rip 77 | } 78 | 79 | memset(ubuf, '\0', sizeof(ubuf)); // Init 'em 80 | count = 0; 81 | list_for_each_entry(acptr, &client_list, client_node) { // Get clients lol 82 | if(!IsUser(acptr) || IsULine(acptr)) // Check if it's a person and NOT a U-Line (as they usually connect w/o SSL) 83 | continue; 84 | 85 | if((acptr->umodes & UMODE_SECURE)) // Check for umode +z (indic8s ur connected wit TLS etc) 86 | continue; 87 | 88 | count++; // Gottem 89 | 90 | if(!ubuf[0]) // First nick in this set 91 | strlcpy(ubuf, acptr->name, sizeof(ubuf)); // Need cpy instead of cat ;] 92 | else { 93 | strlcat(ubuf, ", ", sizeof(ubuf)); // Dat separator lol 94 | strlcat(ubuf, acptr->name, sizeof(ubuf)); // Now append non-first nikk =] 95 | } 96 | 97 | if(strlen(ubuf) > (sizeof(ubuf) - NICKLEN - 3)) { // If another nick won't fit (-3 cuz ", " and nullbyet) 98 | sendnotice(client, "[plainusers] Found: %s", ubuf); // Send what we have 99 | memset(ubuf, 0, sizeof(ubuf)); // And reset buffer lmoa 100 | } 101 | } 102 | if(ubuf[0]) // If we still have some nicks (i.e. we didn't exceed buf's size for the last set) 103 | sendnotice(client, "[plainusers] Found: %s", ubuf); // Dump whatever's left 104 | 105 | if(!count) 106 | sendnotice(client, "[plainusers] No non-SSL/TLS users found"); 107 | } 108 | -------------------------------------------------------------------------------- /files/tracetklbug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * tracetklbug - Temporary module for tracing SHUN bug from 3 | * https://bugs.unrealircd.org/view.php?id=5566 4 | * (C) Copyright 2020 Bram Matthys (Syzop) and the UnrealIRCd team. 5 | * License: GPLv2 6 | */ 7 | 8 | #include "unrealircd.h" 9 | 10 | ModuleHeader MOD_HEADER 11 | = { 12 | "third/tracetklbug", 13 | "1.0.0", 14 | "Trace TKL bug", 15 | "UnrealIRCd Team", 16 | "unrealircd-5", 17 | }; 18 | 19 | /* Externs */ 20 | extern int match_tkls(Client *client); 21 | 22 | /* Forward declarions */ 23 | CMD_FUNC(tracetklbug_cmd); 24 | 25 | MOD_INIT() 26 | { 27 | CommandAdd(modinfo->handle, "TRACETKLBUG", tracetklbug_cmd, MAXPARA, CMD_USER); 28 | return MOD_SUCCESS; 29 | } 30 | 31 | MOD_LOAD() 32 | { 33 | return MOD_SUCCESS; 34 | } 35 | 36 | MOD_UNLOAD() 37 | { 38 | return MOD_SUCCESS; 39 | } 40 | 41 | void verifyevents(Client *client) 42 | { 43 | Event *e; 44 | 45 | e = EventFind("check_pings"); 46 | if (!e) 47 | { 48 | sendnotice(client, "[BUG] The check_pings event is missing???"); 49 | return; 50 | } 51 | 52 | if (e->every_msec != 1000) 53 | sendnotice(client, "[BUG] The check_pings should run every 1000 msec but instead runs every %lld msec", (long long)e->every_msec); 54 | 55 | if (e->count != 0) 56 | sendnotice(client, "[BUG] The check_pings should run with count=0 but insteads count=%lld", (long long)e->count); 57 | 58 | if (loop.do_bancheck) 59 | { 60 | sendnotice(client, "Warning: loop.do_bancheck is still pending. Did you wait a few seconds after placing the SHUN before running TRACETKLBUG? " 61 | "Otherwise this command may produce false results."); 62 | } 63 | } 64 | 65 | CMD_FUNC(tracetklbug_cmd) 66 | { 67 | Client *target = NULL; 68 | int was_shunned = 0; 69 | 70 | if (!IsOper(client)) 71 | { 72 | sendnumeric(client, ERR_NOPRIVILEGES); 73 | return; 74 | } 75 | 76 | verifyevents(client); 77 | 78 | if ((parc < 2) || BadPtr(parv[1])) 79 | { 80 | sendnumeric(client, ERR_NEEDMOREPARAMS, "TRACETKLBUG"); 81 | return; 82 | } 83 | 84 | target = find_person(parv[1], NULL); 85 | if (!target) 86 | { 87 | sendnumeric(client, ERR_NOSUCHNICK, parv[1]); 88 | return; 89 | } 90 | 91 | if (!MyUser(target)) 92 | { 93 | sendnotice(client, "Forwarding your request to %s's server...", target->name); 94 | sendto_one(target, NULL, ":%s TRACETKLBUG :%s", client->name, target->name); 95 | return; 96 | } 97 | 98 | if (IsShunned(target)) 99 | was_shunned = 1; 100 | 101 | match_tkls(target); 102 | 103 | if (!was_shunned && IsShunned(target)) 104 | { 105 | sendnotice(client, "User was not shunned before. User got shunned now once you issued /TRACETKLBUG. %s.", 106 | loop.do_bancheck ? "Ban check was still pending, could be a race condition." : "loop.do_bancheck was zero, so this should not have happened!"); 107 | return; 108 | } 109 | 110 | if (IsShunned(target)) 111 | { 112 | sendnotice(client, "User was already shunned (TRACETKLBUG did not change this)"); 113 | } else { 114 | sendnotice(client, "User is NOT shunned. TKL system thinks it should not shun this user."); 115 | if (find_tkl_exception(TKL_SHUN, target)) 116 | { 117 | sendnotice(client, "User matches a TKL exception, check '/STATS except'"); 118 | } 119 | else 120 | { 121 | sendnotice(client, "User does not match a TKL exception, this means there is simply no SHUN matching this user. " 122 | "If you don't agree with this then check '/STATS shun' and WHOIS the user and copy-paste " 123 | "this proof back to us."); 124 | } 125 | } 126 | } 127 | 128 | /*** <<>> 129 | module 130 | { 131 | documentation "https://bugs.unrealircd.org/view.php?id=5566"; 132 | 133 | // This is displayed in './unrealircd module info ..' and also if compilation of the module fails: 134 | troubleshooting "Contact syzop@unrealircd.org if this module fails to compile"; 135 | 136 | // Minimum version necessary for this module to work: 137 | min-unrealircd-version "5.*"; 138 | 139 | post-install-text { 140 | "The module is installed. Now all you need to do is add a loadmodule line:"; 141 | "loadmodule \"third/tracetklbug\";"; 142 | "And /REHASH the IRCd."; 143 | "The module does not need any other configuration."; 144 | } 145 | } 146 | *** <<>> 147 | */ 148 | -------------------------------------------------------------------------------- /files/listsg.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2024 Jean Chevronnet 4 | 5 | */ 6 | /*** <<>> 7 | module 8 | { 9 | documentation "https://github.com/revrsedev/UnrealIRCD-6-mods-contrib/blob/main/listsg/README.md"; 10 | troubleshooting "In case of problems, documentation or e-mail me at mike.chevronnet@gmail.com"; 11 | min-unrealircd-version "6.*"; 12 | post-install-text { 13 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 14 | "loadmodule \"third/listsg\";"; 15 | "Then /rehash the IRCd."; 16 | "For usage information, refer to the module's documentation found at: https://github.com/revrsedev/UnrealIRCD-6-mods-contrib/blob/main/listsg/README.md"; 17 | } 18 | } 19 | *** <<>> 20 | */ 21 | 22 | #include "unrealircd.h" 23 | 24 | #define MSG_SG "SG" 25 | #define MAX_BUFFER_SIZE 512 26 | #define MAX_NICKNAMES_PER_LINE 10 27 | 28 | CMD_FUNC(cmd_sg); 29 | 30 | // Forward declarations 31 | void list_security_groups_for_user(Client *client, Client *user); 32 | void list_members_of_security_group(Client *client, const char *groupname); 33 | 34 | ModuleHeader MOD_HEADER = { 35 | "third/listsg", // Module name 36 | "1.0", // Version 37 | "Command /SG to list security groups and their members", // Description 38 | "reverse", // Author 39 | "unrealircd-6", // UnrealIRCd version 40 | }; 41 | 42 | MOD_INIT() { 43 | CommandAdd(modinfo->handle, MSG_SG, cmd_sg, 1, CMD_USER); // Adding the command 44 | return MOD_SUCCESS; 45 | } 46 | 47 | MOD_LOAD() { 48 | return MOD_SUCCESS; 49 | } 50 | 51 | MOD_UNLOAD() { 52 | return MOD_SUCCESS; 53 | } 54 | 55 | CMD_FUNC(cmd_sg) { 56 | if (parc < 2) { 57 | sendnotice(client, "Usage: /SG "); 58 | return; 59 | } 60 | 61 | const char *arg = parv[1]; 62 | Client *target_user = find_client(arg, NULL); 63 | if (target_user) { 64 | list_security_groups_for_user(client, target_user); 65 | } else { 66 | list_members_of_security_group(client, arg); 67 | } 68 | } 69 | 70 | // Function to list security groups a user is part of 71 | void list_security_groups_for_user(Client *client, Client *user) { 72 | const char *groups = get_security_groups(user); 73 | if (!groups || *groups == '\0') { 74 | sendnotice(client, "User %s is not part of any security groups.", user->name); 75 | return; 76 | } 77 | 78 | sendnotice(client, "Security groups for user %s:", user->name); 79 | sendnotice(client, "- %s", groups); 80 | } 81 | 82 | // Function to list members of a security group 83 | void list_members_of_security_group(Client *client, const char *groupname) { 84 | SecurityGroup *group = find_security_group(groupname); 85 | if (!group) { 86 | sendnotice(client, "Security group %s does not exist.", groupname); 87 | return; 88 | } 89 | 90 | sendnotice(client, "Members of security group %s:", groupname); 91 | 92 | Client *target; 93 | int member_found = 0; 94 | char buffer[MAX_BUFFER_SIZE]; 95 | buffer[0] = '\0'; 96 | int nickname_count = 0; 97 | 98 | list_for_each_entry(target, &lclient_list, lclient_node) { 99 | if (user_allowed_by_security_group_name(target, groupname)) { 100 | if (nickname_count > 0) { 101 | strlcat(buffer, ", ", sizeof(buffer)); 102 | } 103 | strlcat(buffer, target->name, sizeof(buffer)); 104 | nickname_count++; 105 | member_found = 1; 106 | 107 | // Check if the buffer is near its limit or if we reached the max nicknames per line 108 | if (strlen(buffer) >= MAX_BUFFER_SIZE - 50 || nickname_count >= MAX_NICKNAMES_PER_LINE) { 109 | sendnotice(client, "- %s", buffer); 110 | buffer[0] = '\0'; // Reset buffer 111 | nickname_count = 0; // Reset nickname count 112 | } 113 | } 114 | } 115 | 116 | // Send any remaining nicknames in the buffer 117 | if (nickname_count > 0) { 118 | sendnotice(client, "- %s", buffer); 119 | } 120 | 121 | if (!member_found) { 122 | sendnotice(client, "Security group %s has no members.", groupname); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /files/filehost.c: -------------------------------------------------------------------------------- 1 | /** === Module Information === 2 | * 3 | * NAME: draft/FILEHOST 4 | * LICENCE: GPLv3 or later 5 | * COPYRIGHT: Ⓒ 20253 Valerie Pond, 2022 Val Lorentz 6 | * DOCS: https://github.com/progval/ircv3-specifications/blob/filehost/extensions/filehost.md 7 | * 8 | */ 9 | /*** <<>> 10 | module 11 | { 12 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/filehost/README.md"; 13 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 14 | min-unrealircd-version "6.*"; 15 | max-unrealircd-version "6.*"; 16 | post-install-text { 17 | "The module is installed. Now all you need to do is add a loadmodule line:"; 18 | "loadmodule \"third/filehost\";"; 19 | "And /REHASH the IRCd."; 20 | "The module does not need any other configuration."; 21 | } 22 | } 23 | *** <<>> 24 | */ 25 | #include "unrealircd.h" 26 | 27 | #define CONF_FILEHOST "filehosts" 28 | 29 | /* FILEHOST config struct */ 30 | struct 31 | { 32 | char *isupport_line; 33 | MultiLine *hosts; 34 | unsigned short int has_hosts; 35 | } cfg; 36 | 37 | 38 | 39 | int filehost_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs); 40 | int filehost_configrun(ConfigFile *cf, ConfigEntry *ce, int type); 41 | void setconf(void); 42 | void freeconf(void); 43 | 44 | ModuleHeader MOD_HEADER 45 | = { 46 | "third/filehost", 47 | "1.1", 48 | "IRCv3 draft/FILEHOST - Provides users with an ISUPPORT token with a URL to your file upload service", 49 | "Valware", 50 | "unrealircd-6", 51 | }; 52 | 53 | MOD_TEST() 54 | { 55 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, filehost_configtest); 56 | return MOD_SUCCESS; 57 | } 58 | 59 | MOD_INIT() 60 | { 61 | 62 | setconf(); 63 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, filehost_configrun); 64 | return MOD_SUCCESS; 65 | } 66 | 67 | MOD_LOAD() 68 | { 69 | ISupport *is; 70 | if (!(is = ISupportAdd(modinfo->handle, "draft/FILEHOST", cfg.isupport_line))) 71 | return MOD_FAILED; 72 | return MOD_SUCCESS; 73 | } 74 | 75 | MOD_UNLOAD() 76 | { 77 | freeconf(); 78 | return MOD_SUCCESS; 79 | } 80 | 81 | void setconf(void) 82 | { 83 | memset(&cfg, 0, sizeof(cfg)); 84 | cfg.has_hosts = 0; 85 | safe_strdup(cfg.isupport_line,""); 86 | } 87 | 88 | void freeconf(void) 89 | { 90 | freemultiline(cfg.hosts); 91 | cfg.has_hosts = 0; 92 | safe_free(cfg.isupport_line); 93 | memset(&cfg, 0, sizeof(cfg)); 94 | } 95 | 96 | 97 | int filehost_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) 98 | { 99 | int errors = 0; 100 | ConfigEntry *cep; 101 | 102 | if (type != CONFIG_MAIN) 103 | return 0; 104 | 105 | if (!ce || !ce->name) 106 | return 0; 107 | 108 | if (strcmp(ce->name, CONF_FILEHOST)) 109 | return 0; 110 | 111 | for (cep = ce->items; cep; cep = cep->next) 112 | { 113 | if (!cep->name) 114 | { 115 | config_error("%s:%i: blank %s item", cep->file->filename, cep->line_number, CONF_FILEHOST); 116 | ++errors; 117 | continue; 118 | } 119 | if (!strcasecmp(cep->name, "host")) 120 | { 121 | if (!BadPtr(cep->value)) 122 | cfg.has_hosts = 1; 123 | 124 | else 125 | config_error("%s:%i: Empty host at %s::%s", cep->file->filename, cep->line_number, CONF_FILEHOST, cep->name); 126 | 127 | continue; 128 | } 129 | 130 | // Anything else is unknown to us =] 131 | config_warn("%s:%i: unknown item %s::%s", cep->file->filename, cep->line_number, CONF_FILEHOST, cep->name); // So display just a warning 132 | } 133 | 134 | *errs = errors; 135 | return errors ? -1 : 1; 136 | } 137 | 138 | int filehost_configrun(ConfigFile *cf, ConfigEntry *ce, int type) 139 | { 140 | ConfigEntry *cep; 141 | char buf[BUFSIZE] = "\0"; 142 | 143 | if (type != CONFIG_MAIN) 144 | return 0; 145 | 146 | if (!ce || !ce->name) 147 | return 0; 148 | 149 | if (strcmp(ce->name, "filehosts")) 150 | return 0; 151 | 152 | for (cep = ce->items; cep; cep = cep->next) 153 | { 154 | if (!cep->name) 155 | continue; 156 | 157 | if (!strcmp(cep->name, "host")) 158 | addmultiline(&cfg.hosts, cep->value); 159 | 160 | } 161 | 162 | for (MultiLine *m = cfg.hosts; m; m = m->next) 163 | { 164 | strlcat(buf,m->line, sizeof(buf)); 165 | if (m->next) 166 | strlcat(buf,"\\x20",sizeof(buf)); 167 | } 168 | if (strlen(buf)) 169 | safe_strdup(cfg.isupport_line, buf); 170 | 171 | 172 | return 1; // We good 173 | } 174 | -------------------------------------------------------------------------------- /files/reduced-moderation.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 3 | Copyright Ⓒ 2022-2025 Valerie Pond 4 | 5 | Permissions: By using this module, you agree that it is Free, and you are allowed to make copies 6 | and redistrubite this at your own free will, so long as in doing so, the original author and license remain in-tact. 7 | 8 | 9 | Reduced moderation: Requested by Mahjong 10 | 11 | */ 12 | /*** <<>> 13 | module 14 | { 15 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/reduced-moderation/README.md"; 16 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 17 | min-unrealircd-version "6.*"; 18 | max-unrealircd-version "6.*"; 19 | post-install-text { 20 | "The module is installed. Now all you need to do is add a loadmodule line:"; 21 | "loadmodule \"third/reduced-moderation\";"; 22 | "And /REHASH the IRCd."; 23 | "The module does not need any other configuration."; 24 | } 25 | } 26 | *** <<>> 27 | */ 28 | 29 | #include "unrealircd.h" 30 | 31 | 32 | ModuleHeader MOD_HEADER 33 | = { 34 | "third/reduced-moderation", 35 | "1.2", 36 | "Reduced Moderation mode (+x)", 37 | "Valware", 38 | "unrealircd-6", 39 | }; 40 | 41 | /* Global variables */ 42 | Cmode_t EXTCMODE_REDMOD; 43 | 44 | /* Forward declarations */ 45 | #if UNREAL_VERSION >= 0x06020000 46 | int redmod_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx); 47 | #else 48 | int redmod_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype); 49 | #endif 50 | const char *redmod_pre_local_part(Client *client, Channel *channel, const char *text); 51 | 52 | /* Macros */ 53 | #define IsRedMod(channel) (channel->mode.mode & EXTCMODE_REDMOD) 54 | 55 | MOD_INIT() 56 | { 57 | CmodeInfo req; 58 | 59 | MARK_AS_GLOBAL_MODULE(modinfo); 60 | 61 | memset(&req, 0, sizeof(req)); 62 | req.paracount = 0; 63 | req.letter = 'x'; 64 | req.is_ok = extcmode_default_requirechop; 65 | CmodeAdd(modinfo->handle, req, &EXTCMODE_REDMOD); 66 | 67 | HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_CHANNEL, 123, redmod_can_send_to_channel); 68 | HookAddConstString(modinfo->handle, HOOKTYPE_PRE_LOCAL_PART, 123, redmod_pre_local_part); 69 | 70 | return MOD_SUCCESS; 71 | } 72 | 73 | MOD_LOAD() 74 | { 75 | return MOD_SUCCESS; 76 | } 77 | 78 | MOD_UNLOAD() 79 | { 80 | return MOD_SUCCESS; 81 | } 82 | 83 | /* Overrides for +m also will override +x */ 84 | #if UNREAL_VERSION >= 0x06020000 85 | int redmod_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx) 86 | #else 87 | int redmod_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype) 88 | #endif 89 | { 90 | MessageTag *mtags = NULL; 91 | if (IsRedMod(channel) && (!member || !check_channel_access_membership(member, "vhoaq")) && 92 | !op_can_override("channel:override:message:moderated",client,channel,NULL)) 93 | { 94 | Hook *h; 95 | for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next) 96 | { 97 | int i = (*(h->func.intfunc))(client, channel, BYPASS_CHANMSG_MODERATED); 98 | if (i == HOOK_ALLOW) 99 | return HOOK_CONTINUE; 100 | if (i != HOOK_CONTINUE) 101 | break; 102 | } 103 | 104 | if (sendtype == SEND_TYPE_TAGMSG) 105 | return HOOK_DENY; // DENY all tagmsg for now 106 | 107 | int notice = (sendtype == SEND_TYPE_NOTICE); 108 | 109 | new_message(client, NULL, &mtags); 110 | sendto_channel(channel, client, NULL, "oaq", 0, SEND_ALL, mtags, ":%s %s %s :%s", client->name, (notice ? "NOTICE" : "PRIVMSG"), channel->name, *text); 111 | if (HasCapability(client, "echo-message")) 112 | sendto_one(client, mtags, ":%s %s %s :%s", client->name, (notice ? "NOTICE" : "PRIVMSG"), channel->name, *text); 113 | 114 | free_message_tags(mtags); 115 | *text = NULL; 116 | 117 | } 118 | 119 | return HOOK_CONTINUE; 120 | } 121 | 122 | const char *redmod_pre_local_part(Client *client, Channel *channel, const char *text) 123 | { 124 | if (IsRedMod(channel) && !check_channel_access(client, channel, "v") && !check_channel_access(client, channel, "h")) 125 | return NULL; 126 | return text; 127 | } 128 | -------------------------------------------------------------------------------- /files/sacycle.c: -------------------------------------------------------------------------------- 1 | /* 2 | LICENSE: GPLv3 3 | Copyright Ⓒ 2022 Valerie Pond 4 | 5 | SACYCLE command for forcing someone to cycle a channel 6 | 7 | Largely taken from unrealircd sauce code 8 | 9 | */ 10 | /*** <<>> 11 | module 12 | { 13 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/sayeet/README.md"; 14 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 15 | min-unrealircd-version "6.*"; 16 | max-unrealircd-version "6.*"; 17 | post-install-text { 18 | "The module is installed. Now all you need to do is add a loadmodule line:"; 19 | "loadmodule \"third/sacycle\";"; 20 | "And /REHASH the IRCd."; 21 | "The module does not need any other configuration."; 22 | } 23 | } 24 | *** <<>> 25 | */ 26 | #include "unrealircd.h" 27 | 28 | 29 | #define CheckAPIError(apistr, apiobj) \ 30 | do { \ 31 | if(!(apiobj)) { \ 32 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 33 | return MOD_FAILED; \ 34 | } \ 35 | } while(0) 36 | 37 | 38 | /* the cmd lmao */ 39 | #define CMD "SACYCLE" 40 | 41 | CMD_FUNC(yeetus); 42 | 43 | ModuleHeader MOD_HEADER = { 44 | "third/sacycle", 45 | "1.1", 46 | "Force someone to part and rejoin a channel", 47 | "Valware", 48 | "unrealircd-6", 49 | }; 50 | MOD_INIT() 51 | { 52 | CheckAPIError("CommandAdd(CMD)", CommandAdd(modinfo->handle, CMD, yeetus, 2, CMD_USER|CMD_SERVER)); 53 | MARK_AS_GLOBAL_MODULE(modinfo); 54 | return MOD_SUCCESS; 55 | } 56 | 57 | MOD_LOAD(){ return MOD_SUCCESS; } 58 | MOD_UNLOAD(){ return MOD_SUCCESS; } 59 | 60 | 61 | CMD_FUNC(yeetus){ 62 | Client *target; 63 | Channel *channel; 64 | Membership *lp; 65 | char *name, *p = NULL; 66 | int i; 67 | char jbuf[BUFSIZE]; 68 | char reqtarg[BUFSIZE]; 69 | int ntargets = 0; 70 | int maxtargets = max_targets_for_command("CYCLE"); 71 | 72 | if ((parc < 3) || BadPtr(parv[2])) 73 | { 74 | sendnumeric(client, ERR_NEEDMOREPARAMS, "SACYCLE"); 75 | return; 76 | } 77 | 78 | if (!(target = find_user(parv[1], NULL))) 79 | { 80 | sendnumeric(client, ERR_NOSUCHNICK, parv[1]); 81 | return; 82 | } 83 | 84 | /* See if we can operate on this vicim/this command */ 85 | if (!ValidatePermissionsForPath("sacmd:sapart",client,target,NULL,NULL)) 86 | { 87 | sendnumeric(client, ERR_NOPRIVILEGES); 88 | return; 89 | } 90 | 91 | /* Relay it on, if it's not my target */ 92 | if (!MyUser(target)) 93 | { 94 | 95 | sendto_one(target, NULL, ":%s SACYCLE %s %s", client->id, target->id, parv[2]); 96 | 97 | return; 98 | } 99 | strlcpy(reqtarg, parv[2], sizeof(reqtarg)); 100 | /* Now works like cmd_join */ 101 | *jbuf = 0; 102 | for (i = 0, name = strtoken(&p, reqtarg, ","); name; name = strtoken(&p, NULL, ",")) 103 | { 104 | if (++ntargets > maxtargets) 105 | { 106 | sendnumeric(client, ERR_TOOMANYTARGETS, name, maxtargets, "SACYCLE"); 107 | break; 108 | } 109 | if (!(channel = find_channel(name))) 110 | { 111 | sendnumeric(client, ERR_NOSUCHCHANNEL, 112 | name); 113 | continue; 114 | } 115 | 116 | /* Validate oper can do this on chan/victim */ 117 | if (!IsULine(client) && !ValidatePermissionsForPath("sacmd:sapart",client,target,channel,NULL)) 118 | { 119 | sendnumeric(client, ERR_NOPRIVILEGES); 120 | continue; 121 | } 122 | 123 | if (!(lp = find_membership_link(target->user->channel, channel))) 124 | { 125 | sendnumeric(client, ERR_USERNOTINCHANNEL, target->name, name); 126 | continue; 127 | } 128 | if (*jbuf) 129 | strlcat(jbuf, ",", sizeof jbuf); 130 | strlncat(jbuf, name, sizeof jbuf, sizeof(jbuf) - i - 1); 131 | i += strlen(name) + 1; 132 | } 133 | 134 | if (!*jbuf) 135 | return; 136 | 137 | strlcpy(reqtarg, jbuf, sizeof(reqtarg)); 138 | 139 | 140 | parv[0] = target->name; // nick 141 | parv[1] = reqtarg; // chan 142 | parv[2] = NULL; 143 | 144 | sendnotice(target, "*** You were forced to cycle %s", parv[1]); 145 | if (!IsULine(client)) 146 | unreal_log(ULOG_INFO, "sacmds", "SACYCLE_COMMAND", client, 147 | "SACYCLE: $client used SACYCLE to make $target cycle $channel", 148 | log_data_client("target", target), 149 | log_data_string("channel", parv[1])); 150 | 151 | do_cmd(target, NULL, "CYCLE", 2, parv); 152 | /* target may be killed now due to the part reason @ spamfilter */ 153 | } 154 | -------------------------------------------------------------------------------- /files/chgswhois.c: -------------------------------------------------------------------------------- 1 | /* 2 | This module provides command /CHGSWHOIS which does what it says on the tin 3 | 4 | This module changes a users "special whois" line to the string you specify 5 | 6 | Syntax: CHGSWHOIS username is a bastardó 7 | 8 | This module needs to be loaded on all servers on the network 9 | 10 | License: GPLv3 11 | 12 | Copyright Ⓒ 2022 Valerie Pond 13 | */ 14 | /*** <<>> 15 | module { 16 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/chgswhois/README.md"; 17 | troubleshooting "In case of problems, check the README or e-mail me at v.a.pond@outlook.com"; 18 | min-unrealircd-version "6.*"; 19 | 20 | post-install-text { 21 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 22 | "loadmodule \"third/chgswhois\";"; 23 | "Then /rehash the IRCd."; 24 | "This module have no configuration"; 25 | } 26 | } 27 | *** <<>> 28 | */ 29 | 30 | #include "unrealircd.h" 31 | 32 | // deFIIIINEs 33 | #define CHGCMD "CHGSWHOIS" 34 | #define DELCMD "DELSWHOIS" 35 | #define CheckAPIError(apistr, apiobj) \ 36 | do { \ 37 | if(!(apiobj)) { \ 38 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 39 | return MOD_FAILED; \ 40 | } \ 41 | } while(0) 42 | 43 | 44 | CMD_FUNC(CHGSWHOIS); 45 | CMD_FUNC(DELSWHOIS); 46 | 47 | ModuleHeader MOD_HEADER = { 48 | "third/chgswhois", 49 | "1.0", 50 | "Provides command /CHGSWHOIS and /DELSWHOIS for priviledged IRCops to change a users \"special whois\" line.", 51 | "Valware", 52 | "unrealircd-6", 53 | }; 54 | 55 | MOD_INIT() { 56 | CheckAPIError("CommandAdd(CHGSWHOIS)", CommandAdd(modinfo->handle, CHGCMD, CHGSWHOIS, 2, CMD_USER)); 57 | CheckAPIError("CommandAdd(DELSWHOIS)", CommandAdd(modinfo->handle, DELCMD, DELSWHOIS, 1, CMD_USER)); 58 | MARK_AS_GLOBAL_MODULE(modinfo); 59 | return MOD_SUCCESS; 60 | } 61 | 62 | MOD_LOAD() { 63 | return MOD_SUCCESS; 64 | } 65 | MOD_UNLOAD() { 66 | return MOD_SUCCESS; 67 | } 68 | 69 | CMD_FUNC(CHGSWHOIS) { 70 | 71 | Client *splooge; 72 | char tag[HOSTLEN+1]; 73 | char swhois[SWHOISLEN+1]; 74 | *tag = *swhois = '\0'; 75 | // we're somewhere in there! 76 | int priority = 5; 77 | 78 | if (!ValidatePermissionsForPath("client:set:name",client,NULL,NULL,NULL)) { 79 | sendnumeric(client, ERR_NOPRIVILEGES); 80 | return; 81 | } 82 | 83 | else if ((parc < 3) || !*parv[2]) { 84 | sendnumeric(client, ERR_NEEDMOREPARAMS, CHGCMD); 85 | return; 86 | } 87 | 88 | else if (strlen(parv[2]) > (SWHOISLEN)) { 89 | sendnotice(client, "*** CHGSWHOIS rejected: Too long"); 90 | return; 91 | } 92 | 93 | else if (!(splooge = find_user(parv[1], NULL))) { 94 | sendnumeric(client, ERR_NOSUCHNICK, parv[1]); 95 | return; 96 | } 97 | strlcpy(tag, client->name, sizeof(tag)); 98 | strlcpy(swhois, parv[2], sizeof(swhois)); 99 | 100 | 101 | if (!IsULine(client)) 102 | unreal_log(ULOG_INFO, "chgcmds", "CHGSWHOIS_COMMAND", client, 103 | "CHGSWHOIS: $client changed the special whois of $target to be $new_swhois", 104 | log_data_string("change_type", "swhois"), 105 | log_data_client("target", splooge), 106 | log_data_string("new_swhois", parv[2])); 107 | 108 | // Find and delete old swhois line 109 | 110 | swhois_delete(splooge, "chgswhoislmao", "*", &me, NULL); 111 | 112 | // Add our new one! 113 | swhois_add(splooge, "chgswhoislmao", priority, swhois, &me, NULL); 114 | return; 115 | 116 | } 117 | 118 | // copypasta ninja copies from abooove~~~ 119 | CMD_FUNC(DELSWHOIS) { 120 | 121 | Client *splooge; 122 | char tag[HOSTLEN+1]; 123 | 124 | if (!ValidatePermissionsForPath("client:set:name",client,NULL,NULL,NULL)) { 125 | sendnumeric(client, ERR_NOPRIVILEGES); 126 | return; 127 | } 128 | 129 | else if ((parc < 2) || !*parv[1]) { 130 | sendnumeric(client, ERR_NEEDMOREPARAMS, CHGCMD); 131 | return; 132 | } 133 | 134 | else if (!(splooge = find_user(parv[1], NULL))) { 135 | sendnumeric(client, ERR_NOSUCHNICK, parv[1]); 136 | return; 137 | } 138 | 139 | if (!IsULine(client)) 140 | unreal_log(ULOG_INFO, "chgcmds", "DELSWHOIS_COMMAND", client, 141 | "CHGSWHOIS: $client deleted the special whois of $target.details", 142 | log_data_string("change_type", "swhois"), 143 | log_data_client("target", splooge)); 144 | 145 | // Find and delete old swhois line 146 | swhois_delete(splooge, "chgswhoislmao", "*", &me, NULL); 147 | 148 | return; 149 | 150 | } 151 | 152 | -------------------------------------------------------------------------------- /files/irccloud-tags.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Based on https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/kiwiirc-tags/kiwiirc-tags.c 4 | Copyright © 2022 Valerie Pond 5 | 6 | Provides support for IRCCloud-related tags 7 | Copyright © 2025 IRCCloud 8 | */ 9 | /*** <<>> 10 | module 11 | { 12 | documentation "https://github.com/irccloud/irccloud-tools/tree/master/irccloud-tags-unrealircd"; 13 | troubleshooting "In case of problems, documentation or e-mail us at team@irccloud.com"; 14 | min-unrealircd-version "6.*"; 15 | max-unrealircd-version "6.*"; 16 | post-install-text { 17 | "The module is installed. Now all you need to do is add a loadmodule line:"; 18 | "loadmodule \"third/irccloud-tags\";"; 19 | "And /REHASH the IRCd."; 20 | "The module does not need any other configuration."; 21 | } 22 | } 23 | *** <<>> 24 | */ 25 | 26 | #define MTAG_UNREACT "+draft/unreact" 27 | #define MTAG_EDIT "+draft/edit" 28 | #define MTAG_EDIT_TEXT "+draft/edit-text" 29 | #define MTAG_ATTACHMENTS "+draft/attachments" 30 | #define MTAG_ATTACHMENT_FALLBACK "+draft/attachment-fallback" 31 | #include "unrealircd.h" 32 | 33 | ModuleHeader MOD_HEADER = 34 | { 35 | "third/irccloud-tags", 36 | "1.0", 37 | "Provides support for IRCCloud's MessageTags", 38 | "IRCCloud", 39 | "unrealircd-6", 40 | }; 41 | int irccloud_tag(Client *client, const char *name, const char *value); 42 | void mtag_add_irccloud_tag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature); 43 | 44 | MOD_INIT() 45 | { 46 | MessageTagHandlerInfo mtag; 47 | 48 | MARK_AS_GLOBAL_MODULE(modinfo); 49 | 50 | memset(&mtag, 0, sizeof(mtag)); 51 | mtag.is_ok = irccloud_tag; 52 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 53 | mtag.name = MTAG_UNREACT; 54 | MessageTagHandlerAdd(modinfo->handle, &mtag); 55 | 56 | memset(&mtag, 0, sizeof(mtag)); 57 | mtag.is_ok = irccloud_tag; 58 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 59 | mtag.name = MTAG_EDIT; 60 | MessageTagHandlerAdd(modinfo->handle, &mtag); 61 | 62 | memset(&mtag, 0, sizeof(mtag)); 63 | mtag.is_ok = irccloud_tag; 64 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 65 | mtag.name = MTAG_EDIT_TEXT; 66 | MessageTagHandlerAdd(modinfo->handle, &mtag); 67 | 68 | memset(&mtag, 0, sizeof(mtag)); 69 | mtag.is_ok = irccloud_tag; 70 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 71 | mtag.name = MTAG_ATTACHMENTS; 72 | MessageTagHandlerAdd(modinfo->handle, &mtag); 73 | 74 | memset(&mtag, 0, sizeof(mtag)); 75 | mtag.is_ok = irccloud_tag; 76 | mtag.flags = MTAG_HANDLER_FLAGS_NO_CAP_NEEDED; 77 | mtag.name = MTAG_ATTACHMENT_FALLBACK; 78 | MessageTagHandlerAdd(modinfo->handle, &mtag); 79 | 80 | HookAddVoid(modinfo->handle, HOOKTYPE_NEW_MESSAGE, 0, mtag_add_irccloud_tag); 81 | 82 | 83 | return MOD_SUCCESS; 84 | } 85 | 86 | MOD_LOAD() 87 | { 88 | return MOD_SUCCESS; 89 | } 90 | 91 | MOD_UNLOAD() 92 | { 93 | return MOD_SUCCESS; 94 | } 95 | 96 | int irccloud_tag(Client *client, const char *name, const char *value) 97 | { 98 | if (!strlen(value)) 99 | { 100 | sendto_one(client, NULL, "FAIL * MESSAGE_TAG_TOO_SHORT %s :That message tag must contain a value.", name); 101 | return 0; 102 | } 103 | return 1; 104 | } 105 | 106 | void mtag_add_irccloud_tag(Client *client, MessageTag *recv_mtags, MessageTag **mtag_list, const char *signature) 107 | { 108 | MessageTag *m; 109 | 110 | if (IsUser(client)) 111 | { 112 | m = find_mtag(recv_mtags, MTAG_UNREACT); 113 | if (m) 114 | { 115 | m = duplicate_mtag(m); 116 | AddListItem(m, *mtag_list); 117 | } 118 | m = find_mtag(recv_mtags, MTAG_EDIT); 119 | if (m) 120 | { 121 | m = duplicate_mtag(m); 122 | AddListItem(m, *mtag_list); 123 | } 124 | m = find_mtag(recv_mtags, MTAG_EDIT_TEXT); 125 | if (m) 126 | { 127 | m = duplicate_mtag(m); 128 | AddListItem(m, *mtag_list); 129 | } 130 | m = find_mtag(recv_mtags, MTAG_ATTACHMENTS); 131 | if (m) 132 | { 133 | m = duplicate_mtag(m); 134 | AddListItem(m, *mtag_list); 135 | } 136 | m = find_mtag(recv_mtags, MTAG_ATTACHMENT_FALLBACK); 137 | if (m) 138 | { 139 | m = duplicate_mtag(m); 140 | AddListItem(m, *mtag_list); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /files/block_no_tls.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/block_no_tls"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/block_no_tls\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/block_no_tls"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | // Command strings 27 | #define MSG_BLOCK_NOTLS "BLOCKNOTLS" 28 | #define MSG_UNBLOCK_NOTLS "UNBLOCKNOTLS" 29 | 30 | // Dem macros yo 31 | #define CheckAPIError(apistr, apiobj) \ 32 | do { \ 33 | if(!(apiobj)) { \ 34 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 35 | return MOD_FAILED; \ 36 | } \ 37 | } while(0) 38 | 39 | CMD_FUNC(cmd_block_notls); // Register blocking command function 40 | CMD_FUNC(cmd_unblock_notls); // Register unblocking command function 41 | 42 | // Quality fowod declarations 43 | int block_notls_hook_prelocalconnect(Client *client); 44 | 45 | int blockem = 0; 46 | 47 | // Dat dere module header 48 | ModuleHeader MOD_HEADER = { 49 | "third/block_no_tls", // Module name 50 | "2.1.1", // Version 51 | "Allows privileged opers to temporarily block new, non-TLS (SSL) user connections", // Description 52 | "Gottem", // Author 53 | "unrealircd-6", // Modversion 54 | }; 55 | 56 | // Initialisation routine (register hooks, commands and modes or create structs etc) 57 | MOD_INIT() { 58 | MARK_AS_GLOBAL_MODULE(modinfo); 59 | 60 | HookAdd(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, 0, block_notls_hook_prelocalconnect); 61 | CheckAPIError("CommandAdd(BLOCKNOTLS)", CommandAdd(modinfo->handle, MSG_BLOCK_NOTLS, cmd_block_notls, 0, CMD_USER)); 62 | CheckAPIError("CommandAdd(UNBLOCKNOTLS)", CommandAdd(modinfo->handle, MSG_UNBLOCK_NOTLS, cmd_unblock_notls, 0, CMD_USER)); 63 | return MOD_SUCCESS; 64 | } 65 | 66 | MOD_LOAD() { 67 | return MOD_SUCCESS; // We good 68 | } 69 | 70 | // Called on unload/rehash obv 71 | MOD_UNLOAD() { 72 | blockem = 0; 73 | return MOD_SUCCESS; // We good 74 | } 75 | 76 | int block_notls_hook_prelocalconnect(Client *client) { 77 | if(blockem && !(client->local->listener->options & LISTENER_TLS)) { 78 | unreal_log(ULOG_INFO, "kill", "KILL_COMMAND", client, "Client killed: $client.details ([block_no_tls] tried to connect without SSL/TLS)"); 79 | exit_client(client, NULL, "Non-TLS (SSL) connections are currently not allowed"); // Kbye 80 | return HOOK_DENY; 81 | } 82 | return HOOK_CONTINUE; // We good 83 | } 84 | 85 | CMD_FUNC(cmd_block_notls) { 86 | // Gets args: ClientContext *clictx, Client *client, MessageTag *recv_mtags, int parc, const char *parv[] 87 | if(!IsUser(client)) // Double check imo 88 | return; 89 | 90 | if(!ValidatePermissionsForPath("blocknotls", client, NULL, NULL, NULL)) { 91 | sendnumeric(client, ERR_NOPRIVILEGES); 92 | return; 93 | } 94 | 95 | if(blockem) { 96 | sendnotice(client, "** [block_no_tls] Already blocking all new, non-TLS (SSL) \002user\002 connections"); 97 | return; 98 | } 99 | 100 | // Local server notice, also broadcast em 101 | unreal_log(ULOG_INFO, "block_no_tls", "BLOCK_NO_TLS_CHANGED", client, "$client.details just enabled the blocking of all new, non-TLS (SSL) \002user\002 connections"); 102 | sendto_server(client, 0, 0, NULL, ":%s %s", client->name, MSG_BLOCK_NOTLS); 103 | blockem = 1; 104 | } 105 | 106 | CMD_FUNC(cmd_unblock_notls) { 107 | if(!IsUser(client)) // Double check imo 108 | return; 109 | 110 | if(!ValidatePermissionsForPath("blocknotls", client, NULL, NULL, NULL)) { 111 | sendnumeric(client, ERR_NOPRIVILEGES); 112 | return; 113 | } 114 | 115 | if(!blockem) { 116 | sendnotice(client, "** [block_no_tls] Not currently blocking non-TLS (SSL) connections"); 117 | return; 118 | } 119 | 120 | // Local server notice, also broadcast em 121 | unreal_log(ULOG_INFO, "block_no_tls", "BLOCK_NO_TLS_CHANGED", client, "$client.details just disabled the blocking of non-TLS (SSL) connections"); 122 | sendto_server(client, 0, 0, NULL, ":%s %s", client->name, MSG_UNBLOCK_NOTLS); 123 | blockem = 0; 124 | } 125 | -------------------------------------------------------------------------------- /files/topicgreeting.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/topicgreeting"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/topicgreeting\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/topicgreeting"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | #define CHMODE_FLAG 'g' // As in greet obv =] 27 | 28 | // Dem macros yo 29 | #define HasTopicgreet(x) ((x) && has_channel_mode((x), CHMODE_FLAG)) 30 | 31 | #define CheckAPIError(apistr, apiobj) \ 32 | do { \ 33 | if(!(apiobj)) { \ 34 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 35 | return MOD_FAILED; \ 36 | } \ 37 | } while(0) 38 | 39 | // Quality fowod declarations 40 | int topicgreeting_localjoin(Client *client, Channel *channel, MessageTag *recv_mtags); 41 | 42 | // Muh globals 43 | Cmode_t extcmode_topicgreeting = 0L; // Store bitwise value latur 44 | 45 | // Dat dere module header 46 | ModuleHeader MOD_HEADER = { 47 | "third/topicgreeting", // Module name 48 | "2.1.0", // Version 49 | "Greet users who join a channel by changing the topic (channel mode +g)", // Description 50 | "Gottem", // Author 51 | "unrealircd-6", // Modversion 52 | }; 53 | 54 | // Initialisation routine (register hooks, commands and modes or create structs etc) 55 | MOD_INIT() { 56 | // Request the mode flag 57 | CmodeInfo cmodereq; 58 | memset(&cmodereq, 0, sizeof(cmodereq)); 59 | cmodereq.letter = CHMODE_FLAG; // Flag yo 60 | cmodereq.paracount = 0; // How many params? 61 | cmodereq.is_ok = extcmode_default_requirechop; // For paramless modes that simply require +o/+a/+q etc 62 | CheckAPIError("CmodeAdd(extcmode_topicgreeting)", CmodeAdd(modinfo->handle, cmodereq, &extcmode_topicgreeting)); 63 | 64 | MARK_AS_GLOBAL_MODULE(modinfo); 65 | 66 | // Add a hook with priority 0 (i.e. normal) that returns an int 67 | HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, topicgreeting_localjoin); 68 | return MOD_SUCCESS; 69 | } 70 | 71 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 72 | MOD_LOAD() { 73 | return MOD_SUCCESS; // We good 74 | } 75 | 76 | // Called on unload/rehash obv 77 | MOD_UNLOAD() { 78 | return MOD_SUCCESS; // We good 79 | } 80 | 81 | int topicgreeting_localjoin(Client *client, Channel *channel, MessageTag *recv_mtags) { 82 | // Let's make sure we don't greet ButtServ and co lol 83 | if(HasTopicgreet(channel) && !IsULine(client)) { 84 | char str[BUFSIZE]; 85 | int tlen, nlen; 86 | time_t ttime; 87 | ircsnprintf(str, sizeof(str), "Hey %s, thanks for joining!", client->name); 88 | if(!channel->topic || strcasecmp(channel->topic, str)) { // Only if no topic or if it would differ (to prevent """funny""" business with /cycle) 89 | MessageTag *mtags = NULL; 90 | tlen = strlen(str); 91 | nlen = strlen(me.name); 92 | ttime = TStime(); 93 | 94 | // Make sure we don't exceed the maximum allowed lengths ;] 95 | if(tlen > iConf.topic_length) 96 | tlen = iConf.topic_length; 97 | if(nlen > (NICKLEN + USERLEN + HOSTLEN + 5)) 98 | nlen = (NICKLEN + USERLEN + HOSTLEN + 5); 99 | 100 | // Set new topic 101 | safe_free(channel->topic); 102 | channel->topic = safe_alloc(tlen + 1); 103 | strlcpy(channel->topic, str, tlen + 1); 104 | channel->topic_time = ttime; 105 | 106 | // Also use this server's name for source nick 107 | safe_free(channel->topic_nick); 108 | channel->topic_nick = safe_alloc(nlen + 1); 109 | strlcpy(channel->topic_nick, me.name, nlen + 1); 110 | 111 | // Broadcast that shit twice; once to local users using server *name* and another for remote users with em SID 112 | new_message(&me, NULL, &mtags); 113 | sendto_channel(channel, &me, NULL, 0, 0, SEND_LOCAL, mtags, ":%s TOPIC %s :%s", me.name, channel->name, channel->topic); 114 | sendto_channel(channel, &me, NULL, 0, 0, SEND_REMOTE, mtags, ":%s TOPIC %s :%s", me.id, channel->name, channel->topic); 115 | free_message_tags(mtags); 116 | } 117 | } 118 | return HOOK_CONTINUE; 119 | } 120 | -------------------------------------------------------------------------------- /files/pubnetinfo.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/pubnetinfo"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/pubnetinfo\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/pubnetinfo"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | // Command string 27 | #define MSG_PUBNETINFO "PUBNETINFO" 28 | 29 | // Dem macros yo 30 | #define CheckAPIError(apistr, apiobj) \ 31 | do { \ 32 | if(!(apiobj)) { \ 33 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 34 | return MOD_FAILED; \ 35 | } \ 36 | } while(0) 37 | 38 | CMD_FUNC(pubnetinfo); // Register command function 39 | 40 | int is_loopback_ip(char *ip); 41 | 42 | // Dat dere module header 43 | ModuleHeader MOD_HEADER = { 44 | "third/pubnetinfo", // Module name 45 | "2.1.1", // Version 46 | "Display public network/server information such as SSL/TLS links", // Description 47 | "Gottem", // Author 48 | "unrealircd-6", // Modversion 49 | }; 50 | 51 | // Initialisation routine (register hooks, commands and modes or create structs etc) 52 | MOD_INIT() { 53 | CheckAPIError("CommandAdd(PUBNETINFO)", CommandAdd(modinfo->handle, MSG_PUBNETINFO, pubnetinfo, 2, CMD_USER | CMD_SERVER)); 54 | 55 | MARK_AS_GLOBAL_MODULE(modinfo); 56 | return MOD_SUCCESS; 57 | } 58 | 59 | // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet) 60 | MOD_LOAD() { 61 | return MOD_SUCCESS; // We good 62 | } 63 | 64 | // Called on unload/rehash obv 65 | MOD_UNLOAD() { 66 | // Clean up any structs and other shit 67 | return MOD_SUCCESS; // We good 68 | } 69 | 70 | // Nicked from src/socket.c =]]]] 71 | int is_loopback_ip(char *ip) { 72 | ConfigItem_listen *e; 73 | if(!strcmp(ip, "127.0.0.1") || !strcmp(ip, "0:0:0:0:0:0:0:1") || !strcmp(ip, "0:0:0:0:0:ffff:127.0.0.1")) 74 | return 1; 75 | for(e = conf_listen; e; e = e->next) { 76 | if((e->options & LISTENER_BOUND) && !strcmp(ip, e->ip)) 77 | return 1; 78 | } 79 | return 0; 80 | } 81 | 82 | CMD_FUNC(pubnetinfo) { 83 | // Gets args: ClientContext *clictx, Client *client, MessageTag *recv_mtags, int parc, const char *parv[] 84 | Client *acptr, *from; 85 | int tls, localhost; 86 | const char *serv; 87 | 88 | serv = NULL; 89 | from = (IsUser(client) ? client : NULL); // Respond to client executing command by default 90 | 91 | // In case of forwarding, first arg is user to respond to and second is the server we gettin info fer 92 | if(IsServer(client) && !BadPtr(parv[1]) && !BadPtr(parv[2])) { 93 | from = find_user(parv[1], NULL); 94 | serv = parv[2]; 95 | } 96 | 97 | // Return silently if client executing command is not a person or wasn't found, or was a server forward without enough args 98 | if(!from) 99 | return; 100 | 101 | // Checkem lol 102 | list_for_each_entry(acptr, &global_server_list, client_node) { 103 | // Skip ourselves obv, also if we got a request for a specific server and this isn't the one ;] 104 | if(IsMe(acptr) || (serv && strcasecmp(acptr->name, serv))) 105 | continue; 106 | 107 | // Can only get proper status if the server is directly linked to us =] 108 | if(acptr->uplink != &me) { 109 | // Only forward if the user requesting this shit is local to us imo 110 | if(MyUser(from)) 111 | sendto_one(acptr->uplink, NULL, ":%s %s %s :%s", me.id, MSG_PUBNETINFO, from->name, acptr->name); 112 | continue; 113 | } 114 | 115 | // Initialise to unknown (fallback) ;] 116 | tls = -1; 117 | localhost = -1; 118 | 119 | // Checkem link config 120 | if(acptr->server->conf) { 121 | #if UNREAL_VERSION >= 0x06020000 122 | tls = (acptr->server->conf->outgoing.options & CONNECT_OUTGOING_TLS) ? 1 : 0; 123 | #else 124 | tls = (acptr->server->conf->outgoing.options & CONNECT_TLS) ? 1 : 0; 125 | #endif 126 | } 127 | 128 | // Checkem IP 129 | if(acptr->ip) 130 | localhost = is_loopback_ip(acptr->ip); 131 | 132 | // Shit out status string 133 | sendnotice(from, "[pubnetinfo] Link %s: localhost connection = %s -- SSL/TLS = %s", 134 | acptr->name, 135 | (localhost == 1 ? "yes" : (localhost == 0 ? "no" : "unknown")), 136 | (tls == 1 ? "yes" : (tls == 0 ? "no" : "unknown")) 137 | ); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /files/allsend.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2024 Valerie Pond 4 | 5 | Requested by OmerAti 6 | */ 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/allsend/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/allsend\";"; 17 | "And /REHASH the IRCd."; 18 | "Please see the README for operclass requirements"; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | 24 | #include "unrealircd.h" 25 | 26 | 27 | 28 | ModuleHeader MOD_HEADER = { 29 | "third/allsend", 30 | "1.00", 31 | "Adds the /allsend command which allows privileged server operators to send targetted messages", 32 | "Valware", 33 | "unrealircd-6", 34 | }; 35 | 36 | 37 | #define AMSG_ALL 1 38 | #define AMSG_USERS 2 39 | #define AMSG_OPERS 3 40 | #define AMSG_NOTICE SEND_TYPE_NOTICE 41 | #define AMSG_PRIVMSG SEND_TYPE_PRIVMSG 42 | #define AMSG_LOCAL 1 43 | #define AMSG_GLOBAL 2 44 | 45 | #define MSG_ALLSEND "ALLSEND" 46 | CMD_FUNC(cmd_allsend); 47 | 48 | 49 | static void allsend_halp(Client *client, char **p); 50 | 51 | static char *allsend_help[] = 52 | { 53 | "***** ALLSEND *****", 54 | "-", 55 | "Send a message to a particular group of people.", 56 | "-", 57 | "Syntax:", 58 | " /allsend ", 59 | "-", 60 | "Example:", 61 | "-", 62 | "Send notification about a pending server restart or services outage or something =]:", 63 | " /allsend all notice global There will be a server restart in 30 minutes.", 64 | "-", 65 | NULL 66 | }; 67 | 68 | MOD_INIT() 69 | { 70 | 71 | CommandAdd(modinfo->handle, MSG_ALLSEND, cmd_allsend, 4, CMD_OPER | CMD_SERVER); 72 | return MOD_SUCCESS; 73 | } 74 | /** Called upon module load */ 75 | MOD_LOAD() 76 | { 77 | return MOD_SUCCESS; 78 | } 79 | /** Called upon unload */ 80 | MOD_UNLOAD() 81 | { 82 | return MOD_SUCCESS; 83 | } 84 | 85 | static void allsend_halp(Client *client, char **p) { 86 | if(IsServer(client)) 87 | return; 88 | for(; *p != NULL; p++) 89 | sendto_one(client, NULL, ":%s %03d %s :%s", me.name, RPL_TEXT, client->name, *p); 90 | } 91 | 92 | CMD_FUNC(cmd_allsend) 93 | { 94 | Client *target; 95 | int destination = 0, sendtype = 0, global = 0; 96 | 97 | if (!ValidatePermissionsForPath("allsend", client, NULL, NULL, NULL)) 98 | { 99 | sendnumeric(client, ERR_NOPRIVILEGES); 100 | return; 101 | } 102 | else if (BadPtr(parv[1]) || BadPtr(parv[2]) || BadPtr(parv[3]) || BadPtr(parv[4])) 103 | { 104 | allsend_halp(client,allsend_help); 105 | return; 106 | } 107 | 108 | /* figuring out the options*/ 109 | if (!strcasecmp(parv[1],"users")) 110 | destination = AMSG_USERS; 111 | else if (!strcasecmp(parv[1],"all")) 112 | destination = AMSG_ALL; 113 | else if (!strcasecmp(parv[1],"opers")) 114 | destination = AMSG_OPERS; 115 | if (!strcasecmp(parv[2],"notice")) 116 | sendtype = AMSG_NOTICE; 117 | else if (!strcasecmp(parv[2],"private")) 118 | sendtype = AMSG_PRIVMSG; 119 | if (!strcasecmp(parv[3],"local")) 120 | global = AMSG_LOCAL; 121 | else if (!strcasecmp(parv[3],"global")) 122 | global = AMSG_GLOBAL; 123 | 124 | 125 | if (!destination || !global) // (n)one of these were mentioned correctly 126 | { 127 | allsend_halp(client,allsend_help); 128 | return; 129 | } 130 | 131 | if (global == AMSG_GLOBAL) 132 | { 133 | list_for_each_entry(target, &client_list, client_node) 134 | { 135 | if (destination == AMSG_OPERS && !IsOper(target)) 136 | continue; 137 | else if (destination == AMSG_USERS && IsOper(target)) 138 | continue; 139 | else if (has_user_mode(target, 'B') || IsULine(target)) // skip bots and ulines 140 | continue; 141 | 142 | MessageTag *mtags = NULL; 143 | new_message(client, recv_mtags, &mtags); 144 | sendto_prefix_one(target, client, mtags, ":%s %s %s :%s", 145 | client->name, 146 | (sendtype == AMSG_NOTICE) ? "NOTICE" : "PRIVMSG", 147 | target->name, 148 | parv[4]); 149 | } 150 | return; 151 | } 152 | if (global == AMSG_LOCAL) 153 | { 154 | list_for_each_entry(target, &lclient_list, lclient_node) 155 | { 156 | if (destination == AMSG_OPERS && !IsOper(target)) 157 | continue; 158 | else if (destination == AMSG_USERS && IsOper(target)) 159 | continue; 160 | else if (has_user_mode(target, 'B') || IsULine(target)) // skip bots and ulines 161 | continue; 162 | 163 | MessageTag *mtags = NULL; 164 | new_message(client, recv_mtags, &mtags); 165 | sendto_prefix_one(target, client, mtags, ":%s %s %s :%s", 166 | client->name, 167 | (sendtype == SEND_TYPE_NOTICE) ? "NOTICE" : "PRIVMSG", 168 | target->name, 169 | parv[4]); 170 | } 171 | return; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /files/upgrade-notify.c: -------------------------------------------------------------------------------- 1 | 2 | /*** <<>> 3 | module 4 | { 5 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/upgrade-notify/README.md"; 6 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 7 | min-unrealircd-version "6.1.3"; 8 | max-unrealircd-version "6.*"; 9 | post-install-text { 10 | "The module is installed. Now all you need to do is add a loadmodule line:"; 11 | "loadmodule \"third/upgrade-notify\";"; 12 | "And /REHASH the IRCd."; 13 | "The module does not need any other configuration."; 14 | } 15 | } 16 | *** <<>> 17 | */ 18 | 19 | #include "unrealircd.h" 20 | 21 | void my_download_complete(OutgoingWebRequest *request, OutgoingWebResponse *response); 22 | 23 | #define TWICE_PER_DAY 43200000 24 | EVENT(check_for_updates); 25 | 26 | ModuleHeader MOD_HEADER 27 | = { 28 | "third/upgrade-notify", /* Name of module */ 29 | "2.1", /* Version */ 30 | "Sends out a message to opers when there is an upgrade available for UnrealIRCd", /* Short description of module */ 31 | "Valware", 32 | "unrealircd-6", 33 | }; 34 | 35 | MOD_INIT() 36 | { 37 | RegisterApiCallbackWebResponse(modinfo->handle, "my_download_complete", my_download_complete); 38 | EventAdd(modinfo->handle, "check_for_updates", check_for_updates, NULL, TWICE_PER_DAY, 0); // once per day 39 | return MOD_SUCCESS; 40 | } 41 | 42 | /* Is first run when server is 100% ready */ 43 | MOD_LOAD() 44 | { 45 | return MOD_SUCCESS; 46 | } 47 | 48 | /* Called when module is unloaded */ 49 | MOD_UNLOAD() 50 | { 51 | return MOD_SUCCESS; 52 | } 53 | 54 | 55 | void my_download_complete(OutgoingWebRequest *request, OutgoingWebResponse *response) 56 | { 57 | json_t *result; 58 | json_error_t jerr; 59 | char *version_string = "\0"; 60 | int upgrade_available = 0; 61 | version_string = (char *)malloc(strlen(version) + 1); 62 | strcpy(version_string, version); 63 | char *tok = strtok(version_string, "-"); 64 | char *current_version = "\0"; 65 | 66 | while (tok != NULL) 67 | { 68 | // Check if the tok contains only digits and dots 69 | int is_numeric = 1; 70 | for (int i = 0; tok[i] != '\0'; i++) { 71 | if (!isdigit(tok[i]) && tok[i] != '.') { 72 | is_numeric = 0; 73 | break; 74 | } 75 | } 76 | 77 | // If the tok contains only digits and dots, it's the numbered string 78 | if (is_numeric) { 79 | current_version = tok; 80 | break; // Exit the loop once found 81 | } 82 | 83 | // Get the next tok 84 | tok = strtok(NULL, "-"); 85 | } 86 | if (response->errorbuf || !response->memory) 87 | { 88 | unreal_log(ULOG_INFO, "mymod", "MYMOD_BAD_RESPONSE", NULL, 89 | "Error while trying to check $url: $error", 90 | log_data_string("url", request->url), 91 | log_data_string("error", response->errorbuf ? response->errorbuf : "No data (body) returned")); 92 | return; 93 | } 94 | 95 | // result->memory contains all the data of the web response, in our case 96 | // we assume it is a JSON response, so we are going to parse it. 97 | // If you were expecting BINARY data then you can still use result->memory 98 | // but then have a look at the length in result->memory_len. 99 | result = json_loads(response->memory, JSON_REJECT_DUPLICATES, &jerr); 100 | if (!result) 101 | { 102 | unreal_log(ULOG_INFO, "upgrade", "API_BAD_RESPONSE", NULL, 103 | "Error while trying to check $url: JSON parse error", 104 | log_data_string("url", request->url)); 105 | return; 106 | } 107 | const char *key; 108 | json_t *value; 109 | json_object_foreach(result, key, value) 110 | { 111 | if (!json_is_object(value)) 112 | return; 113 | 114 | const char *key2; 115 | json_t *value2; 116 | json_object_foreach(value, key2, value2) 117 | { 118 | if (!strcmp(key2,"Stable")) 119 | { 120 | const char *key3; 121 | json_t *value3; 122 | json_object_foreach(value2, key3, value3) 123 | { 124 | if (!strcmp(key3, "version")) 125 | { 126 | const char *stable_version = json_string_value(value3); 127 | 128 | int result = strnatcasecmp(current_version, stable_version); 129 | if (result < 0) 130 | { 131 | unreal_log(ULOG_INFO, "upgrade", "UPGRADE_AVAILABLE", NULL, "There is an upgrade available for UnrealIRCd! Your version: UnrealIRCd $old - New version: UnrealIRCd $new", log_data_string("old", current_version), log_data_string("new", stable_version)); 132 | unreal_log(ULOG_INFO, "upgrade", "UPGRADE_AVAILABLE", NULL, "Visit https://www.unrealircd.org/docs/Upgrading for information on upgrading."); 133 | } 134 | break; 135 | } 136 | } 137 | } 138 | } 139 | } 140 | 141 | json_decref(result); 142 | free(version_string); 143 | } 144 | 145 | EVENT(check_for_updates) 146 | { 147 | OutgoingWebRequest *w = safe_alloc(sizeof(OutgoingWebRequest)); 148 | safe_strdup(w->url, "https://www.unrealircd.org/downloads/list.json"); 149 | w->http_method = HTTP_METHOD_GET; 150 | safe_strdup(w->apicallback, "my_download_complete"); 151 | url_start_async(w); 152 | } 153 | -------------------------------------------------------------------------------- /files/clones.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/clones"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/clones\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/clones"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | #define MSG_CLONES "CLONES" 27 | 28 | #define IsParam(x) (parc > (x) && !BadPtr(parv[(x)])) 29 | #define IsNotParam(x) (parc <= (x) || BadPtr(parv[(x)])) 30 | 31 | #define CheckAPIError(apistr, apiobj) \ 32 | do { \ 33 | if(!(apiobj)) { \ 34 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 35 | return MOD_FAILED; \ 36 | } \ 37 | } while(0) 38 | 39 | static void dumpit(Client *client, char **p); 40 | CMD_FUNC(clones); 41 | 42 | ModuleHeader MOD_HEADER = { 43 | "third/clones", 44 | "2.1.0", // Version 45 | "Adds a command /CLONES to list all users having the same IP address matching the given options", 46 | "Gottem", // Author 47 | "unrealircd-6", // Modversion 48 | }; 49 | 50 | MOD_INIT() { 51 | CheckAPIError("CommandAdd(CLONES)", CommandAdd(modinfo->handle, MSG_CLONES, clones, 3, CMD_USER)); 52 | 53 | MARK_AS_GLOBAL_MODULE(modinfo); 54 | return MOD_SUCCESS; 55 | } 56 | 57 | MOD_LOAD() { 58 | return MOD_SUCCESS; 59 | } 60 | 61 | MOD_UNLOAD() { 62 | return MOD_SUCCESS; 63 | } 64 | 65 | // Dump a NULL-terminated array of strings to the user (taken from DarkFire IRCd) 66 | static void dumpit(Client *client, char **p) { 67 | if(IsServer(client)) // Bail out early and silently if it's a server =] 68 | return; 69 | 70 | // Using sendto_one() instead of sendnumericfmt() because the latter strips indentation and stuff ;] 71 | for(; *p != NULL; p++) 72 | sendto_one(client, NULL, ":%s %03d %s :%s", me.name, RPL_TEXT, client->name, *p); 73 | } 74 | 75 | static char *clones_halp[] = { 76 | "*** \002Help on /clones\002 ***", 77 | "Gives you a list of clones based on the specified options.", 78 | "Clones are listed by a nickname or by a minimal number of", 79 | "concurrent sessions connecting from the local or the given", 80 | "server.", 81 | " ", 82 | "Syntax:", 83 | "CLONES <\037min-num-of-sessions|nickname\037> [\037server\037]", 84 | " ", 85 | "Examples:", 86 | " /clones 2", 87 | " Lists local clones having two or more sessions", 88 | " /clones Loser", 89 | " Lists local clones of Loser", 90 | " /clones 3 hub.test.com", 91 | " Lists all clones with at least 3 sessions, which are", 92 | " connecting from hub.test.com", 93 | NULL 94 | }; 95 | 96 | CMD_FUNC(clones) { 97 | Client *acptr, *acptr2; 98 | u_int min, count, found = 0; 99 | 100 | if(!IsUser(client)) 101 | return; 102 | 103 | if(!IsOper(client)) { 104 | sendnumeric(client, ERR_NOPRIVILEGES); 105 | return; 106 | } 107 | 108 | if(!IsParam(1)) { 109 | dumpit(client, clones_halp); 110 | return; 111 | } 112 | 113 | if(IsParam(2)) { 114 | if(hunt_server(client, NULL, "CLONES", 2, parc, parv) != HUNTED_ISME) 115 | return; 116 | } 117 | 118 | if(isdigit(*parv[1])) { 119 | if((min = atoi(parv[1])) < 2) { 120 | sendnotice(client, "*** Invalid minimum clone count number (%s)", parv[1]); 121 | return; 122 | } 123 | 124 | list_for_each_entry(acptr, &client_list, client_node) { 125 | if(!IsUser(acptr) || !acptr->local) 126 | continue; 127 | 128 | count = 1; // Always include acptr in the count =] 129 | 130 | list_for_each_entry(acptr2, &client_list, client_node) { 131 | if(!IsUser(acptr2) || acptr == acptr2 || !acptr2->local) 132 | continue; 133 | 134 | if(!strcmp(acptr->ip, acptr2->ip)) 135 | count++; 136 | } 137 | 138 | if(count >= min) { 139 | found++; 140 | sendnotice(client, "%s (%s!%s@%s)", acptr->ip, acptr->name, acptr->user->username, acptr->user->realhost); 141 | } 142 | } 143 | } 144 | else { 145 | if(!(acptr = find_user(parv[1], NULL))) { 146 | sendnumeric(client, ERR_NOSUCHNICK, parv[1]); 147 | return; 148 | } 149 | 150 | if(!MyConnect(acptr)) { 151 | sendnotice(client, "*** %s is not my client", acptr->name); 152 | return; 153 | } 154 | 155 | found = 0; 156 | list_for_each_entry(acptr2, &client_list, client_node) { 157 | if(!IsUser(acptr2) || acptr == acptr2 || !acptr2->local) 158 | continue; 159 | 160 | if(!strcmp(acptr->ip, acptr2->ip)) { 161 | found++; 162 | sendnotice(client, "%s (%s!%s@%s)", acptr2->ip, acptr2->name, acptr2->user->username, acptr2->user->realhost); 163 | } 164 | } 165 | } 166 | 167 | sendnotice(client, "%d clone%s found", found, (!found || found > 1) ? "s" : ""); 168 | } 169 | -------------------------------------------------------------------------------- /files/commandsno.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) All Rights Reserved 2 | ** Written by Gottem 3 | ** Website: https://gottem.nl/unreal 4 | ** License: https://gottem.nl/unreal/license 5 | */ 6 | 7 | /*** <<>> 8 | module { 9 | documentation "https://gottem.nl/unreal/man/commandsno"; 10 | troubleshooting "In case of problems, check the FAQ at https://gottem.nl/unreal/halp or e-mail me at support@gottem.nl"; 11 | min-unrealircd-version "6.*"; 12 | //max-unrealircd-version "6.*"; 13 | post-install-text { 14 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 15 | "loadmodule \"third/commandsno\";"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://gottem.nl/unreal/man/commandsno"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | // One include for all cross-platform compatibility thangs 24 | #include "unrealircd.h" 25 | 26 | typedef struct _cmdovr CmdOvr; 27 | 28 | struct _cmdovr { 29 | CmdOvr *prev, *next; 30 | char *cmd; 31 | }; 32 | 33 | #define FLAG_CMD 'C' 34 | #define MaxSize (sizeof(mybuf) - strlen(mybuf) - 1) 35 | 36 | #define CheckAPIError(apistr, apiobj) \ 37 | do { \ 38 | if(!(apiobj)) { \ 39 | config_error("A critical error occurred on %s for %s: %s", (apistr), MOD_HEADER.name, ModuleGetErrorStr(modinfo->handle)); \ 40 | return MOD_FAILED; \ 41 | } \ 42 | } while(0) 43 | 44 | #if UNREAL_VERSION >= 0x06020000 45 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, clictx, client, recv_mtags, parc, parv)) 46 | #else 47 | #define CallCommandOverrideCompatU06020000() (CallCommandOverride(ovr, client, recv_mtags, parc, parv)) 48 | #endif 49 | 50 | CMD_OVERRIDE_FUNC(commandsno_override_cmd); 51 | int commandsno_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs); 52 | int commandsno_configrun(ConfigFile *cf, ConfigEntry *ce, int type); 53 | int commandsno_hook_stats(Client *client, const char *stats); 54 | int commandsno_hook_rehash(void); 55 | static void InitConf(void); 56 | static void FreeConf(void); 57 | 58 | char *cmdlist; 59 | 60 | ModuleHeader MOD_HEADER = { 61 | "third/commandsno", 62 | "2.1.1", // Version 63 | "Lets IRC operators see command usages", 64 | "Gottem", // Author 65 | "unrealircd-6", // Modversion 66 | }; 67 | 68 | MOD_TEST() { 69 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, commandsno_configtest); 70 | return MOD_SUCCESS; 71 | } 72 | 73 | MOD_INIT() { 74 | InitConf(); 75 | 76 | MARK_AS_GLOBAL_MODULE(modinfo); 77 | 78 | HookAdd(modinfo->handle, HOOKTYPE_REHASH, 0, commandsno_hook_rehash); 79 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, commandsno_configrun); 80 | HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, commandsno_hook_stats); 81 | return MOD_SUCCESS; 82 | } 83 | 84 | MOD_LOAD() { 85 | if(cmdlist) { 86 | char *cmd, *p; 87 | char buf[64]; // Should be plenty, n0? 88 | char apibuf[96]; 89 | 90 | strlcpy(buf, cmdlist, sizeof(buf)); 91 | for(cmd = strtoken(&p, buf, ","); cmd; cmd = strtoken(&p, NULL, ",")) { 92 | if(!strcasecmp(cmd, "PRIVMSG") || !strcasecmp(cmd, "NOTICE")) 93 | continue; 94 | 95 | snprintf(apibuf, sizeof(apibuf), "CommandOverrideAdd(%s)", cmd); 96 | CheckAPIError(apibuf, CommandOverrideAdd(modinfo->handle, cmd, 0, commandsno_override_cmd)); 97 | } 98 | } 99 | return MOD_SUCCESS; 100 | } 101 | 102 | MOD_UNLOAD() { 103 | FreeConf(); 104 | return MOD_SUCCESS; 105 | } 106 | 107 | static void InitConf(void) { 108 | cmdlist = NULL; 109 | } 110 | 111 | static void FreeConf(void) { 112 | safe_free(cmdlist); 113 | } 114 | 115 | int commandsno_hook_rehash(void) { 116 | FreeConf(); 117 | InitConf(); 118 | return HOOK_CONTINUE; 119 | } 120 | 121 | int commandsno_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { 122 | int errors = 0; 123 | 124 | if(type != CONFIG_SET) 125 | return 0; 126 | 127 | if(strcmp(ce->name, "commandsno")) 128 | return 0; 129 | 130 | if(!ce->value || !strlen(ce->value)) { 131 | config_error("%s:%i: set::%s without contents", ce->file->filename, ce->line_number, ce->name); 132 | errors++; 133 | } 134 | *errs = errors; 135 | return errors ? -1 : 1; 136 | } 137 | 138 | int commandsno_configrun(ConfigFile *cf, ConfigEntry *ce, int type) { 139 | if(type != CONFIG_SET) 140 | return 0; 141 | 142 | if(strcmp(ce->name, "commandsno")) 143 | return 0; 144 | 145 | safe_strdup(cmdlist, ce->value); 146 | return 1; 147 | } 148 | 149 | int commandsno_hook_stats(Client *client, const char *stats) { 150 | if(*stats == 'S') // Corresponds to "set" stats 151 | sendnumericfmt(client, RPL_TEXT, ":commandsno: %s", cmdlist ? cmdlist : ""); 152 | return HOOK_CONTINUE; 153 | } 154 | 155 | CMD_OVERRIDE_FUNC(commandsno_override_cmd) { 156 | if(MyUser(client) && !IsULine(client)) { 157 | char mybuf[BUFSIZE]; 158 | int i; 159 | mybuf[0] = 0; 160 | 161 | for(i = 1; i < parc && !BadPtr(parv[i]); i++) { 162 | if(mybuf[0]) 163 | strncat(mybuf, " ", MaxSize); 164 | strncat(mybuf, parv[i], MaxSize); 165 | } 166 | if(!mybuf[0]) 167 | strcpy(mybuf, ""); 168 | 169 | unreal_log(ULOG_INFO, "commandsno", "COMMANDSNO_USAGE", client, "$client.details used command $command (params: $params)", 170 | log_data_string("command", ovr->command->cmd), 171 | log_data_string("params", mybuf) 172 | ); 173 | } 174 | 175 | CallCommandOverrideCompatU06020000(); // Run original function yo 176 | } 177 | -------------------------------------------------------------------------------- /files/mtag-extban.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 3 | Copyright Ⓒ 2022 Valerie Pond 4 | 5 | Ban mtags from being used in a channel 6 | */ 7 | 8 | /*** <<>> 9 | module 10 | { 11 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/mtag-extban/README.md"; 12 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 13 | min-unrealircd-version "6.1.2"; 14 | max-unrealircd-version "6.*"; 15 | post-install-text { 16 | "The module is installed. Now all you need to do is add a loadmodule line:"; 17 | "loadmodule \"third/mtag-extban\";"; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | #include "unrealircd.h" 24 | 25 | #define MAX_MTAG_BANS_PER_CHAN 15 26 | 27 | ModuleHeader MOD_HEADER 28 | = { 29 | "third/mtag-extban", 30 | "1.1", 31 | "ExtBan ~mtag - Prevent usage of certain IRCv3 message-tags per channel", 32 | "Valware", 33 | "unrealircd-6", 34 | }; 35 | /* Forward declarations */ 36 | int mtag_check_ban(Client *client, Channel *channel, char *ban, char *msg, const char **errmsg); 37 | const char *extban_mtag_conv_param(BanContext *b, Extban *extban); 38 | int extban_mtag_is_ok(BanContext *b); 39 | void mtag_search_and_destroy(MessageTag **mtags, Channel *chan); 40 | int mtag_extban_match(MessageTag *m, char *banstr); 41 | int count_mtag_bans(Ban *ban); 42 | int extban_mtag_check(Client *client, Channel *channel, MessageTag **mtags, const char *text, SendType sendtype); 43 | 44 | /** Called upon module init */ 45 | MOD_INIT() 46 | { 47 | ExtbanInfo req; 48 | 49 | memset(&req, 0, sizeof(req)); 50 | req.letter = 'M'; //needed for some reason in u6 51 | req.name = "mtag"; 52 | req.is_ok = extban_is_ok_nuh_extban; 53 | req.options = EXTBOPT_NOSTACKCHILD; /* disallow things like ~n:~T, as we only affect mtags */ 54 | req.conv_param = extban_mtag_conv_param; 55 | req.is_ok = extban_mtag_is_ok; 56 | if (!ExtbanAdd(modinfo->handle, req)) 57 | { 58 | config_error("could not register extended ban type"); 59 | return MOD_FAILED; 60 | } 61 | 62 | HookAdd(modinfo->handle, HOOKTYPE_PRE_CHANMSG, 0, extban_mtag_check); 63 | // overriding these commands seeeems to be the only way to do this.. 64 | 65 | 66 | MARK_AS_GLOBAL_MODULE(modinfo); 67 | 68 | return MOD_SUCCESS; 69 | } 70 | 71 | /** Called upon module load */ 72 | MOD_LOAD() 73 | { 74 | return MOD_SUCCESS; 75 | } 76 | 77 | /** Called upon unload */ 78 | MOD_UNLOAD() 79 | { 80 | return MOD_SUCCESS; 81 | } 82 | 83 | int extban_mtag_is_ok(BanContext *b) 84 | { 85 | int bans = count_mtag_bans(b->channel->banlist); 86 | int excepts = count_mtag_bans(b->channel->exlist); 87 | if (b->what != MODE_ADD) 88 | return 1; 89 | if ((b->ban_type == EXBTYPE_BAN && bans > MAX_MTAG_BANS_PER_CHAN) 90 | || (b->ban_type == EXBTYPE_EXCEPT && excepts > MAX_MTAG_BANS_PER_CHAN)) 91 | { 92 | sendnumeric(b->client, ERR_BANLISTFULL, b->channel->name, b->banstr); 93 | sendnotice(b->client, "Too many message-tag ban%s for this channel", b->ban_type == EXBTYPE_BAN ? "s" : " exceptions"); 94 | return 0; 95 | } 96 | return 1; 97 | } 98 | 99 | 100 | int extban_mtag_check(Client *client, Channel *channel, MessageTag **mtags, const char *text, SendType sendtype) 101 | { 102 | mtag_search_and_destroy(mtags, channel); 103 | return 0; 104 | } 105 | 106 | 107 | const char *extban_mtag_conv_param(BanContext *b, Extban *extban) 108 | { 109 | static char retbuf[151]; 110 | snprintf(retbuf, sizeof(retbuf), "%s%s", *b->banstr == '+' ? "" : "+", b->banstr); 111 | if (strlen(retbuf) == 1) 112 | strncat(retbuf, "*", sizeof(retbuf)); 113 | 114 | return retbuf; 115 | } 116 | 117 | /** Check and remove messagetags 118 | */ 119 | void mtag_search_and_destroy(MessageTag **mtags, Channel *chan) 120 | { 121 | MessageTag *m, *m_next; 122 | Ban *b, *e; // chmode +b, +e 123 | for (m = *mtags; m; m = m_next) 124 | { 125 | int do_drop_mtag = 0; 126 | m_next = m->next; 127 | if (*m->name != '+') // if it's not a client tag, we don't care 128 | continue; 129 | 130 | for (b = chan->banlist; b; b=b->next) // check the bans list 131 | if (mtag_extban_match(m, b->banstr)) 132 | do_drop_mtag = 1; 133 | 134 | if (chan->exlist) 135 | for (e = chan->exlist; e; e = e->next) // check the exceptions list 136 | if (mtag_extban_match(m, e->banstr)) 137 | do_drop_mtag = 0; 138 | 139 | if (do_drop_mtag) 140 | { // silently drop it so as not to (potentially) spam the user (case of typing tags) 141 | DelListItem(m, *mtags); 142 | safe_free(m->name); 143 | safe_free(m->value); 144 | safe_free(m); 145 | } 146 | } 147 | } 148 | 149 | int mtag_extban_match(MessageTag *m, char *banstr) 150 | { 151 | /* Pretend time does not exist... 152 | taken from textban.c by syzop */ 153 | if (!strncmp(banstr, "~t:", 3)) 154 | { 155 | banstr = strchr(banstr+3, ':'); 156 | if (!banstr) 157 | return 0; 158 | banstr++; 159 | } 160 | 161 | else if (!strncmp(banstr, "~time:", 6)) 162 | { 163 | banstr = strchr(banstr+6, ':'); 164 | if (!banstr) 165 | return 0; 166 | banstr++; 167 | } 168 | 169 | // check if the ban is for message tags 170 | if ( (!strncmp(banstr, "~M:", 3) && ( match_simple(banstr+3, m->name) ) ) 171 | || ( !strncmp(banstr, "~mtag:", 6) && ( match_simple(banstr+6, m->name) ) )) 172 | { 173 | return 1; 174 | } 175 | return 0; 176 | } 177 | 178 | 179 | int count_mtag_bans(Ban *ban) 180 | { 181 | int i = 0; 182 | Ban *b; 183 | for (b = ban; b; b=b->next) 184 | if (strstr(b->banstr,"~mtag:")) 185 | i++; 186 | return i; 187 | } 188 | -------------------------------------------------------------------------------- /files/welcomemessages.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 or later 3 | Copyright Ⓒ 2024 Jean Chevronnet 4 | 5 | */ 6 | /*** <<>> 7 | module 8 | { 9 | documentation "https://github.com/revrsedev/UnrealIRCD-6-mods-contrib/blob/main/welcomemessages/README.md"; 10 | troubleshooting "In case of problems, documentation or e-mail me at mike.chevronnet@gmail.com"; 11 | min-unrealircd-version "6.*"; 12 | post-install-text { 13 | "The module is installed, now all you need to do is add a 'loadmodule' line to your config file:"; 14 | "loadmodule \"third/welcomemessages\";"; 15 | "Add channel and custom messages to your config file"; 16 | "Then /rehash the IRCd."; 17 | "For usage information, refer to the module's documentation found at: https://github.com/revrsedev/UnrealIRCD-6-mods-contrib/blob/main/welcomemessages/README.md"; 18 | } 19 | } 20 | *** <<>> 21 | */ 22 | 23 | #include "unrealircd.h" 24 | #define MYCONF "channel-welcome" 25 | #define MAX_WELCOME_MSG 512 // Define the maximum length for the welcome message 26 | 27 | // Structure to hold channel-specific messages 28 | typedef struct { 29 | char channel[CHANNELLEN + 1]; 30 | char message[MAX_WELCOME_MSG]; 31 | } ChannelMessage; 32 | 33 | // Global array of ChannelMessage structures 34 | ChannelMessage *channel_messages = NULL; 35 | int channel_count = 0; 36 | 37 | // Function declarations 38 | void setcfg(void); 39 | void freecfg(void); 40 | int m_channelwelcome_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs); 41 | int m_channelwelcome_configposttest(int *errs); 42 | int m_channelwelcome_configrun(ConfigFile *cf, ConfigEntry *ce, int type); 43 | int custom_join(Client *sptr, Channel *chptr, MessageTag *mtags); 44 | 45 | // Dat dere module header 46 | ModuleHeader MOD_HEADER = { 47 | "third/welcomemessages", // Module name 48 | "1.0.1", // Version 49 | "Sends server custom welcome messages for differents channels", // Description 50 | "reverse", // Author 51 | "unrealircd-6", // Modversion 52 | }; 53 | 54 | // Configuration testing-related hooks 55 | MOD_TEST() { 56 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, m_channelwelcome_configtest); 57 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, m_channelwelcome_configposttest); 58 | return MOD_SUCCESS; 59 | } 60 | 61 | // Initialisation routine (register hooks, commands and modes or create structs etc) 62 | MOD_INIT() { 63 | MARK_AS_GLOBAL_MODULE(modinfo); 64 | 65 | setcfg(); 66 | HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, m_channelwelcome_configrun); 67 | HookAdd(modinfo->handle, HOOKTYPE_LOCAL_JOIN, 0, custom_join); 68 | return MOD_SUCCESS; 69 | } 70 | 71 | MOD_LOAD() { 72 | return MOD_SUCCESS; // We good 73 | } 74 | 75 | // Called on unload/rehash 76 | MOD_UNLOAD() { 77 | freecfg(); 78 | return MOD_SUCCESS; // We good 79 | } 80 | 81 | // Set config defaults 82 | void setcfg(void) { 83 | // Initialize with no channels 84 | channel_messages = NULL; 85 | channel_count = 0; 86 | } 87 | 88 | // Free allocated memory on unload/reload 89 | void freecfg(void) { 90 | if (channel_messages) { 91 | free(channel_messages); 92 | channel_messages = NULL; 93 | } 94 | channel_count = 0; 95 | } 96 | 97 | // Configuration test 98 | int m_channelwelcome_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { 99 | int errors = 0; 100 | ConfigEntry *cep; 101 | 102 | if (type != CONFIG_MAIN) 103 | return 0; 104 | 105 | if (!ce || !ce->name) 106 | return 0; 107 | 108 | if (strcmp(ce->name, MYCONF)) 109 | return 0; 110 | 111 | for (cep = ce->items; cep; cep = cep->next) { 112 | if (!cep->name || !cep->value) { 113 | config_error("%s:%i: invalid %s entry", cep->file->filename, cep->line_number, MYCONF); 114 | errors++; 115 | continue; 116 | } 117 | 118 | if (strlen(cep->name) >= CHANNELLEN) { 119 | config_error("%s:%i: channel name too long, maximum length is %d characters", cep->file->filename, cep->line_number, CHANNELLEN); 120 | errors++; 121 | continue; 122 | } 123 | 124 | if (strlen(cep->value) >= MAX_WELCOME_MSG) { 125 | config_error("%s:%i: welcome message too long, maximum length is %d characters", cep->file->filename, cep->line_number, MAX_WELCOME_MSG); 126 | errors++; 127 | continue; 128 | } 129 | } 130 | 131 | *errs = errors; 132 | return errors ? -1 : 1; 133 | } 134 | 135 | // Post-test configuration 136 | int m_channelwelcome_configposttest(int *errs) { 137 | return 1; 138 | } 139 | 140 | // Run the configuration 141 | int m_channelwelcome_configrun(ConfigFile *cf, ConfigEntry *ce, int type) { 142 | ConfigEntry *cep; 143 | 144 | if (type != CONFIG_MAIN) 145 | return 0; 146 | 147 | if (!ce || !ce->name) 148 | return 0; 149 | 150 | if (strcmp(ce->name, MYCONF)) 151 | return 0; 152 | 153 | freecfg(); 154 | 155 | for (cep = ce->items; cep; cep = cep->next) 156 | channel_count++; 157 | 158 | channel_messages = malloc(sizeof(ChannelMessage) * channel_count); 159 | 160 | int i = 0; 161 | for (cep = ce->items; cep; cep = cep->next) { 162 | strlcpy(channel_messages[i].channel, cep->name, CHANNELLEN + 1); 163 | strlcpy(channel_messages[i].message, cep->value, MAX_WELCOME_MSG); 164 | i++; 165 | } 166 | 167 | return 1; // We good 168 | } 169 | 170 | // Send custom message on join 171 | int custom_join(Client *sptr, Channel *chptr, MessageTag *mtags) { 172 | if (!IsUser(sptr)) 173 | return HOOK_CONTINUE; 174 | 175 | for (int i = 0; i < channel_count; i++) { 176 | if (match_simple(channel_messages[i].channel, chptr->name)) { 177 | sendnotice(sptr, "%s", channel_messages[i].message); // Use format string properly 178 | break; 179 | } 180 | } 181 | return HOOK_CONTINUE; 182 | } 183 | -------------------------------------------------------------------------------- /files/incredibly-lazy-ops.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licence: GPLv3 3 | Copyright Ⓒ 2024 Valerie Pond 4 | 5 | Provides some easy commands for using extbans for lazy chanops who can't be bothered to learn extbans 6 | */ 7 | /*** <<>> 8 | module 9 | { 10 | documentation "https://github.com/ValwareIRC/valware-unrealircd-mods/blob/main/incredibly-lazy-ops/README.md"; 11 | troubleshooting "In case of problems, documentation or e-mail me at v.a.pond@outlook.com"; 12 | min-unrealircd-version "6.*"; 13 | max-unrealircd-version "6.*"; 14 | post-install-text { 15 | "The module is installed. Now all you need to do is add a loadmodule line:"; 16 | "loadmodule \"third/incredibly-lazy-ops\";"; 17 | "And /REHASH the IRCd."; 18 | "The module does not need any other configuration."; 19 | } 20 | } 21 | *** <<>> 22 | */ 23 | 24 | #include "unrealircd.h" 25 | 26 | CMD_FUNC(cmd_tban); 27 | CMD_FUNC(cmd_qban); 28 | 29 | ModuleHeader MOD_HEADER = { 30 | "third/incredibly-lazy-ops", 31 | "1.0", 32 | "Provides some easy commands for using extbans for lazy chanops who can't be bothered to learn extbans", 33 | "Valware", 34 | "unrealircd-6", 35 | }; 36 | 37 | 38 | MOD_INIT() { 39 | 40 | CommandAdd(modinfo->handle, "TBAN", cmd_tban, 4, CMD_USER); 41 | CommandAdd(modinfo->handle, "TIMEBAN", cmd_tban, 4, CMD_USER); 42 | CommandAdd(modinfo->handle, "QBAN", cmd_qban, 3, CMD_USER); 43 | CommandAdd(modinfo->handle, "QUIETBAN", cmd_qban, 3, CMD_USER); 44 | return MOD_SUCCESS; 45 | } 46 | /** Called upon module load */ 47 | MOD_LOAD() 48 | { 49 | return MOD_SUCCESS; 50 | } 51 | 52 | /** Called upon unload */ 53 | MOD_UNLOAD() 54 | { 55 | return MOD_SUCCESS; 56 | } 57 | 58 | /** 59 | TBAN