+ if ( $message =~ /^chpass(\s+(.*))?$/ ) {
+ my (@args) = split /[\s\t]+/, $2 || '';
+
+ if ( !scalar @args ) {
+ &help('chpass');
+ return;
+ }
+
+ if ( !&IsUser( $args[0] ) ) {
+ &performStrictReply("user $args[0] is not valid.");
+ return;
+ }
+
+ my $u = &getUser( $args[0] );
+ if ( !defined $u ) {
+ &performStrictReply("Internal error, u = NULL.");
+ return;
+ }
+
+ if ( scalar @args == 1 ) {
+
+ # del pass.
+ if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
+ &performStrictReply("cannot remove passwd of others.");
+ return;
+ }
+
+ if ( !exists $users{$u}{PASS} ) {
+ &performStrictReply("$u does not have pass set anyway.");
+ return;
+ }
+
+ &performStrictReply("Deleted pass from $u.");
+
+ $utime_userfile = time();
+ $ucount_userfile++;
+
+ delete $users{$u}{PASS};
+
+ return;
+ }
+
+ my $crypt = &mkcrypt( $args[1] );
+ &performStrictReply("Set $u's passwd to '$crypt'");
+ $users{$u}{PASS} = $crypt;
+
+ $utime_userfile = time();
+ $ucount_userfile++;
+
+ return;
+ }
+
+ if ( $message =~ /^chattr(\s+(.*))?$/ ) {
+ my (@args) = split /[\s\t]+/, $2 || '';
+
+ if ( !scalar @args ) {
+ &help('chattr');
+ return;
+ }
+
+ my $chflag;
+ my $user;
+ if ( $args[0] =~ /^$mask{nick}$/i ) {
+
+ # <nick>
+ $user = &getUser( $args[0] );
+ $chflag = $args[1];
+ }
+ else {
+
+ # <flags>
+ $user = &getUser($who);
+ &DEBUG("user $who... nope.") unless ( defined $user );
+ $user = &getUser($verifyUser);
+ $chflag = $args[0];
+ }
+
+ if ( !defined $user ) {
+ &performStrictReply("user does not exist.");
+ return;
+ }
+
+ my $flags = $users{$user}{FLAGS};
+ if ( !defined $chflag ) {
+ &performStrictReply("Flags for $user: $flags");
+ return;
+ }
+
+ &DEBUG("who => $who");
+ &DEBUG("verifyUser => $verifyUser");
+ if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
+ &performStrictReply("cannto change attributes of others.");
+ return 'REPLY';
+ }
+
+ my $state;
+ my $change = 0;
+ foreach ( split //, $chflag ) {
+ if ( $_ eq "+" ) { $state = 1; next; }
+ if ( $_ eq "-" ) { $state = 0; next; }
+
+ if ( !defined $state ) {
+ &performStrictReply("no initial + or - was found in attr.");
+ return;
+ }
+
+ if ($state) {
+ next if ( $flags =~ /\Q$_\E/ );
+ $flags .= $_;
+ }
+ else {
+ if ( &IsParam('owner')
+ and $param{owner} =~ /^\Q$user\E$/i
+ and $flags =~ /[nmo]/ )
+ {
+ &performStrictReply("not removing flag $_ for $user.");
+ next;
+ }
+ next unless ( $flags =~ s/\Q$_\E// );
+ }
+
+ $change++;
+ }
+
+ if ($change) {
+ $utime_userfile = time();
+ $ucount_userfile++;
+
+ #$flags.*FLAGS sort
+ $flags = join( '', sort split( '', $flags ) );
+ &performStrictReply("Current flags: $flags");
+ $users{$user}{FLAGS} = $flags;
+ }
+ else {
+ &performStrictReply("No flags changed: $flags");
+ }
+
+ return;
+ }
+
+ if ( $message =~ /^chnick(\s+(.*))?$/ ) {
+ my (@args) = split /[\s\t]+/, $2 || '';
+
+ if ( $who eq '_default' ) {
+ &WARN("$who or verifyuser tried to run chnick.");
+ return 'REPLY';
+ }
+
+ if ( !scalar @args or scalar @args > 2 ) {
+ &help('chnick');
+ return;
+ }
+
+ if ( scalar @args == 1 ) { # 1
+ $user = &getUser($who);
+ &DEBUG("nope, not $who.") unless ( defined $user );
+ $user ||= &getUser($verifyUser);
+ $chnick = $args[0];
+ }
+ else { # 2
+ $user = &getUser( $args[0] );
+ $chnick = $args[1];
+ }
+
+ if ( !defined $user ) {
+ &performStrictReply("user $who or $args[0] does not exist.");
+ return;
+ }
+
+ if ( $user =~ /^\Q$chnick\E$/i ) {
+ &performStrictReply("user == chnick. why should I do that?");
+ return;
+ }
+
+ if ( &getUser($chnick) ) {
+ &performStrictReply("user $chnick is already used!");
+ return;
+ }
+
+ if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
+ &performStrictReply("cannto change nick of others.");
+ return 'REPLY' if ( $who eq '_default' );
+ return;
+ }
+
+ foreach ( keys %{ $users{$user} } ) {
+ $users{$chnick}{$_} = $users{$user}{$_};
+ delete $users{$user}{$_};
+ }
+ undef $users{$user}; # ???
+
+ $utime_userfile = time();
+ $ucount_userfile++;
+
+ &performStrictReply("Changed '$user' to '$chnick' successfully.");
+
+ return;
+ }
+
+ if ( $message =~ /^(hostadd|hostdel)(\s+(.*))?$/ ) {
+ my $cmd = $1;
+ my (@args) = split /[\s\t]+/, $3 || '';
+ my $state = ( $1 eq "hostadd" ) ? 1 : 0;
+
+ if ( !scalar @args ) {
+ &help($cmd);
+ return;
+ }
+
+ if ( $who eq '_default' ) {
+ &WARN("$who or verifyuser tried to run $cmd.");
+ return 'REPLY';
+ }
+
+ my ( $user, $mask );
+ if ( $args[0] =~ /^$mask{nick}$/i ) { # <nick>
+ return unless ( &hasFlag('n') );
+ $user = &getUser( $args[0] );
+ $mask = $args[1];
+ }
+ else { # <mask>
+ # FIXME: who or verifyUser. (don't remember why)
+ $user = &getUser($who);
+ $mask = $args[0];
+ }
+
+ if ( !defined $user ) {
+ &performStrictReply("user $user does not exist.");
+ return;
+ }
+
+ if ( !defined $mask ) {
+ &performStrictReply( "Hostmasks for $user: "
+ . join( ' ', keys %{ $users{$user}{HOSTS} } ) );
+ return;
+ }
+
+ if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
+ &performStrictReply("cannto change masks of others.");
+ return;
+ }
+
+ my $count = scalar keys %{ $users{$user}{HOSTS} };
+
+ if ($state) { # add.
+ if ( $mask !~ /^$mask{nuh}$/ ) {
+ &performStrictReply(
+ "error: mask ($mask) is not a real hostmask.");
+ return;
+ }
+
+ if ( exists $users{$user}{HOSTS}{$mask} ) {
+ &performStrictReply("mask $mask already exists.");
+ return;
+ }
+
+ ### TODO: override support.
+ $users{$user}{HOSTS}{$mask} = 1;
+
+ &performStrictReply("Added $mask to list of masks.");
+
+ }
+ else { # delete.
+
+ if ( !exists $users{$user}{HOSTS}{$mask} ) {
+ &performStrictReply("mask $mask does not exist.");
+ return;
+ }
+
+ ### TODO: wildcard support. ?
+ delete $users{$user}{HOSTS}{$mask};
+
+ if ( scalar keys %{ $users{$user}{HOSTS} } != $count ) {
+ &performStrictReply("Removed $mask from list of masks.");
+ }
+ else {
+ &performStrictReply(
+ "error: could not find $mask in list of masks.");
+ return;
+ }
+ }
+
+ $utime_userfile = time();
+ $ucount_userfile++;
+
+ return;
+ }
+
+ if ( $message =~ /^(banadd|bandel)(\s+(.*))?$/ ) {
+ my $cmd = $1;
+ my $flatarg = $3;
+ my (@args) = split /[\s\t]+/, $3 || '';
+ my $state = ( $1 eq "banadd" ) ? 1 : 0;
+
+ if ( !scalar @args ) {
+ &help($cmd);
+ return;
+ }
+
+ my ( $mask, $chan, $time, $reason );
+
+ if ( $flatarg =~ s/^($mask{nuh})\s*// ) {
+ $mask = $1;
+ }
+ else {
+ &DEBUG("arg does not contain nuh mask?");
+ }
+
+ if ( $flatarg =~ s/^($mask{chan})\s*// ) {
+ $chan = $1;
+ }
+ else {
+ $chan = '*'; # _default instead?
+ }
+
+ if ( $state == 0 ) { # delete.
+ my @c = &banDel($mask);
+
+ foreach (@c) {
+ &unban( $mask, $_ );
+ }
+
+ if (@c) {
+ &performStrictReply("Removed $mask from chans: @c");
+ }
+ else {
+ &performStrictReply("$mask was not found in ban list.");
+ }
+
+ return;
+ }
+
+ ###
+ # add ban.
+ ###
+
+ # time.
+ if ( $flatarg =~ s/^(\d+)\s*// ) {
+ $time = $1;
+ &DEBUG("time = $time.");
+ if ( $time < 0 ) {
+ &performStrictReply("error: time cannot be negatime?");
+ return;
+ }
+ }
+ else {
+ $time = 0;
+ }
+
+ if ( $flatarg =~ s/^(.*)$// ) { # need length?
+ $reason = $1;
+ }
+
+ if ( !&IsFlag('n') and $who !~ /^\Q$verifyUser\E$/i ) {
+ &performStrictReply("cannto change masks of others.");
+ return;
+ }
+
+ if ( $mask !~ /^$mask{nuh}$/ ) {
+ &performStrictReply("error: mask ($mask) is not a real hostmask.");
+ return;
+ }
+
+ if ( &banAdd( $mask, $chan, $time, $reason ) == 2 ) {
+ &performStrictReply("ban already exists; overwriting.");
+ }
+ &performStrictReply(
+ "Added $mask for $chan (time => $time, reason => $reason)");
+
+ return;
+ }
+
+ if ( $message =~ /^whois(\s+(.*))?$/ ) {
+ my $arg = $2;
+
+ if ( !defined $arg ) {
+ &help('whois');
+ return;
+ }
+
+ my $user = &getUser($arg);
+ if ( !defined $user ) {
+ &performStrictReply("whois: user '$arg' does not exist.");
+ return;
+ }
+
+ ### TODO: better (eggdrop-like) output.
+ &performStrictReply("user: $user");
+ foreach ( keys %{ $users{$user} } ) {
+ my $ref = ref $users{$user}{$_};
+
+ if ( $ref eq 'HASH' ) {
+ my $type = $_;
+ ### DOES NOT WORK???
+ foreach ( keys %{ $users{$user}{$type} } ) {
+ &performStrictReply(" $type => $_");
+ }
+ next;
+ }
+
+ &performStrictReply(" $_ => $users{$user}{$_}");
+ }
+ &performStrictReply("End of USER whois.");
+
+ return;
+ }
+
+ if ( $message =~ /^bans(\s+(.*))?$/ ) {
+ my $arg = $2;
+
+ if ( defined $arg ) {
+ if ( $arg ne '_default' and !&validChan($arg) ) {
+ &performStrictReply("error: chan $chan is invalid.");
+ return;
+ }
+ }
+
+ if ( !scalar keys %bans ) {
+ &performStrictReply("Ban list is empty.");
+ return;
+ }
+
+ my $c;
+ &performStrictReply(
+ " mask: expire, time-added, count, who-by, reason");
+ foreach $c ( keys %bans ) {
+ next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
+ &performStrictReply(" $c:");
+
+ foreach ( keys %{ $bans{$c} } ) {
+ my $val = $bans{$c}{$_};
+
+ if ( ref $val eq 'ARRAY' ) {
+ my @array = @{$val};
+ &performStrictReply(" $_: @array");
+ }
+ else {
+ &DEBUG("unknown ban: $val");
+ }
+ }
+ }
+ &performStrictReply("END of bans.");
+
+ return;
+ }
+
+ if ( $message =~ /^banlist(\s+(.*))?$/ ) {
+ my $arg = $2;
+
+ if ( defined $arg and $arg !~ /^$mask{chan}$/ ) {
+ &performStrictReply("error: chan $chan is invalid.");
+ return;
+ }
+
+ &DEBUG("bans for global or arg => $arg.");
+ foreach ( keys %bans ) { #CHANGE!!!
+ &DEBUG(" $_ => $bans{$_}.");
+ }
+
+ &DEBUG("End of bans.");
+ &performStrictReply("END of bans.");
+
+ return;
+ }
+
+ if ( $message =~ /^save$/ ) {
+ return unless ( &hasFlag('o') );
+
+ &writeUserFile();
+ &writeChanFile();
+ &performStrictReply('saved user and chan files');
+
+ return;
+ }
+
+ ### ALIASES.
+ $message =~ s/^addignore/+ignore/;
+ $message =~ s/^(del|un)ignore/-ignore/;
+
+ # ignore.
+ if ( $message =~ /^(\+|\-)ignore(\s+(.*))?$/i ) {
+ return unless ( &hasFlag('o') );
+ my $state = ( $1 eq "+" ) ? 1 : 0;
+ my $str = $1 . 'ignore';
+ my $args = $3;
+
+ if ( !$args ) {
+ &help($str);
+ return;
+ }
+
+ my ( $mask, $chan, $time, $comment );
+
+ # mask.
+ if ( $args =~ s/^($mask{nuh})\s*// ) {
+ $mask = $1;
+ }
+ else {
+ &ERROR("no NUH mask?");
+ return;
+ }
+
+ if ( !$state ) { # delignore.
+ if ( &ignoreDel($mask) ) {
+ &performStrictReply("ok, deleted ignores for $mask.");
+ }
+ else {
+ &performStrictReply("could not find $mask in ignore list.");
+ }
+ return;
+ }
+
+ ###
+ # addignore.
+ ###
+
+ # chan.
+ if ( $args =~ s/^($mask{chan}|\*)\s*// ) {
+ $chan = $1;
+ }
+ else {
+ $chan = '*';
+ }
+
+ # time.
+ if ( $args =~ s/^(\d+)\s*// ) {
+ $time = $1; # time is in minutes
+ }
+ else {
+ $time = 0;
+ }
+
+ # time.
+ if ($args) {
+ $comment = $args;
+ }
+ else {
+ $comment = "added by $who";
+ }
+
+ if ( &ignoreAdd( $mask, $chan, $time, $comment ) > 1 ) {
+ &performStrictReply(
+ "FIXME: $mask already in ignore list; written over anyway.");
+ }
+ else {
+ &performStrictReply("added $mask to ignore list.");
+ }
+
+ return;
+ }
+
+ if ( $message =~ /^ignore(\s+(.*))?$/ ) {
+ my $arg = $2;
+
+ if ( defined $arg ) {
+ if ( $arg !~ /^$mask{chan}$/ ) {
+ &performStrictReply("error: chan $chan is invalid.");
+ return;
+ }
+
+ if ( !&validChan($arg) ) {
+ &performStrictReply("error: chan $arg is invalid.");
+ return;
+ }
+
+ &performStrictReply("Showing bans for $arg only.");
+ }
+
+ if ( !scalar keys %ignore ) {
+ &performStrictReply("Ignore list is empty.");
+ return;
+ }
+
+ ### TODO: proper (eggdrop-like) formatting.
+ my $c;
+ &performStrictReply(" mask: expire, time-added, who, comment");
+ foreach $c ( keys %ignore ) {
+ next unless ( !defined $arg or $arg =~ /^\Q$c\E$/i );
+ &performStrictReply(" $c:");
+
+ foreach ( keys %{ $ignore{$c} } ) {
+ my $ref = ref $ignore{$c}{$_};
+ if ( $ref eq 'ARRAY' ) {
+ my @array = @{ $ignore{$c}{$_} };
+ &performStrictReply(" $_: @array");
+ }
+ else {
+ &DEBUG("unknown ignore line?");
+ }
+ }
+ }
+ &performStrictReply("END of ignore.");
+
+ return;
+ }
+
+ # useradd/userdel.
+ if ( $message =~ /^(useradd|userdel)(\s+(.*))?$/i ) {
+ my $cmd = $1;
+ my @args = split /\s+/, $3 || '';
+ my $args = $3;
+ my $state = ( $cmd eq "useradd" ) ? 1 : 0;
+
+ if ( !scalar @args ) {
+ &help($cmd);
+ return;
+ }
+
+ if ( $cmd eq 'useradd' ) {
+ if ( scalar @args != 2 ) {
+ &performStrictReply('useradd requires hostmask argument.');
+ return;
+ }
+ }
+ elsif ( scalar @args != 1 ) {
+ &performStrictReply('too many arguments.');
+ return;
+ }
+
+ if ($state) {
+
+ # adduser.
+ if ( scalar @args == 1 ) {
+ $args[1] = &getHostMask( $args[0] );
+ &performStrictReply(
+ "Attemping to guess $args[0]'s hostmask...");
+
+ # crude hack... crappy Net::IRC
+ $conn->schedule(
+ 5,
+ sub {
+
+ # hopefully this is right.
+ my $nick = ( keys %{ $cache{nuhInfo} } )[0];
+ if ( !defined $nick ) {
+ &performStrictReply(
+"couldn't get nuhinfo... adding user without a hostmask."
+ );
+ &userAdd($nick);
+ return;
+ }
+ my $mask = &makeHostMask( $cache{nuhInfo}{$nick}{NUH} );
+
+ if ( &userAdd( $nick, $mask ) ) {
+
+ # success.
+ &performStrictReply(
+ "Added $nick with flags $users{$nick}{FLAGS}");
+ my @hosts = keys %{ $users{$nick}{HOSTS} };
+ &performStrictReply("hosts: @hosts");
+ }
+ }
+ );
+ return;
+ }
+
+ &DEBUG("args => @args");
+ if ( &userAdd(@args) ) { # success.
+ &performStrictReply(
+ "Added $args[0] with flags $users{$args[0]}{FLAGS}");
+ my @hosts = keys %{ $users{ $args[0] }{HOSTS} };
+ &performStrictReply("hosts: @hosts");
+
+ }
+ else { # failure.
+ &performStrictReply("User $args[0] already exists");
+ }
+
+ }
+ else { # deluser.
+
+ if ( &userDel( $args[0] ) ) { # success.
+ &performStrictReply("Deleted $args[0] successfully.");
+
+ }
+ else { # failure.
+ &performStrictReply("User $args[0] does not exist.");
+ }
+
+ }
+ return;
+ }
+
+ if ( $message =~ /^sched$/ ) {
+ my @list;
+ my @run;
+
+ my %time;
+ foreach ( keys %sched ) {
+ next unless ( exists $sched{$_}{TIME} );
+ $time{ $sched{$_}{TIME} - time() }{$_} = 1;
+ push( @list, $_ );
+
+ next unless ( exists $sched{$_}{RUNNING} );
+ push( @run, $_ );
+ }
+
+ my @time;
+ foreach ( sort { $a <=> $b } keys %time ) {
+ my $str = join( ', ', sort keys %{ $time{$_} } );
+ &DEBUG("time => $_, str => $str");
+ push( @time, "$str (" . &Time2String($_) . ")" );
+ }
+
+ &performStrictReply( &formListReply( 0, "Schedulers: ", @time ) );
+ &performStrictReply(
+ &formListReply( 0, "Scheds to run: ", sort @list ) );
+ &performStrictReply(
+ &formListReply(
+ 0, "Scheds running(should not happen?) ",
+ sort @run
+ )
+ );
+
+ return;
+ }
+
+ # quite a cool hack: reply in DCC CHAT.
+ $msgType = 'chat' if ( exists $dcc{'CHAT'}{$who} );
+
+ my $done = 0;
+ $done++ if &parseCmdHook($message);
+ $done++ unless ( &Modules() );
+
+ if ($done) {
+ &DEBUG("running non DCC CHAT command inside DCC CHAT!");
+ return;
+ }
+
+ return 'REPLY';