]> jfr.im git - irc/SurrealServices/srsv.git/commitdiff
Clean up ban/tempban
authorerry <redacted>
Sat, 7 Jan 2012 11:40:23 +0000 (11:40 +0000)
committererry <redacted>
Sat, 7 Jan 2012 11:40:23 +0000 (11:40 +0000)
git-svn-id: http://svn.tabris.net/repos/srsv@3576 70d4eda1-72e9-0310-a436-91e5bd24443c

branches/0.4.3/modules/serviceslibs/chanserv.pm

index e7a6299a44878f084bebcf0c441e568fb12a0dcd..32da9e47ae16a7839acbf2fb1af73a6a2a1050f9 100644 (file)
@@ -455,7 +455,7 @@ sub init() {
                SELECT ?,    descrip, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), modelock, founderid, successorid, bot, flags, bantype,bantime
                FROM chanreg WHERE chan=?");
        $get_bantime = $dbh->prepare ("SELECT bantime FROM chanreg WHERE chan=?");
-       $set_bantime = $dbh->prepare ("UPDATE chanreg set bantime=? WHERE chan=?");
+       $set_bantime = $dbh->prepare ("UPDATE chanreg SET bantime=? WHERE chan=?");
        $drop_acc = $dbh->prepare("DELETE FROM chanacc WHERE chan=?");
        $drop_lvl = $dbh->prepare("DELETE FROM chanlvl WHERE chan=?");
        $drop_akick = $dbh->prepare("DELETE FROM akick WHERE chan=?");
@@ -519,9 +519,9 @@ sub init() {
        $drop_chantext = $dbh->prepare("DELETE FROM chantext WHERE chan=?");
        $drop_nicktext = $dbh->prepare("DELETE nicktext.* FROM nicktext WHERE nicktext.chan=?");
        $get_host = $dbh->prepare ("SELECT user.host from user where user.nick=?");
-       $get_host_inchan= $dbh->prepare ("select clonedUsers.nick from user as curUser join user as clonedUsers on (curUser.host=clonedUsers.host) join chanuser on (chanuser.nickid=clonedUsers.id) where clonedUsers.id!=curUser.id and curUser.id=? and chanuser.chan=? and chanuser.joined=1");
-       $get_expired_bans = $dbh->prepare("select * from tmpban where expiry < UNIX_TIMESTAMP()");
-       $del_tmpban = $dbh->prepare("delete from tmpban where channel=? and banmask like ?");
+       $get_host_inchan= $dbh->prepare ("SELECT clonedUsers.nick FROM user AS curUser JOIN user AS clonedUsers ON (curUser.host=clonedUsers.host) JOIN chanuser ON (chanuser.nickid=clonedUsers.id) WHERE clonedUsers.id!=curUser.id AND curUser.id=? AND chanuser.chan=? AND chanuser.joined=1");
+       $get_expired_bans = $dbh->prepare("SELECT channel, banmask, expiry, timeset FROM tmpban WHERE expiry < UNIX_TIMESTAMP()");
+       $del_tmpban = $dbh->prepare("DELETE FROM tmpban WHERE channel=? AND banmask LIKE ?");
 }
 
 use SrSv::MySQL::Stub {
@@ -551,36 +551,46 @@ our %high_priority_cmds = (
 sub check_expired_bans() {
        add_timer('ChanServ Expire', 10, __PACKAGE__, 'chanserv::check_expired_bans');
        $get_expired_bans->execute();
-       while (my ($cn, $ban) = $get_expired_bans->fetchrow_array()) {
+
+    while (my ($cn, $ban) = $get_expired_bans->fetchrow_array()) {
                my $chan = {CHAN=>$cn};
                ircd::setmode(agent($chan), $cn, '-b', $ban);
                ircd::flushmodes();
        }
 }
-sub tempban($$$@) {
-       my ($chan, $user, $mask, $args) = @_;
-       my $expiry = 0;
-       my @argz = split (" ",$args);
-       $expiry = parse_time(shift @argz) if $argz[0] =~ /\+/;
-       #kickban($chan, $user, undef, 'No clones allowed in this channel.');
-       my $reason = join(' ', @argz);
-       $reason =~ s/^\:// if $reason;
-       kickban ($chan, $user, $mask, $reason, undef, $expiry);
+sub tempban($$;$) {
+       my ($chan, $bansref, $expiry) = @_;
+       
+    my $cn = $chan->{CHAN};    
+    my @bans = @$bansref;
+
+    if ($expiry) {
+        foreach my $ban (@bans) {
+               $add_tempban->execute($cn, $ban, $expiry);
+        }
+       }
+
+    ircd::ban_list(agent($chan), $cn, +1, 'b', @bans) if (scalar(@bans));
+
 }
 sub clones_exist ($$) {
        my ($user, $chan) = @_;
        my $cn = $chan->{CHAN};
+
        unless(cr_chk_flag($chan, CRF_NOCLONES)) {
                return;
        }
+
        my $nick = $user->{NICK};
        $get_host_inchan->execute(get_user_id($user), $cn);
        my ($joined) = $get_host_inchan->fetchrow_array;
-       $get_host_inchan->finish();
-       if ($joined) {
+    $get_host_inchan->finish();
+
+    if ($joined) {
                return $joined;
        }
-       return 0;
+       
+    return 0;
 }
 sub dispatch($$$) {
        my ($src, $dst, $msg) = @_;
@@ -610,11 +620,11 @@ sub dispatch($$$) {
                }
        }
        elsif ($cmd =~ /^t((e)?mp)?b(an)?$/i) {
-               my @args = split(/\s+/, $msg, 4); shift @args;
-               my ($cn) = $args[0];
-               my ($target) = $args[1];
-               my ($reason) = $args[2];
-               my $chan = {CHAN=>$cn};
+               my @args = split(/\s+/, $msg, 4);
+               
+        my (undef, $cn, $target, $reason) = @args;
+               
+        my $chan = { CHAN => $cn };
                cs_tempban ($user, $chan, $target, $reason);
        }
                
@@ -2338,77 +2348,131 @@ sub cs_drop($$) {
        undef($enforcers{lc $cn});
        botserv::bot_part_if_needed(undef(), $chan, "Channel dropped.");
 }
-sub cs_tempban($$$;$) {
-       my ($user, $chan, $target, $reason) = @_;
-       if(ref($chan) ne 'HASH' || !defined($chan->{CHAN})) {
-               notice($user, "Invalid tempban command, no channel specified");
-               return;
-       }
-       my @argz = split (" ",$reason);
-       my $expiry;
-       $expiry = shift @argz if $argz[0] =~ /\+/;
-       $reason = join (" ", @argz);
-       my $srclevel = get_best_acc($user, $chan);
-       my ($nick, $override) = can_do($chan, 'BAN', $user, { ACC => $srclevel });
-       return unless $nick;
-       my $src = get_user_nick($user);
-       my $cn = $chan->{CHAN};
-       $reason = "$expiry Requested by $src".($reason?": $reason":'' ) . " ($expiry)";
-       my @errors = (
+sub get_bans($$$@) {
+    my ($user, $chan, $type, @targets) = @_;
+
+    my $cn = $chan->{CHAN};
+
+    my (@bans, @unbans);
+    my ($nick, $override);
+
+    my $src = get_user_nick($user);
+    my $srclevel = get_best_acc($user, $chan);
+    
+    if (!is_agent ($src)) {
+        ($nick, $override) = can_do($chan, 'BAN', $user, { ACC => $srclevel });        
+        return unless $nick;
+    } else {
+        $override = 1;
+    }
+    
+    my @errors = (
                ["I'm sorry, $src, I'm afraid I can't do that."],
                ["They are not in \002$cn\002."],
                [$err_deny],
                ["User not found"],
        );
-       my $peace = ({modes::splitmodes(get_modelock($chan))}->{Q}->[0] eq '+');
+    
+    foreach my $target (@targets) {
+        my $tuser;
+
+        if(ref($target)) {
+            $tuser = $target;
+        }
+        elsif($target =~ /\,/) {
+            push @targets, split(',', $target);
+            next;
+        }
+        elsif($target eq '') {
+            # Should never happen
+            # but it could, given the split above
+            next;
+        }
+        elsif($target =~ /^-/) {
+            $target =~ s/^\-//;
+            push @unbans, $target;
+            next;
+        }
+        elsif($target =~ /[!@]+/) {
+            ircd::debug("normalizing hostmask $target");
+            $target = normalize_hostmask($target);
+            push @bans, $target;
+            next;
+        }
+        elsif(valid_nick($target)) {
+            $tuser = { NICK => $target };
+        }
+        elsif($target = validate_ban($target)) {
+            push @bans, $target;
+            next;
+        } else {
+            notice($user, "Not a valid ban target: $target");
+            next;
+        }
+        my $targetlevel = get_best_acc($tuser, $chan);
+
+        if(lc $target eq lc agent($chan) or adminserv::is_service($tuser)) {
+            push @{$errors[0]}, get_user_nick($tuser);
+            next;
+        }
+    
+        unless(get_user_id($tuser)) {
+            push @{$errors[1]}, get_user_nick($tuser);
+            next;
+        }
+        
+        if( $srclevel <= $targetlevel and not ($override && check_override($user, 'BAN', "BAN $cn $target")) ) {
+            push @{$errors[2]}, $target;
+            next;
+        }
+
+        push @bans, make_banmask($chan, $tuser, $type);
+    }
+
+    foreach my $errlist (@errors) {
+        if(@$errlist > 1) {
+            my $msg = shift @$errlist;
+            
+            foreach my $e (@$errlist) { $e = "\002$e\002" }
+        
+            notice($user,
+                "Cannot ban ".
+                enum("or", @$errlist).
+                ": $msg"
+            );
+        }
+    }
+    return (\@bans, \@unbans);
+}
+
+sub cs_tempban($$$;$) {
+    my ($user, $chan, $target, $expiry) = @_;
        my @targets = split(/\,/, $target);
-       foreach $target (@targets) {
-               if($target =~ /[!@]+/) {
-                       ircd::debug("normalizing hostmask $target");
-                       #$target = normalize_hostmask($target);
-#=cut
-                       my ($nick, $ident, $host) = parse_mask($target);
-                       $nick = '*' unless length($nick);
-                       $ident = '*' unless length($ident);
-                       $host = '*' unless length($host);
-                       $target = "$nick\!$ident\@$host";
-#=cut
-                       ircd::debug("normalized hostmask: $target");
-                       tempban ($chan, undef, $target, $reason);
-                       next;
-               }
-               my $tuser = { NICK => $target };
-               my $targetlevel = get_best_acc($tuser, $chan);
-               if(lc $target eq lc agent($chan) or adminserv::is_service($tuser)) {
-                       push @{$errors[0]}, $target;
-                       next;
-               }
-               if(!get_user_id($tuser)) {
-                       push @{$errors[3]}, $target;
-                       next;
-               }
+    
+    my $src = get_user_nick($user);
 
-               if( ( ($peace and $targetlevel > 0) or ($srclevel <= $targetlevel) ) 
-                       and not ($override && check_override($user, 'BAN', "tempban $cn $target")) )
-               {
-                       push @{$errors[2]}, $target;
-                       next;
-               }
-               tempban ($chan, $tuser, undef, $reason);
-       }
-       foreach my $errlist (@errors) {
-               if(@$errlist > 1) {
-                       my $msg = shift @$errlist;
-                       
-                       foreach my $e (@$errlist) { $e = "\002$e\002" }
-                       
-                       notice($user,
-                               "Cannot tempban ".
-                               enum("or", @$errlist).
-                               ": $msg"
-                       );
-               }
+    $expiry = parse_time($expiry) if ($expiry =~/\+/); 
+    my $cn = $chan->{CHAN};
+    
+    if ($expiry eq '') {
+               $get_bantime->execute($cn);
+               ($expiry) = $get_bantime->fetchrow_array();
+               $get_bantime->finish();
        }
+
+    my ($bansref, $unbansref) = get_bans ($user, $chan, '', @targets);
+   
+    if (!$bansref && !$unbansref) {
+        return;
+    }
+
+    my (@bans, @unbans) = (@$bansref, @$unbansref);
+
+    tempban ($chan, $bansref, $expiry);
+
+    ircd::notice(agent($chan), $cn, "$src used TEMPBAN ".join(' ', @bans))
+        if (lc $user->{AGENT} eq lc $csnick) and (cr_chk_flag($chan, CRF_VERBOSE) and scalar(@bans));
+    cs_unban($user, $chan, @unbans) if scalar(@unbans);
 }
 
 sub cs_kick($$$;$$) {
@@ -2416,7 +2480,8 @@ sub cs_kick($$$;$$) {
 
        my $cmd = ($ban ? 'KICKBAN' : 'KICK');
        my $perm = ($ban ? 'BAN' : 'KICK');
-       if(ref($chan) ne 'HASH' || !defined($chan->{CHAN})) {
+       
+    if(ref($chan) ne 'HASH' || !defined($chan->{CHAN})) {
                notice($user, "Invalid $cmd command, no channel specified");
                return;
        }
@@ -2515,101 +2580,20 @@ sub cs_kickmask($$$;$$) {
 
 sub cs_ban($$$@) {
        my ($user, $chan, $type, @targets) = @_;
-       my $cn = $chan->{CHAN};
-       my $src = get_user_nick($user);
-
-       my $srclevel = get_best_acc($user, $chan);
-       my ($nick, $override) = can_do($chan, 'BAN', $user, { ACC => $srclevel });
-       return unless $nick;
 
-       my @errors = (
-               ["I'm sorry, $src, I'm afraid I can't do that."],
-               ["User not found"],
-               [$err_deny]
-       );
-
-       my (@bans, @unbans);
-       foreach my $target (@targets) {
-               my $tuser;
-
-               if(ref($target)) {
-                       $tuser = $target;
-               }
-               elsif($target =~ /\,/) {
-                       push @targets, split(',', $target);
-                       next;
-               }
-               elsif($target eq '') {
-                       # Should never happen
-                       # but it could, given the split above
-                       next;
-               }
-               elsif($target =~ /^-/) {
-                       $target =~ s/^\-//;
-                       push @unbans, $target;
-                       next;
-               }
-=cut
-               elsif($target =~ /[!@]+/) {
-                       ircd::debug("normalizing hostmask $target");
-                       #$target = normalize_hostmask($target);
-#=cut
-                       my ($nick, $ident, $host) = parse_mask($target);
-                       $nick = '*' unless length($nick);
-                       $ident = '*' unless length($ident);
-                       $host = '*' unless length($host);
-                       $target = "$nick\!$ident\@$host";
-#=cut
-                       ircd::debug("normalized hostmask: $target");
-
-                       push @bans, $target;
-                       next;
-               }
-=cut
-               elsif(valid_nick($target)) {
-                       $tuser = { NICK => $target };
-               }
-               elsif($target = validate_ban($target)) {
-                       push @bans, $target;
-                       next;
-               } else {
-                       notice($user, "Not a valid ban target: $target");
-                       next;
-               }
-               my $targetlevel = get_best_acc($tuser, $chan);
-
-               if(lc $target eq lc agent($chan) or adminserv::is_service($tuser)) {
-                       push @{$errors[0]}, get_user_nick($tuser);
-                       next;
-               }
-               
-               unless(get_user_id($tuser)) {
-                       push @{$errors[1]}, get_user_nick($tuser);
-                       next;
-               }
-               if( $srclevel <= $targetlevel and not ($override && check_override($user, 'BAN', "BAN $cn $target")) ) {
-                       push @{$errors[2]}, $target;
-                       next;
-               }
-
-               push @bans, make_banmask($chan, $tuser, $type);
-       }
-
-       foreach my $errlist (@errors) {
-               if(@$errlist > 1) {
-                       my $msg = shift @$errlist;
-                       
-                       foreach my $e (@$errlist) { $e = "\002$e\002" }
-                       
-                       notice($user,
-                               "Cannot ban ".
-                               enum("or", @$errlist).
-                               ": $msg"
-                       );
-               }
-       }
-
-       ircd::ban_list(agent($chan), $cn, +1, 'b', @bans) if (scalar(@bans));
+    my $src = get_user_nick ($user);
+
+    my $cn = $chan->{CHAN};
+    
+    my ($bansref, $unbansref) = get_bans ($user, $chan, $type, @targets);
+    
+    if (!$bansref && !$unbansref) {
+        return;
+    }
+    
+    my (@bans, @unbans) = (@$bansref, @$unbansref);
+       
+    ircd::ban_list(agent($chan), $cn, +1, 'b', @bans) if (scalar(@bans));
        ircd::notice(agent($chan), $cn, "$src used BAN ".join(' ', @bans))
                if (lc $user->{AGENT} eq lc $csnick) and (cr_chk_flag($chan, CRF_VERBOSE) and scalar(@bans));
        cs_unban($user, $chan, @unbans) if scalar(@unbans);
@@ -3590,15 +3574,18 @@ sub make_banmask($$;$) {
 }
 
 sub kickban($$$$;$$) {
-       my ($chan, $user, $mask, $reason, $noflush, $expiry) = @_;
-       my $cn = $chan->{CHAN};
+       my ($chan, $user, $mask, $reason, $noflush) = @_;
+       
+    my $cn = $chan->{CHAN};
        my $nick;
        $nick = get_user_nick($user) if ($user);
-       if (!$user && !$mask) {
+       
+    if (!$user && !$mask) {
                ircd::debug ("No user or mask given for /cs kickban!");
                return;
        }
-       return 0 if $user && adminserv::is_service($user);
+       
+    return 0 if $user && adminserv::is_service($user);
 
        my $agent = agent($chan);
 
@@ -3608,15 +3595,8 @@ sub kickban($$$$;$$) {
 
        enforcer_join($chan) if (get_user_count($chan) <= 1);
        ircd::setmode($agent, $cn, '+b', $mask);
-       if (!defined($expiry)) {
-               $get_bantime->execute($cn);
-               ($expiry) = $get_bantime->fetchrow_array();
-               $get_bantime->finish();
-       }
-       if ($expiry) {
-               $add_tempban->execute($cn, $mask, $expiry);
-       }
-       ircd::flushmodes() unless $noflush;
+               
+    ircd::flushmodes() unless $noflush;
        ircd::kick($agent, $cn, $nick, $reason) if ($nick);
        return 1;
 }
@@ -3872,7 +3852,12 @@ sub do_status($$;$) {
        my ($accnick, $override) = can_do($chan, 'JOIN', $user, { ACC => $acc, NOREPLY => 1 });
        unless ($acc > 0 || $override) {
                if (clones_exist ($user, $chan)) {
-                       tempban($chan, $user, undef, "+60s No clones allowed in this channel.");
+            my $mask = make_banmask($chan, $user);
+                       my $cn = $chan->{CHAN};
+
+            tempban($chan, [ $mask ], "+60s");
+
+            ircd::kick(agent($chan), $cn, $nick, "No clones allowed in this channel.") unless adminserv::is_service($user);
                }
        }