@@ -69,6 +69,9 @@ def initialize()
69
69
[ "STATS" , 0 , 0 , SFLG_NOMAXPARAM , ADMIN_FLAG , lm ( 'GS_HLP_STS_SHORT' ) , lm ( 'GS_HLP_STS_LONG' ) ] ,
70
70
[ "ENFORCE" , 0 , 0 , SFLG_NOMAXPARAM , ADMIN_FLAG , lm ( 'GS_HLP_ENF_SHORT' ) , lm ( 'GS_HLP_ENF_LONG' ) ] ,
71
71
[ "BADSERV" , 0 , 1 , SFLG_NOMAXPARAM , ADMIN_FLAG , lm ( 'GS_HLP_SRV_SHORT' ) , lm ( 'GS_HLP_SRV_LONG' ) ] ,
72
+ [ "PROTECT" , 1 , 2 , SFLG_NOMAXPARAM , ADMIN_FLAG , lm ( 'GS_HLP_PRT_SHORT' ) , lm ( 'GS_HLP_PRT_LONG' ) ] ,
73
+ [ "UNPROTECT" , 1 , 2 , SFLG_NOMAXPARAM , ADMIN_FLAG , lm ( 'GS_HLP_UPR_SHORT' ) , lm ( 'GS_HLP_UPR_LONG' ) ] ,
74
+ ]
72
75
] ) # register
73
76
74
77
# Which hooks do we want?
@@ -100,6 +103,15 @@ def initialize()
100
103
irc_lower($1)' )
101
104
@dbq [ 'INCREASE_KILLS' ] = DB . prepare ( 'UPDATE ganneffserv SET kills = kills+1
102
105
WHERE irc_lower(channel) = irc_lower($1)' )
106
+ @dbq [ 'INSERT_PROTECT' ] = DB . prepare ( 'INSERT INTO ganneffprotect(setter, time,
107
+ pattern, reason) VALUES($1, $2, $3, $4)' )
108
+ @dbq [ 'DELETE_PROTECT' ] = DB . prepare ( 'DELETE FROM ganneffprotect WHERE
109
+ irc_lower(pattern) = irc_lower($1)' )
110
+ @dbq [ 'GET_PROTECTED_PATTERNS' ] = DB . prepare ( 'SELECT pattern, reason FROM ganneffprotect' )
111
+ @dbq [ 'GET_PROTECTED_PATTERNS_DETAILED' ] = DB . prepare ( 'SELECT pattern, setter, time,
112
+ reason FROM ganneffprotect' )
113
+
114
+ load_protected_patterns
103
115
end # def initialize
104
116
105
117
########################################################################
@@ -221,6 +233,48 @@ def DEL(client, parv = [])
221
233
true
222
234
end # def DEL
223
235
236
+ # ------------------------------------------------------------------------
237
+
238
+ # Protect users from collatoral damage
239
+ def PROTECT ( client , parv = [ ] )
240
+ parv [ 1 ] . downcase!
241
+ debug ( LOG_DEBUG , "#{ client . name } called PROTECT and the params are #{ parv . join ( "," ) } " )
242
+
243
+ requested_pattern = parv [ 1 ]
244
+ pattern = irc_pattern_to_regex ( requested_pattern )
245
+ reason = parv [ 2 ]
246
+
247
+ ret = DB . execute_nonquery ( @dbq [ 'INSERT_PROTECT' ] , 'iiss' , client . nick . account_id ,
248
+ Time . now . to_i , pattern , reason )
249
+ if ret then
250
+ debug ( LOG_NOTICE , "#{ client . name } added protection #{ pattern } , reason #{ reason } " )
251
+ @protection [ pattern ] = reason
252
+ load_protected_patterns
253
+ reply ( client , "Protection #{ requested_pattern } successfully added" )
254
+ else
255
+ reply ( client , "Failed to add #{ requested_pattern } " )
256
+ end
257
+
258
+ # ------------------------------------------------------------------------
259
+
260
+ # Unprotect users from collatoral damage
261
+ def UNPROTECT ( client , parv = [ ] )
262
+ parv [ 1 ] . downcase!
263
+ debug ( LOG_DEBUG , "#{ client . name } called UNPROTECT and the params are #{ parv . join ( "," ) } " )
264
+
265
+ pattern = irc_pattern_to_regex ( parv [ 1 ] )
266
+ return unless @protection . has_key? ( pattern )
267
+
268
+ ret = DB . execute_nonquery ( @dbq [ 'DELETE_PROTECT' ] , 's' , pattern )
269
+ if ret then
270
+ debug ( LOG_NOTICE , "#{ client . name } removed protection #{ pattern } " )
271
+ @protection . delete ( pattern )
272
+ load_protected_patterns
273
+ reply ( client , "Protection #{ pattern } successfully deleted." )
274
+ else
275
+ reply ( client , "Failed to delete protection #{ pattern } ." )
276
+ end
277
+
224
278
# ------------------------------------------------------------------------
225
279
226
280
# List all channels we monitor
@@ -245,6 +299,18 @@ def LIST(client, parv = [])
245
299
}
246
300
result . free
247
301
302
+ reply ( client , "Protected host patterns\n \n " )
303
+ reply ( client , "%-50s %-10s %-19s %s" % [ "Pattern" , "By" , "When" , "Reason" ] )
304
+ result = DB . execute ( @dbq [ 'GET_PROTECTED_PATTERNS_DETAILED' ] )
305
+ result . row_each { |row |
306
+ pattern = row [ 0 ]
307
+ by = row [ 1 ]
308
+ time = Time . at ( row [ 2 ] . to_i ) . strftime ( '%Y-%m-%d %H:%M:%S' )
309
+ reason = row [ 3 ]
310
+ reply ( client , "%-50s %-10s %-19s %s" % [ pattern , by , time , reason ] )
311
+ }
312
+ result . free
313
+
248
314
reply ( client , "\n CRFJ - checks Connect, Register nick, Join channel within 15 seconds (i.e. Fast)" )
249
315
reply ( client , "J - triggers on every Join" )
250
316
@@ -574,8 +640,13 @@ def akill(client, reason, operreason, channel="")
574
640
ret = kill_user ( client , reason )
575
641
else # if host
576
642
reason = "#{ reason } |#{ operreason } "
577
- debug ( LOG_DEBUG , "Issuing AKILL: *@#{ host } , #{ reason } lasting for #{ @akill_duration } seconds" )
578
- ret = akill_add ( "*@#{ host } " , reason , @akill_duration )
643
+ if client . host =~ /#{ @protected_patterns } /i # if protected hosts
644
+ debug ( LOG_DEBUG , "Using /kill instead of AKILL for protected user #{ client . name } " )
645
+ ret = kill_user ( client , reason )
646
+ else
647
+ debug ( LOG_DEBUG , "Issuing AKILL: *@#{ host } , #{ reason } lasting for #{ @akill_duration } seconds" )
648
+ ret = akill_add ( "*@#{ host } " , reason , @akill_duration )
649
+ end # if protected hosts
579
650
end # if host
580
651
581
652
channel . downcase!
@@ -596,6 +667,31 @@ def akill(client, reason, operreason, channel="")
596
667
end # if kill_user
597
668
end # def akill
598
669
670
+ # ------------------------------------------------------------------------
671
+
672
+ # convert irc pattern to regular expression
673
+ def irc_pattern_to_regex ( pattern
674
+ # "." -> "\.", "*" -> ".*", "?" -> "."
675
+ # wrap with "^...$"
676
+ return pattern if pattern . start_with? '^'
677
+ pattern = pattern . gsub ( /\. / , '\\.' )
678
+ . gsub ( /\* / , '.*' )
679
+ . gsub ( /\? / , '.' )
680
+ return "^#{ pattern } $"
681
+ end
682
+
683
+ # ------------------------------------------------------------------------
684
+
685
+ # get protected patterns as pattern
686
+ def load_protected_patterns ( )
687
+ patterns = @protection . keys
688
+ if patterns . empty?
689
+ @protected_patterns = '^$'
690
+ else
691
+ @protected_patterns = patterns . join ( '|' )
692
+ end
693
+ end # def get_protected_patterns
694
+
599
695
# ------------------------------------------------------------------------
600
696
601
697
# enforce a channel - kill all of its users
@@ -648,6 +744,21 @@ def load_data()
648
744
count += 1
649
745
}
650
746
result . free
747
+
748
+ @protection = Hash . new
749
+ result = DB . execute ( @dbq [ 'GET_PROTECTED_PATTERNS' ] , '' )
750
+ count = 0
751
+ result . row_each { |row |
752
+ pattern = row [ 0 ]
753
+ reason = row [ 1 ]
754
+ pattern = irc_pattern_to_regex ( pattern )
755
+ pattern = Regexp . escape ( pattern )
756
+ @protection [ pattern ] = reason
757
+ count += 1
758
+ }
759
+ result . free
760
+ load_protected_patterns
761
+
651
762
debug ( LOG_DEBUG , "All channel data successfully loaded" )
652
763
end # def load_data
653
764
0 commit comments