Add badword handling for messages. Users will get rude messages back if
[spider.git] / perl / DXCommandmode.pm
index b6140082f6a741b59ab5ece9541823213e2eafaa..3972e8b5b6509ebab966b8aa5303cab3e3cb6e69 100644 (file)
@@ -30,6 +30,8 @@ use AnnTalk;
 use WCY;
 use Sun;
 use Internet;
+use Script;
+
 
 use strict;
 use vars qw(%Cache %cmd_cache $errstr %aliases $scriptbase $maxerrors %nothereslug);
@@ -59,7 +61,7 @@ sub new
        my $pkg = shift;
        my $call = shift;
        my @rout = $main::routeroot->add_user($call, Route::here(1));
-       DXProt::route_pc16($DXProt::me, $main::routeroot, @rout) if @rout;
+       DXProt::route_pc16($main::me, $main::routeroot, @rout) if @rout;
 
        return $self;
 }
@@ -75,6 +77,10 @@ sub start
        my $call = $self->{call};
        my $name = $user->{name};
        
+       # log it
+       my $host = $self->{conn}->{peerhost} || "unknown";
+       Log('DXCommand', "$call connected from $host");
+
        $self->{name} = $name ? $name : $call;
        $self->send($self->msg('l2',$self->{name}));
        $self->send_file($main::motd) if (-e $main::motd);
@@ -96,6 +102,7 @@ sub start
        $self->{wx} = $user->wantwx;
        $self->{dx} = $user->wantdx;
        $self->{logininfo} = $user->wantlogininfo;
+       $self->{ann_talk} = $user->wantann_talk;
        $self->{here} = 1;
 
        # get the filters
@@ -113,18 +120,6 @@ sub start
                $user->qra(DXBearing::lltoqra($lat, $long)) if (defined $lat && defined $long);  
        }
 
-       Log('DXCommand', "$call connected");
-
-       # send prompts and things
-       my $info = Route::cluster();
-       $self->send("Cluster:$info");
-       $self->send($self->msg('namee1')) if !$user->name;
-       $self->send($self->msg('qthe1')) if !$user->qth;
-       $self->send($self->msg('qll')) if !$user->qra || (!$user->lat && !$user->long);
-       $self->send($self->msg('hnodee1')) if !$user->qth;
-       $self->send($self->msg('m9')) if DXMsg::for_me($call);
-       $self->prompt;
-
        # decide on echo
        if (!$user->wantecho) {
                $self->send_now('E', "0");
@@ -137,9 +132,25 @@ sub start
        my $lastoper = $user->lastoper || 0;
        my $homenode = $user->homenode || ""; 
        if ($homenode eq $main::mycall && $lastoper + $DXUser::lastoperinterval < $main::systime) {
-               run_cmd($DXProt::me, "forward/opernam $call");
+               run_cmd($main::me, "forward/opernam $call");
                $user->lastoper($main::systime);
        }
+
+       # run a script send the output to the punter
+       my $script = new Script(lc $call) || new Script('user_default');
+       $script->run($self) if $script;
+
+       # send cluster info
+       my $info = Route::cluster();
+       $self->send("Cluster:$info");
+
+       # send prompts and things
+       $self->send($self->msg('namee1')) if !$user->name;
+       $self->send($self->msg('qthe1')) if !$user->qth;
+       $self->send($self->msg('qll')) if !$user->qra || (!$user->lat && !$user->long);
+       $self->send($self->msg('hnodee1')) if !$user->qth;
+       $self->send($self->msg('m9')) if DXMsg::for_me($call);
+       $self->prompt;
 }
 
 #
@@ -217,6 +228,16 @@ sub normal
                        # for safety
                        $self->state('prompt');
                }
+       } elsif (my $func = $self->{func}) {
+               no strict 'refs';
+               my @ans;
+               if (ref $self->{edit}) {
+                       eval { @ans = $self->{edit}->$func($self, $cmdline)};
+               } else {
+                       eval {  @ans = &{$self->{func}}($self, $cmdline) };
+               }
+               $self->send_ans("Syserr: on stored func $self->{func}", $@) if $@;
+               $self->send_ans(@ans);
        } else {
                $self->send_ans(run_cmd($self, $cmdline));
        } 
@@ -303,77 +324,54 @@ sub run_cmd
        my $cmdline = shift;
        my @ans;
        
-       if ($self->{func}) {
-               my $c = qq{ \@ans = $self->{func}(\$self, \$cmdline) };
-               dbg("stored func cmd = $c\n") if isdbg('eval');
-               eval  $c;
-               if ($@) {
-                       return ("Syserr: Eval err $errstr on stored func $self->{func}", $@);
-               }
-       } else {
 
-               return () if length $cmdline == 0;
+       return () if length $cmdline == 0;
                
-               # strip out //
-               $cmdline =~ s|//|/|og;
+       # strip out //
+       $cmdline =~ s|//|/|og;
                
-               # split the command line up into parts, the first part is the command
-               my ($cmd, $args) = split /\s+/, $cmdline, 2;
-               $args = "" unless defined $args;
+       # split the command line up into parts, the first part is the command
+       my ($cmd, $args) = split /\s+/, $cmdline, 2;
+       $args = "" unless defined $args;
                
-               if ($cmd) {
+       if ($cmd) {
                        
-                       my ($path, $fcmd);
+               my ($path, $fcmd);
                        
-                       dbg("cmd: $cmd") if isdbg('command');
+               dbg("cmd: $cmd") if isdbg('command');
                        
-                       # alias it if possible
-                       my $acmd = CmdAlias::get_cmd($cmd);
-                       if ($acmd) {
-                               ($cmd, $args) = split /\s+/, "$acmd $args", 2;
-                               $args = "" unless defined $args;
-                               dbg("aliased cmd: $cmd $args") if isdbg('command');
-                       }
+               # alias it if possible
+               my $acmd = CmdAlias::get_cmd($cmd);
+               if ($acmd) {
+                       ($cmd, $args) = split /\s+/, "$acmd $args", 2;
+                       $args = "" unless defined $args;
+                       dbg("aliased cmd: $cmd $args") if isdbg('command');
+               }
                        
-                       # first expand out the entry to a command
-                       ($path, $fcmd) = search($main::localcmd, $cmd, "pl");
-                       ($path, $fcmd) = search($main::cmd, $cmd, "pl") if !$path || !$fcmd;
+               # first expand out the entry to a command
+               ($path, $fcmd) = search($main::localcmd, $cmd, "pl");
+               ($path, $fcmd) = search($main::cmd, $cmd, "pl") if !$path || !$fcmd;
 
-                       if ($path && $cmd) {
-                               dbg("path: $cmd cmd: $fcmd") if isdbg('command');
+               if ($path && $cmd) {
+                       dbg("path: $cmd cmd: $fcmd") if isdbg('command');
                        
-                               my $package = find_cmd_name($path, $fcmd);
-                               @ans = (0) if !$package ;
+                       my $package = find_cmd_name($path, $fcmd);
+                       return ($@) if $@;
                                
-                               if ($package) {
-                                       dbg("package: $package") if isdbg('command');
-                                       my $c;
-                                       unless (exists $Cache{$package}->{'sub'}) {
-                                               $c = eval $Cache{$package}->{'eval'};
-                                               if ($@) {
-                                                       return DXDebug::shortmess($@);
-                                               }
-                                               $Cache{$package}->{'sub'} = $c;
-                                       }
-                                       $c = $Cache{$package}->{'sub'};
-                                       eval {
-                                               @ans = &{$c}($self, $args);
-                                   };
-                                       
-                                       if ($@) {
-                                               #cluck($@);
-                                               return (DXDebug::shortmess($@));
-                                       };
-                               }
+                       if ($package) {
+                               no strict 'refs';
+                               dbg("package: $package") if isdbg('command');
+                               eval { @ans = &$package($self, $args) };
+                               return (DXDebug::shortmess($@)) if $@;
+                       }
+               } else {
+                       dbg("cmd: $cmd not found") if isdbg('command');
+                       if (++$self->{errors} > $maxerrors) {
+                               $self->send($self->msg('e26'));
+                               $self->disconnect;
+                               return ();
                        } else {
-                               dbg("cmd: $cmd not found") if isdbg('command');
-                               if (++$self->{errors} > $maxerrors) {
-                                       $self->send($self->msg('e26'));
-                                       $self->disconnect;
-                                       return ();
-                               } else {
-                                       return ($self->msg('e1'));
-                               }
+                               return ($self->msg('e1'));
                        }
                }
        }
@@ -425,6 +423,9 @@ sub disconnect
 {
        my $self = shift;
        my $call = $self->call;
+
+       return if $self->{disconnecting}++;
+
        delete $self->{senddbg};
 
        my $uref = Route::User::get($call);
@@ -437,7 +438,7 @@ sub disconnect
        }
 
        # issue a pc17 to everybody interested
-       DXProt::route_pc17($DXProt::me, $main::routeroot, @rout) if @rout;
+       DXProt::route_pc17($main::me, $main::routeroot, @rout) if @rout;
 
        # I was the last node visited
     $self->user->node($main::mycall);
@@ -541,7 +542,7 @@ sub search
                                        $l = join '.', @lparts;
                                        #                 chop $dirfn;               # remove trailing /
                                        $dirfn = "" unless $dirfn;
-                                       $cmd_cache{"$short_cmd"} = join(',', ($path, "$dirfn$l")); # cache it
+                                       $cmd_cache{$short_cmd} = join(',', ($path, "$dirfn$l")); # cache it
                                        dbg("got path: $path cmd: $dirfn$l\n") if isdbg('command');
                                        return ($path, "$dirfn$l"); 
                                }
@@ -554,7 +555,14 @@ sub search
 # clear the command name cache
 sub clear_cmd_cache
 {
+       no strict 'refs';
+       
+       for (keys %Cache) {
+               undef *{$_};
+               dbg("Undefining cmd $_") if isdbg('command');
+       }
        %cmd_cache = ();
+       %Cache = ();
 }
 
 #
@@ -570,39 +578,10 @@ sub clear_cmd_cache
 
 sub valid_package_name {
        my($string) = @_;
-       $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg;
-       
-       #second pass only for words starting with a digit
-       $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg;
+       $string =~ s|([^A-Za-z0-9_/])|sprintf("_%2x",unpack("C",$1))|eg;
        
-       #Dress it up as a real package name
-       $string =~ s/\//_/og;
-       return $string;
-}
-
-# find a cmd reference
-# this is really for use in user written stubs
-#
-# use the result as a symbolic reference:-
-#
-# no strict 'refs';
-# @out = &$r($self, $line);
-#
-sub find_cmd_ref
-{
-       my $cmd = shift;
-       my $r;
-       
-       if ($cmd) {
-               
-               # first expand out the entry to a command
-               my ($path, $fcmd) = search($main::localcmd, $cmd, "pl");
-               ($path, $fcmd) = search($main::cmd, $cmd, "pl") if !$path || !$fcmd;
-               
-               # make sure it is loaded
-               $r = find_cmd_name($path, $fcmd);
-       }
-       return $r;
+       $string =~ s|/|_|g;
+       return "cmd_$string";
 }
 
 # 
@@ -635,7 +614,7 @@ sub find_cmd_name {
                };
                
                #wrap the code into a subroutine inside our unique package
-               my $eval = qq( sub { $sub } );
+               my $eval = qq( sub $package { $sub } );
                
                if (isdbg('eval')) {
                        my @list = split /\n/, $eval;
@@ -645,7 +624,19 @@ sub find_cmd_name {
                        }
                }
                
-               $Cache{$package} = {mtime => $mtime, 'eval' => $eval };
+               # get rid of any existing sub and try to compile the new one
+               no strict 'refs';
+
+               if (exists $Cache{$package}) {
+                       dbg("Redefining $package") if isdbg('command');
+                       undef *$package;
+               } else {
+                       dbg("Defining $package") if isdbg('command');
+               }
+               eval $eval;
+               
+               $Cache{$package} = {mtime => $mtime };
+           
        }
 
        return $package;
@@ -698,6 +689,11 @@ sub announce
        my $text = shift;
        my ($filter, $hops);
 
+       if (!$self->{ann_talk} && $to ne $self->{call}) {
+               my $call = AnnTalk::is_talk_candidate($_[0], $text);
+               return if $call;
+       }
+
        if ($self->{annfilter}) {
                ($filter, $hops) = $self->{annfilter}->it(@_ );
                return unless $filter;