#
# Perl5 module for despam.
# Copyright 1997 by Leslie M. Barstow III
#
# Search.* files are of the format:
#
# Search Match={Once|Line|Any} Limit={#|All}
#     [HhBb]/pattern/
#     [...]
# [Search...]
#
# Match:  Once = only one instance of each pattern counts
#         Line = only one instance of each pattern per line counts
#         Any  = multiple instances per line and/or multiple lines count
# Limit:  number - once you find this many matches, it is junk
#         All - at least one instance of each pattern must be found
# Patterns: H|h: search header, case sensitive|insensitive
#           B|b: search body, case sensitive|insensitive
#           none: search body, case sensitive (same as B)

package Search;

#
# Setup for search - suck in the mail message, otherwise it will take
# forever
#
sub Setup
 {
  ($tmpfile) = @_;
  open(TMPF,"$tmpfile");
if ($::debug)
 {
  print STDERR "entering Search setup with $tmpfile\n";
 }
  $count = 0;
if ($::debug)
 {
  print STDERR "reading header\n";
 }
  while (<TMPF>)
   {
    @header[$count++] = $_;
    last if (/^\s+$/);
   }
if ($::debug)
 {
  print STDERR "Header\n\n";
  print STDERR @header;
 }
  $count = 0;
if ($::debug)
 {
  print STDERR "reading body\n";
 }
  while (<TMPF>)
   {
    @body[$count++] = $_;
   }
  close(TMPF);
if ($::debug)
 {
  print STDERR "Body\n\n";
  print STDERR @body;
 }
 }


sub Compare
 {
  ($patfile) = @_;
  open(PATF,"$patfile");
if ($::debug)
 {
  print STDERR "Entering Search compare to $patfile\n";
 }
  $count = 0;
  $case = 0;
  while(<PATF>)
   {
    next if (/^#/);
    if ($case == 0)
     {
      if (!/^Search/)
       {
if ($::debug)
 {
        print STDERR "Search expecting 'Search' line\n";
 }
        close(PATF);
        return 0;
       }
# Read search parameters
      ($matchtype,$limit) =
          /^Search\s+Match=(Once|Line|Any)\s+Limit=(\d*|All)/;
if ($::debug)
 {
      print STDERR "Search: Matching: $matchtype, need $limit matches\n";
 }
      $matchtype = "Once" if ($limit eq "All");
# Read pattern list
      $numpats = 0;
      $matchcount = 0;
      $case = 1;
     }
    elsif ($case == 1)
     {
      if (!/^\s+/)
       {
if ($::debug)
 {
        print STDERR "Search: matched $matchcount, needed $limit\n" unless
            ($limit eq "All");
        print STDERR "Search: matched $matchcount, needed $patcount\n" if
            ($limit eq "All");
 }
        if ($numpats)
         {
          if ((($limit eq "All") && ($matchcount == $patcount)) ||
              ($matchcount >= $limit))
           {
            close(PATF);
            return 1;
           }
         }
        $case = 0;
       }
      else
       {
        ($qualifiers,$pattern) = /^\s+([HhBb]*)\/(.*)\//;
if ($::debug)
 {
        print STDERR "Search: Pattern: $pattern, qualifiers: $qualifiers\n";
 }
        $qualifiers = "B" unless $qualifiers;
        ($readheader) = $qualifiers =~ /[Hh]/;
        ($hsensitive) = $qualifiers =~ /H/;
        ($readbody) = $qualifiers =~ /[Bb]/;
        ($bsensitive) = $qualifiers =~ /B/;
        $match = 0;
        $numpats++;
        if ($readheader)
         {
if ($::debug)
 {
          print STDERR "Search: checking headers\n";
 }
          @foundlist = grep(/$pattern/,@header) if $hsensitive;
          @foundlist = grep(/$pattern/i,@header) unless $hsensitive;
          $patcount = scalar(@foundlist);
if ($::debug)
 {
          print STDERR "Search: $patcount matches\n" if $patcount;
 }
          if (($matchtype eq "Once") && $patcount)
           {
            $matchcount++;
            $match++;
           }
          elsif ($matchtype eq "Line")
           {
            $matchcount += $patcount;
           }
          elsif ($matchtype eq "Any")
           {
            foreach $item (@foundlist)
             {
              while (length($item))
               {
                if (($hsensitive && ($item =~ /$pattern/)) ||
                    (!$hsensitive && ($item =~ /$pattern/i)))
                 {
                  $item = $';
                  $matchcount++;
                 }
                else
                 {
                  last;
                 }
               }
             }
           }
         }
        if ($readbody && !$match)
         {
if ($::debug)
 {
          print STDERR "Search: checking body\n";
 }
          @foundlist = grep(/$pattern/,@body) if $bsensitive;
          @foundlist = grep(/$pattern/i,@body) unless $bsensitive;
          $patcount = scalar(@foundlist);
if ($::debug)
 {
          print STDERR "Search: $patcount matches\n" if $patcount;
 }
          if (($matchtype eq "Once") && $patcount)
           {
            $matchcount++;
           }
          elsif ($matchtype eq "Line")
           {
            $matchcount += $patcount;
           }
          elsif ($matchtype eq "Any")
           {
            foreach $item (@foundlist)
             {
              while (length($item))
               {
                if (($hsensitive && ($item =~ /$pattern/)) ||
                    (!$hsensitive && ($item =~ /$pattern/i)))
                 {
                  $item = $';
                  $matchcount++;
                 }
                else
                 {
                  last;
                 }
               }
             }
           }
         }
       }
     }
   }
if ($::debug)
 {
  print STDERR "Search: matched $matchcount, needed $limit\n" unless
      ($limit eq "All");
  print STDERR "Search: matched $matchcount, needed $patcount\n" if
      ($limit eq "All");
 }
  if ($numpats)
   {
    if ((($limit eq "All") && ($matchcount == $patcount)) ||
        ($matchcount >= $limit))
     {
      close(PATF);
      return 1;
     }
   }
 }
    
sub Description
 {
  return "Searches the body and or header for specific phrases\n";
 }

1;
