Changeset 89

Show
Ignore:
Timestamp:
06.12.2006 23:46:25 (2 years ago)
Author:
jorge
Message:

Update: fuzzy-find can now handle lookups with MySQL hashing
Change: fuzzy-find can specify where to find FuzzyOcr?.cf with --config option
Change: fuzzy-find can specify the score to use when learning ham/spam with --score option (default: 0/ham 10/spam)
Change: FuzzyOcr/Config?.pm Thresholds can be specified as plugin options to make changing these easier
Change: Log with 2 lines instead of 3 when a word match is found (cosmetic)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/devel/FuzzyOcr.pm

    r88 r89  
    139139        my $test  = 0; 
    140140        $test++ if ($ctype =~ /image/i); 
    141         $test++ if ($fname =~ /(gif|jpg|jpeg|png|bmp|tiff?)$/i); 
     141        $test++ if ($fname =~ /\.(gif|jpe?g|png|bmp|tiff?)$/i); 
    142142 
    143143        if ($test == 0) { 
     
    262262        print PICT $pdata; 
    263263        close PICT; 
    264         infolog("Saved: $imgfilename"); 
     264        debuglog("Saved: $imgfilename"); 
    265265        $cnt++; 
    266266    } 
     
    756756                            $wcnt++; 
    757757                            infolog( 
    758                                 "Found word \"$w\" in line\n \"$_\" \n with fuzz of " 
     758                                "Scanset \"$scanlabel\" found word \"$w\" with fuzz of " 
    759759                                . sprintf("%0.4f",$matched) 
    760                                 . " scanned with scanset \"$scanlabel\"" 
     760                                . "\nline: \"$_\"" 
    761761                            ); 
    762762                            if ($conf->{focr_unique_matches}) { 
  • trunk/devel/FuzzyOcr/Config.pm

    r88 r89  
    6868my @img_types = qw/gif png jpeg bmp tiff/; 
    6969 
    70 # Default thresolds 
    71 $Threshold{s}  =  
    72 $Threshold{h}  =  
    73 $Threshold{w}  =  
    74 $Threshold{cn} = 0.01; 
    75 $Threshold{c}  = 5; 
    76 $Threshold{max_hash} = 5; 
    77  
    7870sub get_timeout { 
    7971    unless (defined $timeout) { 
     
    164156    $dsn .= ";port=".$conf->{focr_mysql_port} if $conf->{focr_mysql_port} != 3306; 
    165157    } 
    166     infolog("Connecting to: $dsn"); 
     158    debuglog("Connecting to: $dsn"); 
    167159    my $ddb = DBI->connect($dsn, 
    168160        $conf->{focr_mysql_user}, 
     
    176168    my @cmds = (); 
    177169 
     170    foreach my $t (qw/s h w cn/) { 
     171        push (@cmds, { 
     172            setting => 'focr_threshold_'.$t, 
     173            default => 0.01, 
     174            type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC 
     175        }); 
     176    } 
     177    foreach my $t (qw/c max_hash/) { 
     178        push (@cmds, { 
     179            setting => 'focr_threshold_'.$t, 
     180            default => 5, 
     181            type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC 
     182        }); 
     183    } 
    178184    push (@cmds, { 
    179185        setting => 'focr_threshold', 
     
    552558    } 
    553559 
     560    # Allow scanning if in debug mode? 
     561    $conf->{focr_autodisable_score} = 1000 
     562        if $Mail::SpamAssassin::Logger::LOG_SA{level} == 3; 
     563 
     564    # Extract Thresholds 
     565    foreach my $k (keys %{$conf}) { 
     566        if ($k =~ m/^focr_threshold_(\S+)/) { 
     567            $Threshold{$1} = $conf->{$k}; 
     568            debuglog("Threshold[$1] => $conf->{$k}"); 
     569        } 
     570    } 
    554571    # Display All Options 
    555572    foreach my $k (sort keys %{$conf}) { 
  • trunk/devel/Utils/fuzzy-find

    r40 r89  
    1 #!/usr/bin/perl 
     1#!/usr/local/bin/perl 
    22use Getopt::Long; 
     3use DBI; 
    34use MLDBM qw(DB_File Storable); 
    45my %Files = ( 
     
    78    );   
    89 
     10my %MySQL = ( 
     11     db   => 'FuzzyOcr' 
     12    ,hash => 'Hash' 
     13    ,safe => 'Safe' 
     14    ,user => 'fuzzyocr' 
     15    ,pass => 'fuzzyocr' 
     16    ,host => 'localhost' 
     17    ,port => 3306 
     18); 
     19 
    920# defaults 
    10 my $cfgfile = "FuzzyOcr.cf"; 
     21my $cfgfile = "/etc/mail/spamassassin/FuzzyOcr.cf"; 
    1122my %App; 
    1223my @bin_utils = qw/pamfile ppmhist jpegtopnm giftopnm pngtopnm bmptopnm/; 
    13 foreach (@bin_utils) { 
    14     $App{$_} = "/usr/bin/$_"; 
    15 } 
    1624 
    1725my $delete = 0; 
     
    1927my $learn_ham = 0; 
    2028my $learn_spam = 0; 
     29my $score; 
    2130GetOptions( 
    2231    'verbose' => \$verbose, 
    2332    'delete'  => \$delete, 
     33    'config=s' => \$cfgfile, 
     34    'score=f' => \$score, 
    2435    'learn-ham' => \$learn_ham, 
    2536    'learn-spam' => \$learn_spam, 
     
    3041    print "\n"; 
    3142    print "Available options:\n"; 
     43    print "--config=s   Specify location of FuzzyOcr.cf\n"; 
     44    print "             Default: /etc/mail/spamassasin/FuzzyOcr.cf\n"; 
    3245    print "--delete     Removes the hash from the database\n"; 
    3346    print "--learn-ham  Add the hash as ham to the database\n"; 
    3447    print "--learn-spam Add the hash as spam to the database\n"; 
     48    print "--score=i    Score to use when adding ham/spam\n"; 
    3549    print "--verbose    Show more informations\n"; 
    3650    print "\n"; 
     
    3852} 
    3953 
     54# Setup default score 
     55unless (defined $score) { 
     56    $score = $learn_ham ? 10 : 0; 
     57} 
     58 
    4059# Read custom paths from FuzzyOcr.cf 
     60my $app_path = q(/usr/local/netpbm/bin:/usr/local/bin:/usr/bin); 
    4161open CONFIG, "< $cfgfile" or warn "Can't read configuration file, using defaults...\n"; 
    4262 
     
    4464    chomp; 
    4565    if ($_ =~ m/^focr_bin_(\w+) (.+)/) { 
    46         $App{$1} = $2; 
    47         printf "Found custom path \"$2\" for application \"$1\"\n" if $verbose 
     66        $App{$1} = $2; 
     67        printf "Found custom path \"$2\" for application \"$1\"\n" if $verbose; 
     68    } 
     69    if ($_ =~ m/^focr_path_bin (.+)/) { 
     70        $app_path = $1; 
     71        printf "Found new path: \"$1\"\n" if $verbose; 
     72    } 
     73    if ($_ =~ m/^focr_enable_image_hashing (\d)/) { 
     74        $App{hashing_type} = $1; 
     75        printf "Found DB Hashing\n" if ($verbose and $1 == 2); 
     76        printf "Found MySQL Hashing\n" if ($verbose and $1 == 3); 
     77    } 
     78    if ($_ =~ m/^focr_mysql_(\w+) (.+)/) { 
     79        $MySQL{$1} = $2; 
     80        printf "Found MySQL option $1 => '$2'\n" if $verbose; 
     81    } 
     82    if ($_ =~ m/^focr_threshold_max_hash (.+)/) { 
     83        $App{max_hash} = $1; 
     84        printf "Updated Thresold{max_hash} = $1\n" if $verbose; 
    4885    } 
    4986} 
    5087 
    5188close CONFIG; 
     89 
     90# make shure we have this threshold set 
     91$App{max_hash} = 5 unless defined $App{max_hash}; 
     92 
     93# search path for bin_util unless already specified in configuration file 
     94foreach my $app (@bin_utils) { 
     95    next if defined $App{$app}; 
     96    foreach my $d (split(':',$app_path)) { 
     97        if (-x "$d/$app") { 
     98            $App{$app} = "$d/$app"; 
     99            last; 
     100        } 
     101    } 
     102} 
     103 
     104sub get_ddb { 
     105    my %dopts = ( AutoCommit => 1 ); 
     106    my $dsn = "dbi:mysql:database=".$MySQL{db}; 
     107    if (defined $MySQL{socket}) { 
     108        $dsn .= ";mysql_socket=$MySQL{socket}"; 
     109    } else { 
     110        $dsn .= ";host=$MySQL{host}"; 
     111        $dns .= ";port=$MySQL{port}" unless $MySQL{port} == 3306; 
     112    } 
     113    printf "Connecting to: $dsn\n" if $verbose; 
     114    return DBI->connect($dsn,$MySQL{user},$MySQL{pass},\%dopts); 
     115} 
    52116 
    53117while (@ARGV) { 
     
    64128    my $key = ''; 
    65129    my $ctype = ''; 
     130    my $ftype = 0; 
    66131    unless (@data) { 
    67132        my $app; 
    68133        if (($file =~ m/\.jpg$/i) or ($file =~ m/\.jpeg$/i)) { 
    69134            $app = $App{jpegtopnm}; 
    70             $ctype = "image/jpeg"; 
     135            $ctype = "image/jpeg"; 
     136            $ftype = 2; 
    71137        } elsif ($file =~ m/\.png$/i) { 
    72138            $app = $App{pngtopnm}; 
    73             $ctype = "image/png"; 
     139            $ctype = "image/png"; 
     140            $ftype = 3; 
    74141        } elsif ($file =~ m/\.bmp$/i) { 
     142            $ctype = "image/bmp"; 
    75143            $app = $App{bmptopnm}; 
    76             $ctype = "image/bmp"; 
     144            $ftype = 4; 
     145        } elsif ($file =~ m/\.tiff?$/i) { 
     146            $app = $App{tifftopnm}; 
     147            $ctype = "image/tiff"; 
     148            $ftype = 5; 
     149        } elsif ($file =~ m/\.gif$/i) { 
     150            $app = $App{giftopnm}; 
     151            $ctype = "image/gif"; 
     152            $ftype = 1; 
    77153        } elsif ($file =~ m/\.pnm$/i) { 
    78             $ctype = "image/pnm"; 
    79154            $app = '/bin/cat'; 
    80         } elsif ($file =~ m/\.gif$/i) { 
    81             $ctype = "image/gif"; 
    82             $app = $App{giftopnm}; 
     155            $ctype = "image/pnm"; 
    83156        } else { 
    84            print "Unknown extension given in \"$file\", aborting...\n"; 
    85            exit 1; 
    86        
    87         my @hist = `$app $file |$App{ppmhist} -noheader -`; 
    88         my @res = `$app $file |$App{pamfile} -`; 
     157            print "Unknown extension given in \"$file\", aborting...\n"; 
     158            exit 1; 
     159       
     160        my @hist = `$app $file 2>/dev/null |$App{ppmhist} -noheader -`; 
     161        my @res = `$app $file 2>/dev/null |$App{pamfile} -`; 
    89162        my ($h,$w) = (0,0); 
    90163        if ($res[0] =~ m/(\d+) by (\d+)/) { 
     
    99172            my @d = split(' ',$_); 
    100173            $hash .= sprintf("::%d:%d:%d:%d:%d",@d); 
    101             last if ($cnt++ ge 5); 
     174            last if ($cnt++ ge $App{max_hash}); 
    102175        } 
    103176        $key = substr($hash,2); 
     
    106179    printf "key = <$key>\n" if ($key); 
    107180    if ($learn_spam || $learn_ham) { 
    108         my %DB; 
    109         my $ff = $learn_spam ? 'db_hash' : 'db_safe'; 
    110         tie %DB, 'MLDBM', $Files{$ff} or die "Can't open $ff"; 
    111         print "Adding key to database...\n"; 
    112         if (defined $key) { 
    113             my $dbm = $DB{$key}; 
    114             $dbm->{fname} = $file; 
    115             $dbm->{ctype} = $ctype; 
    116             $dbm->{dinfo} = "Manually added to the database\n"; 
    117             $dbm->{basic} = join(':', @data); 
    118             $dbm->{score} = $learn_spam ? 10 : 0; 
    119             $dbm->{input} = 
    120             $dbm->{check} = time; 
    121             $dbm->{match} = $learn_spam ? 0 : 1; 
    122             $DB{$key} = $dbm; 
    123         } 
    124         untie %DB; 
    125         exit 0; 
     181        if ($App{hashing_type} == 2) { 
     182            my %DB; 
     183            my $ff = $learn_spam ? 'db_hash' : 'db_safe'; 
     184            tie %DB, 'MLDBM', $Files{$ff} or die "Can't open $ff"; 
     185            print "Adding key to database...\n"; 
     186            if (defined $key) { 
     187                my $dbm = $DB{$key}; 
     188                $dbm->{fname} = $file; 
     189                $dbm->{ctype} = $ctype; 
     190                $dbm->{dinfo} = "Manually added to the database\n"; 
     191                $dbm->{basic} = join(':', @data); 
     192                $dbm->{score} = $score; 
     193                $dbm->{input} = 
     194                $dbm->{check} = time; 
     195                $dbm->{match} = $learn_spam ? 0 : 1; 
     196                $DB{$key} = $dbm; 
     197            } 
     198            untie %DB; 
     199            exit 0; 
     200        } elsif ($App{hashing_type} == 3) { 
     201            my $ddb = get_ddb(); 
     202            if ($ddb) { 
     203                my $now = time; 
     204                my $tab = $learn_spam ? 'hash' : 'safe'; 
     205                my $sql = "INSERT INTO $MySQL{$tab} VALUES ('" . $key 
     206                    . "','" . join(':',@data)."','" 
     207                    . "','" . $file 
     208                    . "','" . $ctype 
     209                    . "','" . $ftype 
     210                    . "','" . $learn_spam ? 0 : 1 
     211                    . "','" . $now 
     212                    . "','" . $now 
     213                    . "','" . $score 
     214                    . "','" . "Manually added to the database\n"; 
     215                $ddb->do($sql); 
     216                $dbb->disconnect; 
     217            } else { 
     218                printf "Cannot connect to $dsn\n"; 
     219                exit 1; 
     220            } 
     221            exit 0; 
     222        } 
    126223    } else { 
    127     foreach my $ff (keys %Files) { 
    128         my %DB; 
    129         tie %DB, 'MLDBM', $Files{$ff} or next; 
    130         printf "Searching $Files{$ff}...\n"; 
    131         foreach my $kk (keys %DB) { 
    132             my $db = $DB{$kk}; 
    133             my @dd = split('::',$kk); 
    134             shift @dd if ($dd[0] !~ m/:/); 
    135             my $dd = join('::',@dd); 
    136             if ($key eq '') { 
    137                 next unless ($db->{basic} eq join(':',@data)); 
    138             } else { 
    139                 next unless ($dd eq $key); 
    140             } 
    141             printf "%s HASH\n",($delete)?'Removing':'Found'; 
    142             if ($delete) { 
    143                 delete $DB{$kk}; 
    144             } else { 
    145                 printf "ImageInfo  : %9d:%d:%d:%d\n",split(':',$db->{basic}); 
    146                 printf "Matched    : %4d Time(s)\n",$db->{match}; 
    147                 printf "Calc.Score : %9.3f\n",$db->{score}; 
    148                 printf "in DB since: %s\n",scalar(localtime($db->{input})); 
    149                 printf "Last Match : %s\n",scalar(localtime($db->{check})); 
    150             } 
    151         } 
    152         untie %DB; 
    153     } 
    154     } 
    155 
     224        if ($App{hashing_type} == 2) { 
     225            foreach my $ff (keys %Files) { 
     226                my %DB; 
     227                tie %DB, 'MLDBM', $Files{$ff} or next; 
     228                printf "Searching $Files{$ff}...\n"; 
     229                foreach my $kk (keys %DB) { 
     230                    my $db = $DB{$kk}; 
     231                    my @dd = split('::',$kk); 
     232                    shift @dd if ($dd[0] !~ m/:/); 
     233                    my $dd = join('::',@dd); 
     234                    if ($key eq '') { 
     235                        next unless ($db->{basic} eq join(':',@data)); 
     236                    } else { 
     237                        next unless ($dd eq $key); 
     238                    } 
     239                    printf "%s HASH\n",($delete)?'Removing':'Found'; 
     240                    if ($delete) { 
     241                        delete $DB{$kk}; 
     242                    } else { 
     243                        printf "ImageInfo  : %9d:%d:%d:%d\n",split(':',$db->{basic}); 
     244                        printf "Matched    : %4d Time(s)\n",$db->{match}; 
     245                        printf "Calc.Score : %9.3f\n",$db->{score}; 
     246                        printf "in DB since: %s\n",scalar(localtime($db->{input})); 
     247                        printf "Last Match : %s\n",scalar(localtime($db->{check})); 
     248                    } 
     249                } 
     250                untie %DB; 
     251            } 
     252        } elsif ($App{hashing_type} == 3) { 
     253            my $ddb = get_ddb(); 
     254            if ($ddb) { 
     255                foreach my $ff (sort keys %Files) { 
     256                    my $sql; 
     257                    if ($delete) { 
     258                        $sql = "DELETE FROM $ff WHERE $MySQL{$tab}.key=?"; 
     259                        $ddb->do($sql,undef,$key); 
     260                    } else { 
     261                        my $tab = $ff; $tab =~ s/db_//; 
     262                        $sql = "SELECT * FROM $MySQL{$tab} where $MySQL{$tab}.key=?"; 
     263                        my @data = $ddb->selectrow_array($sql,undef,$key); 
     264                        if (scalar(@data)) { 
     265                            printf "ImageInfo  : %9d:%d:%d:%d\n",split(':',$data[1]); 
     266                            printf "Matched    : %4d Time(s)\n",$data[5]; 
     267                            printf "Calc.Score : %9.3f\n",$data[8]; 
     268                            printf "in DB since: %s\n",scalar(localtime($data[6])); 
     269                            printf "Last Match : %s\n",scalar(localtime($data[7])); 
     270                        } 
     271                    } 
     272                } 
     273                $ddb->disconnect; 
     274            } 
     275        } 
     276    } 
     277