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=?");
$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 {
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) = @_;
}
}
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);
}
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($$$;$$) {
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;
}
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);
}
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);
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;
}
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);
}
}