unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
censor.c (6137B)
1 /* 2 * User Mode +G 3 * (C) Copyright 2005-current Bram Matthys and The UnrealIRCd team. 4 */ 5 6 #include "unrealircd.h" 7 8 9 ModuleHeader MOD_HEADER 10 = { 11 "usermodes/censor", 12 "4.2", 13 "User Mode +G", 14 "UnrealIRCd Team", 15 "unrealircd-6", 16 }; 17 18 19 long UMODE_CENSOR = 0L; 20 21 #define IsCensored(x) (x->umodes & UMODE_CENSOR) 22 23 int censor_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype); 24 25 int censor_config_test(ConfigFile *, ConfigEntry *, int, int *); 26 int censor_config_run(ConfigFile *, ConfigEntry *, int); 27 28 ModuleInfo *ModInfo = NULL; 29 30 ConfigItem_badword *conf_badword_message = NULL; 31 32 static ConfigItem_badword *copy_badword_struct(ConfigItem_badword *ca, int regex, int regflags); 33 34 int censor_stats_badwords_user(Client *client, const char *para); 35 36 MOD_TEST() 37 { 38 HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, censor_config_test); 39 return MOD_SUCCESS; 40 } 41 42 MOD_INIT() 43 { 44 ModInfo = modinfo; 45 46 MARK_AS_OFFICIAL_MODULE(modinfo); 47 UmodeAdd(modinfo->handle, 'G', UMODE_GLOBAL, 0, NULL, &UMODE_CENSOR); 48 HookAdd(modinfo->handle, HOOKTYPE_CAN_SEND_TO_USER, 0, censor_can_send_to_user); 49 HookAdd(modinfo->handle, HOOKTYPE_STATS, 0, censor_stats_badwords_user); 50 HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, censor_config_run); 51 return MOD_SUCCESS; 52 } 53 54 MOD_LOAD() 55 { 56 return MOD_SUCCESS; 57 } 58 59 60 MOD_UNLOAD() 61 { 62 ConfigItem_badword *badword, *next; 63 64 for (badword = conf_badword_message; badword; badword = next) 65 { 66 next = badword->next; 67 DelListItem(badword, conf_badword_message); 68 badword_config_free(badword); 69 } 70 return MOD_SUCCESS; 71 } 72 73 int censor_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) 74 { 75 int errors = 0; 76 ConfigEntry *cep; 77 char has_word = 0, has_replace = 0, has_action = 0, action = 'r'; 78 79 if (type != CONFIG_MAIN) 80 return 0; 81 82 if (!ce || !ce->name || strcmp(ce->name, "badword")) 83 return 0; /* not interested */ 84 85 if (!ce->value) 86 { 87 config_error("%s:%i: badword without type", 88 ce->file->filename, ce->line_number); 89 return 1; 90 } 91 else if (strcmp(ce->value, "message") && strcmp(ce->value, "all")) { 92 /* config_error("%s:%i: badword with unknown type", 93 ce->file->filename, ce->line_number); -- can't do that.. */ 94 return 0; /* unhandled */ 95 } 96 for (cep = ce->items; cep; cep = cep->next) 97 { 98 if (config_is_blankorempty(cep, "badword")) 99 { 100 errors++; 101 continue; 102 } 103 if (!strcmp(cep->name, "word")) 104 { 105 const char *errbuf; 106 if (has_word) 107 { 108 config_warn_duplicate(cep->file->filename, 109 cep->line_number, "badword::word"); 110 continue; 111 } 112 has_word = 1; 113 if ((errbuf = badword_config_check_regex(cep->value,1,1))) 114 { 115 config_error("%s:%i: badword::%s contains an invalid regex: %s", 116 cep->file->filename, 117 cep->line_number, 118 cep->name, errbuf); 119 errors++; 120 } 121 } 122 else if (!strcmp(cep->name, "replace")) 123 { 124 if (has_replace) 125 { 126 config_warn_duplicate(cep->file->filename, 127 cep->line_number, "badword::replace"); 128 continue; 129 } 130 has_replace = 1; 131 } 132 else if (!strcmp(cep->name, "action")) 133 { 134 if (has_action) 135 { 136 config_warn_duplicate(cep->file->filename, 137 cep->line_number, "badword::action"); 138 continue; 139 } 140 has_action = 1; 141 if (!strcmp(cep->value, "replace")) 142 action = 'r'; 143 else if (!strcmp(cep->value, "block")) 144 action = 'b'; 145 else 146 { 147 config_error("%s:%d: Unknown badword::action '%s'", 148 cep->file->filename, cep->line_number, 149 cep->value); 150 errors++; 151 } 152 153 } 154 else 155 { 156 config_error_unknown(cep->file->filename, cep->line_number, 157 "badword", cep->name); 158 errors++; 159 } 160 } 161 162 if (!has_word) 163 { 164 config_error_missing(ce->file->filename, ce->line_number, 165 "badword::word"); 166 errors++; 167 } 168 if (has_action) 169 { 170 if (has_replace && action == 'b') 171 { 172 config_error("%s:%i: badword::action is block but badword::replace exists", 173 ce->file->filename, ce->line_number); 174 errors++; 175 } 176 } 177 178 *errs = errors; 179 return errors ? -1 : 1; 180 } 181 182 183 int censor_config_run(ConfigFile *cf, ConfigEntry *ce, int type) 184 { 185 ConfigEntry *cep, *word = NULL; 186 ConfigItem_badword *ca; 187 188 if (type != CONFIG_MAIN) 189 return 0; 190 191 if (!ce || !ce->name || strcmp(ce->name, "badword")) 192 return 0; /* not interested */ 193 194 if (strcmp(ce->value, "message") && strcmp(ce->value, "all")) 195 return 0; /* not for us */ 196 197 ca = safe_alloc(sizeof(ConfigItem_badword)); 198 ca->action = BADWORD_REPLACE; 199 200 for (cep = ce->items; cep; cep = cep->next) 201 { 202 if (!strcmp(cep->name, "action")) 203 { 204 if (!strcmp(cep->value, "block")) 205 { 206 ca->action = BADWORD_BLOCK; 207 } 208 } 209 else if (!strcmp(cep->name, "replace")) 210 { 211 safe_strdup(ca->replace, cep->value); 212 } 213 else if (!strcmp(cep->name, "word")) 214 { 215 word = cep; 216 } 217 } 218 219 badword_config_process(ca, word->value); 220 221 if (!strcmp(ce->value, "message")) 222 { 223 AddListItem(ca, conf_badword_message); 224 } else 225 if (!strcmp(ce->value, "all")) 226 { 227 AddListItem(ca, conf_badword_message); 228 return 0; /* pretend we didn't see it, so other modules can handle 'all' as well */ 229 } 230 231 return 1; 232 } 233 234 const char *stripbadwords_message(const char *str, int *blocked) 235 { 236 return stripbadwords(str, conf_badword_message, blocked); 237 } 238 239 int censor_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype) 240 { 241 int blocked = 0; 242 243 if (MyUser(client) && IsCensored(target)) 244 { 245 *text = stripbadwords_message(*text, &blocked); 246 if (blocked) 247 { 248 *errmsg = "User does not accept private messages containing swearing"; 249 return HOOK_DENY; 250 } 251 } 252 253 return HOOK_CONTINUE; 254 } 255 256 int censor_stats_badwords_user(Client *client, const char *para) 257 { 258 ConfigItem_badword *words; 259 260 if (!para || !(!strcmp(para, "b") || !strcasecmp(para, "badword"))) 261 return 0; 262 263 for (words = conf_badword_message; words; words = words->next) 264 { 265 sendtxtnumeric(client, "m %c %s%s%s %s", words->type & BADW_TYPE_REGEX ? 'R' : 'F', 266 (words->type & BADW_TYPE_FAST_L) ? "*" : "", words->word, 267 (words->type & BADW_TYPE_FAST_R) ? "*" : "", 268 words->action == BADWORD_REPLACE ? (words->replace ? words->replace : "<censored>") : ""); 269 } 270 return 1; 271 }