- 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;
-
- #Dress it up as a real package name
- $string =~ s|/|_|g;
- return "Emb_" . $string;
-}
-
-#borrowed from Safe.pm
-sub delete_package {
- my $pkg = shift;
- my ($stem, $leaf);
-
- no strict 'refs';
- $pkg = "DXChannel::$pkg\::"; # expand to full symbol table name
- ($stem, $leaf) = $pkg =~ m/(.*::)(\w+::)$/;
-
- my $stem_symtab = *{$stem}{HASH};
-
- delete $stem_symtab->{$leaf};
-}
-
-sub eval_file {
- my $self = shift;
- my $path = shift;
- my $cmdname = shift;
- my $package = valid_package_name($cmdname);
- my $filename = "$path/$cmdname.pl";
- my $mtime = -M $filename;
-
- # return if we can't find it
- return (0, DXM::msg('e1')) if !defined $mtime;
-
- if(defined $Cache{$package}{mtime} && $Cache{$package}{mtime } <= $mtime) {
- #we have compiled this subroutine already,
- #it has not been updated on disk, nothing left to do
- #print STDERR "already compiled $package->handler\n";
- ;
- } else {
- local *FH;
- if (!open FH, $filename) {
- return (0, "Syserr: can't open '$filename' $!");
- };
- local($/) = undef;
- my $sub = <FH>;
- close FH;
+ my $string = shift;
+ $string =~ s|([^A-Za-z0-9_/])|sprintf("_%2x",unpack("C",$1))|eg;
+
+ $string =~ s|/|_|g;
+ return "cmd_$string";
+}
+
+#
+# this bit of magic finds a command in the offered directory
+sub find_cmd_name {
+ my $path = shift;
+ my $cmdname = shift;
+ my $package = valid_package_name($cmdname);
+ my $filename = "$path/$cmdname.pl";
+ my $mtime = -M $filename;
+
+ # return if we can't find it
+ $errstr = undef;
+ unless (defined $mtime) {
+ $errstr = DXM::msg('e1');
+ return undef;
+ }
+
+ if(exists $Cache{$package} && exists $Cache{$package}->{mtime} && $Cache{$package}->{mtime} <= $mtime) {
+ #we have compiled this subroutine already,
+ #it has not been updated on disk, nothing left to do
+ #print STDERR "already compiled $package->handler\n";
+ dbg("find_cmd_name: $package cached") if isdbg('command');
+ } else {
+
+ my $sub = readfilestr($filename);
+ unless ($sub) {
+ $errstr = "Syserr: can't open '$filename' $!";
+ return undef;
+ };
+
+ #wrap the code into a subroutine inside our unique package
+ my $eval = qq(package DXCommandmode::$package; use POSIX qw{:math_h}; use DXLog; use DXDebug; use DXUser; use DXUtil; our \@ISA = qw{DXCommandmode}; );
+
+
+ if ($sub =~ m|\s*sub\s+handle\n|) {
+ $eval .= $sub;
+ } else {
+ $eval .= qq(sub handle { $sub });
+ }
+
+ if (isdbg('eval')) {
+ my @list = split /\n/, $eval;
+ my $line;
+ for (@list) {
+ dbg($_ . "\n") if isdbg('eval');
+ }
+ }
+
+ # get rid of any existing sub and try to compile the new one
+ no strict 'refs';
+
+ if (exists $Cache{$package}) {
+ dbg("find_cmd_name: Redefining $package") if isdbg('command');
+ undef $DXCommandmode::{"${package}::"};
+ delete $Cache{$package};
+ } else {
+ dbg("find_cmd_name: Defining $package") if isdbg('command');
+ }
+
+ eval $eval;
+
+ $Cache{$package} = {mtime => $mtime } unless $@;
+ }
+
+ return "DXCommandmode::$package";
+}
+
+sub send
+{
+ my $self = shift;
+ if ($self->{gtk}) {
+ for (@_) {
+ $self->SUPER::send(dd(['cmd',$_]));
+ }
+ } else {
+ $self->SUPER::send(@_);
+ }
+}
+
+sub local_send
+{
+ my ($self, $let, $buf) = @_;
+ if ($self->{state} eq 'prompt' || $self->{state} eq 'talk' || $self->{state} eq 'chat') {
+ if ($self->{enhanced}) {
+ $self->send_later($let, $buf);
+ } else {
+ $self->send($buf);
+ }
+ } else {
+ $self->delay($buf);
+ }
+}
+
+# send a talk message here
+sub talk
+{
+ my ($self, $from, $to, $via, $line, $onode) = @_;
+ $line =~ s/\\5E/\^/g;
+ if ($self->{talk}) {
+ if ($self->{gtk}) {
+ $self->local_send('T', dd(['talk',$to,$from,$via,$line]));
+ } else {
+ $self->local_send('T', "$to de $from: $line");
+ }
+ }
+ Log('talk', $to, $from, '<' . ($onode || '*'), $line);
+ # send a 'not here' message if required
+ unless ($self->{here} && $from ne $to) {
+ my $key = "$to$from";
+ unless (exists $nothereslug{$key}) {
+ my ($ref, $dxchan);
+ if (($ref = Route::get($from)) && ($dxchan = $ref->dxchan)) {
+ my $name = $self->user->name || $to;
+ my $s = $self->user->nothere || $dxchan->msg('nothere', $name);
+ $nothereslug{$key} = $main::systime;
+ $dxchan->talk($to, $from, undef, $s);
+ }
+ }
+ }
+}
+
+# send an announce
+sub announce
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my $to = shift;
+ my $target = shift;
+ 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;
+ }
+
+ unless ($self->{ann}) {
+ return if $_[0] ne $main::myalias && $_[0] ne $main::mycall;
+ }
+ return if $target eq 'SYSOP' && $self->{priv} < 5;
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['ann', $to, $target, $text, @_])
+ } else {
+ $buf = "$to$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
+ $self->local_send($target eq 'WX' ? 'W' : 'N', $buf);
+}
+
+# send a chat
+sub chat
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ my $target = shift;
+ my $to = shift;
+ my $text = shift;
+ my ($filter, $hops);
+
+ return unless grep uc $_ eq $target, @{$self->{user}->{group}};
+
+ $text =~ s/^\#\d+ //;
+ my $buf;
+ if ($self->{gtk}) {
+ $buf = dd(['chat', $to, $target, $text, @_])
+ } else {
+ $buf = "$target de $_[0]: $text";
+ $buf =~ s/\%5E/^/g;
+ $buf .= "\a\a" if $self->{beep};
+ }
+ $self->local_send('C', $buf);
+}
+
+sub format_dx_spot
+{
+ my $self = shift;
+
+ my $t = ztime($_[2]);
+ my $loc = '';
+ my $clth = $self->{consort} eq 'local' ? 29 : 30;
+ my $comment = substr (($_[3] || ''), 0, $clth);
+ $comment .= ' ' x ($clth - length($comment));
+ if ($self->{user}->wantgrid) {
+ my $ref = DXUser::get_current($_[4]);
+ if ($ref) {
+ $loc = $ref->qra || '';
+ $loc = ' ' . substr($loc, 0, 4) if $loc;
+ }
+ }
+
+ if ($self->{user}->wantdxitu) {
+ $loc = ' ' . sprintf("%2d", $_[10]) if defined $_[10];
+ $comment = substr($comment, 0, $self->{consort} eq 'local' ? 26 : 27) . ' ' . sprintf("%2d", $_[8]) if defined $_[8];
+ } elsif ($self->{user}->wantdxcq) {
+ $loc = ' ' . sprintf("%2d", $_[11]) if defined $_[11];
+ $comment = substr($comment, 0, $self->{consort} eq 'local' ? 26 : 27) . ' ' . sprintf("%2d", $_[9]) if defined $_[9];
+ } elsif ($self->{user}->wantusstate) {
+ $loc = ' ' . $_[13] if $_[13];
+ $comment = substr($comment, 0, $self->{consort} eq 'local' ? 26 : 27) . ' ' . $_[12] if $_[12];
+ }
+
+ return sprintf "DX de %-7.7s%11.1f %-12.12s %-s $t$loc", "$_[4]:", $_[0], $_[1], $comment;
+}
+
+# send a dx spot
+sub dx_spot
+{
+ my $self = shift;
+ my $line = shift;
+ my $isolate = shift;
+ return unless $self->{dx};
+
+ my ($filter, $hops);
+
+ if ($self->{spotsfilter}) {
+ ($filter, $hops) = $self->{spotsfilter}->it(@_ );
+ return unless $filter;
+ }
+
+ dbg('spot: "' . join('","', @_) . '"') if isdbg('dxspot');
+
+ my $buf;
+ if ($self->{ve7cc}) {
+ $buf = VE7CC::dx_spot($self, @_);
+ } elsif ($self->{gtk}) {
+ my ($dxloc, $byloc);
+
+ my $ref = DXUser::get_current($_[4]);
+ if ($ref) {
+ $byloc = $ref->qra;
+ $byloc = substr($byloc, 0, 4) if $byloc;
+ }
+
+ my $spot = $_[1];
+ $spot =~ s|/\w{1,4}$||;
+ $ref = DXUser::get_current($spot);
+ if ($ref) {
+ $dxloc = $ref->qra;
+ $dxloc = substr($dxloc, 0, 4) if $dxloc;
+ }
+ $buf = dd(['dx', @_, ($dxloc||''), ($byloc||'')]);