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 2 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.
31 #define SPAMSERV_CONF_NAME "services/spamserv"
33 #define KEY_EXCEPTIONS "exceptions"
34 #define KEY_BADWORDS "badwords"
35 #define KEY_FLAGS "flags"
36 #define KEY_INFO "info"
37 #define KEY_EXPIRY "expiry"
39 #define KEY_DEBUG_CHANNEL "debug_channel"
40 #define KEY_GLOBAL_EXCEPTIONS "global_exceptions"
41 #define KEY_GLOBAL_BADWORDS "global_badwords"
42 #define KEY_NETWORK_RULES "network_rules"
43 #define KEY_TRIGGER "trigger"
44 #define KEY_SHORT_BAN_DURATION "short_ban_duration"
45 #define KEY_LONG_BAN_DURATION "long_ban_duration"
46 #define KEY_GLINE_DURATION "gline_duration"
47 #define KEY_EXCEPTION_MAX "exception_max"
48 #define KEY_EXCEPTION_MIN_LEN "exception_min_len"
49 #define KEY_EXCEPTION_MAX_LEN "exception_max_len"
50 #define KEY_BADWORD_MAX "badword_max"
51 #define KEY_BADWORD_MIN_LEN "badword_min_len"
52 #define KEY_BADWORD_MAX_LEN "badword_max_len"
53 #define KEY_ADV_CHAN_MUST_EXIST "adv_chan_must_exist"
54 #define KEY_STRIP_MIRC_CODES "strip_mirc_codes"
55 #define KEY_ALLOW_MOVE_MERGE "allow_move_merge"
57 #define SPAMSERV_FUNC(NAME) MODCMD_FUNC(NAME)
58 #define SPAMSERV_SYNTAX() svccmd_send_help(user, spamserv, cmd)
59 #define SPAMSERV_MIN_PARMS(N) do { \
62 ss_reply(MSG_MISSING_PARAMS, argv[0]); \
64 return 0; } } while(0)
66 struct userNode
*spamserv
;
67 static struct module *spamserv_module
;
68 static struct service
*spamserv_service
;
69 static struct log_type
*SS_LOG
;
70 static unsigned long crc_table
[256];
72 dict_t registered_channels_dict
;
73 dict_t connected_users_dict
;
74 dict_t killed_users_dict
;
76 #define spamserv_notice(target, format...) send_message(target , spamserv , ## format)
77 #define spamserv_debug(format...) do { if(spamserv_conf.debug_channel) send_channel_notice(spamserv_conf.debug_channel , spamserv , ## format); } while(0)
78 #define ss_reply(format...) send_message(user , spamserv , ## format)
80 #define SET_SUBCMDS_SIZE 13
82 const char *set_subcommands
[SET_SUBCMDS_SIZE
] = {"SPAMLIMIT", "BADREACTION", "ADVREACTION", "WARNREACTION", "ADVSCAN", "SPAMSCAN", "BADWORDSCAN", "CHANFLOODSCAN", "JOINFLOODSCAN", "SCANCHANOPS", "SCANHALFOPS", "SCANVOICED"};
84 extern struct string_list
*autojoin_channels
;
85 static void spamserv_clear_spamNodes(struct chanNode
*channel
);
86 static void spamserv_punish(struct chanNode
*channel
, struct userNode
*user
, time_t expires
, char *reason
, int ban
);
87 static unsigned long crc32(const char *text
);
89 #define BINARY_OPTION(arguments...) return binary_option(arguments, user, channel, argc, argv);
90 #define MULTIPLE_OPTION(arguments...) return multiple_option(arguments, values, ArrayLength(values), user, channel, argc, argv);
92 static const struct message_entry msgtab
[] = {
93 { "SSMSG_CHANNEL_OPTIONS", "Channel Options:" },
94 { "SSMSG_STRING_VALUE", "$b%s$b%s" },
95 { "SSMSG_NUMERIC_VALUE", "$b%s$b%d - %s" },
96 { "SSMSG_INVALID_NUM_SET", "$b'%d'$b is an invalid %s setting." },
97 { "SSMSG_INVALID_OPTION", "$b%s$b is not a valid %s option." },
98 { "SSMSG_INVALID_BINARY", "$b%s$b is an invalid binary value." },
100 { "SSMSG_NOT_REGISTERED", "$b%s$b has not been registered with $b$X$b." },
101 { "SSMSG_NOT_REGISTERED_CS", "$b%s$b has not been registered with $b$C$b." },
102 { "SSMSG_ALREADY_REGISTERED", "$b%s$b is already registered." },
103 { "SSMSG_DEBUG_CHAN", "You may not register the debug channel." },
104 { "SSMSG_SUSPENDED_CS", "$b$C$b access to $b%s$b has been temporarily suspended, thus you can't %s it." },
105 { "SSMSG_SUSPENDED", "$b$X$b access to $b%s$b has been temporarily suspended." },
106 { "SSMSG_NO_REGISTER", "Due to an error it was not possible to register $b%s$b." },
107 { "SSMSG_REG_SUCCESS", "Channel $b%s$b registered." },
108 { "SSMSG_UNREG_SUCCESS", "$b%s$b has been unregistered." },
109 { "SSMSG_NO_ACCESS", "You lack sufficient access to use this command." },
110 { "SSMSG_MUST_BE_OPER", "You must be an irc operator to set this option." },
111 { "SSMSG_CONFIRM_UNREG", "To confirm this unregistration, you must append 'CONFIRM' to the end of your command. For example, 'unregister CONFIRM'." },
113 { "SSMSG_NO_EXCEPTIONS", "No words found in the exception list." },
114 { "SSMSG_NO_SUCH_EXCEPTION", "Word $b%s$b not found in the exception list." },
115 { "SSMSG_EXCEPTION_LIST", "The following words are in the exception list:" },
116 { "SSMSG_EXCEPTION_ADDED", "Word $b%s$b added to the exception list." },
117 { "SSMSG_EXCEPTION_DELETED", "Word $b%s$b deleted from the exception list." },
118 { "SSMSG_EXCEPTION_IN_LIST", "The word $b%s$b is already in the exception list." },
119 { "SSMSG_EXCEPTION_MAX", "The exception list has reached the maximum exceptions (max %lu). Delete a word to add another one." },
120 { "SSMSG_EXCEPTION_TOO_SHORT", "The word must be at least %lu characters long." },
121 { "SSMSG_EXCEPTION_TOO_LONG", "The word may not be longer than %lu characters." },
123 { "SSMSG_NO_BADWORDS", "No words found in the badword list." },
124 { "SSMSG_NO_SUCH_BADWORD", "Word $b%s$b not found in the badword list." },
125 { "SSMSG_BADWORD_LIST", "The following words are in the badword list:" },
126 { "SSMSG_BADWORD_ADDED", "Word $b%s$b added to the badword list." },
127 { "SSMSG_BADWORD_DELETED", "Word $b%s$b deleted from the badword list." },
128 { "SSMSG_BADWORD_IN_LIST", "The word $b%s$b is already in the badword list." },
129 { "SSMSG_BADWORD_MAX", "The badword list has reached the maximum badwords (max %lu). Delete a word to add another one." },
130 { "SSMSG_BADWORD_TOO_SHORT", "The word must be at least %lu characters long." },
131 { "SSMSG_BADWORD_TOO_LONG", "The word may not be longer than %lu characters." },
133 { "SSMSG_STATUS", "$bStatus:$b" },
134 { "SSMSG_STATUS_USERS", "Total Users Online: %u" },
135 { "SSMSG_STATUS_CHANNELS", "Registered Channels: %u" },
136 { "SSMSG_STATUS_MEMORY", "$bMemory Information:$b" },
137 { "SSMSG_STATUS_CHANNEL_LIST", "$bRegistered Channels:$b" },
138 { "SSMSG_STATUS_NO_CHANNEL", "No channels registered." },
140 { "SSMSG_WARNING_T", "%s is against the network rules" },
141 { "SSMSG_WARNING_2_T", "You are violating the network rules" },
142 { "SSMSG_WARNING_RULES_T", "%s is against the network rules. Read the network rules at %s" },
143 { "SSMSG_WARNING_RULES_2_T", "You are violating the network rules. Read the network rules at %s" },
148 #define SSMSG_DEBUG_KICK "Kicked user $b%s$b from $b%s$b, reason: %s"
149 #define SSMSG_DEBUG_BAN "Banned user $b%s$b from $b%s$b, reason: %s"
150 #define SSMSG_DEBUG_KILL "Killed user $b%s$b, last violation in $b%s$b"
151 #define SSMSG_DEBUG_GLINE "Glined user $b%s$b, host $b%s$b, last violation in $b%s$b"
152 #define SSMSG_DEBUG_RECONNECT "Killed user $b%s$b reconnected to the network"
154 #define SSMSG_SPAM "Spamming"
155 #define SSMSG_FLOOD "Flooding the channel/network"
156 #define SSMSG_ADV "Advertising"
157 #define SSMSG_BAD "Badwords"
158 #define SSMSG_JOINFLOOD "Join flooding the channel"
160 #define SSMSG_WARNING "%s is against the network rules"
161 #define SSMSG_WARNING_2 "You are violating the network rules"
162 #define SSMSG_WARNING_RULES "%s is against the network rules. Read the network rules at %s"
163 #define SSMSG_WARNING_RULES_2 "You are violating the network rules. Read the network rules at %s"
166 #define SSMSG_WARNING "SSMSG_WARNING_T"
167 #define SSMSG_WARNING_2 "SSMSG_WARNING_2_T"
168 #define SSMSG_WARNING_RULES "SSMSG_WARNING_RULES_T"
169 #define SSMSG_WARNING_RULES_2 "SSMSG_WARNING_RULES_2_T"
174 struct chanNode
*debug_channel
;
175 struct string_list
*global_exceptions
;
176 struct string_list
*global_badwords
;
177 const char *network_rules
;
178 unsigned char trigger
;
179 unsigned long short_ban_duration
;
180 unsigned long long_ban_duration
;
181 unsigned long gline_duration
;
182 unsigned long exception_max
;
183 unsigned long exception_min_len
;
184 unsigned long exception_max_len
;
185 unsigned long badword_max
;
186 unsigned long badword_min_len
;
187 unsigned long badword_max_len
;
188 unsigned int adv_chan_must_exist
: 1;
189 unsigned int strip_mirc_codes
: 1;
190 unsigned int allow_move_merge
: 1;
193 /***********************************************/
195 /***********************************************/
198 get_chanInfo(const char *channelname
)
200 return dict_find(registered_channels_dict
, channelname
, 0);
204 spamserv_join_channel(struct chanNode
*channel
)
206 struct mod_chanmode change
;
207 mod_chanmode_init(&change
);
209 change
.args
[0].mode
= MODE_CHANOP
;
210 change
.args
[0].u
.member
= AddChannelUser(spamserv
, channel
);
211 mod_chanmode_announce(spamserv
, channel
, &change
);
215 spamserv_part_channel(struct chanNode
*channel
, char *reason
)
217 /* we only have to clear the spamNodes because every other node expires on it's own */
218 spamserv_clear_spamNodes(channel
);
219 DelChannelUser(spamserv
, channel
, reason
, 0);
222 static struct chanInfo
*
223 spamserv_register_channel(struct chanNode
*channel
, struct string_list
*exceptions
, struct string_list
*badwords
, unsigned int flags
, char *info
)
225 struct chanInfo
*cInfo
= malloc(sizeof(struct chanInfo
));
229 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for cInfo; channel: %s", channel
->name
);
233 cInfo
->channel
= channel
;
234 cInfo
->exceptions
= exceptions
? string_list_copy(exceptions
) : alloc_string_list(1);
235 cInfo
->badwords
= badwords
? string_list_copy(badwords
) : alloc_string_list(1);
236 cInfo
->flags
= flags
;
237 safestrncpy(cInfo
->info
, info
, sizeof(cInfo
->info
));
238 cInfo
->suspend_expiry
= 0;
239 dict_insert(registered_channels_dict
, cInfo
->channel
->name
, cInfo
);
245 spamserv_unregister_channel(struct chanInfo
*cInfo
)
250 dict_remove(registered_channels_dict
, cInfo
->channel
->name
);
251 free_string_list(cInfo
->exceptions
);
252 free_string_list(cInfo
->badwords
);
257 spamserv_cs_suspend(struct chanNode
*channel
, time_t expiry
, int suspend
, char *reason
)
259 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
265 cInfo
->flags
|= CHAN_SUSPENDED
;
266 cInfo
->suspend_expiry
= expiry
;
267 spamserv_part_channel(channel
, reason
);
271 if(CHECK_SUSPENDED(cInfo
))
273 cInfo
->flags
&= ~CHAN_SUSPENDED
;
274 cInfo
->suspend_expiry
= 0;
281 spamserv_cs_move_merge(struct userNode
*user
, struct chanNode
*channel
, struct chanNode
*target
, int move
)
283 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
289 if(!spamserv_conf
.allow_move_merge
|| get_chanInfo(target
->name
))
292 snprintf(reason
, sizeof(reason
), "unregistered due to a channel move to %s", target
->name
);
294 snprintf(reason
, sizeof(reason
), "unregistered due to a channel merge into %s", target
->name
);
296 spamserv_cs_unregister(user
, channel
, manually
, reason
);
300 cInfo
->channel
= target
;
302 dict_remove(registered_channels_dict
, channel
->name
);
303 dict_insert(registered_channels_dict
, target
->name
, cInfo
);
307 snprintf(reason
, sizeof(reason
), "Channel moved to %s by %s.", target
->name
, user
->handle_info
->handle
);
311 spamserv_join_channel(target
);
312 snprintf(reason
, sizeof(reason
), "%s merged into %s by %s.", channel
->name
, target
->name
, user
->handle_info
->handle
);
315 if(!CHECK_SUSPENDED(cInfo
))
316 spamserv_part_channel(channel
, reason
);
319 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
,
320 "SSMSG_CHANNEL_MOVED", channel
->name
, target
->name
,
321 user
->handle_info
->handle
);
323 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
,
324 "SSMSG_CHANNEL_MERGED", channel
->name
, target
->name
,
325 user
->handle_info
->handle
);
334 spamserv_cs_unregister(struct userNode
*user
, struct chanNode
*channel
, enum cs_unreg type
, char *reason
)
336 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
340 char partmsg
[MAXLEN
];
345 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_UNREG_MANUAL",
346 channel
->name
, reason
, user
->handle_info
->handle
);
347 snprintf(partmsg
, sizeof(partmsg
), "%s %s by %s.", channel
->name
, reason
, user
->handle_info
->handle
);
350 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_REG_EXPIRED",
352 snprintf(partmsg
, sizeof(partmsg
), "%s registration expired.", channel
->name
);
355 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_LOST_ALL_USERS",
357 snprintf(partmsg
, sizeof(partmsg
), "%s lost all users.", channel
->name
);
361 if(!CHECK_SUSPENDED(cInfo
))
362 spamserv_part_channel(channel
, partmsg
);
364 spamserv_unregister_channel(cInfo
);
368 /***********************************************/
370 /***********************************************/
372 static struct userInfo
*
373 get_userInfo(const char *nickname
)
375 return dict_find(connected_users_dict
, nickname
, 0);
379 spamserv_create_spamNode(struct chanNode
*channel
, struct userInfo
*uInfo
, char *text
)
381 struct spamNode
*sNode
= malloc(sizeof(struct spamNode
));
385 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for sNode; channel: %s; user: %s", channel
->name
, uInfo
->user
->nick
);
389 sNode
->channel
= channel
;
390 sNode
->crc32
= crc32(text
);
396 struct spamNode
*temp
= uInfo
->spam
;
412 spamserv_delete_spamNode(struct userInfo
*uInfo
, struct spamNode
*sNode
)
417 if(sNode
== uInfo
->spam
)
418 uInfo
->spam
= sNode
->next
;
421 sNode
->next
->prev
= sNode
->prev
;
423 sNode
->prev
->next
= sNode
->next
;
429 spamserv_clear_spamNodes(struct chanNode
*channel
)
431 struct userInfo
*uInfo
;
432 struct spamNode
*sNode
;
435 for(i
= 0; i
< channel
->members
.used
; i
++)
437 if((uInfo
= get_userInfo(channel
->members
.list
[i
]->user
->nick
)))
439 if((sNode
= uInfo
->spam
))
441 for(; sNode
; sNode
= sNode
->next
)
442 if(sNode
->channel
== channel
)
446 spamserv_delete_spamNode(uInfo
, sNode
);
453 spamserv_create_floodNode(struct chanNode
*channel
, struct userNode
*user
, struct floodNode
**uI_fNode
)
455 struct floodNode
*fNode
= malloc(sizeof(struct floodNode
));
459 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for fNode; channel: %s; user: %s", channel
->name
, user
->nick
);
463 fNode
->channel
= channel
;
471 struct floodNode
*temp
= *uI_fNode
;
487 spamserv_delete_floodNode(struct floodNode
**uI_fNode
, struct floodNode
*fNode
)
492 if(fNode
== *uI_fNode
)
493 *uI_fNode
= fNode
->next
;
496 fNode
->next
->prev
= fNode
->prev
;
498 fNode
->prev
->next
= fNode
->next
;
504 spamserv_create_user(struct userNode
*user
)
506 struct userInfo
*uInfo
= malloc(sizeof(struct userInfo
));
507 struct killNode
*kNode
= dict_find(killed_users_dict
, irc_ntoa(&user
->ip
), 0);
511 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for uInfo; nick: %s", user
->nick
);
516 spamserv_debug(SSMSG_DEBUG_RECONNECT
, user
->nick
);
521 uInfo
->joinflood
= NULL
;
522 uInfo
->flags
= kNode
? USER_KILLED
: 0;
523 uInfo
->warnlevel
= kNode
? kNode
->warnlevel
: 0;
527 dict_insert(connected_users_dict
, user
->nick
, uInfo
);
531 dict_remove(killed_users_dict
, irc_ntoa(&user
->ip
));
537 spamserv_delete_user(struct userInfo
*uInfo
)
544 spamserv_delete_spamNode(uInfo
, uInfo
->spam
);
548 spamserv_delete_floodNode(&uInfo
->flood
, uInfo
->flood
);
551 while(uInfo
->joinflood
)
552 spamserv_delete_floodNode(&uInfo
->joinflood
, uInfo
->joinflood
);
554 dict_remove(connected_users_dict
, uInfo
->user
->nick
);
559 spamserv_new_user_func(struct userNode
*user
)
562 spamserv_create_user(user
);
568 spamserv_del_user_func(struct userNode
*user
, struct userNode
*killer
, UNUSED_ARG(const char *why
))
570 struct userInfo
*uInfo
= get_userInfo(user
->nick
);
571 struct killNode
*kNode
;
573 if(killer
== spamserv
)
575 kNode
= malloc(sizeof(struct killNode
));
579 log_module(SS_LOG
, LOG_ERROR
, "Couldn't allocate memory for killNode - nickname %s", user
->nick
);
580 spamserv_delete_user(uInfo
);
584 if(uInfo
->warnlevel
> KILL_WARNLEVEL
)
585 kNode
->warnlevel
= uInfo
->warnlevel
- KILL_WARNLEVEL
;
587 kNode
->warnlevel
= 0;
591 dict_insert(killed_users_dict
, irc_ntoa(&user
->ip
), kNode
);
594 spamserv_delete_user(uInfo
);
598 spamserv_nick_change_func(struct userNode
*user
, const char *old_nick
)
600 struct userInfo
*uInfo
= get_userInfo(old_nick
);
602 dict_remove(connected_users_dict
, old_nick
);
603 dict_insert(connected_users_dict
, user
->nick
, uInfo
);
607 spamserv_user_join(struct modeNode
*mNode
)
609 struct chanNode
*channel
= mNode
->channel
;
610 struct userNode
*user
= mNode
->user
;
611 struct chanInfo
*cInfo
;
612 struct userInfo
*uInfo
;
613 struct floodNode
*jfNode
;
615 if(user
->uplink
->burst
|| !(cInfo
= get_chanInfo(channel
->name
)) || !CHECK_JOINFLOOD(cInfo
) || !(uInfo
= get_userInfo(user
->nick
)))
618 if(!(jfNode
= uInfo
->joinflood
))
620 spamserv_create_floodNode(channel
, user
, &uInfo
->joinflood
);
624 for(; jfNode
; jfNode
= jfNode
->next
)
625 if(jfNode
->channel
== channel
)
630 spamserv_create_floodNode(channel
, user
, &uInfo
->joinflood
);
637 if(jfNode
->count
> JOINFLOOD_MAX
)
641 spamserv_delete_floodNode(&uInfo
->joinflood
, jfNode
);
642 snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_JOINFLOOD
, spamserv_conf
.network_rules
);
643 spamserv_punish(channel
, user
, JOINFLOOD_B_DURATION
, reason
, 1);
652 spamserv_user_part(struct modeNode
*mn
, UNUSED_ARG(const char *reason
))
654 struct userNode
*user
= mn
->user
;
655 struct chanNode
*channel
= mn
->channel
;
656 struct userInfo
*uInfo
;
657 struct spamNode
*sNode
;
658 struct floodNode
*fNode
;
660 if(user
->dead
|| !get_chanInfo(channel
->name
) || !(uInfo
= get_userInfo(user
->nick
)))
663 if((sNode
= uInfo
->spam
))
665 for(; sNode
; sNode
= sNode
->next
)
666 if(sNode
->channel
== channel
)
670 spamserv_delete_spamNode(uInfo
, sNode
);
673 if((fNode
= uInfo
->flood
))
675 for(; fNode
; fNode
= fNode
->next
)
676 if(fNode
->channel
== channel
)
680 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
684 /***********************************************/
686 /***********************************************/
694 for(i
= 0; i
< 256; i
++)
698 for(j
= 8; j
> 0; j
--)
702 crc
= (crc
>> 1) ^ 0xEDB88320L
;
715 crc32(const char *text
)
717 register unsigned long crc
= 0xFFFFFFFF;
718 unsigned int c
, i
= 0;
720 while((c
= (unsigned int)text
[i
++]) != 0)
721 crc
= ((crc
>> 8) & 0x00FFFFFF) ^ crc_table
[(crc
^c
) & 0xFF];
723 return (crc
^0xFFFFFFFF);
727 timeq_flood(UNUSED_ARG(void *data
))
730 struct userInfo
*uInfo
;
731 struct floodNode
*fNode
;
733 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
735 uInfo
= iter_data(it
);
740 if(!(fNode
= uInfo
->flood
))
743 for(; fNode
; fNode
= fNode
->next
)
745 if(now
- fNode
->time
> FLOOD_EXPIRE
)
747 if(!(--fNode
->count
))
748 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
753 timeq_add(now
+ FLOOD_TIMEQ_FREQ
, timeq_flood
, NULL
);
757 timeq_joinflood(UNUSED_ARG(void *data
))
760 struct userInfo
*uInfo
;
761 struct floodNode
*fNode
;
763 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
765 uInfo
= iter_data(it
);
767 if(!(fNode
= uInfo
->joinflood
))
770 for(; fNode
; fNode
= fNode
->next
)
772 if(now
- fNode
->time
> JOINFLOOD_EXPIRE
)
774 if(!(--fNode
->count
))
775 spamserv_delete_floodNode(&uInfo
->joinflood
, fNode
);
780 timeq_add(now
+ JOINFLOOD_TIMEQ_FREQ
, timeq_joinflood
, NULL
);
784 timeq_bad(UNUSED_ARG(void *data
))
787 struct userInfo
*uInfo
;
789 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
791 uInfo
= iter_data(it
);
793 if(uInfo
->lastbad
&& uInfo
->lastbad
- now
> BAD_EXPIRE
)
796 uInfo
->flags
&= ~USER_BAD_WARNED
;
800 timeq_add(now
+ BAD_TIMEQ_FREQ
, timeq_bad
, NULL
);
804 timeq_adv(UNUSED_ARG(void *data
))
807 struct userInfo
*uInfo
;
809 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
811 uInfo
= iter_data(it
);
813 if(uInfo
->lastadv
&& uInfo
->lastadv
- now
> ADV_EXPIRE
)
816 uInfo
->flags
&= ~USER_ADV_WARNED
;
820 timeq_add(now
+ ADV_TIMEQ_FREQ
, timeq_adv
, NULL
);
824 timeq_warnlevel(UNUSED_ARG(void *data
))
827 struct userInfo
*uInfo
;
829 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
831 uInfo
= iter_data(it
);
833 if(uInfo
->warnlevel
> 0)
837 timeq_add(now
+ WARNLEVEL_TIMEQ_FREQ
, timeq_warnlevel
, NULL
);
841 timeq_kill(UNUSED_ARG(void *data
))
844 struct killNode
*kNode
;
846 for(it
= dict_first(killed_users_dict
); it
; it
= iter_next(it
))
848 kNode
= iter_data(it
);
850 if(kNode
->time
- now
> KILL_EXPIRE
)
854 timeq_add(now
+ KILL_TIMEQ_FREQ
, timeq_kill
, NULL
);
858 binary_option(char *name
, unsigned long mask
, struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[])
860 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
865 if(enabled_string(argv
[1]))
867 cInfo
->flags
|= mask
;
870 else if(disabled_string(argv
[1]))
872 cInfo
->flags
&= ~mask
;
877 spamserv_notice(user
, "SSMSG_INVALID_BINARY", argv
[1]);
883 value
= (cInfo
->flags
& mask
) ? 1 : 0;
886 spamserv_notice(user
, "SSMSG_STRING_VALUE", name
, value
? "Enabled." : "Disabled.");
898 multiple_option(char *name
, char *description
, enum channelinfo info
, struct valueData
*values
, int count
, struct userNode
*user
, struct chanNode
*channel
, int argc
, char *argv
[])
900 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
905 index
= atoi(argv
[1]);
907 if(index
< 0 || index
>= count
)
909 spamserv_notice(user
, "SSMSG_INVALID_NUM_SET", index
, description
);
911 for(index
= 0; index
< count
; index
++)
912 spamserv_notice(user
, "SSMSG_NUMERIC_VALUE", name
, index
, values
[index
].description
);
917 if(values
[index
].oper_only
&& !IsOper(user
))
919 spamserv_notice(user
, "SSMSG_MUST_BE_OPER");
923 cInfo
->info
[info
] = values
[index
].value
;
927 for(index
= 0; index
< count
&& cInfo
->info
[info
] != values
[index
].value
; index
++);
930 spamserv_notice(user
, "SSMSG_NUMERIC_VALUE", name
, index
, values
[index
].description
);
935 show_exceptions(struct userNode
*user
, struct chanInfo
*cInfo
)
937 struct helpfile_table table
;
940 if(!cInfo
->exceptions
->used
)
942 spamserv_notice(user
, "SSMSG_NO_EXCEPTIONS");
946 spamserv_notice(user
, "SSMSG_EXCEPTION_LIST");
950 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
951 table
.contents
= alloca(cInfo
->exceptions
->used
* sizeof(*table
.contents
));
953 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
955 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
956 table
.contents
[table
.length
][0] = cInfo
->exceptions
->list
[i
];
960 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
966 show_badwords(struct userNode
*user
, struct chanInfo
*cInfo
)
968 struct helpfile_table table
;
971 if(!cInfo
->badwords
->used
)
973 spamserv_notice(user
, "SSMSG_NO_BADWORDS");
977 spamserv_notice(user
, "SSMSG_BADWORD_LIST");
981 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
982 table
.contents
= alloca(cInfo
->badwords
->used
* sizeof(*table
.contents
));
984 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
986 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
987 table
.contents
[table
.length
][0] = cInfo
->badwords
->list
[i
];
991 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
997 show_memory_usage(struct userNode
*user
)
1000 struct helpfile_table table
;
1001 struct chanInfo
*cInfo
;
1002 struct userInfo
*uInfo
;
1003 struct spamNode
*sNode
;
1004 struct floodNode
*fNode
;
1005 double channel_size
= 0, user_size
, size
;
1006 unsigned int spamcount
= 0, floodcount
= 0, i
, j
;
1009 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
1011 cInfo
= iter_data(it
);
1013 if(!cInfo
->exceptions
->used
)
1016 if(!cInfo
->badwords
->used
)
1019 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1020 channel_size
+= strlen(cInfo
->exceptions
->list
[i
]) * sizeof(char);
1022 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1023 channel_size
+= strlen(cInfo
->badwords
->list
[i
]) * sizeof(char);
1026 for(it
= dict_first(connected_users_dict
); it
; it
= iter_next(it
))
1028 uInfo
= iter_data(it
);
1030 for(sNode
= uInfo
->spam
; sNode
; sNode
= sNode
->next
, spamcount
++);
1031 for(fNode
= uInfo
->flood
; fNode
; fNode
= fNode
->next
, floodcount
++);
1032 for(fNode
= uInfo
->joinflood
; fNode
; fNode
= fNode
->next
, floodcount
++);
1035 channel_size
+= dict_size(registered_channels_dict
) * sizeof(struct chanInfo
);
1037 user_size
= dict_size(connected_users_dict
) * sizeof(struct userInfo
) +
1038 dict_size(killed_users_dict
) * sizeof(struct killNode
) +
1039 spamcount
* sizeof(struct spamNode
) +
1040 floodcount
* sizeof(struct floodNode
);
1042 size
= channel_size
+ user_size
;
1044 ss_reply("SSMSG_STATUS_MEMORY");
1048 table
.flags
= TABLE_NO_FREE
| TABLE_NO_HEADERS
| TABLE_PAD_LEFT
;
1049 table
.contents
= calloc(table
.length
, sizeof(char**));
1052 table
.contents
[0] = calloc(table
.width
, sizeof(char*));
1053 snprintf(buffer
, sizeof(buffer
), "Channel Memory Usage:");
1054 table
.contents
[0][0] = strdup(buffer
);
1055 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", channel_size
);
1056 table
.contents
[0][1] = strdup(buffer
);
1057 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", channel_size
/ 1024);
1058 table
.contents
[0][2] = strdup(buffer
);
1059 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", channel_size
/ 1024 / 1024);
1060 table
.contents
[0][3] = strdup(buffer
);
1063 table
.contents
[1] = calloc(table
.width
, sizeof(char*));
1064 snprintf(buffer
, sizeof(buffer
), "User Memory Usage :");
1065 table
.contents
[1][0] = strdup(buffer
);
1066 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", user_size
);
1067 table
.contents
[1][1] = strdup(buffer
);
1068 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", user_size
/ 1024);
1069 table
.contents
[1][2] = strdup(buffer
);
1070 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", user_size
/ 1024 / 1024);
1071 table
.contents
[1][3] = strdup(buffer
);
1073 // total memory usage
1074 table
.contents
[2] = calloc(table
.width
, sizeof(char*));
1075 snprintf(buffer
, sizeof(buffer
), "Total Memory Usage :");
1076 table
.contents
[2][0] = strdup(buffer
);
1077 snprintf(buffer
, sizeof(buffer
), " %g Byte; ", size
);
1078 table
.contents
[2][1] = strdup(buffer
);
1079 snprintf(buffer
, sizeof(buffer
), "%g KiloByte; ", size
/ 1024);
1080 table
.contents
[2][2] = strdup(buffer
);
1081 snprintf(buffer
, sizeof(buffer
), "%g MegaByte", size
/ 1024 / 1024);
1082 table
.contents
[2][3] = strdup(buffer
);
1084 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1086 for(i
= 0; i
< table
.length
; i
++)
1088 for(j
= 0; j
< table
.width
; j
++)
1089 free((char*)table
.contents
[i
][j
]);
1091 free(table
.contents
[i
]);
1094 free(table
.contents
);
1098 show_registered_channels(struct userNode
*user
)
1100 struct helpfile_table table
;
1103 spamserv_notice(user
, "SSMSG_STATUS_CHANNEL_LIST");
1105 if(!dict_size(registered_channels_dict
))
1107 spamserv_notice(user
, "SSMSG_STATUS_NO_CHANNEL");
1113 table
.flags
= TABLE_REPEAT_ROWS
| TABLE_NO_FREE
| TABLE_NO_HEADERS
;
1114 table
.contents
= alloca(dict_size(registered_channels_dict
) * sizeof(*table
.contents
));
1116 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
1118 struct chanInfo
*cInfo
= iter_data(it
);
1120 table
.contents
[table
.length
] = alloca(table
.width
* sizeof(**table
.contents
));
1121 table
.contents
[table
.length
][0] = cInfo
->channel
->name
;
1125 table_send(spamserv
, user
->nick
, 0, NULL
, table
);
1128 /***********************************************/
1130 /***********************************************/
1133 SPAMSERV_FUNC(cmd_register
)
1135 struct chanInfo
*cInfo
;
1137 if(!channel
|| !channel
->channel_info
)
1139 ss_reply("SSMSG_NOT_REGISTERED_CS", channel
->name
);
1143 if(get_chanInfo(channel
->name
))
1145 ss_reply("SSMSG_ALREADY_REGISTERED", channel
->name
);
1149 if(IsSuspended(channel
->channel_info
))
1151 ss_reply("SSMSG_SUSPENDED_CS", channel
->name
, "register");
1155 if(channel
== spamserv_conf
.debug_channel
)
1157 ss_reply("SSMSG_DEBUG_CHAN");
1161 if(!(cInfo
= spamserv_register_channel(channel
, spamserv_conf
.global_exceptions
, spamserv_conf
.global_badwords
, CHAN_FLAGS_DEFAULT
, CHAN_INFO_DEFAULT
)))
1163 ss_reply("SSMSG_NO_REGISTER", channel
->name
);
1167 spamserv_join_channel(cInfo
->channel
);
1169 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_REGISTERED_BY",
1170 channel
->name
, user
->handle_info
->handle
);
1171 ss_reply("SSMSG_REG_SUCCESS", channel
->name
);
1177 SPAMSERV_FUNC(cmd_unregister
)
1179 struct chanInfo
*cInfo
;
1180 struct chanData
*cData
;
1181 struct userData
*uData
;
1182 char reason
[MAXLEN
];
1184 if(!channel
|| !(cData
= channel
->channel_info
) || !(cInfo
= get_chanInfo(channel
->name
)))
1186 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1190 if(!(uData
= GetChannelUser(cData
, user
->handle_info
)) || (uData
->access
< UL_OWNER
))
1192 ss_reply("SSMSG_NO_ACCESS");
1196 if(!IsHelping(user
))
1198 if(IsSuspended(cData
))
1200 ss_reply("SSMSG_SUSPENDED_CS", channel
->name
, "unregister");
1204 if(argc
< 2 || strcasecmp(argv
[1], "CONFIRM"))
1206 ss_reply("SSMSG_CONFIRM_UNREG");
1211 if(!CHECK_SUSPENDED(cInfo
))
1213 snprintf(reason
, sizeof(reason
), "%s unregistered by %s.", spamserv
->nick
, user
->handle_info
->handle
);
1214 spamserv_part_channel(channel
, reason
);
1217 spamserv_unregister_channel(cInfo
);
1219 global_message_args(MESSAGE_RECIPIENT_OPERS
| MESSAGE_RECIPIENT_HELPERS
, "SSMSG_UNREGISTERED_BY",
1220 channel
->name
, user
->handle_info
->handle
);
1221 ss_reply("SSMSG_UNREG_SUCCESS", channel
->name
);
1227 SPAMSERV_FUNC(cmd_status
)
1229 ss_reply("SSMSG_STATUS");
1230 ss_reply("SSMSG_STATUS_USERS", dict_size(connected_users_dict
));
1231 ss_reply("SSMSG_STATUS_CHANNELS", dict_size(registered_channels_dict
));
1233 if(IsOper(user
) && argc
> 1)
1235 if(!irccasecmp(argv
[1], "memory"))
1236 show_memory_usage(user
);
1237 else if(!irccasecmp(argv
[1], "channels"))
1238 show_registered_channels(user
);
1245 SPAMSERV_FUNC(cmd_addexception
)
1247 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1248 struct userData
*uData
;
1251 if(!cInfo
|| !channel
->channel_info
)
1253 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1257 if(CHECK_SUSPENDED(cInfo
))
1259 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1263 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1265 ss_reply("SSMSG_NO_ACCESS");
1270 return show_exceptions(user
, cInfo
);
1272 if(cInfo
->exceptions
->used
== spamserv_conf
.exception_max
&& !IsOper(user
))
1274 ss_reply("SSMSG_EXCEPTION_MAX", spamserv_conf
.exception_max
);
1278 if(strlen(argv
[1]) < spamserv_conf
.exception_min_len
)
1280 ss_reply("SSMSG_EXCEPTION_TOO_SHORT", spamserv_conf
.exception_min_len
);
1283 else if(strlen(argv
[1]) > spamserv_conf
.exception_max_len
)
1285 ss_reply("SSMSG_EXCEPTION_TOO_LONG", spamserv_conf
.exception_max_len
);
1289 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1291 if(!irccasecmp(argv
[1], cInfo
->exceptions
->list
[i
]))
1293 ss_reply("SSMSG_EXCEPTION_IN_LIST", argv
[1]);
1298 string_list_append(cInfo
->exceptions
, strdup(argv
[1]));
1299 ss_reply("SSMSG_EXCEPTION_ADDED", argv
[1]);
1305 SPAMSERV_FUNC(cmd_delexception
)
1307 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1308 struct userData
*uData
;
1312 if(!cInfo
|| !channel
->channel_info
)
1314 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1318 if(CHECK_SUSPENDED(cInfo
))
1320 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1324 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1326 ss_reply("SSMSG_NO_ACCESS");
1331 return show_exceptions(user
, cInfo
);
1333 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1335 if(!irccasecmp(argv
[1], cInfo
->exceptions
->list
[i
]))
1344 ss_reply("SSMSG_NO_SUCH_EXCEPTION", argv
[1]);
1348 string_list_delete(cInfo
->exceptions
, i
);
1349 ss_reply("SSMSG_EXCEPTION_DELETED", argv
[1]);
1355 SPAMSERV_FUNC(cmd_addbadword
)
1357 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1358 struct userData
*uData
;
1361 if(!cInfo
|| !channel
->channel_info
)
1363 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1367 if(CHECK_SUSPENDED(cInfo
))
1369 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1373 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1375 ss_reply("SSMSG_NO_ACCESS");
1380 return show_badwords(user
, cInfo
);
1382 if(cInfo
->badwords
->used
== spamserv_conf
.badword_max
&& !IsOper(user
))
1384 ss_reply("SSMSG_BADWORD_MAX", spamserv_conf
.badword_max
);
1388 if(strlen(argv
[1]) < spamserv_conf
.badword_min_len
)
1390 ss_reply("SSMSG_BADWORD_TOO_SHORT", spamserv_conf
.badword_min_len
);
1393 else if(strlen(argv
[1]) > spamserv_conf
.badword_max_len
)
1395 ss_reply("SSMSG_BADWORD_TOO_LONG", spamserv_conf
.badword_max_len
);
1399 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1401 if(!irccasecmp(argv
[1], cInfo
->badwords
->list
[i
]))
1403 ss_reply("SSMSG_BADWORD_IN_LIST", argv
[1]);
1408 string_list_append(cInfo
->badwords
, strdup(argv
[1]));
1409 ss_reply("SSMSG_BADWORD_ADDED", argv
[1]);
1415 SPAMSERV_FUNC(cmd_delbadword
)
1417 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1418 struct userData
*uData
;
1422 if(!cInfo
|| !channel
->channel_info
)
1424 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1428 if(CHECK_SUSPENDED(cInfo
))
1430 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1434 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1436 ss_reply("SSMSG_NO_ACCESS");
1441 return show_badwords(user
, cInfo
);
1443 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1445 if(!irccasecmp(argv
[1], cInfo
->badwords
->list
[i
]))
1454 ss_reply("SSMSG_NO_SUCH_BADWORD", argv
[1]);
1458 string_list_delete(cInfo
->badwords
, i
);
1459 ss_reply("SSMSG_BADWORD_DELETED", argv
[1]);
1465 SPAMSERV_FUNC(cmd_set
)
1467 struct chanInfo
*cInfo
= get_chanInfo(channel
->name
);
1468 struct userData
*uData
;
1469 struct svccmd
*subcmd
;
1470 char cmd_name
[MAXLEN
];
1475 ss_reply("SSMSG_NOT_REGISTERED", channel
->name
);
1479 if(CHECK_SUSPENDED(cInfo
))
1481 ss_reply("SSMSG_SUSPENDED", channel
->name
);
1485 if(!(uData
= GetChannelUser(channel
->channel_info
, user
->handle_info
)) || (uData
->access
< 400))
1487 ss_reply("SSMSG_NO_ACCESS");
1493 ss_reply("SSMSG_CHANNEL_OPTIONS");
1495 for(i
= 0; i
< SET_SUBCMDS_SIZE
; i
++)
1497 sprintf(cmd_name
, "%s %s", cmd
->name
, set_subcommands
[i
]);
1499 if((subcmd
= dict_find(cmd
->parent
->commands
, cmd_name
, NULL
)))
1500 subcmd
->command
->func(user
, channel
, 1, argv
+ 1, subcmd
);
1506 sprintf(cmd_name
, "%s %s", cmd
->name
, argv
[1]);
1507 subcmd
= dict_find(cmd
->parent
->commands
, cmd_name
, NULL
);
1511 reply("SSMSG_INVALID_OPTION", argv
[1], argv
[0]);
1515 return subcmd
->command
->func(user
, channel
, argc
- 1, argv
+ 1, subcmd
);
1519 SPAMSERV_FUNC(opt_spamlimit
)
1521 struct valueData values
[] =
1523 {"Users may send the same message $b2$b times.", 'a', 0},
1524 {"Users may send the same message $b3$b times.", 'b', 0},
1525 {"Users may send the same message $b4$b times.", 'c', 0},
1526 {"Users may send the same message $b5$b times.", 'd', 0},
1527 {"Users may send the same message $b6$b times.", 'e', 0}
1530 MULTIPLE_OPTION("SpamLimit ", "SpamLimit", ci_SpamLimit
);
1534 SPAMSERV_FUNC(opt_advreaction
)
1536 struct valueData values
[] =
1538 {"Kick on disallowed advertising.", 'k', 0},
1539 {"Kickban on disallowed advertising.", 'b', 0},
1540 {"Short timed ban on disallowed advertising.", 's', 0},
1541 {"Long timed ban on disallowed advertising.", 'l', 0},
1542 {"Kill on disallowed advertising.", 'd', 1}
1545 MULTIPLE_OPTION("AdvReaction ", "AdvReaction", ci_AdvReaction
);
1549 SPAMSERV_FUNC(opt_warnreaction
)
1551 struct valueData values
[] =
1553 {"Kick after warning.", 'k', 0},
1554 {"Kickban after warning.", 'b', 0},
1555 {"Short timed ban after warning.", 's', 0},
1556 {"Long timed ban after warning.", 'l', 0},
1557 {"Kill after warning.", 'd', 1}
1560 MULTIPLE_OPTION("WarnReaction ", "WarnReaction", ci_WarnReaction
);
1564 SPAMSERV_FUNC(opt_badreaction
)
1566 struct valueData values
[] =
1568 {"Kick on disallowed badwords.", 'k', 0},
1569 {"Kickban on disallowed badwords.", 'b', 0},
1570 {"Short timed ban on disallowed badwords.", 's', 0},
1571 {"Long timed ban on disallowed badwords.", 'l', 0},
1572 {"Kill on disallowed badwords.", 'd', 1}
1575 MULTIPLE_OPTION("BadReaction ", "BadReaction", ci_BadReaction
);
1579 SPAMSERV_FUNC(opt_advscan
)
1581 BINARY_OPTION("AdvScan ", CHAN_ADV_SCAN
);
1585 SPAMSERV_FUNC(opt_spamscan
)
1587 BINARY_OPTION("SpamScan ", CHAN_SPAMSCAN
);
1591 SPAMSERV_FUNC(opt_badwordscan
)
1593 BINARY_OPTION("BadWordScan ", CHAN_BADWORDSCAN
);
1597 SPAMSERV_FUNC(opt_chanfloodscan
)
1599 BINARY_OPTION("ChanFloodScan ", CHAN_CHANFLOODSCAN
);
1603 SPAMSERV_FUNC(opt_joinflood
)
1605 BINARY_OPTION("JoinFloodScan ", CHAN_JOINFLOOD
);
1609 SPAMSERV_FUNC(opt_scanops
)
1611 BINARY_OPTION("ScanChanOps ", CHAN_SCAN_CHANOPS
);
1615 SPAMSERV_FUNC(opt_scanhalfops
)
1617 BINARY_OPTION("ScanHalfOps ", CHAN_SCAN_HALFOPS
);
1621 SPAMSERV_FUNC(opt_scanvoiced
)
1623 BINARY_OPTION("ScanVoiced ", CHAN_SCAN_VOICED
);
1627 to_lower(char *message
)
1629 unsigned int i
, diff
= 'a' - 'A';
1631 for(i
= 0; i
< strlen(message
); i
++)
1633 if((message
[i
] >= 'A') && (message
[i
] <= 'Z'))
1634 message
[i
] = message
[i
] + diff
;
1639 strip_mirc_codes(char *text
)
1641 // taken from xchat and modified
1642 int nc
= 0, i
= 0, col
= 0, len
= strlen(text
);
1643 static char new_str
[MAXLEN
];
1647 if((col
&& isdigit(*text
) && nc
< 2) ||
1648 (col
&& *text
== ',' && isdigit(*(text
+ 1)) && nc
< 3))
1687 is_in_exception_list(struct chanInfo
*cInfo
, char *message
)
1691 for(i
= 0; i
< cInfo
->exceptions
->used
; i
++)
1692 if(strstr(message
, cInfo
->exceptions
->list
[i
]))
1699 is_in_badword_list(struct chanInfo
*cInfo
, char *message
)
1703 for(i
= 0; i
< cInfo
->badwords
->used
; i
++)
1704 if(strstr(message
, cInfo
->badwords
->list
[i
]))
1711 check_badwords(struct chanInfo
*cInfo
, char *message
)
1713 if(spamserv_conf
.strip_mirc_codes
)
1714 message
= strip_mirc_codes(message
);
1716 /* This needs improving */
1717 if(is_in_exception_list(cInfo
, message
))
1720 if(is_in_badword_list(cInfo
, message
))
1727 check_advertising(struct chanInfo
*cInfo
, char *message
)
1731 if(spamserv_conf
.strip_mirc_codes
)
1732 message
= strip_mirc_codes(message
);
1734 if(is_in_exception_list(cInfo
, message
))
1737 while(message
[i
] != 0)
1739 if(message
[i
] == '#')
1741 char channelname
[CHANNELLEN
];
1744 if(!spamserv_conf
.adv_chan_must_exist
)
1747 /* only return 1, if the channel does exist */
1749 while((message
[i
] != 0) && (message
[i
] != ' '))
1751 channelname
[j
] = message
[i
];
1756 channelname
[j
] = '\0';
1758 if(GetChannel(channelname
))
1761 else if((message
[i
] == 'w') && (message
[i
+1] == 'w') && (message
[i
+2] == 'w') && (message
[i
+3] == '.'))
1763 else if((message
[i
] == 'h') && (message
[i
+1] == 't') && (message
[i
+2] == 't') && (message
[i
+3] == 'p') && (message
[i
+4] == ':'))
1765 else if((message
[i
] == 'f') && (message
[i
+1] == 't') && (message
[i
+2] == 'p') && ((message
[i
+3] == '.') || (message
[i
+3] == ':')))
1775 spamserv_punish(struct chanNode
*channel
, struct userNode
*user
, time_t expires
, char *reason
, int ban
)
1779 struct mod_chanmode change
;
1780 char *hostmask
= generate_hostmask(user
, GENMASK_STRICT_HOST
| GENMASK_ANY_IDENT
);
1782 sanitize_ircmask(hostmask
);
1785 add_channel_ban(channel
->channel_info
, hostmask
, spamserv
->nick
, now
, now
, now
+ expires
, reason
);
1787 mod_chanmode_init(&change
);
1789 change
.args
[0].mode
= MODE_BAN
;
1790 change
.args
[0].u
.hostmask
= hostmask
;
1791 mod_chanmode_announce(spamserv
, channel
, &change
);
1795 spamserv_debug(SSMSG_DEBUG_BAN
, user
->nick
, channel
->name
, reason
);
1798 spamserv_debug(SSMSG_DEBUG_KICK
, user
->nick
, channel
->name
, reason
);
1800 KickChannelUser(user
, channel
, spamserv
, reason
);
1804 spamserv_channel_message(struct chanNode
*channel
, struct userNode
*user
, char *text
)
1806 struct chanData
*cData
;
1807 struct chanInfo
*cInfo
;
1808 struct userInfo
*uInfo
;
1809 struct userData
*uData
;
1810 struct spamNode
*sNode
;
1811 struct floodNode
*fNode
;
1812 unsigned int violation
= 0;
1813 char reason
[MAXLEN
];
1815 /* make sure: spamserv is not disabled; x3 is running; spamserv is in the chan; chan is regged, user does exist */
1816 if(!spamserv
|| quit_services
|| !GetUserMode(channel
, spamserv
) || IsOper(user
) || !(cInfo
= get_chanInfo(channel
->name
)) || !(uInfo
= get_userInfo(user
->nick
)))
1819 cData
= channel
->channel_info
;
1820 uData
= GetChannelUser(cData
, user
->handle_info
);
1822 if(!CHECK_CHANOPS(cInfo
))
1824 struct modeNode
*mn
= GetUserMode(channel
, user
);
1825 if (mn
&& (mn
->modes
& MODE_CHANOP
))
1828 /* Chan Ops covers all levels except peon and half op */
1829 if(uData
&& ((uData
->access
< UL_OP
) || (uData
->access
< UL_MANAGER
) ||
1830 (uData
->access
< UL_COOWNER
) || (uData
->access
< UL_OWNER
)))
1834 if(!CHECK_HALFOPS(cInfo
))
1836 struct modeNode
*mn
= GetUserMode(channel
, user
);
1837 if (mn
&& (mn
->modes
& MODE_HALFOP
))
1840 if(uData
&& (uData
->access
< UL_HALFOP
))
1844 if(!CHECK_VOICED(cInfo
))
1846 struct modeNode
*mn
= GetUserMode(channel
, user
);
1847 if (mn
&& ((mn
->modes
& MODE_VOICE
) && !(mn
->modes
& MODE_CHANOP
) && !(mn
->modes
& MODE_HALFOP
)))
1850 if(uData
&& (uData
->access
< UL_PEON
))
1856 if(CHECK_SPAM(cInfo
))
1858 if(!(sNode
= uInfo
->spam
))
1860 spamserv_create_spamNode(channel
, uInfo
, text
);
1864 for(; sNode
; sNode
= sNode
->next
)
1865 if(sNode
->channel
== channel
)
1870 spamserv_create_spamNode(channel
, uInfo
, text
);
1874 unsigned long crc
= crc32(text
);
1876 if(crc
== sNode
->crc32
)
1878 unsigned int spamlimit
= 2;
1881 switch(cInfo
->info
[ci_SpamLimit
])
1883 case 'a': spamlimit
= 2; break;
1884 case 'b': spamlimit
= 3; break;
1885 case 'c': spamlimit
= 4; break;
1886 case 'd': spamlimit
= 5; break;
1887 case 'e': spamlimit
= 6; break;
1890 if(sNode
->count
== spamlimit
)
1892 uInfo
->warnlevel
+= SPAM_WARNLEVEL
;
1894 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
1895 if (spamserv_conf
.network_rules
)
1896 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_SPAM
, spamserv_conf
.network_rules
);
1898 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_SPAM
, spamserv_conf
.network_rules
);
1901 else if(sNode
->count
> spamlimit
)
1903 switch(cInfo
->info
[ci_WarnReaction
])
1905 case 'k': uInfo
->flags
|= USER_KICK
; break;
1906 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
1907 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
1908 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
1909 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
1912 spamserv_delete_spamNode(uInfo
, sNode
);
1913 uInfo
->warnlevel
+= SPAM_WARNLEVEL
;
1926 if(CHECK_FLOOD(cInfo
))
1928 if(!(fNode
= uInfo
->flood
))
1930 spamserv_create_floodNode(channel
, user
, &uInfo
->flood
);
1934 for(; fNode
; fNode
= fNode
->next
)
1935 if(fNode
->channel
== channel
)
1940 spamserv_create_floodNode(channel
, user
, &uInfo
->flood
);
1944 if(((now
- fNode
->time
) < FLOOD_EXPIRE
))
1948 if(fNode
->count
== FLOOD_MAX_LINES
- 1)
1950 uInfo
->warnlevel
+= FLOOD_WARNLEVEL
;
1952 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
1953 if (spamserv_conf
.network_rules
)
1954 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_FLOOD
, spamserv_conf
.network_rules
);
1956 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_FLOOD
, spamserv_conf
.network_rules
);
1959 else if(fNode
->count
> FLOOD_MAX_LINES
)
1961 switch(cInfo
->info
[ci_WarnReaction
])
1963 case 'k': uInfo
->flags
|= USER_KICK
; break;
1964 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
1965 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
1966 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
1967 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
1970 spamserv_delete_floodNode(&uInfo
->flood
, fNode
);
1971 uInfo
->warnlevel
+= FLOOD_WARNLEVEL
;
1981 if(CHECK_BADWORDSCAN(cInfo
) && check_badwords(cInfo
, text
))
1983 if(CHECK_BAD_WARNED(uInfo
))
1985 switch(cInfo
->info
[ci_BadReaction
])
1987 case 'k': uInfo
->flags
|= USER_KICK
; break;
1988 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
1989 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
1990 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
1991 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
1994 uInfo
->warnlevel
+= BAD_WARNLEVEL
;
1999 uInfo
->flags
|= USER_BAD_WARNED
;
2000 uInfo
->lastbad
= now
;
2001 uInfo
->warnlevel
+= BAD_WARNLEVEL
;
2003 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2004 if (spamserv_conf
.network_rules
)
2005 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_BAD
, spamserv_conf
.network_rules
);
2007 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_BAD
, spamserv_conf
.network_rules
);
2012 if(CHECK_ADV(cInfo
) && check_advertising(cInfo
, text
))
2014 if(CHECK_ADV_WARNED(uInfo
))
2016 switch(cInfo
->info
[ci_AdvReaction
])
2018 case 'k': uInfo
->flags
|= USER_KICK
; break;
2019 case 'b': uInfo
->flags
|= USER_KICKBAN
; break;
2020 case 's': uInfo
->flags
|= USER_SHORT_TBAN
; break;
2021 case 'l': uInfo
->flags
|= USER_LONG_TBAN
; break;
2022 case 'd': uInfo
->flags
|= CHECK_KILLED(uInfo
) ? USER_GLINE
: USER_KILL
; break;
2025 uInfo
->warnlevel
+= ADV_WARNLEVEL
;
2030 uInfo
->flags
|= USER_ADV_WARNED
;
2031 uInfo
->lastadv
= now
;
2032 uInfo
->warnlevel
+= ADV_WARNLEVEL
;
2034 if(uInfo
->warnlevel
< MAX_WARNLEVEL
) {
2035 if (spamserv_conf
.network_rules
)
2036 spamserv_notice(user
, "SSMSG_WARNING_RULES_T", SSMSG_ADV
, spamserv_conf
.network_rules
);
2038 spamserv_notice(user
, "SSMSG_WARNING_T", SSMSG_ADV
, spamserv_conf
.network_rules
);
2043 if(!CHECK_WARNED(uInfo
) && !CHECK_KILL(uInfo
) && !CHECK_GLINE(uInfo
) && uInfo
->warnlevel
== MAX_WARNLEVEL
)
2045 uInfo
->flags
|= USER_WARNED
;
2046 if (spamserv_conf
.network_rules
)
2047 snprintf(reason
, sizeof(reason
), SSMSG_WARNING_RULES_2
, spamserv_conf
.network_rules
);
2049 snprintf(reason
, sizeof(reason
), SSMSG_WARNING_2
);
2050 irc_notice(spamserv
, user
->numeric
, reason
);
2051 irc_privmsg(spamserv
, user
->numeric
, reason
);
2053 else if(uInfo
->warnlevel
> MAX_WARNLEVEL
)
2055 if(CHECK_KILLED(uInfo
))
2056 uInfo
->flags
|= USER_GLINE
;
2058 uInfo
->flags
|= USER_KILL
;
2069 case 1: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_SPAM
, spamserv_conf
.network_rules
); break;
2070 case 2: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_FLOOD
, spamserv_conf
.network_rules
); break;
2071 case 3: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_ADV
, spamserv_conf
.network_rules
); break;
2072 case 4: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES
: SSMSG_WARNING
, SSMSG_BAD
, spamserv_conf
.network_rules
); break;
2073 default: snprintf(reason
, sizeof(reason
), spamserv_conf
.network_rules
? SSMSG_WARNING_RULES_2
: SSMSG_WARNING_2
, spamserv_conf
.network_rules
); break;
2076 if(CHECK_GLINE(uInfo
))
2078 int size
= strlen(user
->hostname
) + 3;
2079 char *mask
= alloca(size
);
2080 snprintf(mask
, size
, "*@%s", user
->hostname
);
2081 gline_add(spamserv
->nick
, mask
, spamserv_conf
.gline_duration
, reason
, now
, 1, 0);
2082 spamserv_debug(SSMSG_DEBUG_GLINE
, user
->nick
, user
->hostname
, channel
->name
);
2084 else if(CHECK_KILL(uInfo
))
2086 DelUser(user
, spamserv
, 1, reason
);
2087 spamserv_debug(SSMSG_DEBUG_KILL
, user
->nick
, channel
->name
);
2089 else if(CHECK_LONG_TBAN(uInfo
))
2091 spamserv_punish(channel
, user
, spamserv_conf
.long_ban_duration
, reason
, 1);
2093 else if(CHECK_SHORT_TBAN(uInfo
))
2095 spamserv_punish(channel
, user
, spamserv_conf
.short_ban_duration
, reason
, 1);
2097 else if(CHECK_KICKBAN(uInfo
))
2099 spamserv_punish(channel
, user
, 0, reason
, 1);
2101 else if(CHECK_KICK(uInfo
))
2103 spamserv_punish(channel
, user
, 0, reason
, 0);
2108 spamserv_saxdb_read(struct dict
*database
)
2111 struct record_data
*hir
;
2112 struct chanNode
*channel
;
2113 struct chanInfo
*cInfo
;
2114 struct string_list
*strlist
, *strlist2
;
2119 for(it
= dict_first(database
); it
; it
= iter_next(it
))
2121 hir
= iter_data(it
);
2123 if(hir
->type
!= RECDB_OBJECT
)
2125 log_module(SS_LOG
, LOG_WARNING
, "Unexpected rectype %d for %s.", hir
->type
, iter_key(it
));
2129 channel
= GetChannel(iter_key(it
));
2131 strlist
= database_get_data(hir
->d
.object
, KEY_EXCEPTIONS
, RECDB_STRING_LIST
);
2132 strlist2
= database_get_data(hir
->d
.object
, KEY_BADWORDS
, RECDB_STRING_LIST
);
2134 str
= database_get_data(hir
->d
.object
, KEY_FLAGS
, RECDB_QSTRING
);
2135 flags
= str
? atoi(str
) : 0;
2137 info
= database_get_data(hir
->d
.object
, KEY_INFO
, RECDB_QSTRING
);
2139 str
= database_get_data(hir
->d
.object
, KEY_EXPIRY
, RECDB_QSTRING
);
2140 expiry
= str
? strtoul(str
, NULL
, 0) : 0;
2144 if((cInfo
= spamserv_register_channel(channel
, strlist
, strlist2
, flags
, info
)))
2146 /* if the channel is suspended and expiry = 0 it means: channel will
2147 never expire ! it does NOT mean, the channel is not suspended */
2148 if(CHECK_SUSPENDED(cInfo
) && expiry
&& (expiry
< now
))
2150 cInfo
->flags
&= ~CHAN_SUSPENDED
;
2151 spamserv_join_channel(cInfo
->channel
);
2153 else if(!CHECK_SUSPENDED(cInfo
))
2154 spamserv_join_channel(cInfo
->channel
);
2156 cInfo
->suspend_expiry
= expiry
;
2160 log_module(SS_LOG
, LOG_ERROR
, "Couldn't register channel %s. Channel or info invalid.", iter_key(it
));
2167 spamserv_saxdb_write(struct saxdb_context
*ctx
)
2171 for(it
= dict_first(registered_channels_dict
); it
; it
= iter_next(it
))
2173 struct chanInfo
*cInfo
= iter_data(it
);
2175 saxdb_start_record(ctx
, cInfo
->channel
->name
, 1);
2177 if(cInfo
->exceptions
->used
)
2178 saxdb_write_string_list(ctx
, KEY_EXCEPTIONS
, cInfo
->exceptions
);
2180 if(cInfo
->badwords
->used
)
2181 saxdb_write_string_list(ctx
, KEY_BADWORDS
, cInfo
->badwords
);
2184 saxdb_write_int(ctx
, KEY_FLAGS
, cInfo
->flags
);
2186 saxdb_write_string(ctx
, KEY_INFO
, cInfo
->info
);
2188 if(cInfo
->suspend_expiry
)
2189 saxdb_write_int(ctx
, KEY_EXPIRY
, cInfo
->suspend_expiry
);
2191 saxdb_end_record(ctx
);
2197 spamserv_conf_read(void)
2202 if(!(conf_node
= conf_get_data(SPAMSERV_CONF_NAME
, RECDB_OBJECT
)))
2204 log_module(SS_LOG
, LOG_ERROR
, "config node `%s' is missing or has wrong type.", SPAMSERV_CONF_NAME
);
2208 str
= database_get_data(conf_node
, KEY_DEBUG_CHANNEL
, RECDB_QSTRING
);
2212 spamserv_conf
.debug_channel
= AddChannel(str
, now
, "+tinms", NULL
, NULL
);
2214 if(spamserv_conf
.debug_channel
)
2215 spamserv_join_channel(spamserv_conf
.debug_channel
);
2219 spamserv_conf
.debug_channel
= NULL
;
2222 spamserv_conf
.global_exceptions
= database_get_data(conf_node
, KEY_GLOBAL_EXCEPTIONS
, RECDB_STRING_LIST
);
2224 spamserv_conf
.global_badwords
= database_get_data(conf_node
, KEY_GLOBAL_BADWORDS
, RECDB_STRING_LIST
);
2226 str
= database_get_data(conf_node
, KEY_NETWORK_RULES
, RECDB_QSTRING
);
2227 spamserv_conf
.network_rules
= str
? str
: NULL
;
2229 str
= database_get_data(conf_node
, KEY_TRIGGER
, RECDB_QSTRING
);
2230 spamserv_conf
.trigger
= str
? str
[0] : 0;
2232 str
= database_get_data(conf_node
, KEY_SHORT_BAN_DURATION
, RECDB_QSTRING
);
2233 spamserv_conf
.short_ban_duration
= str
? ParseInterval(str
) : ParseInterval("15m");
2235 str
= database_get_data(conf_node
, KEY_LONG_BAN_DURATION
, RECDB_QSTRING
);
2236 spamserv_conf
.long_ban_duration
= str
? ParseInterval(str
) : ParseInterval("1h");
2238 str
= database_get_data(conf_node
, KEY_GLINE_DURATION
, RECDB_QSTRING
);
2239 spamserv_conf
.gline_duration
= str
? ParseInterval(str
) : ParseInterval("1h");
2241 str
= database_get_data(conf_node
, KEY_EXCEPTION_MAX
, RECDB_QSTRING
);
2242 spamserv_conf
.exception_max
= str
? strtoul(str
, NULL
, 0) : 10;
2244 str
= database_get_data(conf_node
, KEY_EXCEPTION_MIN_LEN
, RECDB_QSTRING
);
2245 spamserv_conf
.exception_min_len
= str
? strtoul(str
, NULL
, 0) : 4;
2247 str
= database_get_data(conf_node
, KEY_EXCEPTION_MAX_LEN
, RECDB_QSTRING
);
2248 spamserv_conf
.exception_max_len
= str
? strtoul(str
, NULL
, 0) : 15;
2250 str
= database_get_data(conf_node
, KEY_BADWORD_MAX
, RECDB_QSTRING
);
2251 spamserv_conf
.badword_max
= str
? strtoul(str
, NULL
, 0) : 10;
2253 str
= database_get_data(conf_node
, KEY_BADWORD_MIN_LEN
, RECDB_QSTRING
);
2254 spamserv_conf
.badword_min_len
= str
? strtoul(str
, NULL
, 0) : 4;
2256 str
= database_get_data(conf_node
, KEY_BADWORD_MAX_LEN
, RECDB_QSTRING
);
2257 spamserv_conf
.badword_max_len
= str
? strtoul(str
, NULL
, 0) : 15;
2259 str
= database_get_data(conf_node
, KEY_ADV_CHAN_MUST_EXIST
, RECDB_QSTRING
);
2260 spamserv_conf
.adv_chan_must_exist
= str
? enabled_string(str
) : 1;
2262 str
= database_get_data(conf_node
, KEY_STRIP_MIRC_CODES
, RECDB_QSTRING
);
2263 spamserv_conf
.strip_mirc_codes
= str
? enabled_string(str
) : 0;
2265 str
= database_get_data(conf_node
, KEY_ALLOW_MOVE_MERGE
, RECDB_QSTRING
);
2266 spamserv_conf
.allow_move_merge
= str
? enabled_string(str
) : 0;
2270 spamserv_db_cleanup(void)
2274 while((it
= dict_first(registered_channels_dict
)))
2276 spamserv_unregister_channel(iter_data(it
));
2279 while((it
= dict_first(killed_users_dict
)))
2281 free(iter_data(it
));
2284 dict_delete(registered_channels_dict
);
2285 dict_delete(connected_users_dict
);
2286 dict_delete(killed_users_dict
);
2290 init_spamserv(const char *nick
)
2292 struct chanNode
*chan
;
2298 const char *modes
= conf_get_data("services/spamserv/modes", RECDB_QSTRING
);
2299 spamserv
= AddService(nick
, modes
? modes
: NULL
, "Anti Spam Services", NULL
);
2300 spamserv_service
= service_register(spamserv
);
2302 conf_register_reload(spamserv_conf_read
);
2304 SS_LOG
= log_register_type("SpamServ", "file:spamserv.log");
2306 registered_channels_dict
= dict_new();
2307 connected_users_dict
= dict_new();
2308 killed_users_dict
= dict_new();
2310 saxdb_register("SpamServ", spamserv_saxdb_read
, spamserv_saxdb_write
);
2312 reg_new_user_func(spamserv_new_user_func
);
2313 reg_del_user_func(spamserv_del_user_func
);
2314 reg_nick_change_func(spamserv_nick_change_func
);
2315 reg_join_func(spamserv_user_join
);
2316 reg_part_func(spamserv_user_part
);
2318 timeq_add(now
+ FLOOD_TIMEQ_FREQ
, timeq_flood
, NULL
);
2319 timeq_add(now
+ JOINFLOOD_TIMEQ_FREQ
, timeq_joinflood
, NULL
);
2320 timeq_add(now
+ ADV_TIMEQ_FREQ
, timeq_adv
, NULL
);
2321 timeq_add(now
+ BAD_TIMEQ_FREQ
, timeq_bad
, NULL
);
2322 timeq_add(now
+ WARNLEVEL_TIMEQ_FREQ
, timeq_warnlevel
, NULL
);
2323 timeq_add(now
+ KILL_TIMEQ_FREQ
, timeq_kill
, NULL
);
2325 spamserv_module
= module_register("SpamServ", SS_LOG
, "spamserv.help", NULL
);
2326 modcmd_register(spamserv_module
, "REGISTER", cmd_register
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, "flags", "+acceptchan,+helping", NULL
);
2327 modcmd_register(spamserv_module
, "UNREGISTER", cmd_unregister
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, "flags", "+loghostmask", NULL
);
2328 modcmd_register(spamserv_module
, "ADDEXCEPTION", cmd_addexception
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2329 modcmd_register(spamserv_module
, "DELEXCEPTION", cmd_delexception
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2330 modcmd_register(spamserv_module
, "ADDBADWORD", cmd_addbadword
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2331 modcmd_register(spamserv_module
, "DELBADWORD", cmd_delbadword
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2332 modcmd_register(spamserv_module
, "STATUS", cmd_status
, 1, 0, NULL
);
2333 modcmd_register(spamserv_module
, "SET", cmd_set
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2334 modcmd_register(spamserv_module
, "SET SPAMLIMIT", opt_spamlimit
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2335 modcmd_register(spamserv_module
, "SET BADREACTION", opt_badreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2336 modcmd_register(spamserv_module
, "SET ADVREACTION", opt_advreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2337 modcmd_register(spamserv_module
, "SET WARNREACTION", opt_warnreaction
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2338 modcmd_register(spamserv_module
, "SET ADVSCAN", opt_advscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2339 modcmd_register(spamserv_module
, "SET BADWORDSCAN", opt_badwordscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2340 modcmd_register(spamserv_module
, "SET SPAMSCAN", opt_spamscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2341 modcmd_register(spamserv_module
, "SET CHANFLOODSCAN", opt_chanfloodscan
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2342 modcmd_register(spamserv_module
, "SET JOINFLOODSCAN", opt_joinflood
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2343 modcmd_register(spamserv_module
, "SET SCANCHANOPS", opt_scanops
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2344 modcmd_register(spamserv_module
, "SET SCANHALFOPS", opt_scanhalfops
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2345 modcmd_register(spamserv_module
, "SET SCANVOICED", opt_scanvoiced
, 1, MODCMD_REQUIRE_AUTHED
|MODCMD_REQUIRE_CHANNEL
, NULL
);
2347 spamserv_service
->trigger
= spamserv_conf
.trigger
;
2350 if (autojoin_channels
&& spamserv
) {
2351 for (i
= 0; i
< autojoin_channels
->used
; i
++) {
2352 chan
= AddChannel(autojoin_channels
->list
[i
], now
, "+nt", NULL
, NULL
);
2353 AddChannelUser(spamserv
, chan
)->modes
|= MODE_CHANOP
;
2357 reg_exit_func(spamserv_db_cleanup
);
2358 message_register_table(msgtab
);