1 /* spamserv.c - anti spam service
2 * Copyright 2004 feigling
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version. Important limitations are
8 * listed in the COPYING file that accompanies this software.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, email evilnet-devel@lists.sourceforge.net.
33 #define SPAMSERV_CONF_NAME "services/spamserv"
35 #define KEY_EXCEPTIONS "exceptions"
36 #define KEY_BADWORDS "badwords"
37 #define KEY_FLAGS "flags"
38 #define KEY_INFO "info"
39 #define KEY_EXPIRY "expiry"
40 #define KEY_TRUSTED_HOSTS "trusted"
41 #define KEY_CHANNELS "channel"
42 #define KEY_ISSUER "issuer"
43 #define KEY_ISSUED "issued"
44 #define KEY_TRUSTED_ACCOUNTS "trusted"
45 #define KEY_DEBUG_CHANNEL "debug_channel"
46 #define KEY_DEBUG_CHANNEL_MODES "debug_channel_modes"
47 #define KEY_GLOBAL_EXCEPTIONS "global_exceptions"
48 #define KEY_GLOBAL_BADWORDS "global_badwords"
49 #define KEY_NETWORK_RULES "network_rules"
50 #define KEY_TRIGGER "trigger"
51 #define KEY_SHORT_BAN_DURATION "short_ban_duration"
52 #define KEY_LONG_BAN_DURATION "long_ban_duration"
53 #define KEY_GLINE_DURATION "gline_duration"
54 #define KEY_EXCEPTION_MAX "exception_max"
55 #define KEY_EXCEPTION_MIN_LEN "exception_min_len"
56 #define KEY_EXCEPTION_MAX_LEN "exception_max_len"
57 #define KEY_BADWORD_MAX "badword_max"
58 #define KEY_BADWORD_MIN_LEN "badword_min_len"
59 #define KEY_BADWORD_MAX_LEN "badword_max_len"
60 #define KEY_ADV_CHAN_MUST_EXIST "adv_chan_must_exist"
61 #define KEY_STRIP_MIRC_CODES "strip_mirc_codes"
62 #define KEY_ALLOW_MOVE_MERGE "allow_move_merge"
63 #define KEY_CAPSMIN "capsmin"
64 #define KEY_CAPSPERCENT "capspercent"
65 #define KEY_EXCEPTLEVEL "exceptlevel"
66 #define KEY_EXCEPTSPAMLEVEL "exceptspamlevel"
67 #define KEY_EXCEPTFLOODLEVEL "exceptfloodlevel"
68 #define KEY_EXCEPTADVLEVEL "exceptadvlevel"
69 #define KEY_EXCEPTBADWORDLEVEL "exceptbadwordlevel"
70 #define KEY_EXCEPTCAPSLEVEL "exceptcapslevel"
72 #define SPAMSERV_FUNC(NAME) MODCMD_FUNC(NAME)
73 #define SPAMSERV_SYNTAX() svccmd_send_help(user, spamserv, cmd)
74 #define SPAMSERV_MIN_PARMS(N) do { \
77 ss_reply(MSG_MISSING_PARAMS, argv[0]); \
79 return 0; } } while(0)
81 struct userNode
*spamserv
;
82 static struct module *spamserv_module
;
83 static struct service
*spamserv_service
;
84 static struct log_type
*SS_LOG
;
85 static unsigned long crc_table
[256];
87 dict_t registered_channels_dict
;
88 dict_t connected_users_dict
;
89 dict_t killed_users_dict
;
91 #define SSFUNC_ARGS user, channel, argc, argv, cmd
93 #define spamserv_notice(target, format...) send_message(target , spamserv , ## format)
94 #define spamserv_debug(format...) do { if(spamserv_conf.debug_channel) send_channel_notice(spamserv_conf.debug_channel , spamserv , ## format); } while(0)
95 #define ss_reply(format...) send_message(user , spamserv , ## format)
97 #define SET_SUBCMDS_SIZE 20
99 const char *set_subcommands
[SET_SUBCMDS_SIZE
] = {"EXCEPTLEVEL", "EXCEPTADVLEVEL", "EXCEPTBADWORDLEVEL", "EXCEPTCAPSLEVEL", "EXCEPTFLOODLEVEL", "EXCEPTSPAMLEVEL", "SPAMLIMIT", "BADREACTION", "CAPSREACTION", "ADVREACTION", "WARNREACTION", "ADVSCAN", "CAPSSCAN", "SPAMSCAN", "BADWORDSCAN", "CHANFLOODSCAN", "JOINFLOODSCAN", "CAPSMIN", "CAPSPERCENT"};
101 extern struct string_list
*autojoin_channels
;
102 static void spamserv_clear_spamNodes(struct chanNode
*channel
);
103 static void spamserv_punish(struct chanNode
*channel
, struct userNode
*user
, time_t expires
, char *reason
, int ban
);
104 static unsigned long crc32(const char *text
);
106 #define BINARY_OPTION(arguments...) return binary_option(arguments, user, channel, argc, argv);
107 #define MULTIPLE_OPTION(arguments...) return multiple_option(arguments, values, ArrayLength(values), user, channel, argc, argv);
109 static const struct message_entry msgtab
[] = {
110 { "SSMSG_CHANNEL_OPTIONS", "Channel Options:" },
111 { "SSMSG_STRING_VALUE", "$b%s$b%s" },
112 { "SSMSG_NUMERIC_VALUE", "$b%s$b%d - %s" },
113 { "SSMSG_INVALID_NUM_SET", "$b'%d'$b is an invalid %s setting." },
114 { "SSMSG_INVALID_OPTION", "$b%s$b is not a valid %s option." },
115 { "SSMSG_INVALID_BINARY", "$b%s$b is an invalid binary value." },
117 { "SSMSG_NOT_REGISTERED", "$b%s$b has not been registered with $b$X$b." },
118 { "SSMSG_NOT_REGISTERED_CS", "$b%s$b has not been registered with $b$C$b." },
119 { "SSMSG_ALREADY_REGISTERED", "$b%s$b is already registered." },
120 { "SSMSG_DEBUG_CHAN", "You may not register the debug channel." },
121 { "SSMSG_SUSPENDED_CS", "$b$C$b access to $b%s$b has been temporarily suspended, thus you can't %s it." },
122 { "SSMSG_SUSPENDED", "$b$X$b access to $b%s$b has been temporarily suspended." },
123 { "SSMSG_NO_REGISTER", "Due to an error it was not possible to register $b%s$b." },
124 { "SSMSG_REG_SUCCESS", "Channel $b%s$b registered." },
125 { "SSMSG_UNREG_SUCCESS", "$b%s$b has been unregistered." },
126 { "SSMSG_NO_ACCESS", "You lack sufficient access to use this command." },
127 { "SSMSG_MUST_BE_OPER", "You must be an irc operator to set this option." },
128 { "SSMSG_CONFIRM_UNREG", "To confirm this unregistration, you must append 'CONFIRM' to the end of your command. For example, 'unregister CONFIRM'." },
130 { "SSMSG_NO_EXCEPTIONS", "No words found in the exception list." },
131 { "SSMSG_NO_SUCH_EXCEPTION", "Word $b%s$b not found in the exception list." },
132 { "SSMSG_EXCEPTION_LIST", "The following words are in the exception list:" },
133 { "SSMSG_EXCEPTION_ADDED", "Word $b%s$b added to the exception list." },
134 { "SSMSG_EXCEPTION_DELETED", "Word $b%s$b deleted from the exception list." },
135 { "SSMSG_EXCEPTION_IN_LIST", "The word $b%s$b is already in the exception list." },
136 { "SSMSG_EXCEPTION_MAX", "The exception list has reached the maximum exceptions (max %lu). Delete a word to add another one." },
137 { "SSMSG_EXCEPTION_TOO_SHORT", "The word must be at least %lu characters long." },
138 { "SSMSG_EXCEPTION_TOO_LONG", "The word may not be longer than %lu characters." },
140 { "SSMSG_NO_BADWORDS", "No words found in the badword list." },
141 { "SSMSG_NO_SUCH_BADWORD", "Word $b%s$b not found in the badword list." },
142 { "SSMSG_BADWORD_LIST", "The following words are in the badword list:" },
143 { "SSMSG_BADWORD_ADDED", "Word $b%s$b added to the badword list." },
144 { "SSMSG_BADWORD_DELETED", "Word $b%s$b deleted from the badword list." },
145 { "SSMSG_BADWORD_IN_LIST", "The word $b%s$b is already in the badword list." },
146 { "SSMSG_BADWORD_MAX", "The badword list has reached the maximum badwords (max %lu). Delete a word to add another one." },
147 { "SSMSG_BADWORD_TOO_SHORT", "The word must be at least %lu characters long." },
148 { "SSMSG_BADWORD_TOO_LONG", "The word may not be longer than %lu characters." },
150 { "SSMSG_STATUS", "$bStatus:$b" },
151 { "SSMSG_STATUS_USERS", "Total Users Online: %u" },
152 { "SSMSG_STATUS_CHANNELS", "Registered Channels: %u" },
153 { "SSMSG_STATUS_MEMORY", "$bMemory Information:$b" },
154 { "SSMSG_STATUS_CHANNEL_LIST", "$bRegistered Channels:$b" },
155 { "SSMSG_STATUS_NO_CHANNEL", "No channels registered." },
157 { "SSMSG_WARNING_T", "%s is against the network rules" },
158 { "SSMSG_WARNING_2_T", "You are violating the network rules" },
159 { "SSMSG_WARNING_RULES_T", "%s is against the network rules. Read the network rules at %s" },
160 { "SSMSG_WARNING_RULES_2_T", "You are violating the network rules. Read the network rules at %s" },
162 { "SSMSG_ALREADY_TRUSTED", "Account $b%s$b is already trusted." },
163 { "SSMSG_NOT_TRUSTED", "Account $b%s$b is not trusted." },
164 { "SSMSG_ADDED_TRUSTED", "Added %s to the global trusted-accounts list" },
165 { "SSMSG_ADDED_TRUSTED_CHANNEL", "Added %s to the trusted-accounts list for channel %s." },
166 { "SSMSG_REMOVED_TRUSTED", "Removed %s from the global trusted-accounts list." },
167 { "SSMSG_REMOVED_TRUSTED_CHANNEL", "Removed %s from channel %s trusted-account list." },
168 { "SSMSG_TRUSTED_LIST", "$bTrusted Accounts$b" },
169 { "SSMSG_TRUSTED_LIST_HEADER", "Account Added By Time" },
170 { "SSMSG_HOST_IS_TRUSTED", "%-15s %-10s set %s ago" },
171 { "SSMSG_TRUSTED_LIST_BAR", "----------------------------------------" },
172 { "SSMSG_TRUSTED_LIST_END", "---------End of Trusted Accounts--------" },
173 { "SSMSG_HOST_NOT_TRUSTED", "%s does not have a special trust." },
175 { "SSMSG_MUST_BE_HELPING", "You must have security override (helping mode) on to use this command." },
177 { "SSMSG_SET_CAPSMIN", "$bCapsMin$b %d - atleast this min caps and atleast CapsPercent of the total line." },
178 { "SSMSG_SET_CAPSPERCENT", "$bCapsPercent$b %d - atleast CapsPercent of the total line." },
179 { "SSMSG_SET_EXCEPTLEVEL" , "$bExceptLevel$b %d - level and above will be excepted from all checks." },
180 { "SSMSG_SET_EXCEPTADVLEVEL", "$bExceptAdvLevel$b %d - and above will be excepted from advertising checks." },
181 { "SSMSG_SET_EXCEPTBADWORDLEVEL", "$bExceptBadWordLevel$b %d - and above will be excepted from badword checks." },
182 { "SSMSG_SET_EXCEPTCAPSLEVEL" , "$bExceptCapsLevel$b %d - and above will be excepted from caps checks." },
183 { "SSMSG_SET_EXCEPTFLOODLEVEL", "$bExceptFloodLevel$b %d - and above will be excepted from flood checks." },
184 { "SSMSG_SET_EXCEPTSPAMLEVEL", "$bExceptSpamLevel$b %d - and above will be excepted from spam checks." },
189 #define SSMSG_DEBUG_KICK "Kicked user $b%s$b from $b%s$b, reason: %s"
190 #define SSMSG_DEBUG_BAN "Banned user $b%s$b from $b%s$b, reason: %s"
191 #define SSMSG_DEBUG_KILL "Killed user $b%s$b, last violation in $b%s$b"
192 #define SSMSG_DEBUG_GLINE "Glined user $b%s$b, host $b%s$b, last violation in $b%s$b"
193 #define SSMSG_DEBUG_RECONNECT "Killed user $b%s$b reconnected to the network"
195 #define SSMSG_SPAM "Spamming"
196 #define SSMSG_FLOOD "Flooding the channel/network"
197 #define SSMSG_ADV "Advertising"
198 #define SSMSG_BAD "Badwords"
199 #define SSMSG_CAPS "Caps"
200 #define SSMSG_JOINFLOOD "Join flooding the channel"
202 #define SSMSG_WARNING "%s is against the network rules"
203 #define SSMSG_WARNING_2 "You are violating the network rules"
204 #define SSMSG_WARNING_RULES "%s is against the network rules. Read the network rules at %s"
205 #define SSMSG_WARNING_RULES_2 "You are violating the network rules. Read the network rules at %s"
208 #define SSMSG_WARNING "SSMSG_WARNING_T"
209 #define SSMSG_WARNING_2 "SSMSG_WARNING_2_T"
210 #define SSMSG_WARNING_RULES "SSMSG_WARNING_RULES_T"
211 #define SSMSG_WARNING_RULES_2 "SSMSG_WARNING_RULES_2_T"
214 static dict_t spamserv_trusted_accounts
;
218 struct chanNode
*debug_channel
;
219 struct string_list
*global_exceptions
;
220 struct string_list
*global_badwords
;
221 const char *network_rules
;
222 unsigned char trigger
;
223 unsigned long short_ban_duration
;
224 unsigned long long_ban_duration
;
225 unsigned long gline_duration
;
226 unsigned long exception_max
;
227 unsigned long exception_min_len
;
228 unsigned long exception_max_len
;
229 unsigned long badword_max
;
230 unsigned long badword_min_len
;
231 unsigned long badword_max_len
;
232 unsigned int adv_chan_must_exist
: 1;
233 unsigned int strip_mirc_codes
: 1;
234 unsigned int allow_move_merge
: 1;
235 unsigned long untrusted_max
;
238 struct trusted_account
{
240 struct string_list
*channel
;
246 /***********************************************/
248 /***********************************************/
251 get_chanInfo(const char *channelname
)
253 return dict_find(registered_channels_dict
, channelname
, 0);
257 spamserv_join_channel(struct chanNode
*channel
)
259 struct mod_chanmode change
;
260 mod_chanmode_init(&change
);
262 change
.args
[0].mode
= MODE_CHANOP
;
263 change
.args
[0].u
.member
= AddChannelUser(spamserv
, channel
);
264 mod_chanmode_announce(spamserv
, channel
, &change
);
268 spamserv_part_channel(struct chanNode
*channel
, char *reason
)
270 /* we only have to clear the spamNodes because every other node expires on it's own */
271 spamserv_clear_spamNodes(channel
);
272 DelChannelUser(spamserv
, channel
, reason
, 0);
275 static struct chanInfo
*
276 spamserv_register_channel(struct chanNode
*channel
, struct string_list
*exceptions
, struct string_list
*badwords
, unsigned int flags
, char *info
)
278 struct chanInfo
*cInfo
= malloc(sizeof(struct chanInfo
));
282 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for cInfo; channel: %s", channel
->name
);
286 cInfo
->channel
= channel
;
287 cInfo
->exceptions
= exceptions
? string_list_copy(exceptions
) : alloc_string_list(1);
288 cInfo
->badwords
= badwords
? string_list_copy(badwords
) : alloc_string_list(1);
289 cInfo
->flags
= flags
;
290 cInfo
->exceptlevel
= 300;
291 cInfo
->exceptspamlevel
= 100;
292 cInfo
->exceptadvlevel
= 100;
293 cInfo
->exceptbadwordlevel
= 100;
294 cInfo
->exceptcapslevel
= 100;
295 cInfo
->exceptfloodlevel
= 100;
297 cInfo
->capspercent
= 25;
299 /* XXX Rewrite the flag system */
300 if (strlen(info
) < 5)
302 if (strlen(info
) < 6)
305 safestrncpy(cInfo
->info
, info
, sizeof(cInfo
->info
));
306 cInfo
->suspend_expiry
= 0;
307 dict_insert(registered_channels_dict
, strdup(cInfo
->channel
->name
), cInfo
);
313 spamserv_unregister_channel(struct chanInfo
*cInfo
)
318 free_string_list(cInfo
->exceptions
);
319 free_string_list(cInfo
->badwords
);
320 dict_remove(registered_channels_dict
, cInfo
->channel
->name
);
325 spamserv_cs_suspend(struct chanNode
*channel
, time_t expiry
, int suspend
, char *reason
)
327 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
333 cInfo
->flags
|= CHAN_SUSPENDED
;
334 cInfo
->suspend_expiry
= expiry
;
335 spamserv_part_channel(channel
, reason
);
339 if(CHECK_SUSPENDED(cInfo
))
341 cInfo
->flags
&= ~CHAN_SUSPENDED
;
342 cInfo
->suspend_expiry
= 0;
349 spamserv_cs_move_merge(struct userNode
*user
, struct chanNode
*channel
, struct chanNode
*target
, int move
)
351 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
357 if(!spamserv_conf
.allow_move_merge
|| get_chanInfo(target
->name
))
360 snprintf(reason
, sizeof(reason
), "unregistered due to a channel move to %s", target
->name
);
362 snprintf(reason
, sizeof(reason
), "unregistered due to a channel merge into %s", target
->name
);
364 spamserv_cs_unregister(user
, channel
, manually
, reason
);
368 cInfo
->channel
= target
;
370 dict_remove(registered_channels_dict
, channel
->name
);
371 dict_insert(registered_channels_dict
, strdup(target
->name
), cInfo
);
375 snprintf(reason
, sizeof(reason
), "Channel moved to %s by %s.", target
->name
, user
->handle_info
->handle
);
379 spamserv_join_channel(target
);
380 snprintf(reason
, sizeof(reason
), "%s merged into %s by %s.", channel
->name
, target
->name
, user
->handle_info
->handle
);
383 if(!CHECK_SUSPENDED(cInfo
))
384 spamserv_part_channel(channel
, reason
);
387 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
,
388 "SSMSG_CHANNEL_MOVED", channel
->name
, target
->name
,
389 user
->handle_info
->handle
);
391 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
,
392 "SSMSG_CHANNEL_MERGED", channel
->name
, target
->name
,
393 user
->handle_info
->handle
);
402 spamserv_cs_unregister(struct userNode
*user
, struct chanNode
*channel
, enum cs_unreg type
, char *reason
)
404 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
408 char partmsg
[MAXLEN
];
413 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_UNREG_MANUAL",
414 channel
->name
, reason
, user
->handle_info
->handle
);
415 snprintf(partmsg
, sizeof(partmsg
), "%s %s by %s.", channel
->name
, reason
, user
->handle_info
->handle
);
418 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_REG_EXPIRED",
420 snprintf(partmsg
, sizeof(partmsg
), "%s registration expired.", channel
->name
);
423 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_LOST_ALL_USERS",
425 snprintf(partmsg
, sizeof(partmsg
), "%s lost all users.", channel
->name
);
429 if(!CHECK_SUSPENDED(cInfo
))
430 spamserv_part_channel(channel
, partmsg
);
432 spamserv_unregister_channel(cInfo
);
436 /***********************************************/
438 /***********************************************/
440 static struct userInfo
*
441 get_userInfo(const char *nickname
)
443 return dict_find(connected_users_dict
, nickname
, 0);
447 spamserv_create_spamNode(struct chanNode
*channel
, struct userInfo
*uInfo
, char *text
)
449 struct spamNode
*sNode
= malloc(sizeof(struct spamNode
));
453 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for sNode; channel: %s; user: %s", channel
->name
, uInfo
->user
->nick
);
457 sNode
->channel
= channel
;
458 sNode
->crc32
= crc32(text
);
464 struct spamNode
*temp
= uInfo
->spam
;
480 spamserv_delete_spamNode(struct userInfo
*uInfo
, struct spamNode
*sNode
)
485 if(sNode
== uInfo
->spam
)
486 uInfo
->spam
= sNode
->next
;
489 sNode
->next
->prev
= sNode
->prev
;
491 sNode
->prev
->next
= sNode
->next
;
497 spamserv_clear_spamNodes(struct chanNode
*channel
)
499 struct userInfo
*uInfo
;
500 struct spamNode
*sNode
;
503 for(i
= 0; i
< channel
->members
.used
; i
++)
505 if((uInfo
= get_userInfo(channel
->members
.list
[i
]->user
->nick
)))
507 if((sNode
= uInfo
->spam
))
509 for(; sNode
; sNode
= sNode
->next
)
510 if(sNode
->channel
== channel
)
514 spamserv_delete_spamNode(uInfo
, sNode
);
521 spamserv_create_floodNode(struct chanNode
*channel
, struct userNode
*user
, struct floodNode
**uI_fNode
)
523 struct floodNode
*fNode
= malloc(sizeof(struct floodNode
));
527 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for fNode; channel: %s; user: %s", channel
->name
, user
->nick
);
531 fNode
->channel
= channel
;
539 struct floodNode
*temp
= *uI_fNode
;
555 spamserv_delete_floodNode(struct floodNode
**uI_fNode
, struct floodNode
*fNode
)
560 if(fNode
== *uI_fNode
)
561 *uI_fNode
= fNode
->next
;
564 fNode
->next
->prev
= fNode
->prev
;
566 fNode
->prev
->next
= fNode
->next
;
572 spamserv_create_user(struct userNode
*user
)
574 struct userInfo
*uInfo
= malloc(sizeof(struct userInfo
));
575 struct killNode
*kNode
= dict_find(killed_users_dict
, irc_ntoa(&user
->ip
), 0);
579 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for uInfo; nick: %s", user
->nick
);
584 spamserv_debug(SSMSG_DEBUG_RECONNECT
, user
->nick
);
589 uInfo
->joinflood
= NULL
;
590 uInfo
->flags
= kNode
? USER_KILLED
: 0;
591 uInfo
->warnlevel
= kNode
? kNode
->warnlevel
: 0;
596 dict_insert(connected_users_dict
, strdup(user
->nick
), uInfo
);
600 /* free(kNode); dict_remove does this */
601 dict_remove(killed_users_dict
, irc_ntoa(&user
->ip
));
606 spamserv_delete_user(struct userInfo
*uInfo
)
613 spamserv_delete_spamNode(uInfo
, uInfo
->spam
);
617 spamserv_delete_floodNode(&uInfo
->flood
, uInfo
->flood
);
620 while(uInfo
->joinflood
)
621 spamserv_delete_floodNode(&uInfo
->joinflood
, uInfo
->joinflood
);
623 dict_remove(connected_users_dict
, uInfo
->user
->nick
);
628 spamserv_new_user_func(struct userNode
*user
, UNUSED_ARG(void *extra
))
631 spamserv_create_user(user
);
637 spamserv_del_user_func(struct userNode
*user
, struct userNode
*killer
, UNUSED_ARG(const char *why
), UNUSED_ARG(void *extra
))
639 struct userInfo
*uInfo
= get_userInfo(user
->nick
);
640 struct killNode
*kNode
;
642 if(killer
== spamserv
)
644 kNode
= malloc(sizeof(struct killNode
));
648 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for killNode - nickname %s", user
->nick
);
649 spamserv_delete_user(uInfo
);
653 if(uInfo
->warnlevel
> KILL_WARNLEVEL
)
654 kNode
->warnlevel
= uInfo
->warnlevel
- KILL_WARNLEVEL
;
656 kNode
->warnlevel
= 0;
660 dict_insert(killed_users_dict
, strdup(irc_ntoa(&user
->ip
)), kNode
);
663 spamserv_delete_user(uInfo
);
667 spamserv_nick_change_func(struct userNode
*user
, const char *old_nick
, UNUSED_ARG(void *extra
))
669 struct userInfo
*uInfo
= get_userInfo(old_nick
);
672 dict_remove(connected_users_dict
, old_nick
);
673 dict_insert(connected_users_dict
, strdup(user
->nick
), uInfo
);
678 spamserv_user_join(struct modeNode
*mNode
, UNUSED_ARG(void *extra
))
680 struct chanNode
*channel
= mNode
->channel
;
681 struct userNode
*user
= mNode
->user
;
682 struct chanInfo
*cInfo
;
683 struct userInfo
*uInfo
;
684 struct floodNode
*jfNode
;
686 if(user
->uplink
->burst
|| !(cInfo
= get_chanInfo(channel
->name
)) || !CHECK_JOINFLOOD(cInfo
) || !(uInfo
= get_userInfo(user
->nick
)))
689 if(!(jfNode
= uInfo
->joinflood
))
691 spamserv_create_floodNode(channel
, user
, &uInfo
->joinflood
);
695 for(; jfNode
; jfNode
= jfNode
->next
)
696 if(jfNode
->channel
== channel
)
701 spamserv_create_floodNode(channel
, user
, &uInfo
->joinflood
);
708 if(jfNode
->count
> JOINFLOOD_MAX
)
712 spamserv_delete_floodNode(&uInfo
->joinflood
, jfNode
);
713 snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_JOINFLOOD
, spamserv_conf
.network_rules
);
714 spamserv_punish(channel
, user
, JOINFLOOD_B_DURATION
, reason
, 1);
723 spamserv_user_part(struct modeNode
*mn
, UNUSED_ARG(const char *reason
), UNUSED_ARG(void *extra
))
725 struct userNode
*user
= mn
->user
;
726 struct chanNode
*channel
= mn
->channel
;
727 struct userInfo
*uInfo
;
728 struct spamNode
*sNode
;
729 struct floodNode
*fNode
;
731 if(user
->dead
|| !get_chanInfo(channel
->name
) || !(uInfo
= get_userInfo(user
->nick
)))
734 if((sNode
= uInfo
->spam
))
736 for(; sNode
; sNode
= sNode
->next
)
737 if(sNode
->channel
== channel
)
741 spamserv_delete_spamNode(uInfo
, sNode
);
744 if((fNode
= uInfo
->flood
))
746 for(; fNode
; fNode
= fNode
->next
)
747 if(fNode
->channel
== channel
)
751 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
755 /***********************************************/
757 /***********************************************/
765 for(i
= 0; i
< 256; i
++)
769 for(j
= 8; j
> 0; j
--)
773 crc
= (crc
>> 1) ^ 0xEDB88320L
;
786 crc32(const char *text
)
788 register unsigned long crc
= 0xFFFFFFFF;
789 unsigned int c
, i
= 0;
791 while((c
= (unsigned int)text
[i
++]) != 0)
792 crc
= ((crc
>> 8) & 0x00FFFFFF) ^ crc_table
[(crc
^c
) & 0xFF];
794 return (crc
^0xFFFFFFFF);
798 timeq_flood(UNUSED_ARG(void *data
))
801 struct userInfo
*uInfo
;
802 struct floodNode
*fNode
;
804 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
806 uInfo
= iter_data(it
);
811 if(!(fNode
= uInfo
->flood
))
814 for(; fNode
; fNode
= fNode
->next
)
816 if(now
- fNode
->time
> FLOOD_EXPIRE
)
818 if(!(--fNode
->count
))
819 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
824 timeq_add(now
+ FLOOD_TIMEQ_FREQ
, timeq_flood
, NULL
);
828 timeq_joinflood(UNUSED_ARG(void *data
))
831 struct userInfo
*uInfo
;
832 struct floodNode
*fNode
, *nextnode
;
834 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
836 uInfo
= iter_data(it
);
838 if(!(fNode
= uInfo
->joinflood
))
841 for(; fNode
; fNode
= nextnode
)
843 nextnode
= fNode
->next
;
844 if(now
- fNode
->time
> JOINFLOOD_EXPIRE
)
846 if(!(--fNode
->count
))
847 spamserv_delete_floodNode(&uInfo
->joinflood
, fNode
);
852 timeq_add(now
+ JOINFLOOD_TIMEQ_FREQ
, timeq_joinflood
, NULL
);
856 timeq_bad(UNUSED_ARG(void *data
))
859 struct userInfo
*uInfo
;
861 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
863 uInfo
= iter_data(it
);
865 if(uInfo
->lastbad
&& uInfo
->lastbad
- now
> BAD_EXPIRE
)
868 uInfo
->flags
&= ~USER_BAD_WARNED
;
872 timeq_add(now
+ BAD_TIMEQ_FREQ
, timeq_bad
, NULL
);
876 timeq_caps(UNUSED_ARG(void *data
))
879 struct userInfo
*uInfo
;
881 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
883 uInfo
= iter_data(it
);
885 if(uInfo
->lastcaps
&& uInfo
->lastcaps
- now
> CAPS_EXPIRE
)
888 uInfo
->flags
&= ~USER_CAPS_WARNED
;
892 timeq_add(now
+ CAPS_TIMEQ_FREQ
, timeq_caps
, NULL
);
896 timeq_adv(UNUSED_ARG(void *data
))
899 struct userInfo
*uInfo
;
901 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
903 uInfo
= iter_data(it
);
905 if(uInfo
->lastadv
&& uInfo
->lastadv
- now
> ADV_EXPIRE
)
908 uInfo
->flags
&= ~USER_ADV_WARNED
;
912 timeq_add(now
+ ADV_TIMEQ_FREQ
, timeq_adv
, NULL
);
916 timeq_warnlevel(UNUSED_ARG(void *data
))
919 struct userInfo
*uInfo
;
921 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
923 uInfo
= iter_data(it
);
925 if(uInfo
->warnlevel
> 0)
929 timeq_add(now
+ WARNLEVEL_TIMEQ_FREQ
, timeq_warnlevel
, NULL
);
933 timeq_kill(UNUSED_ARG(void *data
))
936 struct killNode
*kNode
;
939 for(it
= dict_first(killed_users_dict
); it
; it
= iter_next(it
))
941 kNode
= iter_data(it
);
943 if(now
- kNode
->time
> KILL_EXPIRE
) {
944 dict_remove(killed_users_dict
, iter_key(it
));
945 /* have to restart the loop because next is
946 * now invalid. FIXME: how could we do this better? */
947 break; /* out of for() loop */
950 /* no more killed_users to delete, so stop while loop */
951 break; /* out of while() loop */
954 timeq_add(now
+ KILL_TIMEQ_FREQ
, timeq_kill
, NULL
);
958 binary_option(char *name
, unsigned long mask
, struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[])
960 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
965 if(enabled_string(argv
[1]))
967 cInfo
->flags
|= mask
;
970 else if(disabled_string(argv
[1]))
972 cInfo
->flags
&= ~mask
;
977 spamserv_notice(user
, "SSMSG_INVALID_BINARY", argv
[1]);
983 value
= (cInfo
->flags
& mask
) ? 1 : 0;
986 spamserv_notice(user
, "SSMSG_STRING_VALUE", name
, value
? "Enabled." : "Disabled.");
998 multiple_option(char *name
, char *description
, enum channelinfo info
, struct valueData
*values
, int count
, struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[])
1000 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1005 index
= atoi(argv
[1]);
1007 if(index
< 0 || index
>= count
)
1009 spamserv_notice(user
, "SSMSG_INVALID_NUM_SET", index
, description
);
1011 for(index
= 0; index
< count
; index
++)
1012 spamserv_notice(user
, "SSMSG_NUMERIC_VALUE", name
, index
, values
[index
].description
);
1017 if(values
[index
].oper_only
&& !IsOper(user
))
1019 spamserv_notice(user
, "SSMSG_MUST_BE_OPER");
1023 cInfo
->info
[info
] = values
[index
].value
;
1027 for(index
= 0; index
< count
&& cInfo
->info
[info
] != values
[index
].value
; index
++);
1030 spamserv_notice(user
, "SSMSG_NUMERIC_VALUE", name
, index
, values
[index
].description
);
1035 show_exceptions(struct userNode
*user
, struct chanInfo
*cInfo
)
1037 struct helpfile_table table
;
1040 if(!cInfo
->exceptions
->used
)
1042 spamserv_notice(user
, "SSMSG_NO_EXCEPTIONS");
1046 spamserv_notice(user
, "SSMSG_EXCEPTION_LIST");
1050 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
1051 table
.contents
= alloca(cInfo
->exceptions
->used
* sizeof(*table
.contents
));
1053 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1055 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
1056 table
.contents
[table
.length
][0] = cInfo
->exceptions
->list
[i
];
1060 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1066 show_badwords(struct userNode
*user
, struct chanInfo
*cInfo
)
1068 struct helpfile_table table
;
1071 if(!cInfo
->badwords
->used
)
1073 spamserv_notice(user
, "SSMSG_NO_BADWORDS");
1077 spamserv_notice(user
, "SSMSG_BADWORD_LIST");
1081 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
1082 table
.contents
= alloca(cInfo
->badwords
->used
* sizeof(*table
.contents
));
1084 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1086 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
1087 table
.contents
[table
.length
][0] = cInfo
->badwords
->list
[i
];
1091 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1097 show_memory_usage(struct userNode
*user
)
1100 struct helpfile_table table
;
1101 struct chanInfo
*cInfo
;
1102 struct userInfo
*uInfo
;
1103 struct spamNode
*sNode
;
1104 struct floodNode
*fNode
;
1105 double channel_size
= 0, user_size
, size
;
1106 unsigned int spamcount
= 0, floodcount
= 0, i
, j
;
1109 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
1111 cInfo
= iter_data(it
);
1113 if(!cInfo
->exceptions
->used
)
1116 if(!cInfo
->badwords
->used
)
1119 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1120 channel_size
+= strlen(cInfo
->exceptions
->list
[i
]) * sizeof(char);
1122 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1123 channel_size
+= strlen(cInfo
->badwords
->list
[i
]) * sizeof(char);
1126 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
1128 uInfo
= iter_data(it
);
1130 for(sNode
= uInfo
->spam
; sNode
; sNode
= sNode
->next
, spamcount
++);
1131 for(fNode
= uInfo
->flood
; fNode
; fNode
= fNode
->next
, floodcount
++);
1132 for(fNode
= uInfo
->joinflood
; fNode
; fNode
= fNode
->next
, floodcount
++);
1135 channel_size
+= dict_size(registered_channels_dict
) * sizeof(struct chanInfo
);
1137 user_size
= dict_size(connected_users_dict
) * sizeof(struct userInfo
) +
1138 dict_size(killed_users_dict
) * sizeof(struct killNode
) +
1139 spamcount
* sizeof(struct spamNode
) +
1140 floodcount
* sizeof(struct floodNode
);
1142 size
= channel_size
+ user_size
;
1144 ss_reply("SSMSG_STATUS_MEMORY");
1148 table
.flags
= TABLE_NO_FREE
| TABLE_NO_HEADERS
| TABLE_PAD_LEFT
;
1149 table
.contents
= calloc(table
.length
, sizeof(char**));
1152 table
.contents
[0] = calloc(table
.width
, sizeof(char*));
1153 snprintf(buffer
, sizeof(buffer
), "Channel Memory Usage:");
1154 table
.contents
[0][0] = strdup(buffer
);
1155 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", channel_size
);
1156 table
.contents
[0][1] = strdup(buffer
);
1157 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", channel_size
/ 1024);
1158 table
.contents
[0][2] = strdup(buffer
);
1159 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", channel_size
/ 1024 / 1024);
1160 table
.contents
[0][3] = strdup(buffer
);
1163 table
.contents
[1] = calloc(table
.width
, sizeof(char*));
1164 snprintf(buffer
, sizeof(buffer
), "User Memory Usage :");
1165 table
.contents
[1][0] = strdup(buffer
);
1166 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", user_size
);
1167 table
.contents
[1][1] = strdup(buffer
);
1168 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", user_size
/ 1024);
1169 table
.contents
[1][2] = strdup(buffer
);
1170 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", user_size
/ 1024 / 1024);
1171 table
.contents
[1][3] = strdup(buffer
);
1173 // total memory usage
1174 table
.contents
[2] = calloc(table
.width
, sizeof(char*));
1175 snprintf(buffer
, sizeof(buffer
), "Total Memory Usage :");
1176 table
.contents
[2][0] = strdup(buffer
);
1177 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", size
);
1178 table
.contents
[2][1] = strdup(buffer
);
1179 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", size
/ 1024);
1180 table
.contents
[2][2] = strdup(buffer
);
1181 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", size
/ 1024 / 1024);
1182 table
.contents
[2][3] = strdup(buffer
);
1184 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1186 for(i
= 0; i
< table
.length
; i
++)
1188 for(j
= 0; j
< table
.width
; j
++)
1189 free((char*)table
.contents
[i
][j
]);
1191 free(table
.contents
[i
]);
1194 free(table
.contents
);
1198 show_registered_channels(struct userNode
*user
)
1200 struct helpfile_table table
;
1203 spamserv_notice(user
, "SSMSG_STATUS_CHANNEL_LIST");
1205 if(!dict_size(registered_channels_dict
))
1207 spamserv_notice(user
, "SSMSG_STATUS_NO_CHANNEL");
1213 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
1214 table
.contents
= alloca(dict_size(registered_channels_dict
) * sizeof(*table
.contents
));
1216 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
1218 struct chanInfo
*cInfo
= iter_data(it
);
1220 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
1221 table
.contents
[table
.length
][0] = cInfo
->channel
->name
;
1225 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1228 /***********************************************/
1230 /***********************************************/
1233 SPAMSERV_FUNC(cmd_register
)
1235 struct chanInfo
*cInfo
;
1237 if(!channel
|| !channel
->channel_info
)
1239 ss_reply("SSMSG_NOT_REGISTERED_CS", channel
->name
);
1243 if(get_chanInfo(channel
->name
))
1245 ss_reply("SSMSG_ALREADY_REGISTERED", channel
->name
);
1249 if(IsSuspended(channel
->channel_info
))
1251 ss_reply("SSMSG_SUSPENDED_CS", channel
->name
, "register");
1255 if(channel
== spamserv_conf
.debug_channel
)
1257 ss_reply("SSMSG_DEBUG_CHAN");
1261 if(!(cInfo
= spamserv_register_channel(channel
, spamserv_conf
.global_exceptions
, spamserv_conf
.global_badwords
, CHAN_FLAGS_DEFAULT
, CHAN_INFO_DEFAULT
)))
1263 ss_reply("SSMSG_NO_REGISTER", channel
->name
);
1267 spamserv_join_channel(cInfo
->channel
);
1269 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_REGISTERED_BY",
1270 channel
->name
, user
->handle_info
->handle
);
1271 ss_reply("SSMSG_REG_SUCCESS", channel
->name
);
1277 SPAMSERV_FUNC(cmd_unregister
)
1279 struct chanInfo
*cInfo
;
1280 struct chanData
*cData
;
1281 struct userData
*uData
;
1282 char reason
[MAXLEN
];
1284 if(!channel
|| !(cData
= channel
->channel_info
) || !(cInfo
= get_chanInfo(channel
->name
)))
1286 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1290 if(!(uData
= GetChannelUser(cData
, user
->handle_info
)) || (uData
->access
< UL_OWNER
))
1292 ss_reply("SSMSG_NO_ACCESS");
1296 if(!IsHelping(user
))
1298 if(IsSuspended(cData
))
1300 ss_reply("SSMSG_SUSPENDED_CS", channel
->name
, "unregister");
1304 if(argc
< 2 || strcasecmp(argv
[1], "CONFIRM"))
1306 ss_reply("SSMSG_CONFIRM_UNREG");
1311 if(!CHECK_SUSPENDED(cInfo
))
1313 snprintf(reason
, sizeof(reason
), "%s unregistered by %s.", spamserv
->nick
, user
->handle_info
->handle
);
1314 spamserv_part_channel(channel
, reason
);
1317 spamserv_unregister_channel(cInfo
);
1319 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_UNREGISTERED_BY",
1320 channel
->name
, user
->handle_info
->handle
);
1321 ss_reply("SSMSG_UNREG_SUCCESS", channel
->name
);
1327 SPAMSERV_FUNC(cmd_status
)
1329 ss_reply("SSMSG_STATUS");
1330 ss_reply("SSMSG_STATUS_USERS", dict_size(connected_users_dict
));
1331 ss_reply("SSMSG_STATUS_CHANNELS", dict_size(registered_channels_dict
));
1333 if(IsOper(user
) && argc
> 1)
1335 if(!irccasecmp(argv
[1], "memory"))
1336 show_memory_usage(user
);
1337 else if(!irccasecmp(argv
[1], "channels"))
1338 show_registered_channels(user
);
1345 SPAMSERV_FUNC(cmd_addexception
)
1347 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1348 struct userData
*uData
;
1351 if(!cInfo
|| !channel
->channel_info
)
1353 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1357 if(CHECK_SUSPENDED(cInfo
))
1359 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1363 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1365 ss_reply("SSMSG_NO_ACCESS");
1370 return show_exceptions(user
, cInfo
);
1372 if(cInfo
->exceptions
->used
== spamserv_conf
.exception_max
&& !IsOper(user
))
1374 ss_reply("SSMSG_EXCEPTION_MAX", spamserv_conf
.exception_max
);
1378 if(strlen(argv
[1]) < spamserv_conf
.exception_min_len
)
1380 ss_reply("SSMSG_EXCEPTION_TOO_SHORT", spamserv_conf
.exception_min_len
);
1383 else if(strlen(argv
[1]) > spamserv_conf
.exception_max_len
)
1385 ss_reply("SSMSG_EXCEPTION_TOO_LONG", spamserv_conf
.exception_max_len
);
1389 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1391 if(!irccasecmp(argv
[1], cInfo
->exceptions
->list
[i
]))
1393 ss_reply("SSMSG_EXCEPTION_IN_LIST", argv
[1]);
1398 string_list_append(cInfo
->exceptions
, strdup(argv
[1]));
1399 ss_reply("SSMSG_EXCEPTION_ADDED", argv
[1]);
1405 SPAMSERV_FUNC(cmd_delexception
)
1407 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1408 struct userData
*uData
;
1412 if(!cInfo
|| !channel
->channel_info
)
1414 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1418 if(CHECK_SUSPENDED(cInfo
))
1420 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1424 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1426 ss_reply("SSMSG_NO_ACCESS");
1431 return show_exceptions(user
, cInfo
);
1433 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1435 if(!irccasecmp(argv
[1], cInfo
->exceptions
->list
[i
]))
1444 ss_reply("SSMSG_NO_SUCH_EXCEPTION", argv
[1]);
1448 string_list_delete(cInfo
->exceptions
, i
);
1449 ss_reply("SSMSG_EXCEPTION_DELETED", argv
[1]);
1455 SPAMSERV_FUNC(cmd_addbadword
)
1457 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1458 struct userData
*uData
;
1461 if(!cInfo
|| !channel
->channel_info
)
1463 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1467 if(CHECK_SUSPENDED(cInfo
))
1469 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1473 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1475 ss_reply("SSMSG_NO_ACCESS");
1480 return show_badwords(user
, cInfo
);
1482 if(cInfo
->badwords
->used
== spamserv_conf
.badword_max
&& !IsOper(user
))
1484 ss_reply("SSMSG_BADWORD_MAX", spamserv_conf
.badword_max
);
1488 if(strlen(argv
[1]) < spamserv_conf
.badword_min_len
)
1490 ss_reply("SSMSG_BADWORD_TOO_SHORT", spamserv_conf
.badword_min_len
);
1493 else if(strlen(argv
[1]) > spamserv_conf
.badword_max_len
)
1495 ss_reply("SSMSG_BADWORD_TOO_LONG", spamserv_conf
.badword_max_len
);
1499 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1501 if(!irccasecmp(argv
[1], cInfo
->badwords
->list
[i
]))
1503 ss_reply("SSMSG_BADWORD_IN_LIST", argv
[1]);
1508 string_list_append(cInfo
->badwords
, strdup(argv
[1]));
1509 ss_reply("SSMSG_BADWORD_ADDED", argv
[1]);
1515 SPAMSERV_FUNC(cmd_delbadword
)
1517 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1518 struct userData
*uData
;
1522 if(!cInfo
|| !channel
->channel_info
)
1524 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1528 if(CHECK_SUSPENDED(cInfo
))
1530 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1534 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1536 ss_reply("SSMSG_NO_ACCESS");
1541 return show_badwords(user
, cInfo
);
1543 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1545 if(!irccasecmp(argv
[1], cInfo
->badwords
->list
[i
]))
1554 ss_reply("SSMSG_NO_SUCH_BADWORD", argv
[1]);
1558 string_list_delete(cInfo
->badwords
, i
);
1559 ss_reply("SSMSG_BADWORD_DELETED", argv
[1]);
1565 SPAMSERV_FUNC(cmd_set
)
1567 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1568 struct userData
*uData
;
1569 struct svccmd
*subcmd
;
1570 char cmd_name
[MAXLEN
];
1575 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1579 if(CHECK_SUSPENDED(cInfo
))
1581 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1585 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1587 ss_reply("SSMSG_NO_ACCESS");
1593 ss_reply("SSMSG_CHANNEL_OPTIONS");
1595 for(i
= 0; i
< SET_SUBCMDS_SIZE
; i
++)
1597 sprintf(cmd_name
, "%s %s", cmd
->name
, set_subcommands
[i
]);
1599 if((subcmd
= dict_find(cmd
->parent
->commands
, cmd_name
, NULL
)))
1600 subcmd
->command
->func(user
, channel
, 1, argv
+ 1, subcmd
);
1606 sprintf(cmd_name
, "%s %s", cmd
->name
, argv
[1]);
1607 subcmd
= dict_find(cmd
->parent
->commands
, cmd_name
, NULL
);
1611 reply("SSMSG_INVALID_OPTION", argv
[1], argv
[0]);
1615 return subcmd
->command
->func(user
, channel
, argc
- 1, argv
+ 1, subcmd
);
1618 int ss_check_user_level(struct chanNode
*channel
, struct userNode
*user
, unsigned int minimum
, int allow_override
, int exempt_owner
)
1620 struct userData
*uData
;
1621 struct chanData
*cData
= channel
->channel_info
;
1624 uData
= _GetChannelUser(cData
, user
->handle_info
, allow_override
, 0);
1627 if(minimum
<= uData
->access
)
1629 if((minimum
> UL_OWNER
) && (uData
->access
== UL_OWNER
) && exempt_owner
)
1636 channel_except_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1638 struct chanData
*cData
= channel
->channel_info
;
1639 struct chanInfo
*cInfo
;
1640 struct userData
*uData
;
1641 unsigned short value
;
1643 cInfo
= get_chanInfo(channel
->name
);
1647 if(!ss_check_user_level(channel
, user
, cInfo
->exceptlevel
, 1, 1))
1649 reply("SSMSG_CANNOT_SET");
1652 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1653 if(!value
&& strcmp(argv
[1], "0"))
1655 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1658 uData
= GetChannelUser(cData
, user
->handle_info
);
1659 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1661 reply("SSMSG_BAD_SETLEVEL");
1664 cInfo
->exceptlevel
= value
;
1666 reply("SSMSG_SET_EXCEPTLEVEL", cInfo
->exceptlevel
);
1671 channel_except_adv_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1673 struct chanData
*cData
= channel
->channel_info
;
1674 struct chanInfo
*cInfo
;
1675 struct userData
*uData
;
1676 unsigned short value
;
1678 cInfo
= get_chanInfo(channel
->name
);
1682 if(!ss_check_user_level(channel
, user
, cInfo
->exceptadvlevel
, 1, 1))
1684 reply("SSMSG_CANNOT_SET");
1687 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1688 if(!value
&& strcmp(argv
[1], "0"))
1690 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1693 uData
= GetChannelUser(cData
, user
->handle_info
);
1694 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1696 reply("SSMSG_BAD_SETLEVEL");
1699 cInfo
->exceptadvlevel
= value
;
1701 reply("SSMSG_SET_EXCEPTADVLEVEL", cInfo
->exceptadvlevel
);
1706 channel_except_badword_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1708 struct chanData
*cData
= channel
->channel_info
;
1709 struct chanInfo
*cInfo
;
1710 struct userData
*uData
;
1711 unsigned short value
;
1713 cInfo
= get_chanInfo(channel
->name
);
1717 if(!ss_check_user_level(channel
, user
, cInfo
->exceptbadwordlevel
, 1, 1))
1719 reply("SSMSG_CANNOT_SET");
1722 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1723 if(!value
&& strcmp(argv
[1], "0"))
1725 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1728 uData
= GetChannelUser(cData
, user
->handle_info
);
1729 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1731 reply("SSMSG_BAD_SETLEVEL");
1734 cInfo
->exceptbadwordlevel
= value
;
1736 reply("SSMSG_SET_EXCEPTBADWORDLEVEL", cInfo
->exceptbadwordlevel
);
1741 channel_except_caps_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1743 struct chanData
*cData
= channel
->channel_info
;
1744 struct chanInfo
*cInfo
;
1745 struct userData
*uData
;
1746 unsigned short value
;
1748 cInfo
= get_chanInfo(channel
->name
);
1752 if(!ss_check_user_level(channel
, user
, cInfo
->exceptcapslevel
, 1, 1))
1754 reply("SSMSG_CANNOT_SET");
1757 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1758 if(!value
&& strcmp(argv
[1], "0"))
1760 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1763 uData
= GetChannelUser(cData
, user
->handle_info
);
1764 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1766 reply("SSMSG_BAD_SETLEVEL");
1769 cInfo
->exceptcapslevel
= value
;
1771 reply("SSMSG_SET_EXCEPTCAPSLEVEL", cInfo
->exceptcapslevel
);
1776 channel_except_flood_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1778 struct chanData
*cData
= channel
->channel_info
;
1779 struct chanInfo
*cInfo
;
1780 struct userData
*uData
;
1781 unsigned short value
;
1783 cInfo
= get_chanInfo(channel
->name
);
1787 if(!ss_check_user_level(channel
, user
, cInfo
->exceptfloodlevel
, 1, 1))
1789 reply("SSMSG_CANNOT_SET");
1792 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1793 if(!value
&& strcmp(argv
[1], "0"))
1795 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1798 uData
= GetChannelUser(cData
, user
->handle_info
);
1799 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1801 reply("SSMSG_BAD_SETLEVEL");
1804 cInfo
->exceptfloodlevel
= value
;
1806 reply("SSMSG_SET_EXCEPTFLOODLEVEL", cInfo
->exceptfloodlevel
);
1811 channel_except_spam_level(struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[], struct svccmd
*cmd
)
1813 struct chanData
*cData
= channel
->channel_info
;
1814 struct chanInfo
*cInfo
;
1815 struct userData
*uData
;
1816 unsigned short value
;
1818 cInfo
= get_chanInfo(channel
->name
);
1822 if(!ss_check_user_level(channel
, user
, cInfo
->exceptspamlevel
, 1, 1))
1824 reply("SSMSG_CANNOT_SET");
1827 value
= user_level_from_name(argv
[1], UL_OWNER
+1);
1828 if(!value
&& strcmp(argv
[1], "0"))
1830 reply("SSMSG_INVALID_ACCESS", argv
[1]);
1833 uData
= GetChannelUser(cData
, user
->handle_info
);
1834 if(!uData
|| ((uData
->access
< UL_OWNER
) && (value
> uData
->access
)))
1836 reply("SSMSG_BAD_SETLEVEL");
1839 cInfo
->exceptspamlevel
= value
;
1841 reply("SSMSG_SET_EXCEPTSPAMLEVEL", cInfo
->exceptspamlevel
);
1846 SPAMSERV_FUNC(opt_capsmin
)
1848 struct chanInfo
*cInfo
;
1850 cInfo
= get_chanInfo(channel
->name
);
1854 char *mask
= strdup(argv
[1]);
1855 unsigned int old
= cInfo
->capsmin
;
1857 if (isdigit(*mask
) && strspn(mask
, "1234567890,-") == strlen(mask
)) {
1858 cInfo
->capsmin
= mask
? strtoul(mask
, NULL
, 0) : 10;
1860 if (cInfo
->capsmin
< 0) {
1861 cInfo
->capsmin
= old
;
1862 reply("SSMSG_BAD_SETLEVEL");
1866 reply("SSMSG_BAD_SETLEVEL");
1870 reply("SSMSG_SET_CAPSMIN", cInfo
->capsmin
);
1875 SPAMSERV_FUNC(opt_capspercent
)
1877 struct chanInfo
*cInfo
;
1879 cInfo
= get_chanInfo(channel
->name
);
1883 char *mask
= strdup(argv
[1]);
1884 unsigned int old
= cInfo
->capspercent
;
1886 if (isdigit(*mask
) && strspn(mask
, "1234567890,-") == strlen(mask
)) {
1887 cInfo
->capspercent
= mask
? strtoul(mask
, NULL
, 0) : 10;
1889 if ((cInfo
->capspercent
< 0) || (cInfo
->capspercent
> 100)) {
1890 cInfo
->capspercent
= old
;
1891 reply("SSMSG_BAD_SETLEVEL");
1895 reply("SSMSG_BAD_SETLEVEL");
1899 reply("SSMSG_SET_CAPSPERCENT", cInfo
->capspercent
);
1904 SPAMSERV_FUNC(opt_exceptlevel
)
1906 return channel_except_level(SSFUNC_ARGS
);
1910 SPAMSERV_FUNC(opt_exceptadvlevel
)
1912 return channel_except_adv_level(SSFUNC_ARGS
);
1916 SPAMSERV_FUNC(opt_exceptbadwordlevel
)
1918 return channel_except_badword_level(SSFUNC_ARGS
);
1922 SPAMSERV_FUNC(opt_exceptcapslevel
)
1924 return channel_except_caps_level(SSFUNC_ARGS
);
1928 SPAMSERV_FUNC(opt_exceptfloodlevel
)
1930 return channel_except_flood_level(SSFUNC_ARGS
);
1934 SPAMSERV_FUNC(opt_exceptspamlevel
)
1936 return channel_except_spam_level(SSFUNC_ARGS
);
1940 SPAMSERV_FUNC(opt_spamlimit
)
1942 struct valueData values
[] =
1944 {"Users may send the same message $b2$b times.", 'a', 0},
1945 {"Users may send the same message $b3$b times.", 'b', 0},
1946 {"Users may send the same message $b4$b times.", 'c', 0},
1947 {"Users may send the same message $b5$b times.", 'd', 0},
1948 {"Users may send the same message $b6$b times.", 'e', 0}
1951 MULTIPLE_OPTION("SpamLimit ", "SpamLimit", ci_SpamLimit
);
1955 SPAMSERV_FUNC(opt_advreaction
)
1957 struct valueData values
[] =
1959 {"Kick on disallowed advertising.", 'k', 0},
1960 {"Kickban on disallowed advertising.", 'b', 0},
1961 {"Short timed ban on disallowed advertising.", 's', 0},
1962 {"Long timed ban on disallowed advertising.", 'l', 0},
1963 {"Kill on disallowed advertising.", 'd', 1}
1966 MULTIPLE_OPTION("AdvReaction ", "AdvReaction", ci_AdvReaction
);
1970 SPAMSERV_FUNC(opt_warnreaction
)
1972 struct valueData values
[] =
1974 {"Kick after warning.", 'k', 0},
1975 {"Kickban after warning.", 'b', 0},
1976 {"Short timed ban after warning.", 's', 0},
1977 {"Long timed ban after warning.", 'l', 0},
1978 {"Kill after warning.", 'd', 1}
1981 MULTIPLE_OPTION("WarnReaction ", "WarnReaction", ci_WarnReaction
);
1985 SPAMSERV_FUNC(opt_badreaction
)
1987 struct valueData values
[] =
1989 {"Kick on disallowed badwords.", 'k', 0},
1990 {"Kickban on disallowed badwords.", 'b', 0},
1991 {"Short timed ban on disallowed badwords.", 's', 0},
1992 {"Long timed ban on disallowed badwords.", 'l', 0},
1993 {"Kill on disallowed badwords.", 'd', 1}
1996 MULTIPLE_OPTION("BadReaction ", "BadReaction", ci_BadReaction
);
2000 SPAMSERV_FUNC(opt_capsreaction
)
2002 struct valueData values
[] =
2004 {"Kick on disallowed caps.", 'k', 0},
2005 {"Kickban on disallowed caps.", 'b', 0},
2006 {"Short timed ban on disallowed caps.", 's', 0},
2007 {"Long timed ban on disallowed caps.", 'l', 0},
2008 {"Kill on disallowed caps.", 'd', 1}
2011 MULTIPLE_OPTION("CapsReaction ", "CapsReaction", ci_CapsReaction
);
2015 SPAMSERV_FUNC(opt_advscan
)
2017 BINARY_OPTION("AdvScan ", CHAN_ADV_SCAN
);
2021 SPAMSERV_FUNC(opt_capsscan
)
2023 BINARY_OPTION("CapsScan ", CHAN_CAPSSCAN
);
2027 SPAMSERV_FUNC(opt_spamscan
)
2029 BINARY_OPTION("SpamScan ", CHAN_SPAMSCAN
);
2033 SPAMSERV_FUNC(opt_badwordscan
)
2035 BINARY_OPTION("BadWordScan ", CHAN_BADWORDSCAN
);
2039 SPAMSERV_FUNC(opt_chanfloodscan
)
2041 BINARY_OPTION("ChanFloodScan ", CHAN_CHANFLOODSCAN
);
2045 SPAMSERV_FUNC(opt_joinflood
)
2047 BINARY_OPTION("JoinFloodScan ", CHAN_JOINFLOOD
);
2051 spamserv_add_trusted_account(const char *account
, struct string_list
*channel
, const char *issuer
, time_t issued
)
2053 struct trusted_account
*ta
;
2054 ta
= calloc(1, sizeof(*ta
));
2057 ta
->account
= strdup(account
);
2058 ta
->channel
= channel
? string_list_copy(channel
) : alloc_string_list(1);
2059 ta
->issuer
= strdup(issuer
);
2060 ta
->issued
= issued
;
2061 dict_insert(spamserv_trusted_accounts
, strdup(ta
->account
), ta
);
2066 free_trusted_account(void *data)
2068 struct trusted_account *ta = data;
2070 free_string_list(ta->channel);
2076 static SPAMSERV_FUNC(cmd_addtrust
)
2079 struct userData
*uData
;
2080 struct chanData
*cData
;
2081 struct chanInfo
*cInfo
;
2082 struct trusted_account
*ta
;
2083 struct string_list
*templist
;
2084 struct handle_info
*hi
;
2086 if (!(channel
= GetChannel(argv
[2]))) {
2087 ss_reply("SSMSG_NOT_REGISTERED", argv
[2]);
2091 cInfo
= get_chanInfo(channel
->name
);
2092 cData
= channel
->channel_info
;
2093 uData
= GetChannelUser(cData
, user
->handle_info
);
2095 if (!cInfo
|| !channel
->channel_info
) {
2096 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
2100 if (CHECK_SUSPENDED(cInfo
)) {
2101 ss_reply("SSMSG_SUSPENDED", channel
->name
);
2105 if (!uData
|| (uData
->access
< UL_MANAGER
)) {
2106 ss_reply("SSMSG_NO_ACCESS");
2110 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
2114 if ((ta
= dict_find(spamserv_trusted_accounts
, argv
[1], NULL
))) {
2115 if (ta
->channel
->used
&& (argc
> 1)) {
2116 for (i
=0; i
< ta
->channel
->used
; i
++) {
2117 if (!strcmp(ta
->channel
->list
[i
], argv
[2])) {
2118 ss_reply("SSMSG_ALREADY_TRUSTED", hi
->handle
);
2124 string_list_append(ta
->channel
, argv
[2]);
2125 ss_reply("SSMSG_ADDED_TRUSTED_CHANNEL", hi
->handle
, argv
[2]);
2129 templist
= alloc_string_list(sizeof(argv
[2])+1);
2130 // templist = alloc_string_list(1);
2131 string_list_append(templist
, argv
[2]);
2133 spamserv_add_trusted_account(hi
->handle
, templist
, user
->handle_info
->handle
, now
);
2134 ss_reply("SSMSG_ADDED_TRUSTED_CHANNEL", hi
->handle
, argv
[2]);
2138 static SPAMSERV_FUNC(cmd_oaddtrust
)
2140 unsigned int i
, global
= 0;
2141 struct chanInfo
*cInfo
;
2142 struct chanData
*cData
;
2143 struct trusted_account
*ta
;
2144 struct string_list
*templist
;
2145 struct handle_info
*hi
;
2147 if (!strcmp(argv
[2], "global"))
2150 if (!(channel
= GetChannel(argv
[2])) && (global
== 0)) {
2151 ss_reply("SSMSG_NOT_REGISTERED", channel
? channel
->name
: (global
? "global" : ""));
2156 cInfo
= get_chanInfo(channel
->name
);
2157 cData
= channel
->channel_info
;
2159 if (!cInfo
|| !cData
) {
2160 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
2165 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
2169 if ((ta
= dict_find(spamserv_trusted_accounts
, argv
[1], NULL
))) {
2170 if (ta
->channel
->used
&& (argc
> 1)) {
2171 for (i
=0; i
< ta
->channel
->used
; i
++) {
2172 if (!strcmp(ta
->channel
->list
[i
], argv
[2])) {
2173 ss_reply("SSMSG_ALREADY_TRUSTED", argv
[1]);
2179 string_list_append(ta
->channel
, argv
[2]);
2182 ss_reply("SSMSG_ADDED_TRUSTED", argv
[1]);
2184 ss_reply("SSMSG_ADDED_TRUSTED_CHANNEL", argv
[1], argv
[2]);
2189 templist
= alloc_string_list(sizeof(argv
[2])+1);
2190 // templist = alloc_string_list(1);
2191 string_list_append(templist
, argv
[2]);
2193 spamserv_add_trusted_account(hi
->handle
, templist
, user
->handle_info
->handle
, now
);
2196 ss_reply("SSMSG_ADDED_TRUSTED", hi
->handle
);
2198 ss_reply("SSMSG_ADDED_TRUSTED_CHANNEL", hi
->handle
, argv
[2]);
2203 static SPAMSERV_FUNC(cmd_deltrust
)
2207 struct trusted_account
*ta
;
2208 struct userData
*uData
;
2209 struct chanData
*cData
;
2210 struct chanInfo
*cInfo
;
2211 struct handle_info
*hi
;
2213 if (!(channel
= GetChannel(argv
[2]))) {
2214 ss_reply("SSMSG_NOT_REGISTERED", argv
[2]);
2218 cInfo
= get_chanInfo(channel
->name
);
2219 cData
= channel
->channel_info
;
2220 uData
= GetChannelUser(cData
, user
->handle_info
);
2222 if (!cInfo
|| !channel
->channel_info
) {
2223 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
2227 if (CHECK_SUSPENDED(cInfo
)) {
2228 ss_reply("SSMSG_SUSPENDED", channel
->name
);
2232 if (!uData
|| (uData
->access
< UL_MANAGER
)) {
2233 ss_reply("SSMSG_NO_ACCESS");
2237 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
2241 ta
= dict_find(spamserv_trusted_accounts
, hi
->handle
, NULL
);
2244 ss_reply("SSMSG_NOT_TRUSTED", argv
[2]);
2249 if (ta
->channel
->used
) {
2250 for (i
=0; i
< ta
->channel
->used
; i
++) {
2251 if (!strcmp(ta
->channel
->list
[i
], argv
[2])) {
2252 string_list_delete(ta
->channel
, i
);
2259 ss_reply("SSMSG_REMOVED_TRUSTED_CHANNEL", hi
->handle
, argv
[2]);
2261 ss_reply("SSMSG_NOT_TRUSTED", hi
->handle
, argv
[2]);
2265 dict_remove(spamserv_trusted_accounts
, hi
->handle
);
2266 ss_reply("SSMSG_REMOVED_TRUSTED", hi
->handle
);
2272 static SPAMSERV_FUNC(cmd_odeltrust
)
2275 int rem
= 0, global
= 0;
2276 struct trusted_account
*ta
;
2277 struct chanInfo
*cInfo
;
2278 struct chanData
*cData
;
2279 struct handle_info
*hi
;
2281 if (!strcmp(argv
[2], "global"))
2284 if (!(channel
= GetChannel(argv
[2])) && (global
== 0)) {
2285 ss_reply("SSMSG_NOT_REGISTERED", channel
? channel
->name
: (global
? "global" : ""));
2290 cInfo
= get_chanInfo(channel
->name
);
2291 cData
= channel
->channel_info
;
2293 if (!cInfo
|| !cData
) {
2294 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
2299 if (!(hi
= modcmd_get_handle_info(user
, argv
[1]))) {
2303 ta
= dict_find(spamserv_trusted_accounts
, hi
->handle
, NULL
);
2306 ss_reply("SSMSG_NOT_TRUSTED", argv
[2]);
2311 if (ta
->channel
->used
) {
2312 for (i
=0; i
< ta
->channel
->used
; i
++) {
2313 if (!strcmp(ta
->channel
->list
[i
], argv
[2])) {
2314 string_list_delete(ta
->channel
, i
);
2321 ss_reply("SSMSG_REMOVED_TRUSTED_CHANNEL", hi
->handle
, argv
[2]);
2323 ss_reply("SSMSG_NOT_TRUSTED", argv
[2]);
2327 dict_remove(spamserv_trusted_accounts
, hi
->handle
);
2328 ss_reply("SSMSG_REMOVED_TRUSTED", hi
->handle
);
2334 static SPAMSERV_FUNC(cmd_listtrust
) {
2336 struct trusted_account
*ta
;
2337 char issued
[INTERVALLEN
];
2342 if (!strcmp(argv
[1], "global")) {
2343 if (!IsHelping(user
)) {
2344 reply("SSMSG_MUST_BE_HELPING");
2349 channel
= GetChannel(argv
[1]);
2351 chan
= strdup(channel
->name
);
2353 ss_reply("SSMSG_NOT_REGISTERED", argv
[1]);
2358 reply("MSG_INVALID_CHANNEL");
2362 reply("SSMSG_TRUSTED_LIST");
2363 reply("SSMSG_TRUSTED_LIST_BAR");
2364 reply("SSMSG_TRUSTED_LIST_HEADER");
2365 reply("SSMSG_TRUSTED_LIST_BAR");
2366 for (it
= dict_first(spamserv_trusted_accounts
); it
; it
= iter_next(it
)) {
2369 if (ta
->channel
->used
) {
2370 for (i
=0; i
< ta
->channel
->used
; i
++) {
2372 if (!strcmp(ta
->channel
->list
[i
], chan
)) {
2374 intervalString(issued
, now
- ta
->issued
, user
->handle_info
);
2376 ss_reply("SSMSG_HOST_IS_TRUSTED", iter_key(it
),
2377 (ta
->issuer
? ta
->issuer
: "<unknown>"),
2378 (ta
->issued
? issued
: "some time"));
2380 } else if (!strcmp(ta
->channel
->list
[i
], "global") && (!strcmp(chan
, "global"))) {
2382 intervalString(issued
, now
- ta
->issued
, user
->handle_info
);
2384 ss_reply("SSMSG_HOST_IS_TRUSTED", iter_key(it
),
2385 (ta
->issuer
? ta
->issuer
: "<unknown>"),
2386 (ta
->issued
? issued
: 0));
2391 ss_reply("SSMSG_TRUSTED_LIST_END");
2396 to_lower(char *message
)
2398 unsigned int i
, diff
= 'a' - 'A';
2400 for(i
= 0; i
< strlen(message
); i
++)
2402 if((message
[i
] >= 'A') && (message
[i
] <= 'Z'))
2403 message
[i
] = message
[i
] + diff
;
2408 strip_mirc_codes(char *text
)
2410 // taken from xchat and modified
2411 int nc
= 0, i
= 0, col
= 0, len
= strlen(text
);
2412 static char new_str
[MAXLEN
];
2416 if((col
&& isdigit(*text
) && nc
< 2) ||
2417 (col
&& *text
== ',' && isdigit(*(text
+ 1)) && nc
< 3))
2456 is_in_exception_list(struct chanInfo
*cInfo
, char *message
)
2460 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
2461 if(strstr(message
, cInfo
->exceptions
->list
[i
]))
2468 is_in_badword_list(struct chanInfo
*cInfo
, char *message
)
2472 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
2473 if(strstr(message
, cInfo
->badwords
->list
[i
]))
2480 check_caps(struct chanInfo
*cInfo
, char *message
)
2484 if ( (c
= strlen(message
)) >= cInfo
->capsmin
) {
2486 char *s
= strdup(message
);
2493 if (i
>= cInfo
->capsmin
&& i
* 100 / c
>= cInfo
->capspercent
)
2501 check_badwords(struct chanInfo
*cInfo
, char *message
)
2503 if(spamserv_conf
.strip_mirc_codes
)
2504 message
= strip_mirc_codes(message
);
2506 /* This needs improving */
2507 if(is_in_exception_list(cInfo
, message
))
2510 if(is_in_badword_list(cInfo
, message
))
2517 check_advertising(struct chanInfo
*cInfo
, char *message
)
2521 if(spamserv_conf
.strip_mirc_codes
)
2522 message
= strip_mirc_codes(message
);
2524 if(is_in_exception_list(cInfo
, message
))
2527 while(message
[i
] != 0)
2529 if(message
[i
] == '#')
2531 char channelname
[CHANNELLEN
];
2534 if(!spamserv_conf
.adv_chan_must_exist
)
2537 /* only return 1, if the channel does exist */
2539 while((message
[i
] != 0) && (message
[i
] != ' '))
2541 channelname
[j
] = message
[i
];
2546 channelname
[j
] = '\0';
2548 if(GetChannel(channelname
))
2551 else if((message
[i
] == 'w') && (message
[i
+1] == 'w') && (message
[i
+2] == 'w') && (message
[i
+3] == '.'))
2553 else if((message
[i
] == 'h') && (message
[i
+1] == 't') && (message
[i
+2] == 't') && (message
[i
+3] == 'p') && (message
[i
+4] == ':'))
2555 else if((message
[i
] == 'f') && (message
[i
+1] == 't') && (message
[i
+2] == 'p') && ((message
[i
+3] == '.') || (message
[i
+3] == ':')))
2565 spamserv_punish(struct chanNode
*channel
, struct userNode
*user
, time_t expires
, char *reason
, int ban
)
2569 struct mod_chanmode change
;
2570 char *hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
| GENMASK_ANY_IDENT
);
2572 sanitize_ircmask(hostmask
);
2575 add_channel_ban(channel
->channel_info
, hostmask
, spamserv
->nick
, now
, now
, now
+ expires
, reason
);
2577 mod_chanmode_init(&change
);
2579 change
.args
[0].mode
= MODE_BAN
;
2580 change
.args
[0].u
.hostmask
= hostmask
;
2581 mod_chanmode_announce(spamserv
, channel
, &change
);
2585 spamserv_debug(SSMSG_DEBUG_BAN
, user
->nick
, channel
->name
, reason
);
2588 spamserv_debug(SSMSG_DEBUG_KICK
, user
->nick
, channel
->name
, reason
);
2590 KickChannelUser(user
, channel
, spamserv
, reason
);
2594 spamserv_channel_message(struct chanNode
*channel
, struct userNode
*user
, char *text
)
2596 struct chanData
*cData
;
2597 struct chanInfo
*cInfo
;
2598 struct userInfo
*uInfo
;
2599 struct userData
*uData
;
2600 struct spamNode
*sNode
;
2601 struct floodNode
*fNode
;
2602 struct trusted_account
*ta
;
2603 unsigned int violation
= 0;
2604 char reason
[MAXLEN
];
2606 /* make sure: spamserv is not disabled; x3 is running; spamserv is in the chan; chan is regged, user does exist */
2607 if(!spamserv
|| quit_services
|| !GetUserMode(channel
, spamserv
) || IsOper(user
) || !(cInfo
= get_chanInfo(channel
->name
)) || !(uInfo
= get_userInfo(user
->nick
)))
2610 cData
= channel
->channel_info
;
2611 uData
= GetChannelUser(cData
, user
->handle_info
);
2613 if (user
->handle_info
) {
2614 ta
= dict_find(spamserv_trusted_accounts
, user
->handle_info
->handle
, NULL
);
2617 for (i
=0; i
< ta
->channel
->used
; i
++) {
2618 if (!strcmp(ta
->channel
->list
[i
], channel
->name
))
2621 if (!strcmp(ta
->channel
->list
[i
], "global"))
2628 if(uData
&& (uData
->access
>= cInfo
->exceptlevel
))
2631 if(CHECK_CAPSSCAN(cInfo
) && check_caps(cInfo
, text
))
2633 if(uData
&& (uData
->access
>= cInfo
->exceptcapslevel
))
2636 if(CHECK_CAPS_WARNED(uInfo
))
2638 switch(cInfo
->info
[ci_CapsReaction
])
2640 case 'k': uInfo
->flags
|= USER_KICK
; break;
2641 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2642 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2643 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2644 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2647 uInfo
->warnlevel
+= CAPS_WARNLEVEL
;
2652 uInfo
->flags
|= USER_CAPS_WARNED
;
2653 uInfo
->lastcaps
= now
;
2654 uInfo
->warnlevel
+= CAPS_WARNLEVEL
;
2656 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2657 if (spamserv_conf
.network_rules
)
2658 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_CAPS
, spamserv_conf
.network_rules
);
2660 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_CAPS
, spamserv_conf
.network_rules
);
2668 if(CHECK_SPAM(cInfo
))
2670 if(uData
&& (uData
->access
>= cInfo
->exceptspamlevel
))
2673 if(!(sNode
= uInfo
->spam
))
2675 spamserv_create_spamNode(channel
, uInfo
, text
);
2679 for(; sNode
; sNode
= sNode
->next
)
2680 if(sNode
->channel
== channel
)
2685 spamserv_create_spamNode(channel
, uInfo
, text
);
2689 unsigned long crc
= crc32(text
);
2691 if(crc
== sNode
->crc32
)
2693 unsigned int spamlimit
= 2;
2696 switch(cInfo
->info
[ci_SpamLimit
])
2698 case 'a': spamlimit
= 2; break;
2699 case 'b': spamlimit
= 3; break;
2700 case 'c': spamlimit
= 4; break;
2701 case 'd': spamlimit
= 5; break;
2702 case 'e': spamlimit
= 6; break;
2705 if(sNode
->count
== spamlimit
)
2707 uInfo
->warnlevel
+= SPAM_WARNLEVEL
;
2709 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2710 if (spamserv_conf
.network_rules
)
2711 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_SPAM
, spamserv_conf
.network_rules
);
2713 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_SPAM
, spamserv_conf
.network_rules
);
2716 else if(sNode
->count
> spamlimit
)
2718 switch(cInfo
->info
[ci_WarnReaction
])
2720 case 'k': uInfo
->flags
|= USER_KICK
; break;
2721 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2722 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2723 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2724 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2727 spamserv_delete_spamNode(uInfo
, sNode
);
2728 uInfo
->warnlevel
+= SPAM_WARNLEVEL
;
2741 if(CHECK_FLOOD(cInfo
))
2743 if(uData
&& (uData
->access
>= cInfo
->exceptfloodlevel
))
2746 if(!(fNode
= uInfo
->flood
))
2748 spamserv_create_floodNode(channel
, user
, &uInfo
->flood
);
2752 for(; fNode
; fNode
= fNode
->next
)
2753 if(fNode
->channel
== channel
)
2757 spamserv_create_floodNode(channel
, user
, &uInfo
->flood
);
2759 if(((now
- fNode
->time
) < FLOOD_EXPIRE
)) {
2762 if(fNode
->count
== FLOOD_MAX_LINES
- 1) {
2763 uInfo
->warnlevel
+= FLOOD_WARNLEVEL
;
2765 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2766 if (spamserv_conf
.network_rules
)
2767 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_FLOOD
, spamserv_conf
.network_rules
);
2769 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_FLOOD
, spamserv_conf
.network_rules
);
2773 else if(fNode
->count
> FLOOD_MAX_LINES
) {
2774 switch(cInfo
->info
[ci_WarnReaction
]) {
2775 case 'k': uInfo
->flags
|= USER_KICK
; break;
2776 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2777 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2778 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2779 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2782 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
2783 uInfo
->warnlevel
+= FLOOD_WARNLEVEL
;
2793 if(CHECK_BADWORDSCAN(cInfo
) && check_badwords(cInfo
, text
))
2795 if(uData
&& (uData
->access
>= cInfo
->exceptbadwordlevel
))
2798 if(CHECK_BAD_WARNED(uInfo
))
2800 switch(cInfo
->info
[ci_BadReaction
])
2802 case 'k': uInfo
->flags
|= USER_KICK
; break;
2803 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2804 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2805 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2806 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2809 uInfo
->warnlevel
+= BAD_WARNLEVEL
;
2814 uInfo
->flags
|= USER_BAD_WARNED
;
2815 uInfo
->lastbad
= now
;
2816 uInfo
->warnlevel
+= BAD_WARNLEVEL
;
2818 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2819 if (spamserv_conf
.network_rules
)
2820 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_BAD
, spamserv_conf
.network_rules
);
2822 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_BAD
, spamserv_conf
.network_rules
);
2827 if(CHECK_ADV(cInfo
) && check_advertising(cInfo
, text
))
2829 if(uData
&& (uData
->access
>= cInfo
->exceptspamlevel
))
2832 if(CHECK_ADV_WARNED(uInfo
))
2834 switch(cInfo
->info
[ci_AdvReaction
])
2836 case 'k': uInfo
->flags
|= USER_KICK
; break;
2837 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2838 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2839 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2840 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2843 uInfo
->warnlevel
+= ADV_WARNLEVEL
;
2848 uInfo
->flags
|= USER_ADV_WARNED
;
2849 uInfo
->lastadv
= now
;
2850 uInfo
->warnlevel
+= ADV_WARNLEVEL
;
2852 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2853 if (spamserv_conf
.network_rules
)
2854 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_ADV
, spamserv_conf
.network_rules
);
2856 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_ADV
, spamserv_conf
.network_rules
);
2861 if(!CHECK_WARNED(uInfo
) && !CHECK_KILL(uInfo
) && !CHECK_GLINE(uInfo
) && uInfo
->warnlevel
== MAX_WARNLEVEL
)
2863 uInfo
->flags
|= USER_WARNED
;
2864 if (spamserv_conf
.network_rules
)
2865 snprintf(reason
, sizeof(reason
), SSMSG_WARNING_RULES_2
, spamserv_conf
.network_rules
);
2867 snprintf(reason
, sizeof(reason
), SSMSG_WARNING_2
);
2868 irc_notice(spamserv
, user
->numeric
, reason
);
2869 irc_privmsg(spamserv
, user
->numeric
, reason
);
2871 else if(uInfo
->warnlevel
> MAX_WARNLEVEL
)
2873 if(CHECK_KILLED(uInfo
))
2874 uInfo
->flags
|= USER_GLINE
;
2876 uInfo
->flags
|= USER_KILL
;
2887 case 1: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_SPAM
, spamserv_conf
.network_rules
); break;
2888 case 2: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_FLOOD
, spamserv_conf
.network_rules
); break;
2889 case 3: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_ADV
, spamserv_conf
.network_rules
); break;
2890 case 4: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_BAD
, spamserv_conf
.network_rules
); break;
2891 case 5: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_CAPS
, spamserv_conf
.network_rules
); break;
2892 default: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES_2
: SSMSG_WARNING_2
, spamserv_conf
.network_rules
); break;
2895 if(CHECK_GLINE(uInfo
))
2897 int size
= strlen(user
->hostname
) + 3;
2898 char *mask
= alloca(size
);
2899 snprintf(mask
, size
, "*@%s", user
->hostname
);
2900 gline_add(spamserv
->nick
, mask
, spamserv_conf
.gline_duration
, reason
, now
, 1, 0);
2901 spamserv_debug(SSMSG_DEBUG_GLINE
, user
->nick
, user
->hostname
, channel
->name
);
2903 else if(CHECK_KILL(uInfo
))
2905 DelUser(user
, spamserv
, 1, reason
);
2906 spamserv_debug(SSMSG_DEBUG_KILL
, user
->nick
, channel
->name
);
2908 else if(CHECK_LONG_TBAN(uInfo
))
2910 spamserv_punish(channel
, user
, spamserv_conf
.long_ban_duration
, reason
, 1);
2912 else if(CHECK_SHORT_TBAN(uInfo
))
2914 spamserv_punish(channel
, user
, spamserv_conf
.short_ban_duration
, reason
, 1);
2916 else if(CHECK_KICKBAN(uInfo
))
2918 spamserv_punish(channel
, user
, 0, reason
, 1);
2920 else if(CHECK_KICK(uInfo
))
2922 spamserv_punish(channel
, user
, 0, reason
, 0);
2927 trusted_account_read(const char *account
, void *data
, UNUSED_ARG(void *extra
))
2929 struct record_data
*rd
= data
;
2930 const char *str
, *issuer
;
2931 struct string_list
*strlist
;
2934 if (rd
->type
== RECDB_OBJECT
) {
2935 dict_t obj
= GET_RECORD_OBJECT(rd
);
2936 /* new style structure */
2937 strlist
= database_get_data(obj
, KEY_CHANNELS
, RECDB_STRING_LIST
);
2938 issuer
= database_get_data(obj
, KEY_ISSUER
, RECDB_QSTRING
);
2939 str
= database_get_data(obj
, KEY_ISSUED
, RECDB_QSTRING
);
2940 issued
= str
? ParseInterval(str
) : 0;
2944 spamserv_add_trusted_account(account
, strlist
, issuer
, issued
);
2949 spamserv_saxdb_read(struct dict
*database
)
2952 struct record_data
*hir
;
2953 struct chanNode
*channel
;
2954 struct chanInfo
*cInfo
;
2955 struct string_list
*strlist
, *strlist2
;
2957 unsigned int exceptlevel
, exceptadvlevel
, exceptbadwordlevel
;
2958 unsigned int exceptfloodlevel
, exceptspamlevel
, exceptcapslevel
;
2959 unsigned int capsmin
, capspercent
;
2964 if ((object
= database_get_data(database
, KEY_TRUSTED_HOSTS
, RECDB_OBJECT
)))
2965 dict_foreach(object
, trusted_account_read
, spamserv_trusted_accounts
);
2967 for(it
= dict_first(database
); it
; it
= iter_next(it
))
2969 hir
= iter_data(it
);
2971 if(hir
->type
!= RECDB_OBJECT
)
2973 log_module(SS_LOG
, LOG_WARNING
, "Unexpected rectype %d for %s.", hir
->type
, iter_key(it
));
2977 channel
= GetChannel(iter_key(it
));
2978 if (!strcmp("trusted", iter_key(it
)))
2981 strlist
= database_get_data(hir
->d
.object
, KEY_EXCEPTIONS
, RECDB_STRING_LIST
);
2982 strlist2
= database_get_data(hir
->d
.object
, KEY_BADWORDS
, RECDB_STRING_LIST
);
2984 str
= database_get_data(hir
->d
.object
, KEY_FLAGS
, RECDB_QSTRING
);
2985 flags
= str
? atoi(str
) : 0;
2987 info
= database_get_data(hir
->d
.object
, KEY_INFO
, RECDB_QSTRING
);
2989 str
= database_get_data(hir
->d
.object
, KEY_EXPIRY
, RECDB_QSTRING
);
2990 expiry
= str
? strtoul(str
, NULL
, 0) : 0;
2992 str
= database_get_data(hir
->d
.object
, KEY_CAPSMIN
, RECDB_QSTRING
);
2993 capsmin
= str
? strtoul(str
, NULL
, 0) : 10;
2995 str
= database_get_data(hir
->d
.object
, KEY_CAPSPERCENT
, RECDB_QSTRING
);
2996 capspercent
= str
? strtoul(str
, NULL
, 0) : 25;
2998 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTLEVEL
, RECDB_QSTRING
);
2999 exceptlevel
= str
? strtoul(str
, NULL
, 0) : UL_MANAGER
;
3001 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTADVLEVEL
, RECDB_QSTRING
);
3002 exceptadvlevel
= str
? strtoul(str
, NULL
, 0) : UL_OP
;
3004 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTBADWORDLEVEL
, RECDB_QSTRING
);
3005 exceptbadwordlevel
= str
? strtoul(str
, NULL
, 0) : UL_OP
;
3007 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTCAPSLEVEL
, RECDB_QSTRING
);
3008 exceptcapslevel
= str
? strtoul(str
, NULL
, 0) : UL_OP
;
3010 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTFLOODLEVEL
, RECDB_QSTRING
);
3011 exceptfloodlevel
= str
? strtoul(str
, NULL
, 0) : UL_OP
;
3013 str
= database_get_data(hir
->d
.object
, KEY_EXCEPTSPAMLEVEL
, RECDB_QSTRING
);
3014 exceptspamlevel
= str
? strtoul(str
, NULL
, 0) : UL_OP
;
3018 if((cInfo
= spamserv_register_channel(channel
, strlist
, strlist2
, flags
, info
)))
3020 /* if the channel is suspended and expiry = 0 it means: channel will
3021 never expire ! it does NOT mean, the channel is not suspended */
3022 if(CHECK_SUSPENDED(cInfo
) && expiry
&& (expiry
< now
))
3024 cInfo
->flags
&= ~CHAN_SUSPENDED
;
3025 spamserv_join_channel(cInfo
->channel
);
3027 else if(!CHECK_SUSPENDED(cInfo
))
3028 spamserv_join_channel(cInfo
->channel
);
3030 cInfo
->suspend_expiry
= expiry
;
3032 cInfo
->capsmin
= capsmin
;
3033 cInfo
->capspercent
= capspercent
;
3034 cInfo
->exceptlevel
= exceptlevel
;
3035 cInfo
->exceptadvlevel
= exceptadvlevel
;
3036 cInfo
->exceptbadwordlevel
= exceptbadwordlevel
;
3037 cInfo
->exceptcapslevel
= exceptcapslevel
;
3038 cInfo
->exceptfloodlevel
= exceptfloodlevel
;
3039 cInfo
->exceptspamlevel
= exceptspamlevel
;
3043 log_module(SS_LOG
, LOG_ERROR
, "Couldn't register channel %s. Channel or info invalid.", iter_key(it
));
3050 spamserv_saxdb_write(struct saxdb_context
*ctx
)
3054 if (dict_size(spamserv_trusted_accounts
)) {
3055 saxdb_start_record(ctx
, KEY_TRUSTED_ACCOUNTS
, 1);
3056 for (it
= dict_first(spamserv_trusted_accounts
); it
; it
= iter_next(it
)) {
3057 struct trusted_account
*ta
= iter_data(it
);
3058 saxdb_start_record(ctx
, iter_key(it
), 0);
3059 if (ta
->channel
) saxdb_write_string_list(ctx
, KEY_CHANNELS
, ta
->channel
);
3060 if (ta
->issued
) saxdb_write_int(ctx
, KEY_ISSUED
, ta
->issued
);
3061 if (ta
->issuer
) saxdb_write_string(ctx
, KEY_ISSUER
, ta
->issuer
);
3062 saxdb_end_record(ctx
);
3064 saxdb_end_record(ctx
);
3067 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
3069 struct chanInfo
*cInfo
= iter_data(it
);
3071 saxdb_start_record(ctx
, cInfo
->channel
->name
, 1);
3073 if(cInfo
->exceptions
->used
)
3074 saxdb_write_string_list(ctx
, KEY_EXCEPTIONS
, cInfo
->exceptions
);
3076 if(cInfo
->badwords
->used
)
3077 saxdb_write_string_list(ctx
, KEY_BADWORDS
, cInfo
->badwords
);
3080 saxdb_write_int(ctx
, KEY_FLAGS
, cInfo
->flags
);
3083 saxdb_write_int(ctx
, KEY_CAPSMIN
, cInfo
->capsmin
);
3085 if(cInfo
->capspercent
)
3086 saxdb_write_int(ctx
, KEY_CAPSPERCENT
, cInfo
->capspercent
);
3088 if(cInfo
->exceptlevel
)
3089 saxdb_write_int(ctx
, KEY_EXCEPTLEVEL
, cInfo
->exceptlevel
);
3091 if(cInfo
->exceptadvlevel
)
3092 saxdb_write_int(ctx
, KEY_EXCEPTADVLEVEL
, cInfo
->exceptadvlevel
);
3094 if(cInfo
->exceptbadwordlevel
)
3095 saxdb_write_int(ctx
, KEY_EXCEPTBADWORDLEVEL
, cInfo
->exceptbadwordlevel
);
3097 if(cInfo
->exceptcapslevel
)
3098 saxdb_write_int(ctx
, KEY_EXCEPTCAPSLEVEL
, cInfo
->exceptcapslevel
);
3100 if(cInfo
->exceptfloodlevel
)
3101 saxdb_write_int(ctx
, KEY_EXCEPTFLOODLEVEL
, cInfo
->exceptfloodlevel
);
3103 if(cInfo
->exceptspamlevel
)
3104 saxdb_write_int(ctx
, KEY_EXCEPTSPAMLEVEL
, cInfo
->exceptspamlevel
);
3106 saxdb_write_string(ctx
, KEY_INFO
, cInfo
->info
);
3108 if(cInfo
->suspend_expiry
)
3109 saxdb_write_int(ctx
, KEY_EXPIRY
, cInfo
->suspend_expiry
);
3111 saxdb_end_record(ctx
);
3117 spamserv_conf_read(void)
3120 const char *str
, *modes
;
3122 if(!(conf_node
= conf_get_data(SPAMSERV_CONF_NAME
, RECDB_OBJECT
)))
3124 log_module(SS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", SPAMSERV_CONF_NAME
);
3128 str
= database_get_data(conf_node
, KEY_DEBUG_CHANNEL
, RECDB_QSTRING
);
3132 modes
= database_get_data(conf_node
, KEY_DEBUG_CHANNEL_MODES
, RECDB_QSTRING
);
3134 spamserv_conf
.debug_channel
= AddChannel(str
, now
, (modes
? modes
: "+tinms"), NULL
, NULL
);
3136 if(spamserv_conf
.debug_channel
)
3137 spamserv_join_channel(spamserv_conf
.debug_channel
);
3141 spamserv_conf
.debug_channel
= NULL
;
3144 spamserv_conf
.global_exceptions
= database_get_data(conf_node
, KEY_GLOBAL_EXCEPTIONS
, RECDB_STRING_LIST
);
3146 spamserv_conf
.global_badwords
= database_get_data(conf_node
, KEY_GLOBAL_BADWORDS
, RECDB_STRING_LIST
);
3148 str
= database_get_data(conf_node
, KEY_NETWORK_RULES
, RECDB_QSTRING
);
3149 spamserv_conf
.network_rules
= str
? str
: NULL
;
3151 str
= database_get_data(conf_node
, KEY_TRIGGER
, RECDB_QSTRING
);
3152 spamserv_conf
.trigger
= str
? str
[0] : 0;
3154 str
= database_get_data(conf_node
, KEY_SHORT_BAN_DURATION
, RECDB_QSTRING
);
3155 spamserv_conf
.short_ban_duration
= str
? ParseInterval(str
) : ParseInterval("15m");
3157 str
= database_get_data(conf_node
, KEY_LONG_BAN_DURATION
, RECDB_QSTRING
);
3158 spamserv_conf
.long_ban_duration
= str
? ParseInterval(str
) : ParseInterval("1h");
3160 str
= database_get_data(conf_node
, KEY_GLINE_DURATION
, RECDB_QSTRING
);
3161 spamserv_conf
.gline_duration
= str
? ParseInterval(str
) : ParseInterval("1h");
3163 str
= database_get_data(conf_node
, KEY_EXCEPTION_MAX
, RECDB_QSTRING
);
3164 spamserv_conf
.exception_max
= str
? strtoul(str
, NULL
, 0) : 10;
3166 str
= database_get_data(conf_node
, KEY_EXCEPTION_MIN_LEN
, RECDB_QSTRING
);
3167 spamserv_conf
.exception_min_len
= str
? strtoul(str
, NULL
, 0) : 4;
3169 str
= database_get_data(conf_node
, KEY_EXCEPTION_MAX_LEN
, RECDB_QSTRING
);
3170 spamserv_conf
.exception_max_len
= str
? strtoul(str
, NULL
, 0) : 15;
3172 str
= database_get_data(conf_node
, KEY_BADWORD_MAX
, RECDB_QSTRING
);
3173 spamserv_conf
.badword_max
= str
? strtoul(str
, NULL
, 0) : 10;
3175 str
= database_get_data(conf_node
, KEY_BADWORD_MIN_LEN
, RECDB_QSTRING
);
3176 spamserv_conf
.badword_min_len
= str
? strtoul(str
, NULL
, 0) : 4;
3178 str
= database_get_data(conf_node
, KEY_BADWORD_MAX_LEN
, RECDB_QSTRING
);
3179 spamserv_conf
.badword_max_len
= str
? strtoul(str
, NULL
, 0) : 15;
3181 str
= database_get_data(conf_node
, KEY_ADV_CHAN_MUST_EXIST
, RECDB_QSTRING
);
3182 spamserv_conf
.adv_chan_must_exist
= str
? enabled_string(str
) : 1;
3184 str
= database_get_data(conf_node
, KEY_STRIP_MIRC_CODES
, RECDB_QSTRING
);
3185 spamserv_conf
.strip_mirc_codes
= str
? enabled_string(str
) : 0;
3187 str
= database_get_data(conf_node
, KEY_ALLOW_MOVE_MERGE
, RECDB_QSTRING
);
3188 spamserv_conf
.allow_move_merge
= str
? enabled_string(str
) : 0;
3192 spamserv_db_cleanup(UNUSED_ARG(void* extra
))
3196 while((it
= dict_first(registered_channels_dict
)))
3198 spamserv_unregister_channel(iter_data(it
));
3201 /* now handled automatically
3202 * while((it = dict_first(killed_users_dict)))
3204 free(iter_data(it));
3208 dict_delete(registered_channels_dict
);
3209 dict_delete(connected_users_dict
);
3210 dict_delete(killed_users_dict
);
3211 dict_delete(spamserv_trusted_accounts
);
3215 init_spamserv(const char *nick
)
3217 struct chanNode
*chan
;
3223 const char *modes
= conf_get_data("services/spamserv/modes", RECDB_QSTRING
);
3224 spamserv
= AddLocalUser(nick
, nick
, NULL
, "Anti Spam Services", modes
);
3225 spamserv_service
= service_register(spamserv
);
3227 conf_register_reload(spamserv_conf_read
);
3229 SS_LOG
= log_register_type("SpamServ", "file:spamserv.log");
3231 /* auto-free the keys for these dicts,
3232 * and auto-free the keys AND data for killed_users_dict.
3233 * other data need free'd manually. */
3234 registered_channels_dict
= dict_new();
3235 dict_set_free_keys(registered_channels_dict
, free
);
3236 connected_users_dict
= dict_new();
3237 dict_set_free_keys(connected_users_dict
, free
);
3238 killed_users_dict
= dict_new();
3239 dict_set_free_keys(killed_users_dict
, free
);
3240 dict_set_free_data(killed_users_dict
, free
);
3241 spamserv_trusted_accounts
= dict_new();
3242 dict_set_free_keys(spamserv_trusted_accounts
, free
);
3243 dict_set_free_data(spamserv_trusted_accounts
, free
);
3245 saxdb_register("SpamServ", spamserv_saxdb_read
, spamserv_saxdb_write
);
3247 reg_new_user_func(spamserv_new_user_func
, NULL
);
3248 reg_del_user_func(spamserv_del_user_func
, NULL
);
3249 reg_nick_change_func(spamserv_nick_change_func
, NULL
);
3250 reg_join_func(spamserv_user_join
, NULL
);
3251 reg_part_func(spamserv_user_part
, NULL
);
3253 timeq_add(now
+ FLOOD_TIMEQ_FREQ
, timeq_flood
, NULL
);
3254 timeq_add(now
+ JOINFLOOD_TIMEQ_FREQ
, timeq_joinflood
, NULL
);
3255 timeq_add(now
+ ADV_TIMEQ_FREQ
, timeq_adv
, NULL
);
3256 timeq_add(now
+ BAD_TIMEQ_FREQ
, timeq_bad
, NULL
);
3257 timeq_add(now
+ CAPS_TIMEQ_FREQ
, timeq_caps
, NULL
);
3258 timeq_add(now
+ WARNLEVEL_TIMEQ_FREQ
, timeq_warnlevel
, NULL
);
3259 timeq_add(now
+ KILL_TIMEQ_FREQ
, timeq_kill
, NULL
);
3261 spamserv_module
= module_register("SpamServ", SS_LOG
, "spamserv.help", NULL
);
3263 modcmd_register(spamserv_module
, "ADDTRUST", cmd_addtrust
, 3, MODCMD_REQUIRE_AUTHED
, "flags", "+acceptchan", NULL
);
3264 modcmd_register(spamserv_module
, "DELTRUST", cmd_deltrust
, 3, MODCMD_REQUIRE_AUTHED
, "flags", "+acceptchan", NULL
);
3265 modcmd_register(spamserv_module
, "OADDTRUST", cmd_oaddtrust
, 3, MODCMD_REQUIRE_AUTHED
, "flags", "+acceptchan,+helping", NULL
);
3266 modcmd_register(spamserv_module
, "ODELTRUST", cmd_odeltrust
, 3, MODCMD_REQUIRE_AUTHED
, "flags", "+acceptchan,+helping", NULL
);
3267 modcmd_register(spamserv_module
, "LISTTRUST", cmd_listtrust
, 2, MODCMD_REQUIRE_AUTHED
, NULL
);
3268 modcmd_register(spamserv_module
, "REGISTER", cmd_register
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, "flags", "+acceptchan,+helping", NULL
);
3269 modcmd_register(spamserv_module
, "UNREGISTER", cmd_unregister
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, "flags", "+loghostmask", NULL
);
3270 modcmd_register(spamserv_module
, "ADDEXCEPTION", cmd_addexception
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3271 modcmd_register(spamserv_module
, "DELEXCEPTION", cmd_delexception
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3272 modcmd_register(spamserv_module
, "ADDBADWORD", cmd_addbadword
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3273 modcmd_register(spamserv_module
, "DELBADWORD", cmd_delbadword
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3274 modcmd_register(spamserv_module
, "STATUS", cmd_status
, 1, 0, NULL
);
3275 modcmd_register(spamserv_module
, "SET", cmd_set
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3276 modcmd_register(spamserv_module
, "SET EXCEPTLEVEL", opt_exceptlevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3277 modcmd_register(spamserv_module
, "SET EXCEPTADVLEVEL", opt_exceptadvlevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3278 modcmd_register(spamserv_module
, "SET EXCEPTBADWORDLEVEL", opt_exceptbadwordlevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3279 modcmd_register(spamserv_module
, "SET EXCEPTCAPSLEVEL", opt_exceptcapslevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3280 modcmd_register(spamserv_module
, "SET EXCEPTFLOODLEVEL", opt_exceptfloodlevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3281 modcmd_register(spamserv_module
, "SET EXCEPTSPAMLEVEL", opt_exceptspamlevel
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3282 modcmd_register(spamserv_module
, "SET SPAMLIMIT", opt_spamlimit
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3283 modcmd_register(spamserv_module
, "SET BADREACTION", opt_badreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3284 modcmd_register(spamserv_module
, "SET CAPSREACTION", opt_capsreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3285 modcmd_register(spamserv_module
, "SET ADVREACTION", opt_advreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3286 modcmd_register(spamserv_module
, "SET WARNREACTION", opt_warnreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3287 modcmd_register(spamserv_module
, "SET ADVSCAN", opt_advscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3288 modcmd_register(spamserv_module
, "SET CAPSSCAN", opt_capsscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3289 modcmd_register(spamserv_module
, "SET BADWORDSCAN", opt_badwordscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3290 modcmd_register(spamserv_module
, "SET SPAMSCAN", opt_spamscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3291 modcmd_register(spamserv_module
, "SET CHANFLOODSCAN", opt_chanfloodscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3292 modcmd_register(spamserv_module
, "SET JOINFLOODSCAN", opt_joinflood
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3293 modcmd_register(spamserv_module
, "SET CAPSMIN", opt_capsmin
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3294 modcmd_register(spamserv_module
, "SET CAPSPERCENT", opt_capspercent
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
3296 spamserv_service
->trigger
= spamserv_conf
.trigger
;
3299 if (autojoin_channels
&& spamserv
) {
3300 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
3301 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
3302 AddChannelUser(spamserv
, chan
)->modes
|= MODE_CHANOP
;
3306 reg_exit_func(spamserv_db_cleanup
, NULL
);
3307 message_register_table(msgtab
);