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 }