X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FFilter.pm;h=12caeef398d21c20b95d1f87e43b48d9c1bdd11d;hb=b7dedfebf0e11a5fc3050f8a0350a45a5a680e11;hp=bcf081e6b860b85c6694af54e2ed3d2e36e605a9;hpb=8bb4b460148fbc97739e8645f627cb9ab049d512;p=spider.git diff --git a/perl/Filter.pm b/perl/Filter.pm index bcf081e6..12caeef3 100644 --- a/perl/Filter.pm +++ b/perl/Filter.pm @@ -208,7 +208,7 @@ sub it if ($filter->{reject} && exists $filter->{reject}->{code}) { $type = 'reject'; $asc = $filter->{reject}->{user}; - if (&{$filter->{reject}->{code}}(\@_)) { + if (&{$filter->{reject}->{code}}(ref $_[0] ? $_[0] : \@_)) { $r = 0; last; } else { @@ -218,7 +218,7 @@ sub it if ($filter->{accept} && exists $filter->{accept}->{code}) { $type = 'accept'; $asc = $filter->{accept}->{user}; - if (&{$filter->{accept}->{code}}(\@_)) { + if (&{$filter->{accept}->{code}}(ref $_[0] ? $_[0] : \@_)) { $r = 1; last; } else { @@ -231,7 +231,7 @@ sub it my $hops = $self->{hops} if exists $self->{hops}; if (isdbg('filter')) { - my $args = join '\',\'', map {defined $_ ? $_ : 'undef'} @_; + my $args = join '\',\'', map {defined $_ ? $_ : 'undef'} (ref $_[0] ? @{$_[0]} : @_); my $true = $r ? "OK " : "REJ"; my $sort = $self->{sort}; my $dir = $self->{name} =~ /^in_/i ? "IN " : "OUT"; @@ -364,7 +364,7 @@ use vars qw(@ISA); # this is called as a subroutine not as a method sub parse { - my ($self, $dxchan, $sort, $line) = @_; + my ($self, $dxchan, $sort, $line, $forcenew) = @_; my $ntoken = 0; my $fno = 1; my $filter; @@ -373,19 +373,27 @@ sub parse my $user; # check the line for non legal characters - return ('ill', $dxchan->msg('e19')) if $line =~ /[^\s\w,_\-\*\/\(\)!]/; + dbg("Filter::parse line: '$line'") if isdbg('filter'); + return ('ill', $dxchan->msg('e19')) if $line !~ /{.*}/ && $line =~ /[^\s\w,_\-\*\/\(\)\$!]/; + + $line = lc $line; + + # disguise regexes + $line =~ s/\{(.*)\}/'{'. unpack('H*', $1) . '}'/eg; + dbg("Filter parse line after regex check: '$line'") if isdbg('filter'); # add some spaces for ease of parsing - $line =~ s/([\(\)])/ $1 /g; - $line = lc $line; + $line =~ s/([\(\!\)])/ $1 /g; my @f = split /\s+/, $line; + my $conj = ' && '; my $not = ""; + my $lasttok = ''; while (@f) { if ($ntoken == 0) { - if (@f && $dxchan->priv >= 8 && ((is_callsign(uc $f[0]) && DXUser::get(uc $f[0])) || $f[0] =~ /(?:node|user)_default/)) { + if (!$forcenew && @f && $dxchan->priv >= 8 && ((is_callsign(uc $f[0]) && DXUser::get(uc $f[0])) || $f[0] =~ /(?:node|user)_default/)) { $call = shift @f; if ($f[0] eq 'input') { shift @f; @@ -399,7 +407,7 @@ sub parse $fno = shift @f; } - $filter = Filter::read_in($sort, $call, $flag); + $filter = Filter::read_in($sort, $call, $flag) unless $forcenew; $filter = Filter->new($sort, $call, $flag) if !$filter || $filter->isa('Filter::Old'); $ntoken++; @@ -411,9 +419,12 @@ sub parse my $tok = shift @f; if ($tok eq '(') { if ($s) { - $s .= $conj; - $user .= $conj; + unless ($lasttok eq '(') { + $s .= $conj ; + $user .= $conj; + } $conj = ""; + $lasttok = $tok; } if ($not) { $s .= $not; @@ -422,12 +433,14 @@ sub parse } $s .= $tok; $user .= $tok; + $lasttok = $tok; next; } elsif ($tok eq ')') { $conj = ' && '; $not =""; $s .= $tok; $user .= $tok; + $lasttok = $tok; next; } elsif ($tok eq 'all') { $s .= '1'; @@ -435,12 +448,14 @@ sub parse last; } elsif ($tok eq 'or') { $conj = ' || ' if $conj ne ' || '; + $lasttok = $tok; next; } elsif ($tok eq 'and') { $conj = ' && ' if $conj ne ' && '; next; } elsif ($tok eq 'not' || $tok eq '!') { - $not = '!'; + $not = '! '; + $lasttok = $tok; next; } if (@f) { @@ -448,11 +463,12 @@ sub parse my @val = split /,/, $val; if ($s) { - $s .= $conj ; - $user .= $conj; - $conj = ' && '; + unless ($lasttok eq '(') { + $s .= $conj ; + $user .= $conj; + $conj = ' && '; + } } - if ($not) { $s .= $not; $user .= $not; @@ -473,18 +489,24 @@ sub parse } @val = @nval; } - if ($fref->[1] eq 'a') { + if ($fref->[1] eq 'a' || $fref->[1] eq 't') { my @t; - for (@val) { - s/\*//g; - push @t, "\$r->[$fref->[2]]=~/$_/i"; + foreach my $v (@val) { + $v =~ s/\*//g; # remove any trailing * + if (my ($r) = $v =~ /^\{(.*)\}$/) { # we have a regex + dbg("Filter::parse regex b: '\{$r\}'") if isdbg('filter'); + $v = pack('H*', $r); + dbg("Filter::parse regex a: '$v'") if isdbg('filter'); + return ('regex', $dxchan->msg('e38', $v)) unless (qr{$v}); + } + push @t, "\$r->[$fref->[2]]=~m{$v}i"; } $s .= "(" . join(' || ', @t) . ")"; } elsif ($fref->[1] eq 'c') { my @t; for (@val) { s/\*//g; - push @t, "\$r->[$fref->[2]]=~/^\U$_/"; + push @t, "\$r->[$fref->[2]]=~m{^\U$_}"; } $s .= "(" . join(' || ', @t) . ")"; } elsif ($fref->[1] eq 'n') { @@ -511,13 +533,6 @@ sub parse push @t, "(\$r->[$fref->[2]]>=$1 && \$r->[$fref->[2]]<=$2)"; } $s .= "(" . join(' || ', @t) . ")"; - } elsif ($fref->[1] eq 't') { - my @t; - for (@val) { - s/\*//g; - push @t, "\$r->[$fref->[2]]=~/$_/i"; - } - $s .= "(" . join(' || ', @t) . ")"; } else { confess("invalid filter function $fref->[1]"); } @@ -525,12 +540,12 @@ sub parse last; } } - return ('unknown', $dxchan->msg('e20', $tok)) unless $found; + return (1, $dxchan->msg('e20', $tok)) unless $found; } else { - return ('no', $dxchan->msg('filter2', $tok)); + return (1, $dxchan->msg('filter2', $tok)); } + $lasttok = $tok; } - } # tidy up the user string @@ -539,20 +554,20 @@ sub parse $user =~ s/\!/ not /g; $user =~ s/\s+/ /g; - return (0, $filter, $fno, $user, "$s"); + return (0, $filter, $fno, $user, $s); } # a filter accept/reject command sub cmd { my ($self, $dxchan, $sort, $type, $line) = @_; - return $dxchan->msg('filter5') unless $line; my ($r, $filter, $fno, $user, $s) = $self->parse($dxchan, $sort, $line); + return (1, $filter) if $r; + my $u = DXUser::get_current($user); return (1, $dxchan->msg('isow', $user)) if $u && $u->isolate; - return (1, $filter) if $r; my $fn = "filter$fno"; @@ -597,8 +612,11 @@ use vars qw(@ISA); # to 'Filter::it' # # The fieldsort is the type of field that we are dealing with which -# currently can be 'a', 'n', 'r' or 'd'. 'a' is alphanumeric, 'n' is -# numeric, 'r' is ranges of pairs of numeric values and 'd' is default. +# currently can be 'a', 'n', 'r' or 'd'. +# 'a' is alphanumeric +# 'n' is# numeric +# 'r' is ranges of pairs of numeric values +# 'd' is default (effectively, don't filter) # # Filter::it basically goes thru the list of comparisons from top to # bottom and when one matches it will return the action and the action data as a list. @@ -637,9 +655,9 @@ sub it return ($action, $actiondata) if $val >= $range[$i] && $val <= $range[$i+1]; } } elsif ($fieldsort eq 'a') { - return ($action, $actiondata) if $_[$field] =~ m{$comp}; + return ($action, $actiondata) if $_[$field] =~ m{$comp}i; } else { - return ($action, $actiondata); # the default action + return ($action, $actiondata); # the default action (just pass through) } } }